Coverage Report - org.dozer.fieldmap.FieldMap
 
Classes in this File Line Coverage Branch Coverage Complexity
FieldMap
89%
137/153
90%
36/40
1.436
 
 1  
 /**
 2  
  * Copyright 2005-2013 Dozer Project
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *      http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package org.dozer.fieldmap;
 17  
 
 18  
 import org.apache.commons.lang3.builder.ToStringBuilder;
 19  
 import org.apache.commons.lang3.builder.ToStringStyle;
 20  
 import org.dozer.BeanBuilder;
 21  
 import org.dozer.MappingException;
 22  
 import org.dozer.builder.BuilderUtil;
 23  
 import org.dozer.classmap.ClassMap;
 24  
 import org.dozer.classmap.DozerClass;
 25  
 import org.dozer.classmap.MappingDirection;
 26  
 import org.dozer.classmap.RelationshipType;
 27  
 import org.dozer.propertydescriptor.DozerPropertyDescriptor;
 28  
 import org.dozer.propertydescriptor.GetterSetterPropertyDescriptor;
 29  
 import org.dozer.propertydescriptor.PropertyDescriptorFactory;
 30  
 import org.dozer.util.DozerConstants;
 31  
 import org.dozer.util.MappingUtils;
 32  
 import org.slf4j.Logger;
 33  
 import org.slf4j.LoggerFactory;
 34  
 
 35  
 import java.lang.reflect.Method;
 36  
 import java.util.concurrent.ConcurrentHashMap;
 37  
 import java.util.concurrent.ConcurrentMap;
 38  
 
 39  
 /**
 40  
  * Internal class that represents a field mapping definition. Holds all of the information about a single field mapping
 41  
  * definition. Only intended for internal use.
 42  
  * 
 43  
  * @author garsombke.franz
 44  
  * @author sullins.ben
 45  
  * @author tierney.matt
 46  
  * @author johnsen.knut-erik
 47  
  * 
 48  
  */
 49  
 public abstract class FieldMap implements Cloneable {
 50  
   
 51  38866
   private final Logger log = LoggerFactory.getLogger(FieldMap.class);
 52  
 
 53  
   private ClassMap classMap;
 54  
   private DozerField srcField;
 55  
   private DozerField destField;
 56  
   private HintContainer srcHintContainer;
 57  
   private HintContainer destHintContainer;
 58  
   private HintContainer srcDeepIndexHintContainer;
 59  
   private HintContainer destDeepIndexHintContainer;
 60  
   private MappingDirection type;
 61  
   private boolean copyByReference;
 62  
   private boolean copyByReferenceOveridden;
 63  
   private String mapId;
 64  
   private String customConverter;
 65  
   private String customConverterId;
 66  
   private String customConverterParam;
 67  
   private RelationshipType relationshipType;
 68  
   private boolean removeOrphans;
 69  
 
 70  38866
   private final ConcurrentMap<Class<?>, DozerPropertyDescriptor> srcPropertyDescriptorMap = new ConcurrentHashMap<Class<?>, DozerPropertyDescriptor>(); // For Caching Purposes
 71  38866
   private final ConcurrentMap<Class<?>, DozerPropertyDescriptor> destPropertyDescriptorMap = new ConcurrentHashMap<Class<?>, DozerPropertyDescriptor>();
 72  
 
 73  38866
   public FieldMap(ClassMap classMap) {
 74  38866
     this.classMap = classMap;
 75  38866
   }
 76  
 
 77  
   public ClassMap getClassMap() {
 78  586206
     return classMap;
 79  
   }
 80  
 
 81  
   public void setClassMap(ClassMap classMap) {
 82  13040
     this.classMap = classMap;
 83  13040
   }
 84  
 
 85  
   public Object getSrcFieldValue(Object runtimeSrcObj) {
 86  179400
     return getSrcPropertyDescriptor(runtimeSrcObj.getClass()).getPropertyValue(runtimeSrcObj);
 87  
   }
 88  
 
 89  
   public void writeDestValue(Object runtimeDestObj, Object destFieldValue) {
 90  179242
     if (log.isDebugEnabled()) {
 91  0
       String className = MappingUtils.getClassNameWithoutPackage(runtimeDestObj.getClass());
 92  0
       log.debug("Getting ready to invoke write method on the destination object. Dest Obj: {}, Dest value: {}",
 93  
               className, destFieldValue);
 94  
     }
 95  179242
     DozerPropertyDescriptor propDescriptor = getDestPropertyDescriptor(BuilderUtil.unwrapDestClassFromBuilder(runtimeDestObj));
 96  179242
     propDescriptor.setPropertyValue(runtimeDestObj, destFieldValue, this);
 97  179238
   }
 98  
 
 99  
   public Class<?> getDestHintType(Class<?> runtimeSrcClass) {
 100  831
     if (getDestHintContainer() != null) {
 101  671
       if (getSrcHintContainer() != null) {
 102  544
         return getDestHintContainer().getHint(runtimeSrcClass, getSrcHintContainer().getHints());
 103  
       } else {
 104  127
         return getDestHintContainer().getHint();
 105  
       }
 106  
     } else {
 107  160
       return runtimeSrcClass;
 108  
     }
 109  
   }
 110  
 
 111  
   public Class<?> getDestFieldType(Class<?> runtimeDestClass) {
 112  231998
     Class<?> result = null;
 113  231998
     if (isDestFieldIndexed()) {
 114  298
       result = destHintContainer != null ? destHintContainer.getHint() : null;
 115  
     }
 116  231998
     if (result == null) {
 117  231928
       result = getDestPropertyDescriptor(runtimeDestClass).getPropertyType();
 118  
     }
 119  231996
     return result;
 120  
   }
 121  
 
 122  
   public Class<?> getSrcFieldType(Class<?> runtimeSrcClass) {
 123  148443
     return getSrcPropertyDescriptor(runtimeSrcClass).getPropertyType();
 124  
   }
 125  
 
 126  
   /**
 127  
    * @deprecated As of 3.2 release
 128  
    */
 129  
   @Deprecated
 130  
   public Class<?> getDestFieldWriteMethodParameter(Class<?> runtimeDestClass) {
 131  
     // 4-07 mht: The getWriteMethod was removed from the prop descriptor interface. This was done as part of
 132  
     // refactoring effort to clean up the prop descriptor stuff. The underlying write method should not be exposed.
 133  
     // For now, just explicitly cast to the only prop descriptor(getter/setter) that could have been used in this
 134  
     // context. The other types of prop descriptors would have failed.
 135  54
     DozerPropertyDescriptor dpd = getDestPropertyDescriptor(runtimeDestClass);
 136  54
     return ((GetterSetterPropertyDescriptor) dpd).getWriteMethodPropertyType();
 137  
   }
 138  
 
 139  
   public Class<?> getGenericType(Class<?> runtimeDestClass) {
 140  464
     DozerPropertyDescriptor propertyDescriptor = getDestPropertyDescriptor(runtimeDestClass);
 141  464
     return propertyDescriptor.genericType();
 142  
   }
 143  
 
 144  
   public Object getDestValue(Object runtimeDestObj) {
 145  41667
     return getDestPropertyDescriptor(BuilderUtil.unwrapDestClassFromBuilder(runtimeDestObj)).getPropertyValue(runtimeDestObj);
 146  
   }
 147  
 
 148  
   public HintContainer getDestHintContainer() {
 149  189638
     return destHintContainer;
 150  
   }
 151  
 
 152  
   public void setDestHintContainer(HintContainer destHint) {
 153  28374
     this.destHintContainer = destHint;
 154  28374
   }
 155  
 
 156  
   public HintContainer getSrcHintContainer() {
 157  16134
     return srcHintContainer;
 158  
   }
 159  
 
 160  
   public void setSrcHintContainer(HintContainer sourceHint) {
 161  28344
     this.srcHintContainer = sourceHint;
 162  28344
   }
 163  
 
 164  
   public String getSrcFieldMapGetMethod() {
 165  18312
     return !MappingUtils.isBlankOrNull(srcField.getMapGetMethod()) ? srcField.getMapGetMethod() : classMap
 166  
         .getSrcClassMapGetMethod();
 167  
   }
 168  
 
 169  
   public String getSrcFieldMapSetMethod() {
 170  17933
     return !MappingUtils.isBlankOrNull(srcField.getMapSetMethod()) ? srcField.getMapSetMethod() : classMap
 171  
         .getSrcClassMapSetMethod();
 172  
   }
 173  
 
 174  
   public String getDestFieldMapGetMethod() {
 175  41476
     return !MappingUtils.isBlankOrNull(destField.getMapGetMethod()) ? destField.getMapGetMethod() : classMap
 176  
         .getDestClassMapGetMethod();
 177  
   }
 178  
 
 179  
   public String getDestFieldMapSetMethod() {
 180  40980
     return !MappingUtils.isBlankOrNull(destField.getMapSetMethod()) ? destField.getMapSetMethod() : classMap
 181  
         .getDestClassMapSetMethod();
 182  
   }
 183  
 
 184  
   public String getSrcFieldName() {
 185  353370
     return srcField.getName();
 186  
   }
 187  
 
 188  
   public String getDestFieldName() {
 189  834358
     return destField.getName();
 190  
   }
 191  
 
 192  
   public String getDestFieldType() {
 193  221029
     return destField.getType();
 194  
   }
 195  
 
 196  
   public String getSrcFieldType() {
 197  0
     return srcField.getType();
 198  
   }
 199  
 
 200  
   public String getDateFormat() {
 201  46257
     if (!MappingUtils.isBlankOrNull(destField.getDateFormat())) {
 202  12
       return destField.getDateFormat();
 203  46245
     } else if (!MappingUtils.isBlankOrNull(srcField.getDateFormat())) {
 204  8
       return srcField.getDateFormat();
 205  
     } else {
 206  46237
       return classMap.getDateFormat();
 207  
     }
 208  
   }
 209  
 
 210  
   public String getDestFieldCreateMethod() {
 211  40807
     return destField.getCreateMethod();
 212  
   }
 213  
 
 214  
   public String getSrcFieldCreateMethod() {
 215  0
     return srcField.getCreateMethod();
 216  
   }
 217  
 
 218  
   public boolean isDestFieldIndexed() {
 219  497639
     return destField.isIndexed();
 220  
   }
 221  
 
 222  
   public boolean isSrcFieldIndexed() {
 223  18354
     return srcField.isIndexed();
 224  
   }
 225  
 
 226  
   public int getSrcFieldIndex() {
 227  18296
     return srcField.getIndex();
 228  
   }
 229  
 
 230  
   public int getDestFieldIndex() {
 231  41646
     return destField.getIndex();
 232  
   }
 233  
 
 234  
   public String getSrcFieldTheGetMethod() {
 235  17917
     return srcField.getTheGetMethod();
 236  
   }
 237  
 
 238  
   public String getDestFieldTheGetMethod() {
 239  40962
     return destField.getTheGetMethod();
 240  
   }
 241  
 
 242  
   public String getSrcFieldTheSetMethod() {
 243  17917
     return srcField.getTheSetMethod();
 244  
   }
 245  
 
 246  
   public String getDestFieldTheSetMethod() {
 247  40962
     return destField.getTheSetMethod();
 248  
   }
 249  
 
 250  
   public String getSrcFieldKey() {
 251  18285
     return srcField.getKey();
 252  
   }
 253  
 
 254  
   public String getDestFieldKey() {
 255  485036
     return destField.getKey();
 256  
   }
 257  
 
 258  
   public boolean isDestFieldAccessible() {
 259  41521
     return determineAccess(destField, classMap.getDestClass());
 260  
   }
 261  
 
 262  
   public boolean isSrcFieldAccessible() {
 263  18296
     return determineAccess(srcField, classMap.getSrcClass());
 264  
   }
 265  
 
 266  
   private boolean determineAccess(DozerField field, DozerClass clazz) {
 267  59817
     Boolean fieldLevel = field.isAccessible();
 268  59817
     if (fieldLevel != null) {
 269  334
       return fieldLevel;
 270  
     } else {
 271  59483
       Boolean classLevel = clazz.isAccesible();
 272  59483
       if (classLevel == null) {
 273  57114
         return false;
 274  
       }
 275  2369
       return classLevel;
 276  
     }
 277  
   }
 278  
 
 279  
   public void setSrcField(DozerField sourceField) {
 280  51924
     this.srcField = sourceField;
 281  51924
   }
 282  
 
 283  
   public void setDestField(DozerField destField) {
 284  51915
     this.destField = destField;
 285  51915
   }
 286  
 
 287  
   public HintContainer getDestDeepIndexHintContainer() {
 288  247068
     return destDeepIndexHintContainer;
 289  
   }
 290  
 
 291  
   public void setDestDeepIndexHintContainer(HintContainer destDeepIndexHintHint) {
 292  28344
     this.destDeepIndexHintContainer = destDeepIndexHintHint;
 293  28344
   }
 294  
 
 295  
   public HintContainer getSrcDeepIndexHintContainer() {
 296  74815
     return srcDeepIndexHintContainer;
 297  
   }
 298  
 
 299  
   public void setSrcDeepIndexHintContainer(HintContainer srcDeepIndexHint) {
 300  28344
     this.srcDeepIndexHintContainer = srcDeepIndexHint;
 301  28344
   }
 302  
 
 303  
   @Override
 304  
   public Object clone() {
 305  13070
     Object result = null;
 306  
     try {
 307  13070
       result = super.clone();
 308  0
     } catch (CloneNotSupportedException e) {
 309  0
       MappingUtils.throwMappingException(e);
 310  13070
     }
 311  13070
     return result;
 312  
   }
 313  
 
 314  
   public MappingDirection getType() {
 315  16175
     return type;
 316  
   }
 317  
 
 318  
   public void setType(MappingDirection type) {
 319  15579
     this.type = type;
 320  15579
   }
 321  
 
 322  
   public boolean isCopyByReference() {
 323  89268
     return copyByReference;
 324  
   }
 325  
 
 326  
   public void setCopyByReference(boolean copyByReference) {
 327  1750
     this.copyByReference = copyByReference;
 328  1750
     this.copyByReferenceOveridden = true;
 329  1750
   }
 330  
 
 331  
   /**
 332  
    * Return true if is self referencing. Is considered self referencing where no other sources are specified, i.e., no
 333  
    * source properties or #CDATA in the xml def.
 334  
    */
 335  
   protected boolean isSrcSelfReferencing() {
 336  17917
     return getSrcFieldName().equals(DozerConstants.SELF_KEYWORD);
 337  
   }
 338  
 
 339  
   protected boolean isDestSelfReferencing() {
 340  40962
     return getDestFieldName().equals(DozerConstants.SELF_KEYWORD);
 341  
   }
 342  
 
 343  
   public boolean isCopyByReferenceOveridden() {
 344  244
     return copyByReferenceOveridden;
 345  
   }
 346  
 
 347  
   public String getMapId() {
 348  96964
     return mapId;
 349  
   }
 350  
 
 351  
   public void setMapId(String mapId) {
 352  28344
     this.mapId = mapId;
 353  28344
   }
 354  
 
 355  
   public String getCustomConverter() {
 356  194974
     return customConverter;
 357  
   }
 358  
 
 359  
   public void setCustomConverter(String customConverter) {
 360  28344
     this.customConverter = customConverter;
 361  28344
   }
 362  
 
 363  
   public RelationshipType getRelationshipType() {
 364  58519
     return relationshipType != null ? relationshipType : classMap.getRelationshipType();
 365  
   }
 366  
 
 367  
   public void setRelationshipType(RelationshipType relationshipType) {
 368  28344
     this.relationshipType = relationshipType;
 369  28344
   }
 370  
 
 371  
   public void validate() {
 372  14069
     if (srcField == null) {
 373  0
       MappingUtils.throwMappingException("src field must be specified");
 374  
     }
 375  14069
     if (destField == null) {
 376  0
       MappingUtils.throwMappingException("dest field must be specified");
 377  
     }
 378  14069
   }
 379  
 
 380  
   protected DozerPropertyDescriptor getSrcPropertyDescriptor(Class<?> runtimeSrcClass) {
 381  328590
     DozerPropertyDescriptor result = this.srcPropertyDescriptorMap.get(runtimeSrcClass);
 382  328590
     if (result == null) {
 383  17917
       String srcFieldMapGetMethod = getSrcFieldMapGetMethod();
 384  17917
       String srcFieldMapSetMethod = getSrcFieldMapSetMethod();
 385  17917
       DozerPropertyDescriptor descriptor = PropertyDescriptorFactory.getPropertyDescriptor(runtimeSrcClass,
 386  
               getSrcFieldTheGetMethod(), getSrcFieldTheSetMethod(),
 387  
               srcFieldMapGetMethod, srcFieldMapSetMethod, isSrcFieldAccessible(), isSrcFieldIndexed(), getSrcFieldIndex(),
 388  
               getSrcFieldName(), getSrcFieldKey(), isSrcSelfReferencing(), getDestFieldName(), getSrcDeepIndexHintContainer(),
 389  
               getDestDeepIndexHintContainer(), classMap.getSrcClassBeanFactory());
 390  17917
       this.srcPropertyDescriptorMap.putIfAbsent(runtimeSrcClass, descriptor);
 391  17917
       result = descriptor;
 392  
     }
 393  328590
     return result;
 394  
   }
 395  
 
 396  
   protected DozerPropertyDescriptor getDestPropertyDescriptor(Class<?> runtimeDestClass) {
 397  454054
     if (BeanBuilder.class.isAssignableFrom(runtimeDestClass)) {
 398  0
       MappingUtils.throwMappingException(
 399  
               "getDestPropertyDescriptor received builder instead of concrete class - it's a bug, please post stack trace at https://github.com/DozerMapper/dozer or directly to dmitry@spikhalskiy.com ");
 400  0
       return null;
 401  
     }
 402  
 
 403  454054
     DozerPropertyDescriptor result = this.destPropertyDescriptorMap.get(runtimeDestClass);
 404  454054
     if (result == null) {
 405  40962
       DozerPropertyDescriptor descriptor = PropertyDescriptorFactory.getPropertyDescriptor(runtimeDestClass,
 406  
             getDestFieldTheGetMethod(), getDestFieldTheSetMethod(), getDestFieldMapGetMethod(),
 407  
             getDestFieldMapSetMethod(), isDestFieldAccessible(), isDestFieldIndexed(), getDestFieldIndex(),
 408  
             getDestFieldName(), getDestFieldKey(), isDestSelfReferencing(), getSrcFieldName(),
 409  
             getSrcDeepIndexHintContainer(), getDestDeepIndexHintContainer(), classMap.getDestClassBeanFactory());
 410  
 
 411  40962
       this.destPropertyDescriptorMap.putIfAbsent(runtimeDestClass, descriptor);
 412  40962
       result = descriptor;
 413  
     }
 414  454054
     return result;
 415  
   }
 416  
 
 417  
   public DozerField getSrcFieldCopy() {
 418  
     try {
 419  13727
       return (DozerField) srcField.clone();
 420  0
     } catch (CloneNotSupportedException e) {
 421  0
       throw new MappingException(e);
 422  
     }
 423  
   }
 424  
 
 425  
   public DozerField getDestFieldCopy() {
 426  
     try {
 427  13710
       return (DozerField) destField.clone();
 428  0
     } catch (CloneNotSupportedException e) {
 429  0
       throw new MappingException(e);
 430  
     }
 431  
   }
 432  
 
 433  
   protected DozerField getSrcField() {
 434  1280
     return srcField;
 435  
   }
 436  
 
 437  
   protected DozerField getDestField() {
 438  1280
     return destField;
 439  
   }
 440  
 
 441  
   public String getCustomConverterId() {
 442  194961
     return customConverterId;
 443  
   }
 444  
 
 445  
   public void setCustomConverterId(String customConverterId) {
 446  28344
     this.customConverterId = customConverterId;
 447  28344
   }
 448  
 
 449  
   public boolean isRemoveOrphans() {
 450  15454
     return removeOrphans;
 451  
   }
 452  
 
 453  
   public void setRemoveOrphans(boolean removeOrphans) {
 454  28344
     this.removeOrphans = removeOrphans;
 455  28344
   }
 456  
 
 457  
   public boolean isDestMapNull() {
 458  135820
     return classMap.isDestMapNull();
 459  
   }
 460  
 
 461  
   public boolean isDestMapEmptyString() {
 462  44757
     return classMap.isDestMapEmptyString();
 463  
   }
 464  
 
 465  
   public boolean isTrimStrings() {
 466  91014
     return classMap.isTrimStrings();
 467  
   }
 468  
 
 469  
   public boolean isStopOnErrors() {
 470  16
     return classMap.isStopOnErrors();
 471  
   }
 472  
 
 473  
   public boolean isNonCumulativeRelationship() {
 474  0
     return RelationshipType.NON_CUMULATIVE.equals(relationshipType);
 475  
   }
 476  
 
 477  
   @Override
 478  
   public String toString() {
 479  0
     return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE).append("source field", srcField).append("destination field",
 480  
         destField).append("type", type).append("customConverter", customConverter).append("relationshipType", relationshipType)
 481  
         .append("removeOrphans", removeOrphans).append("mapId", mapId).append("copyByReference", copyByReference).append(
 482  
             "copyByReferenceOveridden", copyByReferenceOveridden).append("srcTypeHint", srcHintContainer).append("destTypeHint",
 483  
             destHintContainer).toString();
 484  
   }
 485  
 
 486  
   public String getCustomConverterParam() {
 487  1301
           return customConverterParam;
 488  
   }
 489  
 
 490  
   public void setCustomConverterParam(String customConverterParam) {
 491  14751
           this.customConverterParam = customConverterParam;
 492  14751
   }
 493  
 
 494  
 }