1 16 package org.apache.commons.jxpath.util; 17 18 import java.lang.reflect.Array ; 19 import java.lang.reflect.Modifier ; 20 import java.util.ArrayList ; 21 import java.util.Collection ; 22 import java.util.Collections ; 23 import java.util.HashSet ; 24 import java.util.Iterator ; 25 import java.util.List ; 26 import java.util.Set ; 27 28 import org.apache.commons.beanutils.ConvertUtils; 29 import org.apache.commons.beanutils.Converter; 30 import org.apache.commons.jxpath.JXPathException; 31 import org.apache.commons.jxpath.NodeSet; 32 import org.apache.commons.jxpath.Pointer; 33 34 40 public class BasicTypeConverter implements TypeConverter { 41 42 46 public boolean canConvert(Object object, Class toType) { 47 if (object == null) { 48 return true; 49 } 50 51 if (toType == Object .class) { 52 return true; 53 } 54 55 Class fromType = object.getClass(); 56 if (fromType.equals(toType)) { 57 return true; 58 } 59 60 if (toType.isAssignableFrom(fromType)) { 61 return true; 62 } 63 64 if (toType == String .class) { 65 return true; 66 } 67 68 if (object instanceof Boolean ) { 69 if (toType == boolean.class 70 || Number .class.isAssignableFrom(toType)) { 71 return true; 72 } 73 } 74 else if (object instanceof Number ) { 75 if (toType.isPrimitive() 76 || Number .class.isAssignableFrom(toType)) { 77 return true; 78 } 79 } 80 else if (object instanceof Character ) { 81 if (toType == char.class) { 82 return true; 83 } 84 } 85 else if (object instanceof String ) { 86 if (toType.isPrimitive()) { 87 return true; 88 } 89 if (toType == Boolean .class 90 || toType == Character .class 91 || toType == Byte .class 92 || toType == Short .class 93 || toType == Integer .class 94 || toType == Long .class 95 || toType == Float .class 96 || toType == Double .class) { 97 return true; 98 } 99 } 100 else if (fromType.isArray()) { 101 if (toType.isArray()) { 103 Class cType = toType.getComponentType(); 104 int length = Array.getLength(object); 105 for (int i = 0; i < length; i++) { 106 Object value = Array.get(object, i); 107 if (!canConvert(value, cType)) { 108 return false; 109 } 110 } 111 return true; 112 } 113 else if (Collection .class.isAssignableFrom(toType)) { 114 return canCreateCollection(toType); 115 } 116 else { 117 if (Array.getLength(object) > 0) { 118 Object value = Array.get(object, 0); 119 return canConvert(value, toType); 120 } 121 else { 122 return canConvert("", toType); 123 } 124 } 125 } 126 else if (object instanceof Collection ) { 127 if (toType.isArray()) { 129 Class cType = toType.getComponentType(); 130 Iterator it = ((Collection ) object).iterator(); 131 while (it.hasNext()) { 132 Object value = it.next(); 133 if (!canConvert(value, cType)) { 134 return false; 135 } 136 } 137 return true; 138 } 139 else if (Collection .class.isAssignableFrom(toType)) { 140 return canCreateCollection(toType); 141 } 142 else { 143 if (((Collection ) object).size() > 0) { 144 Object value; 145 if (object instanceof List ) { 146 value = ((List ) object).get(0); 147 } 148 else { 149 Iterator it = ((Collection ) object).iterator(); 150 value = it.next(); 151 } 152 return canConvert(value, toType); 153 } 154 else { 155 return canConvert("", toType); 156 } 157 } 158 } 159 else if (object instanceof NodeSet) { 160 return canConvert(((NodeSet) object).getValues(), toType); 161 } 162 else if (object instanceof Pointer) { 163 return canConvert(((Pointer) object).getValue(), toType); 164 } 165 return ConvertUtils.lookup(toType) != null; 166 } 167 168 173 public Object convert(Object object, Class toType) { 174 if (object == null) { 175 if (toType.isPrimitive()) { 176 return convertNullToPrimitive(toType); 177 } 178 return null; 179 } 180 181 if (toType == Object .class) { 182 if (object instanceof NodeSet) { 183 return convert(((NodeSet) object).getValues(), toType); 184 } 185 else if (object instanceof Pointer) { 186 return convert(((Pointer) object).getValue(), toType); 187 } 188 return object; 189 } 190 191 Class fromType = object.getClass(); 192 if (fromType.equals(toType) || toType.isAssignableFrom(fromType)) { 193 return object; 194 } 195 196 if (fromType.isArray()) { 197 int length = Array.getLength(object); 198 if (toType.isArray()) { 199 Class cType = toType.getComponentType(); 200 201 Object array = Array.newInstance(cType, length); 202 for (int i = 0; i < length; i++) { 203 Object value = Array.get(object, i); 204 Array.set(array, i, convert(value, cType)); 205 } 206 return array; 207 } 208 else if (Collection .class.isAssignableFrom(toType)) { 209 Collection collection = allocateCollection(toType); 210 for (int i = 0; i < length; i++) { 211 collection.add(Array.get(object, i)); 212 } 213 return unmodifiableCollection(collection); 214 } 215 else { 216 if (length > 0) { 217 Object value = Array.get(object, 0); 218 return convert(value, toType); 219 } 220 else { 221 return convert("", toType); 222 } 223 } 224 } 225 else if (object instanceof Collection ) { 226 int length = ((Collection ) object).size(); 227 if (toType.isArray()) { 228 Class cType = toType.getComponentType(); 229 Object array = Array.newInstance(cType, length); 230 Iterator it = ((Collection ) object).iterator(); 231 for (int i = 0; i < length; i++) { 232 Object value = it.next(); 233 Array.set(array, i, convert(value, cType)); 234 } 235 return array; 236 } 237 else if (Collection .class.isAssignableFrom(toType)) { 238 Collection collection = allocateCollection(toType); 239 collection.addAll((Collection ) object); 240 return unmodifiableCollection(collection); 241 } 242 else { 243 if (length > 0) { 244 Object value; 245 if (object instanceof List ) { 246 value = ((List ) object).get(0); 247 } 248 else { 249 Iterator it = ((Collection ) object).iterator(); 250 value = it.next(); 251 } 252 return convert(value, toType); 253 } 254 else { 255 return convert("", toType); 256 } 257 } 258 } 259 else if (object instanceof NodeSet) { 260 return convert(((NodeSet) object).getValues(), toType); 261 } 262 else if (object instanceof Pointer) { 263 return convert(((Pointer) object).getValue(), toType); 264 } 265 else if (toType == String .class) { 266 return object.toString(); 267 } 268 else if (object instanceof Boolean ) { 269 if (toType == boolean.class) { 270 return object; 271 } 272 boolean value = ((Boolean ) object).booleanValue(); 273 return allocateNumber(toType, value ? 1 : 0); 274 } 275 else if (object instanceof Number ) { 276 double value = ((Number ) object).doubleValue(); 277 if (toType == boolean.class || toType == Boolean .class) { 278 return value == 0.0 ? Boolean.FALSE : Boolean.TRUE; 279 } 280 if (toType.isPrimitive() 281 || Number .class.isAssignableFrom(toType)) { 282 return allocateNumber(toType, value); 283 } 284 } 285 else if (object instanceof Character ) { 286 if (toType == char.class) { 287 return object; 288 } 289 } 290 else if (object instanceof String ) { 291 Object value = convertStringToPrimitive(object, toType); 292 if (value != null) { 293 return value; 294 } 295 } 296 297 Converter converter = ConvertUtils.lookup(toType); 298 if (converter != null) { 299 return converter.convert(toType, object); 300 } 301 302 throw new RuntimeException ( 303 "Cannot convert " + object.getClass() + " to " + toType); 304 } 305 306 protected Object convertNullToPrimitive(Class toType) { 307 if (toType == boolean.class) { 308 return Boolean.FALSE; 309 } 310 if (toType == char.class) { 311 return new Character ('\0'); 312 } 313 if (toType == byte.class) { 314 return new Byte ((byte) 0); 315 } 316 if (toType == short.class) { 317 return new Short ((short) 0); 318 } 319 if (toType == int.class) { 320 return new Integer (0); 321 } 322 if (toType == long.class) { 323 return new Long (0L); 324 } 325 if (toType == float.class) { 326 return new Float (0.0f); 327 } 328 if (toType == double.class) { 329 return new Double (0.0); 330 } 331 return null; 332 } 333 334 protected Object convertStringToPrimitive(Object object, Class toType) { 335 if (toType == boolean.class || toType == Boolean .class) { 336 return Boolean.valueOf((String ) object); 337 } 338 if (toType == char.class || toType == Character .class) { 339 return new Character (((String ) object).charAt(0)); 340 } 341 if (toType == byte.class || toType == Byte .class) { 342 return new Byte ((String ) object); 343 } 344 if (toType == short.class || toType == Short .class) { 345 return new Short ((String ) object); 346 } 347 if (toType == int.class || toType == Integer .class) { 348 return new Integer ((String ) object); 349 } 350 if (toType == long.class || toType == Long .class) { 351 return new Long ((String ) object); 352 } 353 if (toType == float.class || toType == Float .class) { 354 return new Float ((String ) object); 355 } 356 if (toType == double.class || toType == Double .class) { 357 return new Double ((String ) object); 358 } 359 return null; 360 } 361 362 protected Number allocateNumber(Class type, double value) { 363 if (type == Byte .class || type == byte.class) { 364 return new Byte ((byte) value); 365 } 366 if (type == Short .class || type == short.class) { 367 return new Short ((short) value); 368 } 369 if (type == Integer .class || type == int.class) { 370 return new Integer ((int) value); 371 } 372 if (type == Long .class || type == long.class) { 373 return new Long ((long) value); 374 } 375 if (type == Float .class || type == float.class) { 376 return new Float ((float) value); 377 } 378 if (type == Double .class || type == double.class) { 379 return new Double (value); 380 } 381 return null; 382 } 383 384 protected boolean canCreateCollection(Class type) { 385 if (!type.isInterface() 386 && ((type.getModifiers() & Modifier.ABSTRACT) == 0)) { 387 return true; 388 } 389 390 if (type == List .class) { 391 return true; 392 } 393 394 if (type == Set .class) { 395 return true; 396 } 397 return false; 398 } 399 400 protected Collection allocateCollection(Class type) { 401 if (!type.isInterface() 402 && ((type.getModifiers() & Modifier.ABSTRACT) == 0)) { 403 try { 404 return (Collection ) type.newInstance(); 405 } 406 catch (Exception ex) { 407 throw new JXPathException( 408 "Cannot create collection of type: " + type, 409 ex); 410 } 411 } 412 413 if (type == List .class) { 414 return new ArrayList (); 415 } 416 if (type == Set .class) { 417 return new HashSet (); 418 } 419 throw new RuntimeException ("Cannot create collection of type: " + type); 420 } 421 422 protected Collection unmodifiableCollection(Collection collection) { 423 if (collection instanceof List ) { 424 return Collections.unmodifiableList((List ) collection); 425 } 426 else if (collection instanceof Set ) { 427 return Collections.unmodifiableSet((Set ) collection); 428 } 429 return collection; 432 } 433 434 static final class ValueNodeSet implements NodeSet { 435 private List values; 436 private List pointers; 437 438 public ValueNodeSet(List values) { 439 this.values = values; 440 } 441 442 public List getValues() { 443 return Collections.unmodifiableList(values); 444 } 445 446 public List getNodes() { 447 return Collections.unmodifiableList(values); 448 } 449 450 public List getPointers() { 451 if (pointers == null) { 452 pointers = new ArrayList (); 453 for (int i = 0; i < values.size(); i++) { 454 pointers.add(new ValuePointer(values.get(i))); 455 } 456 pointers = Collections.unmodifiableList(pointers); 457 } 458 return pointers; 459 } 460 } 461 462 static final class ValuePointer implements Pointer { 463 private Object bean; 464 465 public ValuePointer(Object object) { 466 this.bean = object; 467 } 468 469 public Object getValue() { 470 return bean; 471 } 472 473 public Object getNode() { 474 return bean; 475 } 476 477 public Object getRootNode() { 478 return bean; 479 } 480 481 public void setValue(Object value) { 482 throw new UnsupportedOperationException (); 483 } 484 485 public Object clone() { 486 return this; 487 } 488 489 public int compareTo(Object object) { 490 return 0; 491 } 492 493 public String asPath() { 494 if (bean == null) { 495 return "null()"; 496 } 497 else if (bean instanceof Number ) { 498 String string = bean.toString(); 499 if (string.endsWith(".0")) { 500 string = string.substring(0, string.length() - 2); 501 } 502 return string; 503 } 504 else if (bean instanceof Boolean ) { 505 return ((Boolean ) bean).booleanValue() ? "true()" : "false()"; 506 } 507 else if (bean instanceof String ) { 508 return "'" + bean + "'"; 509 } 510 return "{object of type " + bean.getClass().getName() + "}"; 511 } 512 } 513 } | Popular Tags |