1 16 package net.sf.dozer.util.mapping; 17 18 import java.lang.reflect.Array ; 19 import java.lang.reflect.InvocationTargetException ; 20 import java.lang.reflect.Method ; 21 import java.util.ArrayList ; 22 import java.util.Arrays ; 23 import java.util.Collection ; 24 import java.util.Collections ; 25 import java.util.HashMap ; 26 import java.util.Iterator ; 27 import java.util.List ; 28 import java.util.Map ; 29 import java.util.Set ; 30 31 import net.sf.dozer.util.mapping.cache.Cache; 32 import net.sf.dozer.util.mapping.cache.CacheEntry; 33 import net.sf.dozer.util.mapping.cache.CacheKeyFactory; 34 import net.sf.dozer.util.mapping.cache.CacheManagerIF; 35 import net.sf.dozer.util.mapping.converters.CustomConverter; 36 import net.sf.dozer.util.mapping.converters.CustomConverterContainer; 37 import net.sf.dozer.util.mapping.converters.PrimitiveOrWrapperConverter; 38 import net.sf.dozer.util.mapping.event.DozerEvent; 39 import net.sf.dozer.util.mapping.event.DozerEventManager; 40 import net.sf.dozer.util.mapping.event.EventManagerIF; 41 import net.sf.dozer.util.mapping.fieldmap.ClassMap; 42 import net.sf.dozer.util.mapping.fieldmap.Configuration; 43 import net.sf.dozer.util.mapping.fieldmap.ExcludeFieldMap; 44 import net.sf.dozer.util.mapping.fieldmap.FieldMap; 45 import net.sf.dozer.util.mapping.fieldmap.GenericFieldMap; 46 import net.sf.dozer.util.mapping.fieldmap.MapFieldMap; 47 import net.sf.dozer.util.mapping.stats.StatisticTypeConstants; 48 import net.sf.dozer.util.mapping.stats.StatisticsManagerIF; 49 import net.sf.dozer.util.mapping.util.ClassMapBuilder; 50 import net.sf.dozer.util.mapping.util.ClassMapFinder; 51 import net.sf.dozer.util.mapping.util.ClassMapKeyFactory; 52 import net.sf.dozer.util.mapping.util.CollectionUtils; 53 import net.sf.dozer.util.mapping.util.DateFormatContainer; 54 import net.sf.dozer.util.mapping.util.DestBeanCreator; 55 import net.sf.dozer.util.mapping.util.LogMsgFactory; 56 import net.sf.dozer.util.mapping.util.MapperConstants; 57 import net.sf.dozer.util.mapping.util.MappingUtils; 58 import net.sf.dozer.util.mapping.util.MappingValidator; 59 import net.sf.dozer.util.mapping.util.ReflectionUtils; 60 61 import org.apache.commons.collections.IteratorUtils; 62 import org.apache.commons.collections.set.ListOrderedSet; 63 import org.apache.commons.lang.StringUtils; 64 import org.apache.commons.logging.Log; 65 import org.apache.commons.logging.LogFactory; 66 67 75 public class MappingProcessor implements MapperIF { 76 77 private static final Log log = LogFactory.getLog(MappingProcessor.class); 78 79 82 private List superListOfFieldNames = null; 83 private final transient Map customMappings; 84 private final Configuration globalConfiguration; 85 private final List customConverterObjects; private final StatisticsManagerIF statsMgr; 87 private final EventManagerIF eventMgr; 88 private final CustomFieldMapperIF customFieldMapper; 89 private final ClassMapFinder classMapFinder = new ClassMapFinder(); 90 private final MappingUtils mappingUtils = new MappingUtils(); 91 private final ReflectionUtils reflectionUtils = new ReflectionUtils(); 92 private final CollectionUtils collectionUtils = new CollectionUtils(); 93 private final MappingValidator mappingValidator = new MappingValidator(); 94 private final ClassMapBuilder classMapBuilder = new ClassMapBuilder(); 95 private final LogMsgFactory logMsgFactory = new LogMsgFactory(); 96 private final DestBeanCreator destBeanCreator = new DestBeanCreator(MappingUtils.storedFactories); private final PrimitiveOrWrapperConverter primitiveOrWrapperConverter = new PrimitiveOrWrapperConverter(); 98 private final Map mappedFields = new HashMap (); 99 private final Cache converterByDestTypeCache; 100 private final Cache superTypeCache; 101 102 public MappingProcessor(Map mappings, Configuration globalConfiguration, CacheManagerIF cacheMgr, 103 StatisticsManagerIF statsMgr, List customConverterObjects, List eventListeners, 104 CustomFieldMapperIF customFieldMapper) { 105 this.customMappings = mappings; 106 this.globalConfiguration = globalConfiguration; 107 this.statsMgr = statsMgr; 108 this.customConverterObjects = customConverterObjects; 109 this.eventMgr = new DozerEventManager(eventListeners); 110 this.customFieldMapper = customFieldMapper; 111 this.converterByDestTypeCache = cacheMgr.getCache(MapperConstants.CONVERTER_BY_DEST_TYPE_CACHE); 112 this.superTypeCache = cacheMgr.getCache(MapperConstants.SUPER_TYPE_CHECK_CACHE); 113 } 114 115 public Object map(Object sourceObj, Class destClass) { 116 return map(sourceObj, destClass, (String ) null); 118 } 119 120 public Object map(Object sourceObj, Class destClass, String mapId) { 121 Object destObj = null; 122 ClassMap classMap = null; 123 try { 124 mappingValidator.validateMappingRequest(sourceObj, destClass); 125 classMap = getClassMap(sourceObj, destClass, mapId, false); 126 127 CustomConverterContainer customConverterContainer = classMap.getConfiguration().getCustomConverters(); 129 Class converterClass = mappingUtils.findCustomConverter(converterByDestTypeCache, customConverterContainer, sourceObj.getClass(), destClass); 130 if (converterClass != null) { 131 eventMgr.fireEvent(new DozerEvent(MapperConstants.MAPPING_STARTED_EVENT, classMap, null, sourceObj, destObj, null)); 132 return mapUsingCustomConverter(converterClass, sourceObj.getClass(), sourceObj, destClass, destObj, null, true); 133 } 134 135 destObj = destBeanCreator.create(sourceObj, classMap, destClass); 137 138 eventMgr.fireEvent(new DozerEvent(MapperConstants.MAPPING_STARTED_EVENT, classMap, null, sourceObj, destObj, null)); 140 141 map(classMap, sourceObj, destObj, null, null); 143 } catch (Throwable e) { 144 mappingUtils.throwMappingException(e); 145 } 146 eventMgr.fireEvent(new DozerEvent(MapperConstants.MAPPING_FINISHED_EVENT, classMap, null, sourceObj, destObj, null)); 147 return destObj; 148 } 149 150 public void map(Object sourceObj, Object destObj) { 151 map(sourceObj, destObj, null); 152 } 153 154 public void map(Object sourceObj, Object destObj, String mapId) { 155 ClassMap classMap = null; 156 try { 157 mappingValidator.validateMappingRequest(sourceObj, destObj); 159 classMap = getClassMap(sourceObj, destObj.getClass(), mapId, true); 160 161 CustomConverterContainer customConverterContainer = classMap.getConfiguration().getCustomConverters(); 163 Class converterClass = mappingUtils.findCustomConverter(converterByDestTypeCache, customConverterContainer, sourceObj.getClass(), destObj.getClass()); 164 eventMgr.fireEvent(new DozerEvent(MapperConstants.MAPPING_STARTED_EVENT, classMap, null, sourceObj, destObj, null)); 165 166 if (converterClass != null) { 167 mapUsingCustomConverter(converterClass, sourceObj.getClass(), sourceObj, destObj.getClass(), destObj, null, 168 true); 169 return; 170 } 171 172 map(classMap, sourceObj, destObj, null, null); 174 } catch (Throwable e) { 175 mappingUtils.throwMappingException(e); 176 } 177 eventMgr.fireEvent(new DozerEvent(MapperConstants.MAPPING_FINISHED_EVENT, classMap, null, sourceObj, destObj, null)); 178 } 179 180 private void map(ClassMap classMap, Object sourceObj, Object destObj, ClassMap parentClassMap, FieldMap parentFieldMap) 181 throws NoSuchMethodException , ClassNotFoundException , NoSuchFieldException , IllegalAccessException , 182 InvocationTargetException , InstantiationException { 183 mappingValidator.validateMappingRequest(sourceObj, destObj); 184 185 String key = mappingUtils.getMappedFieldKey(sourceObj); 189 mappedFields.put(key, destObj); 190 191 String mapId = null; 193 if (parentFieldMap != null) { 194 mapId = parentFieldMap.getMapId(); 195 } 196 197 if (classMap == null) { 199 classMap = getClassMap(sourceObj, destObj.getClass(), mapId, true); 200 } 201 202 if (parentClassMap != null) { 204 if (superListOfFieldNames == null) { 205 superListOfFieldNames = new ArrayList (); 206 } 207 } 208 209 Class sourceClass = sourceObj.getClass(); 210 Class destClass = destObj.getClass(); 211 212 CustomConverterContainer customConverterContainer = classMap.getConfiguration().getCustomConverters(); 214 Class converterClass = mappingUtils.findCustomConverter(converterByDestTypeCache, customConverterContainer, sourceObj.getClass(), destClass); 215 if (converterClass != null) { 216 Object rvalue = mapUsingCustomConverter(converterClass, sourceObj.getClass(), sourceObj, destClass, destObj, 217 null, true); 218 if (rvalue != null) { 219 destObj = rvalue; 220 } 221 return; 222 } 223 224 List parentFieldNames = null; 226 if (parentClassMap == null) { 227 List superClasses = checkForSuperTypeMapping(sourceClass, destClass); 229 superClasses.addAll(classMapFinder.findInterfaceMappings(this.customMappings, sourceClass, destClass)); 231 if (superClasses != null && superClasses.size() > 0) { 232 parentFieldNames = processSuperTypeMapping(superClasses, sourceObj, destObj, sourceClass, parentFieldMap); 233 } 234 } 235 236 List fieldMaps = classMap.getFieldMaps(); 238 int size = fieldMaps.size(); 239 for (int i = 0; i < size; i++) { 240 FieldMap fieldMapping = (FieldMap) fieldMaps.get(i); 241 mapField(fieldMapping, classMap, sourceObj, destObj, parentClassMap, parentFieldMap, parentFieldNames); 242 } 243 } 244 245 private void mapField(FieldMap fieldMapping, ClassMap classMap, Object sourceObj, Object destObj, 246 ClassMap parentClassMap, FieldMap parentFieldMap, List parentFieldNames) { 247 248 if (fieldMapping instanceof ExcludeFieldMap) { 250 return; 251 } 252 253 Class sourceClass = sourceObj.getClass(); 254 Class destClass = destObj.getClass(); 255 Object sourceFieldValue = null; 256 try { 257 sourceFieldValue = fieldMapping.getSrcFieldValue(sourceObj); 258 String parentSourceField = null; 260 if (parentFieldMap != null) { 261 parentSourceField = parentFieldMap.getSourceField().getName(); 262 } 263 264 String methodName = fieldMapping.getDestFieldReadMethodName(destClass); 265 String sourceMethodName = fieldMapping.getSourceFieldReadMethodName(sourceClass); 266 String key = mappingUtils.getParentFieldNameKey(parentSourceField, sourceObj, sourceClass.getName(), 267 sourceMethodName, methodName, fieldMapping.getSourceField().getName(), fieldMapping.getDestField().getName()); 268 if (parentClassMap != null) { 269 if (superListOfFieldNames.contains(key)) { 270 return; 271 } else { 272 superListOfFieldNames.add(key); 273 } 274 } 275 if (parentFieldNames != null && parentFieldNames.size() > 0) { 277 if (parentFieldNames.contains(key)) { 278 return; 279 } else { 280 parentFieldNames.add(key); 281 } 282 } 283 284 boolean fieldMapped = false; 288 if (customFieldMapper != null ) { 289 fieldMapped = customFieldMapper.mapField(sourceObj, destObj, sourceFieldValue, classMap, fieldMapping); 290 } 291 292 if (!fieldMapped) { 293 if (fieldMapping instanceof GenericFieldMap && ((GenericFieldMap) fieldMapping).isMethodMap() 294 && fieldMapping.getDestField().getType().equals(MapperConstants.ITERATE)) { 295 mapFromIterateMethodFieldMap(sourceObj, destObj, sourceFieldValue, classMap, fieldMapping); 297 } else { 298 mapFromFieldMap(sourceObj, destObj, sourceFieldValue, classMap, fieldMapping); 300 } 301 } 302 303 statsMgr.increment(StatisticTypeConstants.FIELD_MAPPING_SUCCESS_COUNT); 304 305 } catch (Throwable e) { 306 log.error(logMsgFactory.createFieldMappingErrorMsg(sourceObj, fieldMapping, sourceFieldValue, destObj, e), e); 307 statsMgr.increment(StatisticTypeConstants.FIELD_MAPPING_FAILURE_COUNT); 308 309 if (classMap.getStopOnErrors()) { 311 mappingUtils.throwMappingException(e); 312 } else { 313 if (!classMap.getAllowedExceptions().isEmpty()) { 315 if (e.getCause() instanceof InvocationTargetException ) { 316 Throwable thrownType = ((InvocationTargetException )e.getCause()).getTargetException(); 317 Class exceptionClass = thrownType.getClass(); 318 if(classMap.getAllowedExceptions().contains(exceptionClass)) { 319 throw (RuntimeException )thrownType; 320 } 321 } 322 } 323 statsMgr.increment(StatisticTypeConstants.FIELD_MAPPING_FAILURE_IGNORED_COUNT); 324 } 325 } 326 } 327 328 private void mapFromFieldMap(Object sourceObj, Object destObj, Object sourceFieldValue, ClassMap classMap, 329 FieldMap fieldMapping) throws IllegalAccessException , InvocationTargetException , InvocationTargetException , 330 InstantiationException , NoSuchMethodException , ClassNotFoundException , NoSuchFieldException , NoSuchFieldException { 331 Class destFieldType = null; 332 if (fieldMapping instanceof GenericFieldMap && ((GenericFieldMap) fieldMapping).isMethodMap()) { 334 destFieldType = fieldMapping.getDestFieldWriteMethod(destObj.getClass()).getParameterTypes()[0]; 335 } else { 336 destFieldType = fieldMapping.getDestFieldType(destObj.getClass()); 337 } 338 339 Object destFieldValue = null; 342 if (mappingUtils.isBlankOrNull(fieldMapping.getCustomConverter())) { 343 destFieldValue = mapOrRecurseObject(sourceObj, sourceFieldValue, destFieldType, classMap, fieldMapping, destObj); 344 } else { 345 Class sourceFieldClass = sourceFieldValue != null ? sourceFieldValue.getClass() : fieldMapping.getSourceFieldType(sourceObj.getClass()); 346 destFieldValue = mapUsingCustomConverter(Class.forName(fieldMapping.getCustomConverter()), sourceFieldClass, sourceFieldValue, 347 destFieldType, null, fieldMapping, false); 348 } 349 350 writeDestinationValue(destObj, destFieldValue, classMap, fieldMapping); 351 352 if(log.isDebugEnabled()) { 353 log.debug(logMsgFactory.createFieldMappingSuccessMsg(sourceObj.getClass(), destObj.getClass(), fieldMapping.getSourceField().getName(), 354 fieldMapping.getDestField().getName(), sourceFieldValue, destFieldValue)); 355 } 356 } 357 358 private Object mapOrRecurseObject(Object srcObj, Object sourceFieldValue, Class destFieldType, ClassMap classMap, FieldMap fieldMap, 361 Object destObj) throws InvocationTargetException , InstantiationException , IllegalAccessException , 362 NoSuchMethodException , ClassNotFoundException , NoSuchFieldException { 363 return mapOrRecurseObject(srcObj, sourceFieldValue, destFieldType, classMap, fieldMap, destObj, false); 364 } 365 366 private Object mapOrRecurseObject(Object srcObj, Object sourceFieldValue, Class destFieldType, ClassMap classMap, FieldMap fieldMap, 367 Object destObj, boolean ignoreClassMap) throws InvocationTargetException , InstantiationException , 368 IllegalAccessException , NoSuchMethodException , ClassNotFoundException , NoSuchFieldException { 369 Class sourceFieldClass = sourceFieldValue != null ? sourceFieldValue.getClass() : fieldMap.getSourceFieldType(srcObj.getClass()); 370 CustomConverterContainer customConverters = classMap.getConfiguration().getCustomConverters(); 371 Class converterClass = mappingUtils.determineCustomConverter(fieldMap, converterByDestTypeCache, customConverters, sourceFieldClass, destFieldType); 372 373 if (converterClass != null) { 375 return mapUsingCustomConverter(converterClass, sourceFieldClass, sourceFieldValue, destFieldType, destObj, 376 fieldMap, false); 377 } 378 379 boolean isDestFieldTypeSupportedMap = mappingUtils.isSupportedMap(destFieldType); 380 if (sourceFieldValue == null && !isDestFieldTypeSupportedMap) { 381 return null; 382 } 383 384 if (sourceFieldValue == null && isDestFieldTypeSupportedMap) { 386 return mapMapToProperty(srcObj, sourceFieldValue, null, fieldMap, destObj, destFieldType, classMap); 387 } 388 389 String key = mappingUtils.getMappedFieldKey(sourceFieldValue); 391 Object value = mappedFields.get(key); 392 if (value != null && value.getClass().equals(destFieldType)) { 393 return value; 395 } 396 397 if (fieldMap.getCopyByReference()) { 398 return sourceFieldValue; 400 } 401 if (fieldMap.getMapId() != null && mappingUtils.validateMap(sourceFieldClass, destFieldType, fieldMap)) { 404 return mapCustomObject(fieldMap, destObj, destFieldType, sourceFieldValue); 405 } 406 if (fieldMap instanceof MapFieldMap && !ignoreClassMap) { 407 return mapClassLevelMap(srcObj, fieldMap, sourceFieldValue, sourceFieldClass, classMap, destFieldType, destObj); 410 } 411 boolean isSourceFieldClassSupportedMap = mappingUtils.isSupportedMap(sourceFieldClass); 412 if (isSourceFieldClassSupportedMap && isDestFieldTypeSupportedMap) { 413 return mapMap(srcObj, sourceFieldValue, classMap, fieldMap, destObj, destFieldType); 414 } 415 if (isSourceFieldClassSupportedMap || isDestFieldTypeSupportedMap) { 416 return mapMapToProperty(srcObj, sourceFieldValue, sourceFieldClass, fieldMap, destObj, destFieldType, classMap); 417 } 418 if (mappingUtils.isCustomMapMethod(fieldMap)) { 419 return mapCustomMapToProperty(sourceFieldValue, sourceFieldClass, fieldMap, destObj, destFieldType); 420 } 421 if (mappingUtils.isPrimitiveOrWrapper(sourceFieldClass) || mappingUtils.isPrimitiveOrWrapper(destFieldType)) { 422 if (fieldMap.getDestinationTypeHint() != null) { 424 destFieldType = fieldMap.getDestinationTypeHint().getHint(); 425 } 426 return primitiveOrWrapperConverter.convert(sourceFieldValue, destFieldType, new DateFormatContainer(classMap, fieldMap)); 427 } 428 if (mappingUtils.isSupportedCollection(sourceFieldClass) 429 && (mappingUtils.isSupportedCollection(destFieldType))) { 430 return mapCollection(srcObj, sourceFieldValue, classMap, fieldMap, destObj); 431 } 432 433 return mapCustomObject(fieldMap, destObj, destFieldType, sourceFieldValue); 435 } 436 437 private Object mapClassLevelMap(Object srcObj, FieldMap fieldMap, Object sourceFieldValue, Class sourceFieldClass, 438 ClassMap classMap, Class destType, Object destObj) throws InvocationTargetException , IllegalAccessException , 439 NoSuchFieldException , InstantiationException , ClassNotFoundException , NoSuchMethodException { 440 if (!mappingUtils.isSupportedMap(sourceFieldClass) && !classMap.getSourceClass().isCustomMap()) { 442 return sourceFieldValue; 443 } else { 444 String key = null; 445 if (StringUtils.isEmpty(fieldMap.getDestField().getKey())) { 446 key = fieldMap.getDestField().getName(); 447 } else { 448 key = fieldMap.getDestField().getKey(); 449 } 450 Method resultMethod = reflectionUtils.getMethod(sourceFieldValue, fieldMap.getSourceField().getMapGetMethod()); 451 Object result = resultMethod.invoke(sourceFieldValue, new Object [] { key }); 452 return mapOrRecurseObject(srcObj, result, destType, classMap, fieldMap, destObj, true); 453 } 454 } 455 456 private Object mapCustomObject(FieldMap fieldMap, Object destObj, Class destFieldType, Object sourceFieldValue) 457 throws InvocationTargetException , IllegalAccessException , InstantiationException , NoSuchMethodException , 458 ClassNotFoundException , NoSuchFieldException { 459 Object field = mappingValidator.validateField(fieldMap, destObj, destFieldType); 461 ClassMap classMap = null; 462 if (field == null) { 464 if (fieldMap.getDestinationTypeHint() != null) { 466 Class destType = fieldMap.getDestinationTypeHint().getHint(); 467 if (destType != null) { 470 destFieldType = destType; 471 } 472 } 473 String mapId = null; 475 if (fieldMap != null) { 476 mapId = fieldMap.getMapId(); 477 } 478 classMap = getClassMap(sourceFieldValue, destFieldType, mapId, false); 479 field = destBeanCreator.create(sourceFieldValue, classMap, fieldMap, null); 480 } 481 482 map(classMap, sourceFieldValue, field, null, fieldMap); 483 484 return field; 485 } 486 487 private Object mapCollection(Object srcObj, Object sourceCollectionValue, ClassMap classMap, FieldMap fieldMap, Object destObj) 488 throws IllegalAccessException , InstantiationException , InvocationTargetException , NoSuchMethodException , 489 ClassNotFoundException , NoSuchFieldException { 490 491 if (sourceCollectionValue instanceof Iterator ) { 493 sourceCollectionValue = IteratorUtils.toList((Iterator ) sourceCollectionValue); 494 } 495 496 Class destCollectionType = fieldMap.getDestFieldType(destObj.getClass()); 497 Class sourceFieldType = sourceCollectionValue.getClass(); 498 Object result = null; 499 500 if (destCollectionType.getName().equals(Collection .class.getName())) { 502 destCollectionType = List .class; 503 } 504 if (collectionUtils.isArray(sourceFieldType) && (collectionUtils.isArray(destCollectionType))) { 506 result = mapArrayToArray(srcObj, sourceCollectionValue, classMap, fieldMap, destObj); 507 } else if (collectionUtils.isArray(sourceFieldType) && (collectionUtils.isList(destCollectionType))) { 509 result = mapArrayToList(srcObj, sourceCollectionValue, classMap, fieldMap, destObj); 510 } 511 else if (collectionUtils.isList(sourceFieldType) && (collectionUtils.isArray(destCollectionType))) { 513 result = mapListToArray(srcObj, (List ) sourceCollectionValue, classMap, fieldMap, destObj); 514 } else if (collectionUtils.isList(sourceFieldType) && (collectionUtils.isList(destCollectionType))) { 516 result = mapListToList(srcObj, (List ) sourceCollectionValue, classMap, fieldMap, destObj); 517 } 518 else if (collectionUtils.isSet(sourceFieldType) && collectionUtils.isSet(destCollectionType)) { 520 result = mapSetToSet(srcObj, (Set ) sourceCollectionValue, classMap, fieldMap, destObj, destCollectionType); 521 } 522 else if (collectionUtils.isSet(sourceFieldType) && collectionUtils.isArray(destCollectionType)) { 524 result = mapSetToArray(srcObj, (Set ) sourceCollectionValue, classMap, fieldMap, destObj); 525 } 526 else if (collectionUtils.isArray(sourceFieldType) && collectionUtils.isSet(destCollectionType)) { 528 result = addToSet(srcObj, fieldMap, Arrays.asList((Object []) sourceCollectionValue), classMap, destObj); 529 } 530 else if (collectionUtils.isSet(sourceFieldType) && collectionUtils.isList(destCollectionType)) { 532 result = mapListToList(srcObj, (Set ) sourceCollectionValue, classMap, fieldMap, destObj); 533 } 534 else if (collectionUtils.isList(sourceFieldType) && collectionUtils.isSet(destCollectionType)) { 536 result = addToSet(srcObj, fieldMap, (List ) sourceCollectionValue, classMap, destObj); 537 } 538 return result; 539 } 540 541 private Object mapMap(Object srcObj, Object sourceMapValue, ClassMap classMap, FieldMap fieldMap, Object destObj, Class destFieldType) 542 throws IllegalAccessException , InstantiationException , InvocationTargetException , NoSuchMethodException , 543 ClassNotFoundException , NoSuchFieldException { 544 Map result = null; 545 Object field = fieldMap.doesFieldExist(destObj, destFieldType); 546 if (field == null) { 547 result = (Map ) sourceMapValue.getClass().newInstance(); 549 } else { 550 result = (Map ) field; 551 } 552 Map sourceMap = (Map ) sourceMapValue; 553 Set sourceEntrySet = sourceMap.entrySet(); 554 Iterator iter = sourceEntrySet.iterator(); 555 while (iter.hasNext()) { 556 Map.Entry sourceEntry = (Map.Entry ) iter.next(); 557 Object sourceEntryValue = sourceEntry.getValue(); 558 Object destEntryValue = mapOrRecurseObject(srcObj, sourceEntryValue, sourceEntryValue.getClass(), classMap, fieldMap, 559 destObj); 560 result.put(sourceEntry.getKey(), destEntryValue); 561 } 562 return result; 563 } 564 565 private Object mapMapToProperty(Object srcObj, Object sourceValue, Class sourceFieldClass, FieldMap fieldMap, Object destObj, 566 Class destType, ClassMap classMap) throws IllegalAccessException , InstantiationException , 567 InvocationTargetException , NoSuchMethodException , ClassNotFoundException , NoSuchFieldException { 568 Object srcFieldValue = null; 569 String key = null; 570 571 if (mappingUtils.isSupportedMap(destType)) { 573 Object field = fieldMap.doesFieldExist(destObj, destType); 574 if (sourceFieldClass == null) { 576 return field; 577 } 578 if (field == null) { 579 if (fieldMap.getDestinationTypeHint() != null) { 580 destType = fieldMap.getDestinationTypeHint().getHint(); 582 } else if (destType.isInterface()) { 583 destType = HashMap .class; 585 } 586 srcFieldValue = destType.newInstance(); 588 } else { 589 srcFieldValue = field; 590 } 591 key = fieldMap.getDestKey(); 592 ((Map ) srcFieldValue).put(key, sourceValue); 593 } else { 594 key = fieldMap.getSourceKey(); 595 srcFieldValue = ((Map ) sourceValue).get(key); 596 } 597 return mapOrRecurseObject(srcObj, srcFieldValue, destType, classMap, fieldMap, destObj); 598 } 599 600 private Object mapCustomMapToProperty(Object sourceValue, Class sourceFieldClass, FieldMap fieldMap, Object destObj, 601 Class destType) throws IllegalAccessException , InstantiationException , InvocationTargetException , 602 NoSuchMethodException , ClassNotFoundException , NoSuchFieldException { 603 Object result = null; 604 if (fieldMap.getDestField().getMapGetMethod() != null && fieldMap.getDestField().getMapSetMethod() != null) { 606 Object field = fieldMap.doesFieldExist(destObj, destType); 607 if (sourceFieldClass == null) { 609 return field; 610 } 611 if (field == null) { 612 if (fieldMap.getDestinationTypeHint() != null) { 613 destType = fieldMap.getDestinationTypeHint().getHint(); 615 } 616 result = destType.newInstance(); 618 } else { 619 result = field; 620 } 621 String key = fieldMap.getDestKey(); 622 Method resultMethod = reflectionUtils.getMethod(result, fieldMap.getDestField().getMapSetMethod()); 623 resultMethod.invoke(result, new Object [] { key, sourceValue }); 624 } else { 625 String key = fieldMap.getSourceKey(); 626 Method resultMethod = reflectionUtils.getMethod(sourceValue, fieldMap.getSourceField().getMapGetMethod()); 627 result = resultMethod.invoke(sourceValue, new Object [] { key }); 628 } 629 return result; 630 } 631 632 private Object mapArrayToArray(Object srcObj, Object sourceCollectionValue, ClassMap classMap, FieldMap fieldMap, Object destObj) 633 throws IllegalAccessException , InstantiationException , InvocationTargetException , NoSuchMethodException , 634 ClassNotFoundException , NoSuchFieldException { 635 Class destEntryType = fieldMap.getDestFieldType(destObj.getClass()).getComponentType(); 636 int size = Array.getLength(sourceCollectionValue); 637 if (collectionUtils.isPrimitiveArray(sourceCollectionValue.getClass())) { 638 return addToPrimitiveArray(srcObj, fieldMap, size, sourceCollectionValue, classMap, destObj, destEntryType); 639 } else { 640 List list = Arrays.asList((Object []) sourceCollectionValue); 641 List returnList = null; 642 if (!destEntryType.getName().equals("java.lang.Object")) { 643 returnList = addOrUpdateToList(srcObj, fieldMap, list, classMap, destObj, destEntryType); 644 } else { 645 returnList = addOrUpdateToList(srcObj, fieldMap, list, classMap, destObj, null); 646 } 647 return collectionUtils.convertListToArray(returnList, destEntryType); 648 } 649 } 650 651 private void mapFromIterateMethodFieldMap(Object sourceObj, Object destObj, Object sourceFieldValue, 652 ClassMap classMap, FieldMap fieldMapping) throws IllegalAccessException , InvocationTargetException , 653 InvocationTargetException , InstantiationException , ClassNotFoundException , NoSuchMethodException , 654 NoSuchFieldException { 655 if (sourceFieldValue instanceof Iterator ) { 658 sourceFieldValue = IteratorUtils.toList((Iterator ) sourceFieldValue); 659 } 660 if (sourceFieldValue != null) { 661 for (int i = 0; i < collectionUtils.getLengthOfCollection(sourceFieldValue); i++) { 662 Object value = collectionUtils.getValueFromCollection(sourceFieldValue, i); 663 if (fieldMapping.getDestinationTypeHint() == null) { 665 throw new MappingException("<field type=\"iterate\"> must have a source or destination type hint"); 666 } 667 CustomConverterContainer customConverters = classMap.getConfiguration().getCustomConverters(); 669 Class converterClass = mappingUtils.findCustomConverter(converterByDestTypeCache, customConverters, 670 value.getClass(), Thread.currentThread().getContextClassLoader().loadClass(fieldMapping.getDestinationTypeHint().getHintName())); 671 672 if (converterClass != null) { 673 Class sourceFieldClass = sourceFieldValue != null ? sourceFieldValue.getClass() : fieldMapping.getSourceFieldType(sourceObj.getClass()); 674 value = mapUsingCustomConverter(converterClass, sourceFieldClass, value, fieldMapping 675 .getDestinationTypeHint().getHint(), null, fieldMapping, false); 676 } else { 677 value = map(value, fieldMapping.getDestinationTypeHint().getHint()); 678 } 679 if (value != null) { 680 writeDestinationValue(destObj, value, classMap, fieldMapping); 681 } 682 } 683 } 684 if (log.isDebugEnabled()) { 685 log.debug(logMsgFactory.createFieldMappingSuccessMsg(sourceObj.getClass(), destObj.getClass(), fieldMapping.getSourceField().getName(), 686 fieldMapping.getDestField().getName(), sourceFieldValue, null)); 687 } 688 } 689 690 private Object addToPrimitiveArray(Object srcObj, FieldMap fieldMap, int size, Object sourceCollectionValue, ClassMap classMap, 691 Object destObj, Class destEntryType) throws IllegalAccessException , InstantiationException , 692 InvocationTargetException , NoSuchMethodException , ClassNotFoundException , NoSuchFieldException { 693 694 Object result = null; 695 Object field = fieldMap.doesFieldExist(destObj, destEntryType); 696 int arraySize = 0; 697 if (field == null) { 698 result = Array.newInstance(destEntryType, size); 699 } else { 700 result = Array.newInstance(destEntryType, size + Array.getLength(field)); 701 arraySize = Array.getLength(field); 702 for (int i = 0; i < Array.getLength(field); i++) { 703 Array.set(result, i, Array.get(field, i)); 704 } 705 } 706 for (int i = 0; i < size; i++) { 708 Object toValue = mapOrRecurseObject(srcObj, Array.get(sourceCollectionValue, i), destEntryType, classMap, fieldMap, 709 destObj); 710 Array.set(result, arraySize, toValue); 711 arraySize++; 712 } 713 return result; 714 } 715 716 private Object mapListToArray(Object srcObj, Collection sourceCollectionValue, ClassMap classMap, FieldMap fieldMap, Object destObj) 717 throws IllegalAccessException , InstantiationException , InvocationTargetException , NoSuchMethodException , 718 ClassNotFoundException , NoSuchFieldException { 719 List list = null; 720 Class destEntryType = fieldMap.getDestFieldType(destObj.getClass()).getComponentType(); 721 722 if (!destEntryType.getName().equals("java.lang.Object")) { 723 list = addOrUpdateToList(srcObj, fieldMap, sourceCollectionValue, classMap, destObj, destEntryType); 724 } else { 725 list = addOrUpdateToList(srcObj, fieldMap, sourceCollectionValue, classMap, destObj); 726 } 727 return collectionUtils.convertListToArray(list, destEntryType); 728 } 729 730 private List mapListToList(Object srcObj, Collection sourceCollectionValue, ClassMap classMap, FieldMap fieldMap, Object destObj) 731 throws IllegalAccessException , InstantiationException , InvocationTargetException , NoSuchMethodException , 732 ClassNotFoundException , NoSuchFieldException { 733 return addOrUpdateToList(srcObj, fieldMap, sourceCollectionValue, classMap, destObj); 734 } 735 736 private Set addToSet(Object srcObj, FieldMap fieldMap, Collection sourceCollectionValue, ClassMap classMap, Object destObj) 737 throws IllegalAccessException , InstantiationException , InvocationTargetException , NoSuchMethodException , 738 ClassNotFoundException , NoSuchFieldException { 739 Class destEntryType = null; 740 ListOrderedSet result = new ListOrderedSet(); 741 Object field = fieldMap.doesFieldExist(destObj, null); 743 if (field != null) { 744 result.addAll((Collection ) field); 745 } 746 Object destValue = null; 747 Iterator iter = sourceCollectionValue.iterator(); 748 Object sourceValue = null; 749 while (iter.hasNext()) { 750 sourceValue = iter.next(); 751 if (destEntryType == null 752 || (fieldMap.getDestinationTypeHint() != null && fieldMap.getDestinationTypeHint().hasMoreThanOneHint())) { 753 destEntryType = fieldMap.getDestHintType(sourceValue.getClass()); 754 } 755 destValue = mapOrRecurseObject(srcObj, sourceValue, destEntryType, classMap, fieldMap, destObj); 756 if (fieldMap.isGenericFieldMap()) { 757 GenericFieldMap gfm = (GenericFieldMap) fieldMap; 758 if (gfm.getRelationshipType() == null 759 || gfm.getRelationshipType().equals(MapperConstants.RELATIONSHIP_CUMULATIVE)) { 760 result.add(destValue); 761 } else { 762 if (result.contains(destValue)) { 763 int index = result.indexOf(destValue); 764 Object obj = result.get(index); 766 if (!obj.getClass().isAssignableFrom(String .class)) { 768 map(null, obj, destValue, null, fieldMap); 769 } 770 result.add(destValue); 771 } else { 772 result.add(destValue); 773 } 774 } 775 } else { 776 result.add(destValue); 777 } 778 } 779 if (field == null) { 780 Class destSetType = fieldMap.getDestFieldType(destObj.getClass()); 781 return collectionUtils.createNewSet(destSetType, result); 782 } else { 783 ((Set ) field).addAll(result); 784 return (Set ) field; 785 } 786 } 787 788 private List addOrUpdateToList(Object srcObj, FieldMap fieldMap, Collection sourceCollectionValue, ClassMap classMap, 789 Object destObj, Class destEntryType) throws IllegalAccessException , InstantiationException , 790 InvocationTargetException , NoSuchMethodException , ClassNotFoundException , NoSuchFieldException { 791 792 List result = null; 793 Object field = fieldMap.doesFieldExist(destObj, destEntryType); 797 if (field == null) { 798 result = new ArrayList (sourceCollectionValue.size()); 799 } else { 800 if (collectionUtils.isList(field.getClass())) { 801 result = (List ) field; 802 } else if (collectionUtils.isArray(field.getClass())) { result = new ArrayList (Arrays.asList((Object []) field)); 804 } else { result = new ArrayList (sourceCollectionValue.size()); 807 } 808 } 809 Object destValue = null; 810 Iterator iter = sourceCollectionValue.iterator(); 811 Object sourceValue = null; 812 Class prevDestEntryType = null; 813 while (iter.hasNext()) { 814 sourceValue = iter.next(); 815 if (destEntryType == null 816 || (fieldMap.getDestinationTypeHint() != null && fieldMap.getDestinationTypeHint().hasMoreThanOneHint())) { 817 if (sourceValue == null) { 818 destEntryType = prevDestEntryType; 819 } else { 820 destEntryType = fieldMap.getDestHintType(sourceValue.getClass()); 821 } 822 } 823 destValue = mapOrRecurseObject(srcObj, sourceValue, destEntryType, classMap, fieldMap, destObj); 824 prevDestEntryType = destEntryType; 825 if (fieldMap.isGenericFieldMap()) { 826 GenericFieldMap gfm = (GenericFieldMap) fieldMap; 827 if (gfm.getRelationshipType() == null 828 || gfm.getRelationshipType().equals(MapperConstants.RELATIONSHIP_CUMULATIVE)) { 829 result.add(destValue); 830 } else { 831 if (result.contains(destValue)) { 832 int index = result.indexOf(destValue); 833 Object obj = result.get(index); 835 if (!obj.getClass().isAssignableFrom(String .class)) { 837 map(null, obj, destValue, null, fieldMap); 838 } 839 result.set(index, destValue); 840 } else { 841 result.add(destValue); 842 } 843 } 844 } else { 845 result.add(destValue); 846 } 847 } 848 return result; 849 } 850 851 private List addOrUpdateToList(Object srcObj, FieldMap fieldMap, Collection sourceCollectionValue, ClassMap classMap, Object destObj) 852 throws IllegalAccessException , InstantiationException , InvocationTargetException , NoSuchMethodException , 853 ClassNotFoundException , NoSuchFieldException { 854 return addOrUpdateToList(srcObj, fieldMap, sourceCollectionValue, classMap, destObj, null); 855 } 856 857 private Set mapSetToSet(Object srcObj, Set sourceCollectionValue, ClassMap classMap, FieldMap fieldMap, Object destObj, 858 Class destClass) throws IllegalAccessException , InstantiationException , InvocationTargetException , 859 NoSuchMethodException , ClassNotFoundException , NoSuchFieldException { 860 861 Object field = fieldMap.doesFieldExist(destObj, destClass); 862 Set result = null; 863 if (field == null) { 866 Class destFieldType = fieldMap.getDestFieldType(destObj.getClass()); 867 result = collectionUtils.createNewSet(destFieldType); 868 } else { 869 result = (Set ) field; 870 } 871 Iterator iter = sourceCollectionValue.iterator(); 872 while (iter.hasNext()) { 873 Object obj = iter.next(); 874 Class destEntryType = fieldMap.getDestHintType(obj.getClass()); 875 Object destValue = mapOrRecurseObject(srcObj, obj, destEntryType, classMap, fieldMap, destObj); 876 result.add(destValue); 877 } 878 return result; 879 } 880 881 private Object mapSetToArray(Object srcObj, Collection sourceCollectionValue, ClassMap classMap, FieldMap fieldMap, Object destObj) 882 throws IllegalAccessException , InstantiationException , InvocationTargetException , NoSuchMethodException , 883 ClassNotFoundException , NoSuchFieldException { 884 return mapListToArray(srcObj, sourceCollectionValue, classMap, fieldMap, destObj); 885 } 886 887 private List mapArrayToList(Object srcObj, Object sourceCollectionValue, ClassMap classMap, FieldMap fieldMap, Object destObj) 888 throws IllegalAccessException , InstantiationException , InvocationTargetException , NoSuchMethodException , 889 ClassNotFoundException , NoSuchFieldException { 890 Class destEntryType = null; 891 if (fieldMap.getDestinationTypeHint() != null) { 892 destEntryType = fieldMap.getDestinationTypeHint().getHint(); 893 } else { 894 destEntryType = sourceCollectionValue.getClass().getComponentType(); 895 } 896 List srcValueList = null; 897 if (collectionUtils.isPrimitiveArray(sourceCollectionValue.getClass())) { 898 srcValueList = collectionUtils.convertPrimitiveArrayToList(sourceCollectionValue); 899 } else { 900 srcValueList = Arrays.asList((Object []) sourceCollectionValue); 901 } 902 return addOrUpdateToList(srcObj, fieldMap, srcValueList, classMap, destObj, destEntryType); 903 } 904 905 private void writeDestinationValue(Object destObj, Object destFieldValue, ClassMap classMap, FieldMap fieldMapping) 906 throws IllegalAccessException , InvocationTargetException , InstantiationException , NoSuchMethodException , 907 ClassNotFoundException , NoSuchFieldException { 908 boolean bypass = false; 909 if (destFieldValue == null && !classMap.getDestClass().getMapNull().booleanValue()) { 911 bypass = true; 912 } 913 914 if (destFieldValue != null && destFieldValue.getClass().equals(String .class) && 916 StringUtils.isEmpty((String ) destFieldValue) && !classMap.getDestClass().getMapEmptyString().booleanValue()) { 917 bypass = true; 918 } 919 920 if (!bypass) { 921 eventMgr.fireEvent(new DozerEvent(MapperConstants.MAPPING_PRE_WRITING_DEST_VALUE, classMap, fieldMapping, null, destObj, destFieldValue)); 922 923 fieldMapping.writeDestinationValue(destObj, destFieldValue, classMap); 924 925 eventMgr.fireEvent(new DozerEvent(MapperConstants.MAPPING_POST_WRITING_DEST_VALUE, classMap, fieldMapping, null, destObj, destFieldValue)); 926 } 927 } 928 929 private Object mapUsingCustomConverter(Class customConverterClass, Class srcFieldClass, Object srcFieldValue, 930 Class destFieldClass, Object destFieldValue, FieldMap fieldMap, boolean topLevel) throws IllegalAccessException , 931 InvocationTargetException , InstantiationException , NoSuchMethodException , ClassNotFoundException , 932 NoSuchFieldException { 933 Object converterInstance = null; 934 if (customConverterObjects != null) { 936 for (int i = 0; i < customConverterObjects.size(); i++) { 937 Object customConverter = (Object ) customConverterObjects.get(i); 938 if (customConverter.getClass().isAssignableFrom(customConverterClass)) { 939 converterInstance = customConverter; 941 } 942 } 943 } 944 if (converterInstance == null) { 947 converterInstance = customConverterClass.newInstance(); 948 } 949 if (!(converterInstance instanceof CustomConverter)) { 950 throw new MappingException("Custom Converter does not implement CustomConverter interface"); 951 } 952 CustomConverter theConverter = (CustomConverter) converterInstance; 953 if (topLevel) { 955 return theConverter.convert(destFieldValue, srcFieldValue, destFieldClass, srcFieldClass); 956 } 957 Object field = mappingValidator.validateField(fieldMap, destFieldValue, destFieldClass); 958 return theConverter.convert(field, srcFieldValue, destFieldClass, srcFieldClass); 959 } 960 961 private List checkForSuperTypeMapping(Class sourceClass, Class destClass) { 962 Object cacheKey = CacheKeyFactory.createKey(new Object [] { destClass, sourceClass }); 964 CacheEntry cacheEntry = superTypeCache.get(cacheKey); 965 if (cacheEntry != null) { 966 return (List ) cacheEntry.getValue(); 967 } 968 969 Class superSourceClass = sourceClass.getSuperclass(); 971 Class superDestClass = destClass.getSuperclass(); 972 List superClasses = new ArrayList (); 973 boolean stillHasSuperClasses = true; 974 while (stillHasSuperClasses) { 975 if ((superSourceClass != null && !superSourceClass.getName().equals("java.lang.Object")) 976 || (superDestClass != null && !superDestClass.getName().equals("java.lang.Object"))) { 977 ClassMap superClassMap = (ClassMap) customMappings.get(ClassMapKeyFactory.createKey(superSourceClass, 979 destClass)); 980 if (superClassMap != null) { 981 superClasses.add(superClassMap); 982 } 983 superDestClass = destClass.getSuperclass(); 986 boolean stillHasDestSuperClasses = true; 987 while (stillHasDestSuperClasses) { 988 if (superDestClass != null && !superDestClass.getName().equals("java.lang.Object")) { 989 ClassMap superDestClassMap = (ClassMap) customMappings.get(ClassMapKeyFactory.createKey( 990 superSourceClass, superDestClass)); 991 if (superDestClassMap != null) { 992 superClasses.add(superDestClassMap); 993 } 994 ClassMap sourceClassMap = (ClassMap) customMappings.get(ClassMapKeyFactory.createKey(sourceClass, 995 superDestClass)); 996 if (sourceClassMap != null) { 997 superClasses.add(sourceClassMap); 998 } 999 superDestClass = superDestClass.getSuperclass(); 1000 } else { 1001 break; 1002 } 1003 } 1004 superSourceClass = superSourceClass.getSuperclass(); 1005 } else { 1006 break; 1007 } 1008 } 1010 Collections.reverse(superClasses); 1012 cacheEntry = new CacheEntry(cacheKey, (ArrayList ) superClasses); 1014 superTypeCache.put(cacheEntry); 1015 1016 return superClasses; 1017 } 1018 1019 private List processSuperTypeMapping(List superClasses, Object sourceObj, Object destObj, Class sourceClass, 1020 FieldMap parentFieldMap) throws NoSuchMethodException , NoSuchFieldException , ClassNotFoundException , 1021 IllegalAccessException , InvocationTargetException , InstantiationException { 1022 List fieldNamesList = new ArrayList (); 1023 Object [] superClassArray = superClasses.toArray(); 1024 for (int a = 0; a < superClassArray.length; a++) { 1025 ClassMap map = (ClassMap) superClassArray[a]; 1026 map(map, sourceObj, destObj, map, parentFieldMap); 1027 List fieldMaps = map.getFieldMaps(); 1028 Class destClassToMap = destObj.getClass(); 1029 Class srcClassToMap = sourceObj.getClass(); 1030 for (int i = 0; i < fieldMaps.size(); i++) { 1031 FieldMap fieldMapping = (FieldMap) fieldMaps.get(i); 1032 if (!fieldMapping.isGenericFieldMap() && !(fieldMapping instanceof ExcludeFieldMap)) { 1033 } else { 1035 String methodName = fieldMapping.getDestFieldReadMethodName(destClassToMap); 1036 String sourceMethodName = fieldMapping.getSourceFieldReadMethodName(srcClassToMap); 1037 String parentSourceField = null; 1038 if (parentFieldMap != null) { 1039 parentSourceField = parentFieldMap.getSourceField().getName(); 1040 } 1041 String key = mappingUtils.getParentFieldNameKey(parentSourceField, sourceObj, sourceClass.getName(), 1042 sourceMethodName, methodName, fieldMapping.getSourceField().getName(), fieldMapping.getDestField().getName()); 1043 if (fieldNamesList.contains(key)) { 1044 continue; 1045 } else { 1046 fieldNamesList.add(key); 1047 } 1048 } 1049 } 1050 } 1051 return fieldNamesList; 1052 } 1053 1054 private ClassMap getClassMap(Object sourceObj, Class destClass, String mapId, boolean isInstance) { 1055 ClassMap mapping = classMapFinder.findClassMap(this.customMappings, sourceObj, destClass, mapId, isInstance); 1056 1057 if (mapping == null) { 1060 mapping = classMapBuilder.createDefaultClassMap(globalConfiguration, sourceObj.getClass(), destClass); 1061 customMappings.put(ClassMapKeyFactory.createKey(sourceObj.getClass(), destClass), mapping); 1062 } 1063 1064 return mapping; 1065 } 1066 1067} 1068 | Popular Tags |