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: import ;
60: import ;
61: import ;
62:
63:
68: public class DefaultTypeRegistry implements TypeRegistry
69: {
70:
71: private static class ArrayConverterCallback implements ArrayCallback
72: {
73: private Object retval;
74: private Type targetType;
75:
76: private ArrayConverterCallback(final Object retval, final Type targetType)
77: {
78: this.retval = retval;
79: this.targetType = targetType;
80: }
81:
82: public LValue getRaw(final int row, final int column)
83: {
84: return null;
85: }
86:
87: public Object getValue(final int row, final int column) throws EvaluationException
88: {
89: if (row == 0 && column == 0)
90: {
91: return retval;
92: }
93: return null;
94: }
95:
96: public Type getType(final int row, final int column) throws EvaluationException
97: {
98: if (row == 0 && column == 0)
99: {
100: return targetType;
101: }
102: return null;
103: }
104:
105: public int getColumnCount()
106: {
107: return 1;
108: }
109:
110: public int getRowCount()
111: {
112: return 1;
113: }
114: }
115:
116: private FormulaContext context;
117:
118: private static final BigDecimal ZERO = new BigDecimal(0);
119:
120: private NumberFormat[] numberFormats;
121:
122: public DefaultTypeRegistry()
123: {
124: }
125:
126:
133: public ExtendedComparator getComparator(final Type type1, final Type type2)
134: {
135: final DefaultComparator comparator = new DefaultComparator();
136: comparator.inititalize(context);
137: return comparator;
138: }
139:
140:
149: public Number convertToNumber(final Type type1, final Object value)
150: throws TypeConversionException
151: {
152: final LocalizationContext localizationContext = context.getLocalizationContext();
153:
154: if (value == null)
155: {
156:
157: throw new TypeConversionException();
158: }
159:
160: if (type1.isFlagSet(Type.NUMERIC_TYPE) || type1.isFlagSet(Type.ANY_TYPE))
161: {
162: if (type1.isFlagSet(Type.DATETIME_TYPE)
163: || type1.isFlagSet(Type.TIME_TYPE) || type1.isFlagSet(Type.DATE_TYPE)
164: || type1.isFlagSet(Type.ANY_TYPE))
165: {
166: if (value instanceof Date)
167: {
168: final Number serial = DateUtil.toSerialDate((Date) value, localizationContext);
169:
170:
171: return DateUtil.normalizeDate(serial, type1);
172: }
173: }
174:
175: if (value instanceof Number)
176: {
177: return (Number) value;
178: }
179: }
180:
181: if (type1.isFlagSet(Type.LOGICAL_TYPE) || type1.isFlagSet(Type.ANY_TYPE))
182: {
183: if (value instanceof Boolean)
184: {
185: if (Boolean.TRUE.equals(value))
186: {
187: return new Integer(1);
188: }
189: else
190: {
191: return new Integer(0);
192: }
193: }
194: }
195:
196: if (type1.isFlagSet(Type.TEXT_TYPE) || type1.isFlagSet(Type.ANY_TYPE))
197: {
198: final String val = value.toString();
199:
200:
201: try
202: {
203: return new BigDecimal(val);
204: }
205: catch (NumberFormatException e)
206: {
207:
208: }
209:
210:
211: final Iterator datetimeIterator = localizationContext.getDateFormats(DateTimeType.DATETIME_TYPE).iterator();
212: while (datetimeIterator.hasNext())
213: {
214: final DateFormat df = (DateFormat) datetimeIterator.next();
215: try
216: {
217: final Date date = df.parse(val);
218:
219: return DateUtil.toSerialDate(date, localizationContext);
220: }
221: catch (ParseException e)
222: {
223:
224: }
225: }
226:
227: final Iterator dateIterator = localizationContext.getDateFormats(DateTimeType.DATE_TYPE).iterator();
228: while (dateIterator.hasNext())
229: {
230: final DateFormat df = (DateFormat) dateIterator.next();
231: try
232: {
233: final Date date = df.parse(val);
234:
235: return DateUtil.toSerialDate(date, localizationContext);
236: }
237: catch (ParseException e)
238: {
239:
240: }
241: }
242:
243: final Iterator timeIterator = localizationContext
244: .getDateFormats(DateTimeType.TIME_TYPE).iterator();
245: while (timeIterator.hasNext())
246: {
247: final DateFormat df = (DateFormat) timeIterator.next();
248: try
249: {
250: final Date date = df.parse(val);
251:
252: return DateUtil.toSerialDate(date, localizationContext);
253: }
254: catch (ParseException e)
255: {
256:
257: }
258: }
259:
260:
261: for (int i = 0; i < numberFormats.length; i++)
262: {
263: try
264: {
265: final NumberFormat format = numberFormats[i];
266: return format.parse(val);
267: }
268: catch (ParseException e)
269: {
270:
271: }
272: }
273: }
274:
275: throw new TypeConversionException();
276: }
277:
278: public void initialize(final Configuration configuration,
279: final FormulaContext formulaContext)
280: {
281: this.context = formulaContext;
282: this.numberFormats = loadNumberFormats();
283: }
284:
285: protected NumberFormat[] loadNumberFormats()
286: {
287: final ArrayList formats = new ArrayList();
288: final DecimalFormat defaultFormat = new DecimalFormat("#0.###",
289: new DecimalFormatSymbols(Locale.US));
290: activateBigDecimalMode(defaultFormat);
291: formats.add(defaultFormat);
292:
293: return (NumberFormat[]) formats.toArray(new NumberFormat[formats.size()]);
294: }
295:
296: private void activateBigDecimalMode(final DecimalFormat format)
297: {
298: if (ObjectUtilities.isJDK14())
299: {
300: try
301: {
302: final Method method = DecimalFormat.class.getMethod(
303: "setParseBigDecimal", new Class[]
304: {Boolean.TYPE});
305: method.invoke(format, new Object[]
306: {Boolean.TRUE});
307: }
308: catch (Exception e)
309: {
310:
311: }
312: }
313: }
314:
315: public String convertToText(final Type type1, final Object value)
316: throws TypeConversionException
317: {
318: if (value == null)
319: {
320: return "";
321: }
322:
323:
324: if (type1.isFlagSet(Type.TEXT_TYPE))
325: {
326:
327: return value.toString();
328: }
329:
330: if (type1.isFlagSet(Type.LOGICAL_TYPE))
331: {
332: if (value instanceof Boolean)
333: {
334: final Boolean b = (Boolean) value;
335: if (Boolean.TRUE.equals(b))
336: {
337: return "TRUE";
338: }
339: else
340: {
341: return "FALSE";
342: }
343: }
344: else
345: {
346: throw new TypeConversionException();
347: }
348: }
349:
350:
351: if (type1.isFlagSet(Type.NUMERIC_TYPE))
352: {
353: if (type1.isFlagSet(Type.DATETIME_TYPE)
354: || type1.isFlagSet(Type.DATE_TYPE) || type1.isFlagSet(Type.TIME_TYPE))
355: {
356: final Date d = convertToDate(type1, value);
357: final List dateFormats = context.getLocalizationContext()
358: .getDateFormats(type1);
359: if (dateFormats != null && dateFormats.size() >= 1)
360: {
361: final DateFormat format = (DateFormat) dateFormats.get(0);
362: return format.format(d);
363: }
364: else
365: {
366:
367: return SimpleDateFormat.getDateTimeInstance(
368: SimpleDateFormat.FULL, SimpleDateFormat.FULL).format(d);
369: }
370: }
371: else
372: {
373: try
374: {
375: final Number n = convertToNumber(type1, value);
376: final NumberFormat format = getDefaultNumberFormat();
377: return format.format(n);
378: }
379: catch (TypeConversionException nfe)
380: {
381:
382: }
383: }
384: }
385:
386:
387: return value.toString();
388: }
389:
390: public Boolean convertToLogical(final Type type1, final Object value)
391: throws TypeConversionException
392: {
393: if (value == null)
394: {
395: return Boolean.FALSE;
396: }
397:
398:
399: if (type1.isFlagSet(Type.LOGICAL_TYPE) || type1.isFlagSet(Type.ANY_TYPE))
400: {
401: if (value instanceof Boolean)
402: {
403: return (Boolean) value;
404: }
405:
406:
407: if ("true".equalsIgnoreCase(String.valueOf(value)))
408: {
409: return Boolean.TRUE;
410: }
411: return Boolean.FALSE;
412: }
413:
414: if (type1.isFlagSet(Type.NUMERIC_TYPE))
415: {
416:
417: if (value instanceof Number)
418: {
419: final Number num = (Number) value;
420: if (!ZERO.equals(num))
421: {
422: return Boolean.TRUE;
423: }
424: }
425:
426:
427: return Boolean.FALSE;
428: }
429:
430: if (type1.isFlagSet(Type.TEXT_TYPE))
431: {
432:
433: final String str = value.toString();
434: if ("TRUE".equalsIgnoreCase(str))
435: {
436: return Boolean.TRUE;
437: }
438: else if ("FALSE".equalsIgnoreCase(str))
439: {
440: return Boolean.FALSE;
441: }
442: }
443:
444: throw new TypeConversionException();
445: }
446:
447: public Date convertToDate(final Type type1, final Object value)
448: throws TypeConversionException
449: {
450: if (type1.isFlagSet(Type.NUMERIC_TYPE) || type1.isFlagSet(Type.ANY_TYPE))
451: {
452: if (type1.isFlagSet(Type.DATE_TYPE)
453: || type1.isFlagSet(Type.DATETIME_TYPE)
454: || type1.isFlagSet(Type.TIME_TYPE) || type1.isFlagSet(Type.ANY_TYPE))
455: {
456: if (value instanceof Date)
457: {
458: return DateUtil.normalizeDate((Date) value, type1);
459: }
460: }
461: }
462: final Number serial = convertToNumber(type1, value);
463: return DateUtil.toJavaDate(serial, context.getLocalizationContext());
464: }
465:
466: protected NumberFormat getDefaultNumberFormat()
467: {
468: final Locale locale = context.getLocalizationContext().getLocale();
469: return new DecimalFormat("#0.#########", new DecimalFormatSymbols(locale));
470: }
471:
472: private TypeValuePair convertToSequence(final Type targetType, final TypeValuePair valuePair)
473: throws TypeConversionException
474: {
475: if (targetType.isFlagSet(Type.NUMERIC_TYPE))
476: {
477: return new TypeValuePair(targetType, convertToNumberSequence(valuePair.getType(), valuePair.getValue()));
478: }
479: throw new TypeConversionException();
480: }
481:
482: public NumberSequence convertToNumberSequence(final Type type, final Object value) throws TypeConversionException
483: {
484:
485: if (type.isFlagSet(Type.NUMERIC_SEQUENCE_TYPE))
486: {
487: if (value instanceof NumberSequence)
488: {
489: return (NumberSequence) value;
490: }
491: else
492: {
493: throw new TypeConversionException();
494: }
495: }
496:
497: if (type.isFlagSet(Type.ARRAY_TYPE))
498: {
499: if (value instanceof ArrayCallback)
500: {
501: return new NumberSequence((ArrayCallback) value, context);
502: }
503: else
504: {
505: throw new TypeConversionException();
506: }
507: }
508:
509: if (type.isFlagSet(Type.SCALAR_TYPE) && type.isFlagSet(Type.NUMERIC_TYPE))
510: {
511: return new NumberSequence(convertToNumber(type, value), context);
512: }
513: else
514: {
515: throw new TypeConversionException();
516: }
517: }
518:
519:
526: public TypeValuePair convertTo(final Type targetType,
527: final TypeValuePair valuePair) throws TypeConversionException
528: {
529: if (targetType.isFlagSet(Type.ARRAY_TYPE))
530: {
531:
532: if (valuePair.getType().isFlagSet(Type.ARRAY_TYPE))
533: {
534: if (valuePair.getType().isFlagSet(Type.SEQUENCE_TYPE))
535: {
536: return convertToSequence(targetType, valuePair);
537: }
538: else
539: {
540: if (targetType.isFlagSet(Type.SEQUENCE_TYPE))
541: {
542:
543: return convertToSequence(targetType, valuePair);
544: }
545: else
546: {
547: return convertArrayToArray(targetType, valuePair);
548: }
549: }
550: }
551: else
552: {
553: if (targetType.isFlagSet(Type.SEQUENCE_TYPE))
554: {
555: return convertToSequence(targetType, valuePair);
556: }
557: else
558: {
559: final Object retval = convertPlainToPlain(targetType, valuePair.getType(), valuePair.getValue());
560: return new TypeValuePair(targetType, new ArrayConverterCallback(retval, targetType));
561: }
562: }
563: }
564:
565:
566: final Object value = valuePair.getValue();
567: final Object o = convertPlainToPlain(targetType, valuePair.getType(), value);
568: if (value == o)
569: {
570: return valuePair;
571: }
572: return new TypeValuePair(targetType, o);
573: }
574:
575: private Object convertPlainToPlain(final Type targetType, final Type type,
576: final Object value) throws TypeConversionException
577: {
578: if (targetType.isFlagSet(Type.NUMERIC_TYPE))
579: {
580: if (targetType.isFlagSet(Type.LOGICAL_TYPE))
581: {
582: if (type.isFlagSet(Type.LOGICAL_TYPE))
583: {
584: return value;
585: }
586:
587: return convertToLogical(type, value);
588: }
589:
590: final Number serial = convertToNumber(type, value);
591: if (targetType.isFlagSet(Type.DATE_TYPE)
592: || targetType.isFlagSet(Type.DATETIME_TYPE)
593: || targetType.isFlagSet(Type.TIME_TYPE))
594: {
595: final Number normalizedSerial = DateUtil.normalizeDate(serial,
596: targetType);
597: final Date toJavaDate = DateUtil.toJavaDate(normalizedSerial, context
598: .getLocalizationContext());
599: return DateUtil.normalizeDate(toJavaDate, targetType, false);
600: }
601: return serial;
602: }
603: else if (targetType.isFlagSet(Type.TEXT_TYPE))
604: {
605: return convertToText(type, value);
606: }
607:
608:
609: return value;
610: }
611:
612: private TypeValuePair convertArrayToArray(final Type targetType,
613: final TypeValuePair pair) throws TypeConversionException
614: {
615: final Object value = pair.getValue();
616: if (value instanceof ArrayCallback)
617: {
618: final ArrayCallback array = (ArrayCallback) value;
619: for (int i = 0; i < array.getRowCount(); i++)
620: {
621: for (int j = 0; j < array.getColumnCount(); j++)
622: {
623:
624: throw new UnsupportedOperationException("Not implemented exception");
625: }
626: }
627: }
628:
629: throw new TypeConversionException();
630: }
631:
632: public Type guessTypeOfObject(final Object o)
633: {
634: if (o instanceof Number)
635: {
636: return NumberType.GENERIC_NUMBER;
637: }
638: else if (o instanceof Time)
639: {
640: return DateTimeType.TIME_TYPE;
641: }
642: else if (o instanceof java.sql.Date)
643: {
644: return DateTimeType.DATE_TYPE;
645: }
646: else if (o instanceof Date)
647: {
648: return DateTimeType.DATETIME_TYPE;
649: }
650: else if (o instanceof Boolean)
651: {
652: return LogicalType.TYPE;
653: }
654: else if (o instanceof String)
655: {
656: return TextType.TYPE;
657: }
658:
659: return AnyType.TYPE;
660: }
661: }