1 11 12 package org.eclipse.core.databinding; 13 14 import java.math.BigDecimal ; 15 import java.math.BigInteger ; 16 import java.util.HashMap ; 17 import java.util.Map ; 18 19 import org.eclipse.core.databinding.conversion.IConverter; 20 import org.eclipse.core.databinding.conversion.NumberToStringConverter; 21 import org.eclipse.core.databinding.conversion.StringToNumberConverter; 22 import org.eclipse.core.databinding.util.Policy; 23 import org.eclipse.core.internal.databinding.ClassLookupSupport; 24 import org.eclipse.core.internal.databinding.Pair; 25 import org.eclipse.core.internal.databinding.conversion.IdentityConverter; 26 import org.eclipse.core.internal.databinding.conversion.IntegerToStringConverter; 27 import org.eclipse.core.internal.databinding.conversion.NumberToBigDecimalConverter; 28 import org.eclipse.core.internal.databinding.conversion.NumberToBigIntegerConverter; 29 import org.eclipse.core.internal.databinding.conversion.NumberToByteConverter; 30 import org.eclipse.core.internal.databinding.conversion.NumberToDoubleConverter; 31 import org.eclipse.core.internal.databinding.conversion.NumberToFloatConverter; 32 import org.eclipse.core.internal.databinding.conversion.NumberToIntegerConverter; 33 import org.eclipse.core.internal.databinding.conversion.NumberToLongConverter; 34 import org.eclipse.core.internal.databinding.conversion.NumberToShortConverter; 35 import org.eclipse.core.internal.databinding.conversion.ObjectToStringConverter; 36 import org.eclipse.core.internal.databinding.conversion.StringToByteConverter; 37 import org.eclipse.core.internal.databinding.conversion.StringToShortConverter; 38 import org.eclipse.core.runtime.IStatus; 39 import org.eclipse.core.runtime.Status; 40 41 import com.ibm.icu.text.NumberFormat; 42 43 47 class UpdateStrategy { 48 49 private static final String BOOLEAN_TYPE = "java.lang.Boolean.TYPE"; private static final String SHORT_TYPE = "java.lang.Short.TYPE"; private static final String BYTE_TYPE = "java.lang.Byte.TYPE"; private static final String DOUBLE_TYPE = "java.lang.Double.TYPE"; private static final String FLOAT_TYPE = "java.lang.Float.TYPE"; private static final String INTEGER_TYPE = "java.lang.Integer.TYPE"; private static final String LONG_TYPE = "java.lang.Long.TYPE"; private static Map converterMap; 57 58 private static Class autoboxed(Class clazz) { 59 if (clazz == Float.TYPE) 60 return Float .class; 61 else if (clazz == Double.TYPE) 62 return Double .class; 63 else if (clazz == Short.TYPE) 64 return Short .class; 65 else if (clazz == Integer.TYPE) 66 return Integer .class; 67 else if (clazz == Long.TYPE) 68 return Long .class; 69 else if (clazz == Byte.TYPE) 70 return Byte .class; 71 else if (clazz == Boolean.TYPE) 72 return Boolean .class; 73 return clazz; 74 } 75 76 final protected void checkAssignable(Object toType, Object fromType, 77 String errorString) { 78 Boolean assignableFromModelToModelConverter = isAssignableFromTo( 79 fromType, toType); 80 if (assignableFromModelToModelConverter != null 81 && !assignableFromModelToModelConverter.booleanValue()) { 82 throw new BindingException(errorString 83 + " Expected: " + fromType + ", actual: " + toType); } 85 } 86 87 97 protected IConverter createConverter(Object fromType, Object toType) { 98 if (!(fromType instanceof Class ) || !(toType instanceof Class )) { 99 return new DefaultConverter(fromType, toType); 100 } 101 Class toClass = (Class ) toType; 102 Class originalToClass = toClass; 103 if (toClass.isPrimitive()) { 104 toClass = autoboxed(toClass); 105 } 106 Class fromClass = (Class ) fromType; 107 Class originalFromClass = fromClass; 108 if (fromClass.isPrimitive()) { 109 fromClass = autoboxed(fromClass); 110 } 111 if (!((Class ) toType).isPrimitive() 112 && toClass.isAssignableFrom(fromClass)) { 113 return new IdentityConverter(originalFromClass, originalToClass); 114 } 115 if (((Class ) fromType).isPrimitive() && ((Class ) toType).isPrimitive() 116 && fromType.equals(toType)) { 117 return new IdentityConverter(originalFromClass, originalToClass); 118 } 119 Map converterMap = getConverterMap(); 120 Class [] supertypeHierarchyFlattened = ClassLookupSupport 121 .getTypeHierarchyFlattened(fromClass); 122 for (int i = 0; i < supertypeHierarchyFlattened.length; i++) { 123 Class currentFromClass = supertypeHierarchyFlattened[i]; 124 if (currentFromClass == toType) { 125 return new IdentityConverter(fromClass, toClass); 127 } 128 Pair key = new Pair(getKeyForClass(fromType, currentFromClass), 129 getKeyForClass(toType, toClass)); 130 Object converterOrClassname = converterMap.get(key); 131 if (converterOrClassname instanceof IConverter) { 132 return (IConverter) converterOrClassname; 133 } else if (converterOrClassname instanceof String ) { 134 String classname = (String ) converterOrClassname; 135 Class converterClass; 136 try { 137 converterClass = Class.forName(classname); 138 IConverter result = (IConverter) converterClass 139 .newInstance(); 140 converterMap.put(key, result); 141 return result; 142 } catch (Exception e) { 143 Policy 144 .getLog() 145 .log( 146 new Status( 147 IStatus.ERROR, 148 Policy.JFACE_DATABINDING, 149 0, 150 "Error while instantiating default converter", e)); } 152 } 153 } 154 if (fromClass.isAssignableFrom(toClass)) { 158 return new IdentityConverter(originalFromClass, originalToClass); 159 } 160 return new DefaultConverter(fromType, toType); 161 } 162 163 private static Map getConverterMap() { 164 if (converterMap == null) { 166 NumberFormat integerFormat = NumberFormat.getIntegerInstance(); 168 NumberFormat numberFormat = NumberFormat.getNumberInstance(); 170 171 converterMap = new HashMap (); 172 converterMap 173 .put( 174 new Pair("java.util.Date", "java.lang.String"), "org.eclipse.core.internal.databinding.conversion.DateToStringConverter"); converterMap 176 .put( 177 new Pair("java.lang.String", "java.lang.Boolean"), "org.eclipse.core.internal.databinding.conversion.StringToBooleanConverter"); converterMap 179 .put( 180 new Pair("java.lang.String", "java.lang.Byte"), StringToByteConverter.toByte(integerFormat, false)); converterMap 182 .put( 183 new Pair("java.lang.String", "java.lang.Character"), "org.eclipse.core.internal.databinding.conversion.StringToCharacterConverter"); converterMap 185 .put( 186 new Pair("java.lang.String", "java.util.Date"), "org.eclipse.core.internal.databinding.conversion.StringToDateConverter"); converterMap 188 .put( 189 new Pair("java.lang.String", "java.lang.Short"), StringToShortConverter.toShort(integerFormat, false)); 191 converterMap.put(new Pair("java.lang.String", "java.lang.Integer"), StringToNumberConverter.toInteger(integerFormat, false)); converterMap.put(new Pair("java.lang.String", "java.lang.Double"), StringToNumberConverter.toDouble(numberFormat, false)); converterMap.put(new Pair("java.lang.String", "java.lang.Long"), StringToNumberConverter.toLong(integerFormat, false)); converterMap.put(new Pair("java.lang.String", "java.lang.Float"), StringToNumberConverter.toFloat(numberFormat, false)); converterMap.put(new Pair("java.lang.String", "java.math.BigInteger"), StringToNumberConverter.toBigInteger(integerFormat)); converterMap.put(new Pair("java.lang.Integer", "java.lang.String"), NumberToStringConverter.fromInteger(integerFormat, false)); converterMap.put(new Pair("java.lang.Long", "java.lang.String"), NumberToStringConverter.fromLong(integerFormat, false)); converterMap.put(new Pair("java.lang.Double", "java.lang.String"), NumberToStringConverter.fromDouble(numberFormat, false)); converterMap.put(new Pair("java.lang.Float", "java.lang.String"), NumberToStringConverter.fromFloat(numberFormat, false)); converterMap.put(new Pair("java.math.BigInteger", "java.lang.String"), NumberToStringConverter.fromBigInteger(integerFormat)); converterMap.put(new Pair("java.lang.Byte", "java.lang.String"), IntegerToStringConverter.fromByte(integerFormat, false)); converterMap.put(new Pair("java.lang.Short", "java.lang.String"), IntegerToStringConverter.fromShort(integerFormat, false)); 204 converterMap 205 .put( 206 new Pair("java.lang.Object", "java.lang.String"), "org.eclipse.core.internal.databinding.conversion.ObjectToStringConverter"); 208 converterMap.put(new Pair("java.lang.String", INTEGER_TYPE), StringToNumberConverter.toInteger(integerFormat, true)); converterMap 211 .put( 212 new Pair(INTEGER_TYPE, "java.lang.Integer"), new IdentityConverter(Integer.TYPE, Integer .class)); converterMap 214 .put( 215 new Pair(INTEGER_TYPE, "java.lang.Object"), new IdentityConverter(Integer.TYPE, Object .class)); converterMap.put(new Pair(INTEGER_TYPE, "java.lang.String"), NumberToStringConverter.fromInteger(integerFormat, true)); 218 converterMap 220 .put( 221 new Pair("java.lang.String", BYTE_TYPE), StringToByteConverter.toByte(integerFormat, true)); converterMap 223 .put( 224 new Pair(BYTE_TYPE, "java.lang.Byte"), new IdentityConverter(Byte.TYPE, Byte .class)); converterMap 226 .put( 227 new Pair(BYTE_TYPE, "java.lang.String"), IntegerToStringConverter.fromByte(integerFormat, true)); converterMap 229 .put( 230 new Pair(BYTE_TYPE, "java.lang.Object"), new IdentityConverter(Byte.TYPE, Object .class)); 232 converterMap.put(new Pair("java.lang.String", DOUBLE_TYPE), StringToNumberConverter.toDouble(numberFormat, true)); converterMap.put(new Pair(DOUBLE_TYPE, "java.lang.String"), NumberToStringConverter.fromDouble(numberFormat, true)); 236 converterMap 237 .put( 238 new Pair(DOUBLE_TYPE, "java.lang.Double"), new IdentityConverter(Double.TYPE, Double .class)); converterMap 240 .put( 241 new Pair(DOUBLE_TYPE, "java.lang.Object"), new IdentityConverter(Double.TYPE, Object .class)); 243 converterMap 245 .put( 246 new Pair("java.lang.String", BOOLEAN_TYPE), "org.eclipse.core.internal.databinding.conversion.StringToBooleanPrimitiveConverter"); converterMap 248 .put( 249 new Pair(BOOLEAN_TYPE, "java.lang.Boolean"), new IdentityConverter(Boolean.TYPE, Boolean .class)); converterMap 251 .put( 252 new Pair(BOOLEAN_TYPE, "java.lang.String"), new ObjectToStringConverter(Boolean.TYPE)); converterMap 254 .put( 255 new Pair(BOOLEAN_TYPE, "java.lang.Object"), new IdentityConverter(Boolean.TYPE, Object .class)); 257 converterMap.put(new Pair("java.lang.String", FLOAT_TYPE), StringToNumberConverter.toFloat(numberFormat, true)); converterMap.put(new Pair(FLOAT_TYPE, "java.lang.String"), NumberToStringConverter.fromFloat(numberFormat, true)); converterMap 261 .put( 262 new Pair(FLOAT_TYPE, "java.lang.Float"), new IdentityConverter(Float.TYPE, Float .class)); converterMap 264 .put( 265 new Pair(FLOAT_TYPE, "java.lang.Object"), new IdentityConverter(Float.TYPE, Object .class)); 267 converterMap 269 .put( 270 new Pair("java.lang.String", SHORT_TYPE), StringToShortConverter.toShort(integerFormat, true)); converterMap 272 .put( 273 new Pair(SHORT_TYPE, "java.lang.Short"), new IdentityConverter(Short.TYPE, Short .class)); converterMap 275 .put( 276 new Pair(SHORT_TYPE, "java.lang.String"), IntegerToStringConverter.fromShort(integerFormat, true)); converterMap 278 .put( 279 new Pair(SHORT_TYPE, "java.lang.Object"), new IdentityConverter(Short.TYPE, Object .class)); 281 converterMap.put(new Pair("java.lang.String", LONG_TYPE), StringToNumberConverter.toLong(integerFormat, true)); converterMap.put(new Pair(LONG_TYPE, "java.lang.String"), NumberToStringConverter.fromLong(integerFormat, true)); converterMap 285 .put( 286 new Pair(LONG_TYPE, "java.lang.Long"), new IdentityConverter(Long.TYPE, Long .class)); converterMap 288 .put( 289 new Pair(LONG_TYPE, "java.lang.Object"), new IdentityConverter(Long.TYPE, Object .class)); 291 converterMap 292 .put( 293 new Pair("org.eclipse.core.runtime.IStatus", "java.lang.String"), "org.eclipse.core.internal.databinding.conversion.StatusToStringConverter"); 295 addNumberToByteConverters(converterMap, integerFormat, integerClasses); 296 addNumberToByteConverters(converterMap, numberFormat, floatClasses); 297 298 addNumberToShortConverters(converterMap, integerFormat, integerClasses); 299 addNumberToShortConverters(converterMap, numberFormat, floatClasses); 300 301 addNumberToIntegerConverters(converterMap, integerFormat, integerClasses); 302 addNumberToIntegerConverters(converterMap, numberFormat, floatClasses); 303 304 addNumberToLongConverters(converterMap, integerFormat, integerClasses); 305 addNumberToLongConverters(converterMap, numberFormat, floatClasses); 306 307 addNumberToFloatConverters(converterMap, integerFormat, integerClasses); 308 addNumberToFloatConverters(converterMap, numberFormat, floatClasses); 309 310 addNumberToDoubleConverters(converterMap, integerFormat, integerClasses); 311 addNumberToDoubleConverters(converterMap, numberFormat, floatClasses); 312 313 addNumberToBigIntegerConverters(converterMap, integerFormat, integerClasses); 314 addNumberToBigIntegerConverters(converterMap, numberFormat, floatClasses); 315 316 addNumberToBigDecimalConverters(converterMap, integerFormat, integerClasses); 317 addNumberToBigDecimalConverters(converterMap, numberFormat, floatClasses); 318 } 319 320 return converterMap; 321 } 322 323 private static final Class [] integerClasses = new Class []{ 324 Byte.TYPE, Byte .class, 325 Short.TYPE, Short .class, 326 Integer.TYPE, Integer .class, 327 Long.TYPE, Long .class, 328 BigInteger .class}; 329 330 private static final Class [] floatClasses = new Class [] { 331 Float.TYPE, Float .class, 332 Double.TYPE, Double .class, 333 BigDecimal .class}; 334 335 342 private static void addNumberToByteConverters(Map map, 343 NumberFormat numberFormat, Class [] fromTypes) { 344 345 for (int i = 0; i < fromTypes.length; i++) { 346 Class fromType = fromTypes[i]; 347 if (!fromType.equals(Byte .class) && !fromType.equals(Byte.TYPE)) { 348 String fromName = (fromType.isPrimitive()) ? getKeyForClass(fromType, null) : fromType.getName(); 349 350 map.put(new Pair(fromName, BYTE_TYPE), new NumberToByteConverter(numberFormat, fromType, true)); 351 map.put(new Pair(fromName, Byte .class.getName()), new NumberToByteConverter(numberFormat, fromType, false)); 352 } 353 } 354 } 355 356 363 private static void addNumberToShortConverters(Map map, NumberFormat numberFormat, Class [] fromTypes) { 364 for (int i = 0; i < fromTypes.length; i++) { 365 Class fromType = fromTypes[i]; 366 if (!fromType.equals(Short .class) && !fromType.equals(Short.TYPE)) { 367 String fromName = (fromType.isPrimitive()) ? getKeyForClass(fromType, null) : fromType.getName(); 368 369 map.put(new Pair(fromName, SHORT_TYPE), new NumberToShortConverter(numberFormat, fromType, true)); 370 map.put(new Pair(fromName, Short .class.getName()), new NumberToShortConverter(numberFormat, fromType, false)); 371 } 372 } 373 } 374 375 382 private static void addNumberToIntegerConverters(Map map, NumberFormat numberFormat, Class [] fromTypes) { 383 for (int i = 0; i < fromTypes.length; i++) { 384 Class fromType = fromTypes[i]; 385 if (!fromType.equals(Integer .class) && !fromType.equals(Integer.TYPE)) { 386 String fromName = (fromType.isPrimitive()) ? getKeyForClass(fromType, null) : fromType.getName(); 387 388 map.put(new Pair(fromName, INTEGER_TYPE), new NumberToIntegerConverter(numberFormat, fromType, true)); 389 map.put(new Pair(fromName, Integer .class.getName()), new NumberToIntegerConverter(numberFormat, fromType, false)); 390 } 391 } 392 } 393 394 401 private static void addNumberToLongConverters(Map map, NumberFormat numberFormat, Class [] fromTypes) { 402 for (int i = 0; i < fromTypes.length; i++) { 403 Class fromType = fromTypes[i]; 404 if (!fromType.equals(Long .class) && !fromType.equals(Long.TYPE)) { 405 String fromName = (fromType.isPrimitive()) ? getKeyForClass(fromType, null) : fromType.getName(); 406 407 map.put(new Pair(fromName, LONG_TYPE), new NumberToLongConverter(numberFormat, fromType, true)); 408 map.put(new Pair(fromName, Long .class.getName()), new NumberToLongConverter(numberFormat, fromType, false)); 409 } 410 } 411 } 412 413 420 private static void addNumberToFloatConverters(Map map, NumberFormat numberFormat, Class [] fromTypes) { 421 for (int i = 0; i < fromTypes.length; i++) { 422 Class fromType = fromTypes[i]; 423 if (!fromType.equals(Float .class) && !fromType.equals(Float.TYPE)) { 424 String fromName = (fromType.isPrimitive()) ? getKeyForClass(fromType, null) : fromType.getName(); 425 426 map.put(new Pair(fromName, FLOAT_TYPE), new NumberToFloatConverter(numberFormat, fromType, true)); 427 map.put(new Pair(fromName, Float .class.getName()), new NumberToFloatConverter(numberFormat, fromType, false)); 428 } 429 } 430 } 431 432 439 private static void addNumberToDoubleConverters(Map map, NumberFormat numberFormat, Class [] fromTypes) { 440 for (int i = 0; i < fromTypes.length; i++) { 441 Class fromType = fromTypes[i]; 442 if (!fromType.equals(Double .class) && !fromType.equals(Double.TYPE)) { 443 String fromName = (fromType.isPrimitive()) ? getKeyForClass(fromType, null) : fromType.getName(); 444 445 map.put(new Pair(fromName, DOUBLE_TYPE), new NumberToDoubleConverter(numberFormat, fromType, true)); 446 map.put(new Pair(fromName, Double .class.getName()), new NumberToDoubleConverter(numberFormat, fromType, false)); 447 } 448 } 449 } 450 451 458 private static void addNumberToBigIntegerConverters(Map map, NumberFormat numberFormat, Class [] fromTypes) { 459 for (int i = 0; i < fromTypes.length; i++) { 460 Class fromType = fromTypes[i]; 461 if (!fromType.equals(BigInteger .class)) { 462 String fromName = (fromType.isPrimitive()) ? getKeyForClass(fromType, null) : fromType.getName(); 463 464 map.put(new Pair(fromName, BigInteger .class.getName()), new NumberToBigIntegerConverter(numberFormat, fromType)); 465 } 466 } 467 } 468 469 476 private static void addNumberToBigDecimalConverters(Map map, NumberFormat numberFormat, Class [] fromTypes) { 477 for (int i = 0; i < fromTypes.length; i++) { 478 Class fromType = fromTypes[i]; 479 if (!fromType.equals(BigDecimal .class)) { 480 String fromName = (fromType.isPrimitive()) ? getKeyForClass(fromType, null) : fromType.getName(); 481 482 map.put(new Pair(fromName, BigDecimal .class.getName()), new NumberToBigDecimalConverter(numberFormat, fromType)); 483 } 484 } 485 } 486 487 private static String getKeyForClass(Object originalValue, Class filteredValue) { 488 if (originalValue instanceof Class ) { 489 Class originalClass = (Class ) originalValue; 490 if (originalClass.equals(Integer.TYPE)) { 491 return INTEGER_TYPE; 492 } else if (originalClass.equals(Byte.TYPE)) { 493 return BYTE_TYPE; 494 } else if (originalClass.equals(Boolean.TYPE)) { 495 return BOOLEAN_TYPE; 496 } else if (originalClass.equals(Double.TYPE)) { 497 return DOUBLE_TYPE; 498 } else if (originalClass.equals(Float.TYPE)) { 499 return FLOAT_TYPE; 500 } else if (originalClass.equals(Long.TYPE)) { 501 return LONG_TYPE; 502 } else if (originalClass.equals(Short.TYPE)) { 503 return SHORT_TYPE; 504 } 505 } 506 return filteredValue.getName(); 507 } 508 509 514 protected Boolean isAssignableFromTo(Object fromType, Object toType) { 515 if (fromType instanceof Class && toType instanceof Class ) { 516 Class toClass = (Class ) toType; 517 if (toClass.isPrimitive()) { 518 toClass = autoboxed(toClass); 519 } 520 Class fromClass = (Class ) fromType; 521 if (fromClass.isPrimitive()) { 522 fromClass = autoboxed(fromClass); 523 } 524 return toClass.isAssignableFrom(fromClass) ? Boolean.TRUE 525 : Boolean.FALSE; 526 } 527 return null; 528 } 529 530 533 protected static final class DefaultConverter implements IConverter { 534 535 private final Object toType; 536 537 private final Object fromType; 538 539 543 DefaultConverter(Object fromType, Object toType) { 544 this.toType = toType; 545 this.fromType = fromType; 546 } 547 548 public Object convert(Object fromObject) { 549 return fromObject; 550 } 551 552 public Object getFromType() { 553 return fromType; 554 } 555 556 public Object getToType() { 557 return toType; 558 } 559 } 560 561 } 562 | Popular Tags |