PageRenderTime 46ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/ojc-core/encodersl/converter-ssc2custom/src/com/sun/stc/jcsre/FormatterFactory.java

https://bitbucket.org/pymma/openesb-components
Java | 785 lines | 377 code | 127 blank | 281 comment | 89 complexity | bee6c40c634e65b016878de0c7ca2c77 MD5 | raw file
  1. /*
  2. * BEGIN_HEADER - DO NOT EDIT
  3. *
  4. * The contents of this file are subject to the terms
  5. * of the Common Development and Distribution License
  6. * (the "License"). You may not use this file except
  7. * in compliance with the License.
  8. *
  9. * You can obtain a copy of the license at
  10. * https://open-jbi-components.dev.java.net/public/CDDLv1.0.html.
  11. * See the License for the specific language governing
  12. * permissions and limitations under the License.
  13. *
  14. * When distributing Covered Code, include this CDDL
  15. * HEADER in each file and include the License file at
  16. * https://open-jbi-components.dev.java.net/public/CDDLv1.0.html.
  17. * If applicable add the following below this CDDL HEADER,
  18. * with the fields enclosed by brackets "[]" replaced with
  19. * your own identifying information: Portions Copyright
  20. * [year] [name of copyright owner]
  21. */
  22. /*
  23. * @(#)FormatterFactory.java
  24. *
  25. * Copyright 2004-2008 Sun Microsystems, Inc. All Rights Reserved.
  26. *
  27. * END_HEADER - DO NOT EDIT
  28. */
  29. package com.sun.stc.jcsre;
  30. import java.util.Map;
  31. import java.util.HashMap;
  32. import java.text.NumberFormat;
  33. import java.text.DecimalFormat;
  34. import java.text.DateFormat;
  35. import java.text.SimpleDateFormat;
  36. import java.text.ParseException;
  37. import java.io.UnsupportedEncodingException;
  38. import com.sun.stc.eways.util.MonkUtils;
  39. import com.sun.stc.jcsre.IStringCoder;
  40. import com.sun.stc.jcsre.JCSProperties;
  41. import com.sun.stc.jcsre.StringCoderFactory;
  42. import java.util.Date;
  43. /**
  44. * This class is used to create and cache formatters.
  45. *
  46. * The formatters are used to parse/render java primitive
  47. * types (boolean, short, int, long, float, double) and certain
  48. * objects (java.util.Date).
  49. *
  50. * This class is thread safe.
  51. */
  52. public class FormatterFactory {
  53. private static final boolean unitTest = false;
  54. /**
  55. * for now we'll just use one map for all formatters.
  56. */
  57. private static Map cache = new HashMap(101);
  58. /**
  59. * default numeric formatter
  60. */
  61. private static final NumberFormat DefaultNumberFormat =
  62. getNumberFormat("#.##;-#.##");
  63. /**
  64. * default boolean formatter
  65. */
  66. private static final BooleanFormat DefaultBooleanFormat =
  67. getBooleanFormat("t|true|y|yes|1;f|false|n|no|0;true;false");
  68. /**
  69. * default date formatter
  70. */
  71. private static final DateFormat DefaultDateFormat =
  72. getDateFormat("yyyy-MM-dd HH:mm:ss z");
  73. /**
  74. * default string formatter
  75. */
  76. private static final StringFormat DefaultStringFormat =
  77. getStringFormat("%s");
  78. /**
  79. * inner class to wrap numbers and does range checking.
  80. */
  81. public static class RangeCheckedNumber extends Number {
  82. private static final double MAX_BYTE = (double)Byte.MAX_VALUE;
  83. private static final double MIN_BYTE = (double)Byte.MIN_VALUE;
  84. private static final double MAX_SHORT = (double)Short.MAX_VALUE;
  85. private static final double MIN_SHORT = (double)Short.MIN_VALUE;
  86. private static final double MAX_INT = (double)Integer.MAX_VALUE;
  87. private static final double MIN_INT = (double)Integer.MIN_VALUE;
  88. private static final double MAX_LONG = (double)Long.MAX_VALUE;
  89. private static final double MIN_LONG = (double)Long.MIN_VALUE;
  90. private static final double MAX_FLOAT = (double)Float.MAX_VALUE;
  91. private static final double MIN_FLOAT = (double)Float.MIN_VALUE;
  92. /**
  93. * the encapsulated Number
  94. */
  95. private Number number = null;
  96. /**
  97. * construct an instance that encapsulates the specified
  98. * Number
  99. *
  100. * @param _number the encapsulated number
  101. */
  102. public RangeCheckedNumber (Number _number) {
  103. this.number = _number;
  104. }
  105. /**
  106. * get the double value of the number.
  107. *
  108. * @return the double value of the number
  109. *
  110. * @throws NumberFormatException if the number is Double.POSITIVE_INFINITY,
  111. * Double.NEGATIVE_INFINITY, or Double.NaN
  112. */
  113. public double doubleValue () throws NumberFormatException {
  114. double value = this.number.doubleValue();
  115. if(Double.POSITIVE_INFINITY == value
  116. || Double.NEGATIVE_INFINITY == value
  117. || Double.NaN == value
  118. ) {
  119. throw new NumberFormatException("Value is out of range.");
  120. }
  121. return value;
  122. }
  123. /**
  124. * get the float value of the number.
  125. *
  126. * @return the float value of the number
  127. *
  128. * @throws NumberFormatException if the number is Float.POSITIVE_INFINITY,
  129. * Float.NEGATIVE_INFINITY, Float.NaN, greater than Float.MAX_VALUE,
  130. * or less than Float.MIN_VALUE.
  131. */
  132. public float floatValue () throws NumberFormatException {
  133. double value = this.number.doubleValue();
  134. if(Double.POSITIVE_INFINITY == value
  135. || Double.NEGATIVE_INFINITY == value
  136. || Double.NaN == value
  137. || (value > 0 &&
  138. (value > RangeCheckedNumber.MAX_FLOAT
  139. || value < RangeCheckedNumber.MIN_FLOAT
  140. )
  141. )
  142. || (value < 0 &&
  143. (-value > RangeCheckedNumber.MAX_FLOAT
  144. || -value < RangeCheckedNumber.MIN_FLOAT
  145. )
  146. )
  147. ) {
  148. throw new NumberFormatException("Value is out of range.");
  149. }
  150. return this.number.floatValue();
  151. }
  152. /**
  153. * get the long value of the number.
  154. *
  155. * @return the long value of the number
  156. *
  157. * @throws NumberFormatException if the number is Long.POSITIVE_INFINITY,
  158. * Long.NEGATIVE_INFINITY, Long.NaN, greater than Long.MAX_VALUE,
  159. * or less than Long.MIN_VALUE.
  160. */
  161. public long longValue () throws NumberFormatException {
  162. double value = this.number.doubleValue();
  163. if(Double.POSITIVE_INFINITY == value
  164. || Double.NEGATIVE_INFINITY == value
  165. || Double.NaN == value
  166. || value > RangeCheckedNumber.MAX_LONG
  167. || value < RangeCheckedNumber.MIN_LONG
  168. ) {
  169. throw new NumberFormatException("Value is out of range.");
  170. }
  171. return this.number.longValue();
  172. }
  173. /**
  174. * get the int value of the number.
  175. *
  176. * @return the int value of the number
  177. *
  178. * @throws NumberFormatException if the number is Integer.POSITIVE_INFINITY,
  179. * Integer.NEGATIVE_INFINITY, Integer.NaN, greater than Integer.MAX_VALUE,
  180. * or less than Integer.MIN_VALUE.
  181. */
  182. public int intValue () throws NumberFormatException {
  183. double value = this.number.doubleValue();
  184. if(Double.POSITIVE_INFINITY == value
  185. || Double.NEGATIVE_INFINITY == value
  186. || Double.NaN == value
  187. || value > RangeCheckedNumber.MAX_INT
  188. || value < RangeCheckedNumber.MIN_INT
  189. ) {
  190. throw new NumberFormatException("Value is out of range.");
  191. }
  192. return this.number.intValue();
  193. }
  194. /**
  195. * get the short value of the number.
  196. *
  197. * @return the short value of the number
  198. *
  199. * @throws NumberFormatException if the number is Short.POSITIVE_INFINITY,
  200. * Short.NEGATIVE_INFINITY, Short.NaN, greater than Short.MAX_VALUE,
  201. * or less than Short.MIN_VALUE.
  202. */
  203. public short shortValue () throws NumberFormatException {
  204. double value = this.number.doubleValue();
  205. if(Double.POSITIVE_INFINITY == value
  206. || Double.NEGATIVE_INFINITY == value
  207. || Double.NaN == value
  208. || value > RangeCheckedNumber.MAX_SHORT
  209. || value < RangeCheckedNumber.MIN_SHORT
  210. ) {
  211. throw new NumberFormatException("Value is out of range.");
  212. }
  213. return this.number.shortValue();
  214. }
  215. /**
  216. * get the byte value of the number.
  217. *
  218. * @return the byte value of the number
  219. *
  220. * @throws NumberFormatException if the number is Byte.POSITIVE_INFINITY,
  221. * Byte.NEGATIVE_INFINITY, Byte.NaN, greater than Byte.MAX_VALUE,
  222. * or less than Byte.MIN_VALUE.
  223. */
  224. public byte byteValue () throws NumberFormatException {
  225. double value = this.number.doubleValue();
  226. if(Double.POSITIVE_INFINITY == value
  227. || Double.NEGATIVE_INFINITY == value
  228. || Double.NaN == value
  229. || value > RangeCheckedNumber.MAX_BYTE
  230. || value < RangeCheckedNumber.MIN_BYTE
  231. ) {
  232. throw new NumberFormatException("Value is out of range.");
  233. }
  234. return this.number.byteValue();
  235. }
  236. }
  237. /**
  238. * this inner class wraps NumberFormat's parse method and
  239. * returns a RangeCheckedNumber
  240. *
  241. * @see java.text.NumberFormat
  242. */
  243. public static class RangeCheckedDecimalFormat extends DecimalFormat {
  244. /**
  245. * create an empty instance
  246. */
  247. public RangeCheckedDecimalFormat() {super();}
  248. /**
  249. * construct an instance from a string.
  250. *
  251. * @param _pattern the parse/render pattern
  252. */
  253. public RangeCheckedDecimalFormat (String _pattern) {
  254. super(_pattern);
  255. }
  256. /**
  257. * wrap the parsed java.lang.Number in a RangeCheckedNumber
  258. *
  259. * @see java.text.NumberFormat#parse(String)
  260. */
  261. public Number parse (String _value) throws ParseException {
  262. return new RangeCheckedNumber(super.parse(_value));
  263. }
  264. /**
  265. * parse a byte array in the specified encoding
  266. *
  267. * @param _bytes the byte array
  268. * @param _enc the encoding
  269. *
  270. * @return the number
  271. *
  272. * @throws ParseException unable to parse
  273. * @throws UnsupportedEncodingException _enc bad
  274. */
  275. public Number parse (byte[] _bytes, String _enc)
  276. throws ParseException, UnsupportedEncodingException
  277. {
  278. return parse(StringCoderFactory.getStringCoder(_enc).decode(_bytes));
  279. }
  280. /**
  281. * Formats the specified long into a byte array with specified coder.
  282. *
  283. * @param _value the value to format
  284. * @param _coder string coder to use
  285. *
  286. * @return byte array containing formatted number
  287. *
  288. * @throws unsupported encoding exception
  289. */
  290. public byte[] format (long _value, IStringCoder _coder)
  291. throws UnsupportedEncodingException
  292. {
  293. return _coder.encode(format(_value));
  294. }
  295. /**
  296. * Formats the specified long into a byte array with specified encoding.
  297. * This is for backward compatibility with e*Gate 4.5.1.
  298. *
  299. * @param _value the value to format
  300. * @param _enc encoding to use
  301. *
  302. * @return byte array containing formatted number
  303. *
  304. * @throws unsupported encoding exception
  305. */
  306. public byte[] format (long _value, String _enc)
  307. throws UnsupportedEncodingException
  308. {
  309. return format(_value, StringCoderFactory.getStringCoder(_enc));
  310. }
  311. /**
  312. * Formats the specified double into a byte array with specified coder.
  313. *
  314. * @param _value the value to format
  315. * @param _coder string coder to use
  316. *
  317. * @return byte array containing formatted number
  318. *
  319. * @throws unsupported encoding exception
  320. */
  321. public byte[] format (double _value, IStringCoder _coder)
  322. throws UnsupportedEncodingException
  323. {
  324. return _coder.encode(format(_value));
  325. }
  326. /**
  327. * Formats the specified double into a byte array with specified encoding.
  328. * This is for backward compatibility with e*Gate 4.5.1.
  329. *
  330. * @param _value the value to format
  331. * @param _enc encoding to use
  332. *
  333. * @return byte array containing formatted number
  334. *
  335. * @throws unsupported encoding exception
  336. */
  337. public byte[] format (double _value, String _enc)
  338. throws UnsupportedEncodingException
  339. {
  340. return format(_value, StringCoderFactory.getStringCoder(_enc));
  341. }
  342. }
  343. /**
  344. * This method returns a number formatter that will parse
  345. * and render numeric primitives according to the specified
  346. * pattern.
  347. *
  348. * This method is thread safe.
  349. *
  350. * @param _pattern the parsing/rendering pattern.
  351. *
  352. * @return the number formatter
  353. */
  354. public static NumberFormat getNumberFormat (String _pattern) {
  355. // return default if parameter is null
  356. if(null == _pattern) {
  357. return DefaultNumberFormat;
  358. }
  359. NumberFormat formatter = null;
  360. synchronized(FormatterFactory.cache) {
  361. // try to get formatter from cache
  362. formatter = (NumberFormat)FormatterFactory.cache.get(_pattern);
  363. // create formatter if not in cache
  364. if(null == formatter) {
  365. /*
  366. // COBOL style
  367. if(null == formatter) {
  368. try {
  369. formatter = new COBOLRangeCheckedDecimalFormat(_pattern);
  370. } catch(Exception ex) {
  371. formatter = null;
  372. }
  373. }
  374. */
  375. // C style
  376. if(null == formatter) {
  377. try {
  378. formatter = new CRangeCheckedDecimalFormat(_pattern);
  379. } catch(Exception ex) {
  380. formatter = null;
  381. }
  382. }
  383. // default
  384. if(null == formatter) {
  385. formatter = new RangeCheckedDecimalFormat(_pattern);
  386. }
  387. FormatterFactory.cache.put(_pattern, formatter);
  388. }
  389. }
  390. return formatter;
  391. }
  392. /**
  393. * This method returns a boolean formatter that will parse
  394. * and render boolean primitives according to the specified
  395. * pattern.
  396. *
  397. * This method is thread safe.
  398. *
  399. * @param _pattern the parsing/rendering pattern.
  400. *
  401. * @return the boolean formatter
  402. */
  403. public static BooleanFormat getBooleanFormat (String _pattern) {
  404. // return default if parameter is null
  405. if(null == _pattern) {
  406. return DefaultBooleanFormat;
  407. }
  408. BooleanFormat formatter = null;
  409. synchronized(FormatterFactory.cache) {
  410. // try to get formatter from cache
  411. formatter = (BooleanFormat)FormatterFactory.cache.get(_pattern);
  412. // create formatter if not in cache
  413. if(null == formatter) {
  414. formatter = new BooleanFormat(_pattern);
  415. FormatterFactory.cache.put(_pattern, formatter);
  416. }
  417. }
  418. return formatter;
  419. }
  420. /**
  421. * This method returns a string formatter that will parse
  422. * and render boolean primitives according to the specified
  423. * pattern.
  424. *
  425. * This method is thread safe.
  426. *
  427. * @param _pattern the parsing/rendering pattern.
  428. *
  429. * @return the string formatter
  430. */
  431. public static StringFormat getStringFormat (String _pattern) {
  432. // return default if parameter is null
  433. if(null == _pattern) {
  434. return DefaultStringFormat;
  435. }
  436. StringFormat formatter = null;
  437. synchronized(FormatterFactory.cache) {
  438. // try to get formatter from cache
  439. formatter = (StringFormat)FormatterFactory.cache.get(_pattern);
  440. // create formatter if not in cache
  441. if(null == formatter) {
  442. formatter = new CStringFormat(_pattern);
  443. FormatterFactory.cache.put(_pattern, formatter);
  444. }
  445. }
  446. return formatter;
  447. }
  448. /**
  449. * This method returns a date formatter that will parse
  450. * and render dates according to the specified pattern.
  451. *
  452. * This method is thread safe.
  453. *
  454. * @param _pattern the parsing/rendering pattern.
  455. *
  456. * @return the date formatter
  457. *
  458. * @java.text.SimpleDateFormat
  459. */
  460. public static DateFormat getDateFormat (String _pattern) {
  461. // return default if parameter is null
  462. if(null == _pattern) {
  463. return DefaultDateFormat;
  464. }
  465. DateFormat formatter = null;
  466. String javaPattern = null;
  467. // convert from Monk if necessary
  468. if(MonkUtils.isMonkDatePattern(_pattern)) {
  469. try {
  470. javaPattern = MonkUtils.toJavaDatePattern(_pattern);
  471. } catch(ParseException ex) {
  472. ex.printStackTrace();
  473. throw new IllegalArgumentException("invalid pattern.");
  474. }
  475. }
  476. synchronized(FormatterFactory.cache) {
  477. // try to get formatter from cache
  478. formatter = (DateFormat)FormatterFactory.cache.get(_pattern);
  479. // not found based on user pattern
  480. if(null == formatter) {
  481. // we have a java pattern
  482. if(null != javaPattern) {
  483. formatter = (DateFormat)FormatterFactory.cache.get(javaPattern);
  484. // found using java pattern
  485. if(null != formatter) {
  486. // add under user pattern
  487. FormatterFactory.cache.put(_pattern, formatter);
  488. }
  489. // _pattern is the java pattern
  490. } else {
  491. javaPattern = _pattern;
  492. }
  493. }
  494. // create formatter if not in cache
  495. if(null == formatter) {
  496. formatter = new SimpleDateFormat(javaPattern);
  497. boolean strict = JCSProperties.getFlag("DateFormat.Lenient", true);
  498. formatter.setLenient(strict);
  499. FormatterFactory.cache.put(_pattern, formatter);
  500. if(!_pattern.equals(javaPattern)) {
  501. FormatterFactory.cache.put(javaPattern, formatter);
  502. }
  503. }
  504. }
  505. return formatter;
  506. }
  507. /**
  508. * main class for testing purposes
  509. */
  510. public static void main (String[] _args) {
  511. if(!FormatterFactory.unitTest) return;
  512. final String numberPattern = "#.##;-#.##";
  513. final String booleanPattern = "t|true|1;f|false|0;true;false";
  514. final String[] defaultArgs = {
  515. // numbers
  516. "1.01"
  517. ,"-1.01"
  518. ,"10.01"
  519. ,"-10.01"
  520. ,"100.01"
  521. ,"-100.01"
  522. ,"1000.01"
  523. ,"-1000.01"
  524. ,"9E9"
  525. ,"-9E9"
  526. ,"9E-9"
  527. ,"-9E-9"
  528. ,"9E99"
  529. ,"-9E99"
  530. ,"9E-99"
  531. ,"-9E-99"
  532. ,"9E999"
  533. ,"-9E999"
  534. ,"9E-999"
  535. ,"-9E-999"
  536. // booleans
  537. ,"true"
  538. ,"t"
  539. ,"false"
  540. ,"f"
  541. // failures
  542. ,"blah"
  543. };
  544. java.text.NumberFormat numberFormatter = FormatterFactory.getNumberFormat(numberPattern);
  545. BooleanFormat booleanFormatter = FormatterFactory.getBooleanFormat(booleanPattern);
  546. // do straight pointer comparisons to determine if caching is working
  547. if(FormatterFactory.getNumberFormat(numberPattern) == numberFormatter) {
  548. System.out.println("**** NumberFormats are being cached.");
  549. } else {
  550. System.out.println("**** Not caching NumberFormat.");
  551. System.exit(1);
  552. }
  553. if(FormatterFactory.getBooleanFormat(booleanPattern) == booleanFormatter) {
  554. System.out.println("**** BooleanFormats are being cached.");
  555. } else {
  556. System.out.println("**** Not caching BooleanFormat.");
  557. System.exit(1);
  558. }
  559. // set defaults if none provided on command line
  560. if(0 == _args.length) {
  561. _args = defaultArgs;
  562. }
  563. for(int ii=0; ii<_args.length ;ii++) {
  564. String arg = _args[ii];
  565. // first try to format as number
  566. try {
  567. System.out.println("\nParsing: " + arg);
  568. Number number = numberFormatter.parse(arg);
  569. //
  570. // test each conversion for range exceptions
  571. //
  572. try {
  573. byte num = number.byteValue();
  574. System.out.println("fits in a byte as " + num);
  575. } catch(NumberFormatException ex) {
  576. System.out.println("too big for a byte.");
  577. }
  578. try {
  579. short num = number.shortValue();
  580. System.out.println("fits in a short as " + num);
  581. } catch(NumberFormatException ex) {
  582. System.out.println("too big for a short.");
  583. }
  584. try {
  585. int num = number.intValue();
  586. System.out.println("fits in a int as " + num);
  587. } catch(NumberFormatException ex) {
  588. System.out.println("too big for a int.");
  589. }
  590. try {
  591. long num = number.longValue();
  592. System.out.println("fits in a long as " + num);
  593. } catch(NumberFormatException ex) {
  594. System.out.println("too big for a long.");
  595. }
  596. try {
  597. float num = number.floatValue();
  598. System.out.println("fits in a float as " + num);
  599. } catch(NumberFormatException ex) {
  600. System.out.println("too big for a float.");
  601. }
  602. try {
  603. double num = number.doubleValue();
  604. System.out.println("fits in a double as " + num);
  605. System.out.println(arg
  606. + " rendered as number "
  607. + numberFormatter.format(num)
  608. );
  609. } catch(NumberFormatException ex) {
  610. System.out.println("too big for a double.");
  611. }
  612. // if that fails try as boolean
  613. } catch(java.text.ParseException ex) {
  614. try {
  615. boolean boolVal = booleanFormatter.parse(arg);
  616. System.out.println(arg
  617. + " parsed as boolean "
  618. + boolVal
  619. );
  620. System.out.println(arg
  621. + " rendered as boolean "
  622. + booleanFormatter.format(boolVal)
  623. );
  624. } catch(java.text.ParseException ex2) {
  625. System.out.println("Unable to parse " + arg);
  626. ex.printStackTrace();
  627. }
  628. } catch(Exception ex) {
  629. ex.printStackTrace();
  630. }
  631. }
  632. // Testing DateFormat
  633. // set defaults if none provided on command line
  634. String _date;
  635. String _to;
  636. if(2 != _args.length)
  637. {
  638. // This should fail for a Strict Lenient setting, which can be
  639. // done by an entry in the .jcsrc file "DateFormat.Lenient=false"
  640. _date = "20032003";
  641. _to = "yyyyMMdd";
  642. }
  643. else
  644. {
  645. _date = _args[0];
  646. _to = _args[1];
  647. }
  648. try
  649. {
  650. Date DateF = FormatterFactory.getDateFormat(_to).parse(_date);
  651. System.out.println("\nDate data: " + DateF);
  652. }
  653. catch(ParseException ex)
  654. {
  655. System.out.println("Invalid Date.");
  656. }
  657. }
  658. }