1:
31: package ;
32:
33: import ;
34: import ;
35: import ;
36: import ;
37: import ;
38: import ;
39: import ;
40: import ;
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47:
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57: import ;
58: import ;
59:
60:
65: public class DefaultTypeRegistry implements TypeRegistry
66: {
67: private FormulaContext context;
68:
69: private static final long MILLISECS_PER_DAY = 24 * 60 * 60 * 1000;
70:
71: private static final BigDecimal ZERO = new BigDecimal(0);
72:
73: private NumberFormat[] numberFormats;
74:
75: public DefaultTypeRegistry()
76: {
77: }
78:
79:
86: public ExtendedComparator getComparator(final Type type1, final Type type2)
87: {
88: final DefaultComparator comparator = new DefaultComparator();
89: comparator.inititalize(context);
90: return comparator;
91: }
92:
93:
104: public Number convertToNumber(final Type type1, final Object value)
105: throws TypeConversionException
106: {
107: final LocalizationContext localizationContext = context.getLocalizationContext();
108:
109: if (value == null)
110: {
111:
112: throw new TypeConversionException();
113: }
114:
115: if (type1.isFlagSet(Type.NUMERIC_TYPE) || type1.isFlagSet(Type.ANY_TYPE))
116: {
117: if (type1.isFlagSet(Type.DATETIME_TYPE)
118: || type1.isFlagSet(Type.TIME_TYPE) || type1.isFlagSet(Type.DATE_TYPE)
119: || type1.isFlagSet(Type.ANY_TYPE))
120: {
121: if (value instanceof Date)
122: {
123: final Number serial = DateUtil.toSerialDate((Date) value, localizationContext);
124:
125: final Number ret = DateUtil.normalizeDate(serial, type1);
126:
127: return ret;
128: }
129: }
130:
131: if (value instanceof Number)
132: {
133: return (Number) value;
134: }
135: }
136:
137: if (type1.isFlagSet(Type.LOGICAL_TYPE) || type1.isFlagSet(Type.ANY_TYPE))
138: {
139: if (value instanceof Boolean)
140: {
141: if (Boolean.TRUE.equals(value))
142: {
143: return new Integer(1);
144: }
145: else
146: {
147: return new Integer(0);
148: }
149: }
150: }
151:
152: if (type1.isFlagSet(Type.TEXT_TYPE) || type1.isFlagSet(Type.ANY_TYPE))
153: {
154: final String val = value.toString();
155:
156:
157: try
158: {
159: return new BigDecimal(val);
160: }
161: catch (NumberFormatException e)
162: {
163:
164: }
165:
166:
167: final Iterator datetimeIterator = localizationContext.getDateFormats(DateTimeType.DATETIME_TYPE).iterator();
168: while (datetimeIterator.hasNext())
169: {
170: final DateFormat df = (DateFormat) datetimeIterator.next();
171: try
172: {
173: final Date date = df.parse(val);
174: final Number serial = DateUtil.toSerialDate(date, localizationContext);
175:
176: return serial;
177: }
178: catch (ParseException e)
179: {
180:
181: }
182: }
183:
184: final Iterator dateIterator = localizationContext.getDateFormats(DateTimeType.DATE_TYPE).iterator();
185: while (dateIterator.hasNext())
186: {
187: final DateFormat df = (DateFormat) dateIterator.next();
188: try
189: {
190: final Date date = df.parse(val);
191: final Number serial = DateUtil.toSerialDate(date, localizationContext);
192:
193: return serial;
194: }
195: catch (ParseException e)
196: {
197:
198: }
199: }
200:
201: final Iterator timeIterator = localizationContext
202: .getDateFormats(DateTimeType.TIME_TYPE).iterator();
203: while (timeIterator.hasNext())
204: {
205: final DateFormat df = (DateFormat) timeIterator.next();
206: try
207: {
208: final Date date = df.parse(val);
209: final Number serial = DateUtil.toSerialDate(date, localizationContext);
210:
211: return serial;
212: }
213: catch (ParseException e)
214: {
215:
216: }
217: }
218:
219:
220: for (int i = 0; i < numberFormats.length; i++)
221: {
222: try
223: {
224: final NumberFormat format = numberFormats[i];
225: return format.parse(val);
226: }
227: catch (ParseException e)
228: {
229:
230: }
231: }
232: }
233:
234: throw new TypeConversionException();
235: }
236:
237: public void initialize(final Configuration configuration,
238: final FormulaContext formulaContext)
239: {
240: this.context = formulaContext;
241: this.numberFormats = loadNumberFormats();
242: }
243:
244: protected NumberFormat[] loadNumberFormats()
245: {
246: final ArrayList formats = new ArrayList();
247: final DecimalFormat defaultFormat = new DecimalFormat("#0.###",
248: new DecimalFormatSymbols(Locale.US));
249: activateBigDecimalMode(defaultFormat);
250: formats.add(defaultFormat);
251:
252: return (NumberFormat[]) formats.toArray(new NumberFormat[formats.size()]);
253: }
254:
255: private void activateBigDecimalMode(final DecimalFormat format)
256: {
257: if (ObjectUtilities.isJDK14())
258: {
259: try
260: {
261: final Method method = DecimalFormat.class.getMethod(
262: "setParseBigDecimal", new Class[]
263: { Boolean.TYPE });
264: method.invoke(format, new Object[]
265: { Boolean.TRUE });
266: }
267: catch (Exception e)
268: {
269:
270: }
271: }
272: }
273:
274: public String convertToText(final Type type1, final Object value)
275: throws TypeConversionException
276: {
277: if (value == null)
278: {
279: return "";
280: }
281:
282:
283: if (type1.isFlagSet(Type.TEXT_TYPE))
284: {
285:
286: return value.toString();
287: }
288:
289: if (type1.isFlagSet(Type.LOGICAL_TYPE))
290: {
291: if (value instanceof Boolean)
292: {
293: final Boolean b = (Boolean) value;
294: if (Boolean.TRUE.equals(b))
295: {
296: return "TRUE";
297: }
298: else
299: {
300: return "FALSE";
301: }
302: }
303: else
304: {
305: throw new TypeConversionException();
306: }
307: }
308:
309:
310: if (type1.isFlagSet(Type.NUMERIC_TYPE))
311: {
312: if (type1.isFlagSet(Type.DATETIME_TYPE)
313: || type1.isFlagSet(Type.DATE_TYPE) || type1.isFlagSet(Type.TIME_TYPE))
314: {
315: final Date d = convertToDate(type1, value);
316: final List dateFormats = context.getLocalizationContext()
317: .getDateFormats(type1);
318: if (dateFormats != null && dateFormats.size() >= 1)
319: {
320: final DateFormat format = (DateFormat) dateFormats.get(0);
321: return format.format(d);
322: }
323: else
324: {
325:
326: return SimpleDateFormat.getDateTimeInstance(
327: SimpleDateFormat.FULL, SimpleDateFormat.FULL).format(d);
328: }
329: }
330: else
331: {
332: try
333: {
334: final Number n = convertToNumber(type1, value);
335: final NumberFormat format = getDefaultNumberFormat();
336: return format.format(n);
337: }
338: catch (TypeConversionException nfe)
339: {
340:
341: }
342: }
343: }
344:
345:
346: return value.toString();
347: }
348:
349: public Boolean convertToLogical(final Type type1, final Object value)
350: throws TypeConversionException
351: {
352: if (value == null)
353: {
354: return Boolean.FALSE;
355: }
356:
357:
358: if (type1.isFlagSet(Type.LOGICAL_TYPE) || type1.isFlagSet(Type.ANY_TYPE))
359: {
360: if (value instanceof Boolean)
361: {
362: return (Boolean) value;
363: }
364:
365:
366: return new Boolean(value.toString());
367: }
368:
369: if (type1.isFlagSet(Type.NUMERIC_TYPE))
370: {
371:
372: if (value instanceof Number)
373: {
374: final Number num = (Number) value;
375: if (!ZERO.equals(num))
376: {
377: return Boolean.TRUE;
378: }
379: }
380:
381:
382: return Boolean.FALSE;
383: }
384:
385: if (type1.isFlagSet(Type.TEXT_TYPE))
386: {
387:
388: final String str = value.toString();
389: if ("TRUE".equalsIgnoreCase(str))
390: {
391: return Boolean.TRUE;
392: }
393: else if ("FALSE".equalsIgnoreCase(str))
394: {
395: return Boolean.FALSE;
396: }
397: }
398:
399: throw new TypeConversionException();
400: }
401:
402: public Date convertToDate(final Type type1, final Object value)
403: throws TypeConversionException
404: {
405: if (type1.isFlagSet(Type.NUMERIC_TYPE) || type1.isFlagSet(Type.ANY_TYPE))
406: {
407: if (type1.isFlagSet(Type.DATE_TYPE)
408: || type1.isFlagSet(Type.DATETIME_TYPE)
409: || type1.isFlagSet(Type.TIME_TYPE) || type1.isFlagSet(Type.ANY_TYPE))
410: {
411: if (value instanceof Date)
412: {
413: return DateUtil.normalizeDate((Date) value, type1);
414: }
415: }
416: }
417: final Number serial = convertToNumber(type1, value);
418: return DateUtil.toJavaDate(serial, context.getLocalizationContext());
419: }
420:
421: protected NumberFormat getDefaultNumberFormat()
422: {
423: final Locale locale = context.getLocalizationContext().getLocale();
424: return new DecimalFormat("#0.#########", new DecimalFormatSymbols(locale));
425: }
426:
427:
436: public TypeValuePair convertTo(final Type targetType,
437: final TypeValuePair valuePair) throws TypeConversionException
438: {
439: if (targetType.isFlagSet(Type.ARRAY_TYPE))
440: {
441:
442: if (valuePair.getType().isFlagSet(Type.ARRAY_TYPE))
443: {
444: return convertArrayToArray(targetType, valuePair);
445: }
446: else
447: {
448: final Object retval = convertPlainToPlain(targetType, valuePair
449: .getType(), valuePair.getValue());
450: return new TypeValuePair(targetType, new Object[]
451: { retval });
452: }
453: }
454:
455: final Object value = valuePair.getValue();
456: final Object o = convertPlainToPlain(targetType, valuePair.getType(), value);
457: if (value == o)
458: {
459: return valuePair;
460: }
461: return new TypeValuePair(targetType, o);
462: }
463:
464: private Object convertPlainToPlain(final Type targetType, final Type type,
465: final Object value) throws TypeConversionException
466: {
467:
468:
469:
470:
471:
472:
473: if (targetType.isFlagSet(Type.NUMERIC_TYPE))
474: {
475: final Number serial = convertToNumber(type, value);
476: if (targetType.isFlagSet(Type.DATE_TYPE)
477: || targetType.isFlagSet(Type.DATETIME_TYPE)
478: || targetType.isFlagSet(Type.TIME_TYPE))
479: {
480: final Number normalizedSerial = DateUtil.normalizeDate(serial,
481: targetType);
482: final Date toJavaDate = DateUtil.toJavaDate(normalizedSerial, context
483: .getLocalizationContext());
484: return DateUtil.normalizeDate(toJavaDate, targetType, false);
485: }
486: return serial;
487: }
488: else if (targetType.isFlagSet(Type.LOGICAL_TYPE))
489: {
490: if (type.isFlagSet(Type.LOGICAL_TYPE))
491: {
492: return value;
493: }
494:
495: return convertToLogical(type, value);
496: }
497: else if (targetType.isFlagSet(Type.TEXT_TYPE))
498: {
499: return convertToText(type, value);
500: }
501:
502:
503: return value;
504: }
505:
506: private TypeValuePair convertArrayToArray(final Type targetType,
507: final TypeValuePair pair) throws TypeConversionException
508: {
509: final Type type = pair.getType();
510:
511: final Object[] array = (Object[]) pair.getValue();
512: final Object[] target = new Object[array.length];
513: for (int i = 0; i < array.length; i++)
514: {
515: final Object converted = convertPlainToPlain(targetType, type, array[i]);
516: if (converted == null)
517: {
518: return null;
519: }
520: target[i] = converted;
521: }
522: return new TypeValuePair(targetType, target);
523: }
524:
525: public Type guessTypeOfObject(Object o)
526: {
527: if (o instanceof Number)
528: {
529: return NumberType.GENERIC_NUMBER;
530: }
531: else if (o instanceof Date)
532: {
533: return DateTimeType.DATETIME_TYPE;
534: }
535: else if (o instanceof Time)
536: {
537: return DateTimeType.TIME_TYPE;
538: }
539: else if (o instanceof java.sql.Date)
540: {
541: return DateTimeType.DATE_TYPE;
542: }
543: else if (o instanceof Boolean)
544: {
545: return LogicalType.TYPE;
546: }
547: else if (o instanceof String)
548: {
549: return TextType.TYPE;
550: }
551:
552: return AnyType.TYPE;
553: }
554: }