Mercurial > projects > dwt2
comparison org.eclipse.core.databinding/src/org/eclipse/core/databinding/UpdateStrategy.d @ 78:0a55d2d5a946
Added file for databinding
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Tue, 14 Apr 2009 11:35:29 +0200 |
parents | |
children | 383ce7bd736b |
comparison
equal
deleted
inserted
replaced
76:f05e6e8b2f2d | 78:0a55d2d5a946 |
---|---|
1 /******************************************************************************* | |
2 * Copyright (c) 2007, 2008 IBM Corporation and others. | |
3 * All rights reserved. This program and the accompanying materials | |
4 * are made available under the terms of the Eclipse Public License v1.0 | |
5 * which accompanies this distribution, and is available at | |
6 * http://www.eclipse.org/legal/epl-v10.html | |
7 * | |
8 * Contributors: | |
9 * IBM Corporation - initial API and implementation | |
10 * Matt Carter - Bug 180392 | |
11 * - Character support completed (bug 197679) | |
12 *******************************************************************************/ | |
13 | |
14 module org.eclipse.core.databinding.UpdateStrategy; | |
15 | |
16 import java.lang.all; | |
17 | |
18 import java.math.BigDecimal; | |
19 import java.math.BigInteger; | |
20 import java.util.HashMap; | |
21 import java.util.Map; | |
22 | |
23 import org.eclipse.core.databinding.conversion.IConverter; | |
24 import org.eclipse.core.databinding.conversion.NumberToStringConverter; | |
25 import org.eclipse.core.databinding.conversion.StringToNumberConverter; | |
26 import org.eclipse.core.databinding.util.Policy; | |
27 import org.eclipse.core.internal.databinding.ClassLookupSupport; | |
28 import org.eclipse.core.internal.databinding.Pair; | |
29 import org.eclipse.core.internal.databinding.conversion.CharacterToStringConverter; | |
30 import org.eclipse.core.internal.databinding.conversion.IdentityConverter; | |
31 import org.eclipse.core.internal.databinding.conversion.IntegerToStringConverter; | |
32 import org.eclipse.core.internal.databinding.conversion.NumberToBigDecimalConverter; | |
33 import org.eclipse.core.internal.databinding.conversion.NumberToBigIntegerConverter; | |
34 import org.eclipse.core.internal.databinding.conversion.NumberToByteConverter; | |
35 import org.eclipse.core.internal.databinding.conversion.NumberToDoubleConverter; | |
36 import org.eclipse.core.internal.databinding.conversion.NumberToFloatConverter; | |
37 import org.eclipse.core.internal.databinding.conversion.NumberToIntegerConverter; | |
38 import org.eclipse.core.internal.databinding.conversion.NumberToLongConverter; | |
39 import org.eclipse.core.internal.databinding.conversion.NumberToShortConverter; | |
40 import org.eclipse.core.internal.databinding.conversion.ObjectToStringConverter; | |
41 import org.eclipse.core.internal.databinding.conversion.StringToByteConverter; | |
42 import org.eclipse.core.internal.databinding.conversion.StringToCharacterConverter; | |
43 import org.eclipse.core.internal.databinding.conversion.StringToShortConverter; | |
44 import org.eclipse.core.runtime.IStatus; | |
45 import org.eclipse.core.runtime.Status; | |
46 | |
47 import com.ibm.icu.text.NumberFormat; | |
48 | |
49 /** | |
50 * @since 1.0 | |
51 * | |
52 */ | |
53 /* package */class UpdateStrategy { | |
54 | |
55 private static final String BOOLEAN_TYPE = "java.lang.Boolean.TYPE"; //$NON-NLS-1$ | |
56 | |
57 private static final String SHORT_TYPE = "java.lang.Short.TYPE"; //$NON-NLS-1$ | |
58 | |
59 private static final String BYTE_TYPE = "java.lang.Byte.TYPE"; //$NON-NLS-1$ | |
60 | |
61 private static final String DOUBLE_TYPE = "java.lang.Double.TYPE"; //$NON-NLS-1$ | |
62 | |
63 private static final String FLOAT_TYPE = "java.lang.Float.TYPE"; //$NON-NLS-1$ | |
64 | |
65 private static final String INTEGER_TYPE = "java.lang.Integer.TYPE"; //$NON-NLS-1$ | |
66 | |
67 private static final String LONG_TYPE = "java.lang.Long.TYPE"; //$NON-NLS-1$ | |
68 | |
69 private static final String CHARACTER_TYPE = "java.lang.Character.TYPE"; //$NON-NLS-1$ | |
70 | |
71 private static Map converterMap; | |
72 | |
73 private static ClassInfo autoboxed(ClassInfo clazz) { | |
74 if (clazz is Float.TYPE) | |
75 return Float.classinfo; | |
76 else if (clazz is Double.TYPE) | |
77 return Double.classinfo; | |
78 else if (clazz is Short.TYPE) | |
79 return Short.classinfo; | |
80 else if (clazz is Integer.TYPE) | |
81 return Integer.classinfo; | |
82 else if (clazz is Long.TYPE) | |
83 return Long.classinfo; | |
84 else if (clazz is Byte.TYPE) | |
85 return Byte.classinfo; | |
86 else if (clazz is Boolean.TYPE) | |
87 return Boolean.classinfo; | |
88 else if (clazz is Character.TYPE) | |
89 return Character.classinfo; | |
90 return clazz; | |
91 } | |
92 | |
93 final protected void checkAssignable(Object toType, Object fromType, | |
94 String errorString) { | |
95 Boolean assignableFromModelToModelConverter = isAssignableFromTo( | |
96 fromType, toType); | |
97 if (assignableFromModelToModelConverter !is null | |
98 && !assignableFromModelToModelConverter.booleanValue()) { | |
99 throw new BindingException(errorString | |
100 + " Expected: " + fromType + ", actual: " + toType); //$NON-NLS-1$//$NON-NLS-2$ | |
101 } | |
102 } | |
103 | |
104 /** | |
105 * Tries to create a converter that can convert from values of type | |
106 * fromType. Returns <code>null</code> if no converter could be created. | |
107 * Either toType or modelDescription can be <code>null</code>, but not | |
108 * both. | |
109 * | |
110 * @param fromType | |
111 * @param toType | |
112 * @return an IConverter, or <code>null</code> if unsuccessful | |
113 */ | |
114 protected IConverter createConverter(Object fromType, Object toType) { | |
115 if (!( null !is cast(ClassInfo)fromType ) || !( null !is cast(ClassInfo)toType )) { | |
116 return new DefaultConverter(fromType, toType); | |
117 } | |
118 ClassInfo toClass = cast(ClassInfo) toType; | |
119 ClassInfo originalToClass = toClass; | |
120 if (toClass.isPrimitive()) { | |
121 toClass = autoboxed(toClass); | |
122 } | |
123 ClassInfo fromClass = cast(ClassInfo) fromType; | |
124 ClassInfo originalFromClass = fromClass; | |
125 if (fromClass.isPrimitive()) { | |
126 fromClass = autoboxed(fromClass); | |
127 } | |
128 if (!(cast(ClassInfo) toType).isPrimitive() | |
129 && toClass.isAssignableFrom(fromClass)) { | |
130 return new IdentityConverter(originalFromClass, originalToClass); | |
131 } | |
132 if ((cast(ClassInfo) fromType).isPrimitive() && (cast(ClassInfo) toType).isPrimitive() | |
133 && fromType.equals(toType)) { | |
134 return new IdentityConverter(originalFromClass, originalToClass); | |
135 } | |
136 Map converterMap = getConverterMap(); | |
137 ClassInfo[] supertypeHierarchyFlattened = ClassLookupSupport | |
138 .getTypeHierarchyFlattened(fromClass); | |
139 for (int i = 0; i < supertypeHierarchyFlattened.length; i++) { | |
140 ClassInfo currentFromClass = supertypeHierarchyFlattened[i]; | |
141 if (currentFromClass is toType) { | |
142 // converting to toType is just a widening | |
143 return new IdentityConverter(fromClass, toClass); | |
144 } | |
145 Pair key = new Pair(getKeyForClass(fromType, currentFromClass), | |
146 getKeyForClass(toType, toClass)); | |
147 Object converterOrClassname = converterMap.get(key); | |
148 if ( null !is cast(IConverter)converterOrClassname ) { | |
149 return cast(IConverter) converterOrClassname; | |
150 } else if ( null !is cast(String)converterOrClassname ) { | |
151 String classname = cast(String) converterOrClassname; | |
152 ClassInfo converterClass; | |
153 try { | |
154 converterClass = ClassInfo.forName(classname); | |
155 IConverter result = cast(IConverter) converterClass | |
156 .newInstance(); | |
157 converterMap.put(key, result); | |
158 return result; | |
159 } catch (Exception e) { | |
160 Policy | |
161 .getLog() | |
162 .log( | |
163 new Status( | |
164 IStatus.ERROR, | |
165 Policy.JFACE_DATABINDING, | |
166 0, | |
167 "Error while instantiating default converter", e)); //$NON-NLS-1$ | |
168 } | |
169 } | |
170 } | |
171 // Since we found no converter yet, try a "downcast" converter; | |
172 // the IdentityConverter will automatically check the actual types at | |
173 // runtime. | |
174 if (fromClass.isAssignableFrom(toClass)) { | |
175 return new IdentityConverter(originalFromClass, originalToClass); | |
176 } | |
177 return new DefaultConverter(fromType, toType); | |
178 } | |
179 | |
180 private synchronized static Map getConverterMap() { | |
181 // using string-based lookup avoids loading of too many classes | |
182 if (converterMap is null) { | |
183 // NumberFormat to be shared across converters for the formatting of | |
184 // integer values | |
185 NumberFormat integerFormat = NumberFormat.getIntegerInstance(); | |
186 // NumberFormat to be shared across converters for formatting non | |
187 // integer values | |
188 NumberFormat numberFormat = NumberFormat.getNumberInstance(); | |
189 | |
190 converterMap = new HashMap(); | |
191 // Standard and Boxed Types | |
192 converterMap | |
193 .put( | |
194 new Pair("java.util.Date", "java.lang.String"), "org.eclipse.core.internal.databinding.conversion.DateToStringConverter"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ | |
195 converterMap | |
196 .put( | |
197 new Pair("java.lang.String", "java.lang.Boolean"), "org.eclipse.core.internal.databinding.conversion.StringToBooleanConverter"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ | |
198 converterMap | |
199 .put( | |
200 new Pair("java.lang.String", "java.lang.Byte"), StringToByteConverter.toByte(integerFormat, false)); //$NON-NLS-1$//$NON-NLS-2$ | |
201 converterMap | |
202 .put( | |
203 new Pair("java.lang.String", "java.util.Date"), "org.eclipse.core.internal.databinding.conversion.StringToDateConverter"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ | |
204 converterMap | |
205 .put( | |
206 new Pair("java.lang.String", "java.lang.Short"), StringToShortConverter.toShort(integerFormat, false)); //$NON-NLS-1$//$NON-NLS-2$ | |
207 converterMap | |
208 .put( | |
209 new Pair("java.lang.String", "java.lang.Character"), StringToCharacterConverter.toCharacter(false)); //$NON-NLS-1$//$NON-NLS-2$ | |
210 converterMap | |
211 .put( | |
212 new Pair("java.lang.String", "java.lang.Integer"), StringToNumberConverter.toInteger(integerFormat, false)); //$NON-NLS-1$//$NON-NLS-2$ | |
213 converterMap | |
214 .put( | |
215 new Pair("java.lang.String", "java.lang.Double"), StringToNumberConverter.toDouble(numberFormat, false)); //$NON-NLS-1$//$NON-NLS-2$ | |
216 converterMap | |
217 .put( | |
218 new Pair("java.lang.String", "java.lang.Long"), StringToNumberConverter.toLong(integerFormat, false)); //$NON-NLS-1$//$NON-NLS-2$ | |
219 converterMap | |
220 .put( | |
221 new Pair("java.lang.String", "java.lang.Float"), StringToNumberConverter.toFloat(numberFormat, false)); //$NON-NLS-1$//$NON-NLS-2$ | |
222 converterMap | |
223 .put( | |
224 new Pair("java.lang.String", "java.math.BigInteger"), StringToNumberConverter.toBigInteger(integerFormat)); //$NON-NLS-1$//$NON-NLS-2$ | |
225 converterMap | |
226 .put( | |
227 new Pair("java.lang.Integer", "java.lang.String"), NumberToStringConverter.fromInteger(integerFormat, false)); //$NON-NLS-1$//$NON-NLS-2$ | |
228 converterMap | |
229 .put( | |
230 new Pair("java.lang.Long", "java.lang.String"), NumberToStringConverter.fromLong(integerFormat, false)); //$NON-NLS-1$//$NON-NLS-2$ | |
231 converterMap | |
232 .put( | |
233 new Pair("java.lang.Double", "java.lang.String"), NumberToStringConverter.fromDouble(numberFormat, false)); //$NON-NLS-1$//$NON-NLS-2$ | |
234 converterMap | |
235 .put( | |
236 new Pair("java.lang.Float", "java.lang.String"), NumberToStringConverter.fromFloat(numberFormat, false)); //$NON-NLS-1$//$NON-NLS-2$ | |
237 converterMap | |
238 .put( | |
239 new Pair("java.math.BigInteger", "java.lang.String"), NumberToStringConverter.fromBigInteger(integerFormat)); //$NON-NLS-1$//$NON-NLS-2$ | |
240 converterMap | |
241 .put( | |
242 new Pair("java.lang.Byte", "java.lang.String"), IntegerToStringConverter.fromByte(integerFormat, false)); //$NON-NLS-1$//$NON-NLS-2$ | |
243 converterMap | |
244 .put( | |
245 new Pair("java.lang.Short", "java.lang.String"), IntegerToStringConverter.fromShort(integerFormat, false)); //$NON-NLS-1$//$NON-NLS-2$ | |
246 converterMap | |
247 .put( | |
248 new Pair("java.lang.Character", "java.lang.String"), CharacterToStringConverter.fromCharacter(false)); //$NON-NLS-1$//$NON-NLS-2$ | |
249 | |
250 converterMap | |
251 .put( | |
252 new Pair("java.lang.Object", "java.lang.String"), "org.eclipse.core.internal.databinding.conversion.ObjectToStringConverter"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ | |
253 | |
254 // Integer.TYPE | |
255 converterMap | |
256 .put( | |
257 new Pair("java.lang.String", INTEGER_TYPE), StringToNumberConverter.toInteger(integerFormat, true)); //$NON-NLS-1$ | |
258 converterMap | |
259 .put( | |
260 new Pair(INTEGER_TYPE, "java.lang.Integer"), new IdentityConverter(Integer.TYPE, Integer.classinfo)); //$NON-NLS-1$ | |
261 converterMap | |
262 .put( | |
263 new Pair(INTEGER_TYPE, "java.lang.Object"), new IdentityConverter(Integer.TYPE, Object.classinfo)); //$NON-NLS-1$ | |
264 converterMap | |
265 .put( | |
266 new Pair(INTEGER_TYPE, "java.lang.String"), NumberToStringConverter.fromInteger(integerFormat, true)); //$NON-NLS-1$ | |
267 | |
268 // Byte.TYPE | |
269 converterMap | |
270 .put( | |
271 new Pair("java.lang.String", BYTE_TYPE), StringToByteConverter.toByte(integerFormat, true)); //$NON-NLS-1$ | |
272 converterMap | |
273 .put( | |
274 new Pair(BYTE_TYPE, "java.lang.Byte"), new IdentityConverter(Byte.TYPE, Byte.classinfo)); //$NON-NLS-1$ | |
275 converterMap | |
276 .put( | |
277 new Pair(BYTE_TYPE, "java.lang.String"), IntegerToStringConverter.fromByte(integerFormat, true)); //$NON-NLS-1$ | |
278 converterMap | |
279 .put( | |
280 new Pair(BYTE_TYPE, "java.lang.Object"), new IdentityConverter(Byte.TYPE, Object.classinfo)); //$NON-NLS-1$ | |
281 | |
282 // Double.TYPE | |
283 converterMap | |
284 .put( | |
285 new Pair("java.lang.String", DOUBLE_TYPE), StringToNumberConverter.toDouble(numberFormat, true)); //$NON-NLS-1$ | |
286 converterMap | |
287 .put( | |
288 new Pair(DOUBLE_TYPE, "java.lang.String"), NumberToStringConverter.fromDouble(numberFormat, true)); //$NON-NLS-1$ | |
289 | |
290 converterMap | |
291 .put( | |
292 new Pair(DOUBLE_TYPE, "java.lang.Double"), new IdentityConverter(Double.TYPE, Double.classinfo)); //$NON-NLS-1$ | |
293 converterMap | |
294 .put( | |
295 new Pair(DOUBLE_TYPE, "java.lang.Object"), new IdentityConverter(Double.TYPE, Object.classinfo)); //$NON-NLS-1$ | |
296 | |
297 // Boolean.TYPE | |
298 converterMap | |
299 .put( | |
300 new Pair("java.lang.String", BOOLEAN_TYPE), "org.eclipse.core.internal.databinding.conversion.StringToBooleanPrimitiveConverter"); //$NON-NLS-1$ //$NON-NLS-2$ | |
301 converterMap | |
302 .put( | |
303 new Pair(BOOLEAN_TYPE, "java.lang.Boolean"), new IdentityConverter(Boolean.TYPE, Boolean.classinfo)); //$NON-NLS-1$ | |
304 converterMap | |
305 .put( | |
306 new Pair(BOOLEAN_TYPE, "java.lang.String"), new ObjectToStringConvertercast(Boolean.TYPE)); //$NON-NLS-1$ | |
307 converterMap | |
308 .put( | |
309 new Pair(BOOLEAN_TYPE, "java.lang.Object"), new IdentityConverter(Boolean.TYPE, Object.classinfo)); //$NON-NLS-1$ | |
310 | |
311 // Float.TYPE | |
312 converterMap | |
313 .put( | |
314 new Pair("java.lang.String", FLOAT_TYPE), StringToNumberConverter.toFloat(numberFormat, true)); //$NON-NLS-1$ | |
315 converterMap | |
316 .put( | |
317 new Pair(FLOAT_TYPE, "java.lang.String"), NumberToStringConverter.fromFloat(numberFormat, true)); //$NON-NLS-1$ | |
318 converterMap | |
319 .put( | |
320 new Pair(FLOAT_TYPE, "java.lang.Float"), new IdentityConverter(Float.TYPE, Float.classinfo)); //$NON-NLS-1$ | |
321 converterMap | |
322 .put( | |
323 new Pair(FLOAT_TYPE, "java.lang.Object"), new IdentityConverter(Float.TYPE, Object.classinfo)); //$NON-NLS-1$ | |
324 | |
325 // Short.TYPE | |
326 converterMap | |
327 .put( | |
328 new Pair("java.lang.String", SHORT_TYPE), StringToShortConverter.toShort(integerFormat, true)); //$NON-NLS-1$ | |
329 converterMap | |
330 .put( | |
331 new Pair(SHORT_TYPE, "java.lang.Short"), new IdentityConverter(Short.TYPE, Short.classinfo)); //$NON-NLS-1$ | |
332 converterMap | |
333 .put( | |
334 new Pair(SHORT_TYPE, "java.lang.String"), IntegerToStringConverter.fromShort(integerFormat, true)); //$NON-NLS-1$ | |
335 converterMap | |
336 .put( | |
337 new Pair(SHORT_TYPE, "java.lang.Object"), new IdentityConverter(Short.TYPE, Object.classinfo)); //$NON-NLS-1$ | |
338 | |
339 // Long.TYPE | |
340 converterMap | |
341 .put( | |
342 new Pair("java.lang.String", LONG_TYPE), StringToNumberConverter.toLong(integerFormat, true)); //$NON-NLS-1$ | |
343 converterMap | |
344 .put( | |
345 new Pair(LONG_TYPE, "java.lang.String"), NumberToStringConverter.fromLong(integerFormat, true)); //$NON-NLS-1$ | |
346 converterMap | |
347 .put( | |
348 new Pair(LONG_TYPE, "java.lang.Long"), new IdentityConverter(Long.TYPE, Long.classinfo)); //$NON-NLS-1$ | |
349 converterMap | |
350 .put( | |
351 new Pair(LONG_TYPE, "java.lang.Object"), new IdentityConverter(Long.TYPE, Object.classinfo)); //$NON-NLS-1$ | |
352 | |
353 // Character.TYPE | |
354 converterMap | |
355 .put( | |
356 new Pair("java.lang.String", CHARACTER_TYPE), StringToCharacterConverter.toCharacter(true)); //$NON-NLS-1$ | |
357 converterMap | |
358 .put( | |
359 new Pair(CHARACTER_TYPE, "java.lang.Character"), new IdentityConverter(Character.TYPE, Character.classinfo)); //$NON-NLS-1$ | |
360 converterMap | |
361 .put( | |
362 new Pair(CHARACTER_TYPE, "java.lang.String"), CharacterToStringConverter.fromCharacter(true)); //$NON-NLS-1$ | |
363 converterMap | |
364 .put( | |
365 new Pair(CHARACTER_TYPE, "java.lang.Object"), new IdentityConverter(Character.TYPE, Object.classinfo)); //$NON-NLS-1$ | |
366 | |
367 // Miscellaneous | |
368 converterMap | |
369 .put( | |
370 new Pair( | |
371 "org.eclipse.core.runtime.IStatus", "java.lang.String"), "org.eclipse.core.internal.databinding.conversion.StatusToStringConverter"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ | |
372 | |
373 addNumberToByteConverters(converterMap, integerFormat, | |
374 integerClasses); | |
375 addNumberToByteConverters(converterMap, numberFormat, floatClasses); | |
376 | |
377 addNumberToShortConverters(converterMap, integerFormat, | |
378 integerClasses); | |
379 addNumberToShortConverters(converterMap, numberFormat, floatClasses); | |
380 | |
381 addNumberToIntegerConverters(converterMap, integerFormat, | |
382 integerClasses); | |
383 addNumberToIntegerConverters(converterMap, numberFormat, | |
384 floatClasses); | |
385 | |
386 addNumberToLongConverters(converterMap, integerFormat, | |
387 integerClasses); | |
388 addNumberToLongConverters(converterMap, numberFormat, floatClasses); | |
389 | |
390 addNumberToFloatConverters(converterMap, integerFormat, | |
391 integerClasses); | |
392 addNumberToFloatConverters(converterMap, numberFormat, floatClasses); | |
393 | |
394 addNumberToDoubleConverters(converterMap, integerFormat, | |
395 integerClasses); | |
396 addNumberToDoubleConverters(converterMap, numberFormat, | |
397 floatClasses); | |
398 | |
399 addNumberToBigIntegerConverters(converterMap, integerFormat, | |
400 integerClasses); | |
401 addNumberToBigIntegerConverters(converterMap, numberFormat, | |
402 floatClasses); | |
403 | |
404 addNumberToBigDecimalConverters(converterMap, integerFormat, | |
405 integerClasses); | |
406 addNumberToBigDecimalConverters(converterMap, numberFormat, | |
407 floatClasses); | |
408 } | |
409 | |
410 return converterMap; | |
411 } | |
412 | |
413 private static final ClassInfo[] integerClasses = new ClassInfo[] [ Byte.TYPE, | |
414 Byte.classinfo, Short.TYPE, Short.classinfo, Integer.TYPE, Integer.classinfo, | |
415 Long.TYPE, Long.classinfo, BigInteger.classinfo ]; | |
416 | |
417 private static final ClassInfo[] floatClasses = new ClassInfo[] [ Float.TYPE, | |
418 Float.classinfo, Double.TYPE, Double.classinfo, BigDecimal.classinfo ]; | |
419 | |
420 /** | |
421 * Registers converters to boxed and unboxed types from a list of from | |
422 * classes. | |
423 * | |
424 * @param map | |
425 * @param numberFormat | |
426 * @param fromTypes | |
427 */ | |
428 private static void addNumberToByteConverters(Map map, | |
429 NumberFormat numberFormat, ClassInfo[] fromTypes) { | |
430 | |
431 for (int i = 0; i < fromTypes.length; i++) { | |
432 ClassInfo fromType = fromTypes[i]; | |
433 if (!fromType.equals(Byte.classinfo) && !fromType.equalscast(Byte.TYPE)) { | |
434 String fromName = (fromType.isPrimitive()) ? getKeyForClass( | |
435 fromType, null) : fromType.getName(); | |
436 | |
437 map | |
438 .put(new Pair(fromName, BYTE_TYPE), | |
439 new NumberToByteConverter(numberFormat, | |
440 fromType, true)); | |
441 map | |
442 .put(new Pair(fromName, Byte.classinfo.getName()), | |
443 new NumberToByteConverter(numberFormat, | |
444 fromType, false)); | |
445 } | |
446 } | |
447 } | |
448 | |
449 /** | |
450 * Registers converters to boxed and unboxed types from a list of from | |
451 * classes. | |
452 * | |
453 * @param map | |
454 * @param numberFormat | |
455 * @param fromTypes | |
456 */ | |
457 private static void addNumberToShortConverters(Map map, | |
458 NumberFormat numberFormat, ClassInfo[] fromTypes) { | |
459 for (int i = 0; i < fromTypes.length; i++) { | |
460 ClassInfo fromType = fromTypes[i]; | |
461 if (!fromType.equals(Short.classinfo) && !fromType.equalscast(Short.TYPE)) { | |
462 String fromName = (fromType.isPrimitive()) ? getKeyForClass( | |
463 fromType, null) : fromType.getName(); | |
464 | |
465 map | |
466 .put(new Pair(fromName, SHORT_TYPE), | |
467 new NumberToShortConverter(numberFormat, | |
468 fromType, true)); | |
469 map.put(new Pair(fromName, Short.classinfo.getName()), | |
470 new NumberToShortConverter(numberFormat, fromType, | |
471 false)); | |
472 } | |
473 } | |
474 } | |
475 | |
476 /** | |
477 * Registers converters to boxed and unboxed types from a list of from | |
478 * classes. | |
479 * | |
480 * @param map | |
481 * @param numberFormat | |
482 * @param fromTypes | |
483 */ | |
484 private static void addNumberToIntegerConverters(Map map, | |
485 NumberFormat numberFormat, ClassInfo[] fromTypes) { | |
486 for (int i = 0; i < fromTypes.length; i++) { | |
487 ClassInfo fromType = fromTypes[i]; | |
488 if (!fromType.equals(Integer.classinfo) | |
489 && !fromType.equalscast(Integer.TYPE)) { | |
490 String fromName = (fromType.isPrimitive()) ? getKeyForClass( | |
491 fromType, null) : fromType.getName(); | |
492 | |
493 map.put(new Pair(fromName, INTEGER_TYPE), | |
494 new NumberToIntegerConverter(numberFormat, fromType, | |
495 true)); | |
496 map.put(new Pair(fromName, Integer.classinfo.getName()), | |
497 new NumberToIntegerConverter(numberFormat, fromType, | |
498 false)); | |
499 } | |
500 } | |
501 } | |
502 | |
503 /** | |
504 * Registers converters to boxed and unboxed types from a list of from | |
505 * classes. | |
506 * | |
507 * @param map | |
508 * @param numberFormat | |
509 * @param fromTypes | |
510 */ | |
511 private static void addNumberToLongConverters(Map map, | |
512 NumberFormat numberFormat, ClassInfo[] fromTypes) { | |
513 for (int i = 0; i < fromTypes.length; i++) { | |
514 ClassInfo fromType = fromTypes[i]; | |
515 if (!fromType.equals(Long.classinfo) && !fromType.equalscast(Long.TYPE)) { | |
516 String fromName = (fromType.isPrimitive()) ? getKeyForClass( | |
517 fromType, null) : fromType.getName(); | |
518 | |
519 map | |
520 .put(new Pair(fromName, LONG_TYPE), | |
521 new NumberToLongConverter(numberFormat, | |
522 fromType, true)); | |
523 map | |
524 .put(new Pair(fromName, Long.classinfo.getName()), | |
525 new NumberToLongConverter(numberFormat, | |
526 fromType, false)); | |
527 } | |
528 } | |
529 } | |
530 | |
531 /** | |
532 * Registers converters to boxed and unboxed types from a list of from | |
533 * classes. | |
534 * | |
535 * @param map | |
536 * @param numberFormat | |
537 * @param fromTypes | |
538 */ | |
539 private static void addNumberToFloatConverters(Map map, | |
540 NumberFormat numberFormat, ClassInfo[] fromTypes) { | |
541 for (int i = 0; i < fromTypes.length; i++) { | |
542 ClassInfo fromType = fromTypes[i]; | |
543 if (!fromType.equals(Float.classinfo) && !fromType.equalscast(Float.TYPE)) { | |
544 String fromName = (fromType.isPrimitive()) ? getKeyForClass( | |
545 fromType, null) : fromType.getName(); | |
546 | |
547 map | |
548 .put(new Pair(fromName, FLOAT_TYPE), | |
549 new NumberToFloatConverter(numberFormat, | |
550 fromType, true)); | |
551 map.put(new Pair(fromName, Float.classinfo.getName()), | |
552 new NumberToFloatConverter(numberFormat, fromType, | |
553 false)); | |
554 } | |
555 } | |
556 } | |
557 | |
558 /** | |
559 * Registers converters to boxed and unboxed types from a list of from | |
560 * classes. | |
561 * | |
562 * @param map | |
563 * @param numberFormat | |
564 * @param fromTypes | |
565 */ | |
566 private static void addNumberToDoubleConverters(Map map, | |
567 NumberFormat numberFormat, ClassInfo[] fromTypes) { | |
568 for (int i = 0; i < fromTypes.length; i++) { | |
569 ClassInfo fromType = fromTypes[i]; | |
570 if (!fromType.equals(Double.classinfo) && !fromType.equalscast(Double.TYPE)) { | |
571 String fromName = (fromType.isPrimitive()) ? getKeyForClass( | |
572 fromType, null) : fromType.getName(); | |
573 | |
574 map.put(new Pair(fromName, DOUBLE_TYPE), | |
575 new NumberToDoubleConverter(numberFormat, fromType, | |
576 true)); | |
577 map.put(new Pair(fromName, Double.classinfo.getName()), | |
578 new NumberToDoubleConverter(numberFormat, fromType, | |
579 false)); | |
580 } | |
581 } | |
582 } | |
583 | |
584 /** | |
585 * Registers converters to boxed and unboxed types from a list of from | |
586 * classes. | |
587 * | |
588 * @param map | |
589 * @param numberFormat | |
590 * @param fromTypes | |
591 */ | |
592 private static void addNumberToBigIntegerConverters(Map map, | |
593 NumberFormat numberFormat, ClassInfo[] fromTypes) { | |
594 for (int i = 0; i < fromTypes.length; i++) { | |
595 ClassInfo fromType = fromTypes[i]; | |
596 if (!fromType.equals(BigInteger.classinfo)) { | |
597 String fromName = (fromType.isPrimitive()) ? getKeyForClass( | |
598 fromType, null) : fromType.getName(); | |
599 | |
600 map | |
601 .put(new Pair(fromName, BigInteger.classinfo.getName()), | |
602 new NumberToBigIntegerConverter(numberFormat, | |
603 fromType)); | |
604 } | |
605 } | |
606 } | |
607 | |
608 /** | |
609 * Registers converters to boxed and unboxed types from a list of from | |
610 * classes. | |
611 * | |
612 * @param map | |
613 * @param numberFormat | |
614 * @param fromTypes | |
615 */ | |
616 private static void addNumberToBigDecimalConverters(Map map, | |
617 NumberFormat numberFormat, ClassInfo[] fromTypes) { | |
618 for (int i = 0; i < fromTypes.length; i++) { | |
619 ClassInfo fromType = fromTypes[i]; | |
620 if (!fromType.equals(BigDecimal.classinfo)) { | |
621 String fromName = (fromType.isPrimitive()) ? getKeyForClass( | |
622 fromType, null) : fromType.getName(); | |
623 | |
624 map | |
625 .put(new Pair(fromName, BigDecimal.classinfo.getName()), | |
626 new NumberToBigDecimalConverter(numberFormat, | |
627 fromType)); | |
628 } | |
629 } | |
630 } | |
631 | |
632 private static String getKeyForClass(Object originalValue, | |
633 ClassInfo filteredValue) { | |
634 if ( null !is cast(ClassInfo)originalValue ) { | |
635 ClassInfo originalClass = cast(ClassInfo) originalValue; | |
636 if (originalClass.equalscast(Integer.TYPE)) { | |
637 return INTEGER_TYPE; | |
638 } else if (originalClass.equalscast(Byte.TYPE)) { | |
639 return BYTE_TYPE; | |
640 } else if (originalClass.equalscast(Boolean.TYPE)) { | |
641 return BOOLEAN_TYPE; | |
642 } else if (originalClass.equalscast(Double.TYPE)) { | |
643 return DOUBLE_TYPE; | |
644 } else if (originalClass.equalscast(Float.TYPE)) { | |
645 return FLOAT_TYPE; | |
646 } else if (originalClass.equalscast(Long.TYPE)) { | |
647 return LONG_TYPE; | |
648 } else if (originalClass.equalscast(Short.TYPE)) { | |
649 return SHORT_TYPE; | |
650 } | |
651 } | |
652 return filteredValue.getName(); | |
653 } | |
654 | |
655 /** | |
656 * Returns {@link Boolean#TRUE} if the from type is assignable to the to | |
657 * type, or {@link Boolean#FALSE} if it not, or <code>null</code> if | |
658 * unknown. | |
659 * | |
660 * @param fromType | |
661 * @param toType | |
662 * @return whether fromType is assignable to toType, or <code>null</code> | |
663 * if unknown | |
664 */ | |
665 protected Boolean isAssignableFromTo(Object fromType, Object toType) { | |
666 if ( null !is cast(ClassInfo )fromType && null !is cast(ClassInfo)toType ) { | |
667 ClassInfo toClass = cast(ClassInfo) toType; | |
668 if (toClass.isPrimitive()) { | |
669 toClass = autoboxed(toClass); | |
670 } | |
671 ClassInfo fromClass = cast(ClassInfo) fromType; | |
672 if (fromClass.isPrimitive()) { | |
673 fromClass = autoboxed(fromClass); | |
674 } | |
675 return toClass.isAssignableFrom(fromClass) ? Boolean.TRUE | |
676 : Boolean.FALSE; | |
677 } | |
678 return null; | |
679 } | |
680 | |
681 /* | |
682 * Default converter implementation, does not perform any conversion. | |
683 */ | |
684 protected static final class DefaultConverter : IConverter { | |
685 | |
686 private final Object toType; | |
687 | |
688 private final Object fromType; | |
689 | |
690 /** | |
691 * @param fromType | |
692 * @param toType | |
693 */ | |
694 this(Object fromType, Object toType) { | |
695 this.toType = toType; | |
696 this.fromType = fromType; | |
697 } | |
698 | |
699 public Object convert(Object fromObject) { | |
700 return fromObject; | |
701 } | |
702 | |
703 public Object getFromType() { | |
704 return fromType; | |
705 } | |
706 | |
707 public Object getToType() { | |
708 return toType; | |
709 } | |
710 } | |
711 | |
712 } |