Coverage Report - org.dozer.propertydescriptor.FieldPropertyDescriptor
 
Classes in this File Line Coverage Branch Coverage Complexity
FieldPropertyDescriptor
100%
31/31
92%
13/14
2.8
FieldPropertyDescriptor$ChainedPropertyDescriptor
78%
25/32
90%
9/10
2.8
 
 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.propertydescriptor;
 17  
 
 18  
 import org.dozer.factory.DestBeanCreator;
 19  
 import org.dozer.fieldmap.FieldMap;
 20  
 import org.dozer.fieldmap.HintContainer;
 21  
 import org.dozer.util.DozerConstants;
 22  
 import org.dozer.util.MappingUtils;
 23  
 import org.dozer.util.ReflectionUtils;
 24  
 
 25  
 import java.lang.reflect.Field;
 26  
 import java.lang.reflect.Type;
 27  
 
 28  
 
 29  
 /**
 30  
  * Internal class that directly accesses the field via reflection. The getter/setter methods for the field are bypassed
 31  
  * and will NOT be invoked. Private fields are accessible by Dozer. Only intended for internal use.
 32  
  *
 33  
  * @author garsombke.franz
 34  
  * @author tierney.matt
 35  
  * @author dmitry.buzdin
 36  
  */
 37  
 public class FieldPropertyDescriptor extends AbstractPropertyDescriptor implements DozerPropertyDescriptor {
 38  
 
 39  
   private final DozerPropertyDescriptor[] descriptorChain;
 40  
 
 41  
   public FieldPropertyDescriptor(Class<?> clazz, String fieldName, boolean isIndexed, int index,
 42  
                                  HintContainer srcDeepIndexHintContainer, HintContainer destDeepIndexHintContainer) {
 43  344
     super(clazz, fieldName, isIndexed, index, srcDeepIndexHintContainer, destDeepIndexHintContainer);
 44  
 
 45  344
     String[] tokens = fieldName.split(DozerConstants.DEEP_FIELD_DELIMITER_REGEXP);
 46  344
     descriptorChain = new DozerPropertyDescriptor[tokens.length];
 47  
 
 48  344
     Class<?> currentType = clazz;
 49  710
     for (int i = 0, tokensLength = tokens.length; i < tokensLength; i++) {
 50  367
       String token = tokens[i];
 51  367
       descriptorChain[i] = new ChainedPropertyDescriptor(currentType, token, isIndexed, index);
 52  366
       if (i < tokensLength) {
 53  366
         Field field = ReflectionUtils.getFieldFromBean(currentType, tokens[i]);
 54  366
         currentType = field.getType();
 55  
       }
 56  
     }
 57  343
   }
 58  
 
 59  
   public Class<?> getPropertyType() {
 60  496
     return descriptorChain[descriptorChain.length - 1].getPropertyType();
 61  
   }
 62  
 
 63  
   public Class<?> genericType() {
 64  4
     return descriptorChain[descriptorChain.length - 1].genericType();
 65  
   }
 66  
 
 67  
   public Object getPropertyValue(Object bean) {
 68  136
     Object intermediateResult = bean;
 69  190
     for (DozerPropertyDescriptor descriptor : descriptorChain) {
 70  138
       intermediateResult = descriptor.getPropertyValue(intermediateResult);
 71  138
       if (intermediateResult == null) {
 72  84
         return null;
 73  
       }
 74  
     }
 75  52
     return intermediateResult;
 76  
   }
 77  
 
 78  
   public void setPropertyValue(Object bean, Object value, FieldMap fieldMap) {
 79  137
     Object intermediateResult = bean;
 80  286
     for (int i = 0; i < descriptorChain.length; i++) {
 81  149
       DozerPropertyDescriptor descriptor = descriptorChain[i];
 82  149
       if (i != descriptorChain.length - 1) {
 83  12
         Object currentValue = descriptor.getPropertyValue(intermediateResult);
 84  12
         if (currentValue == null) {
 85  4
           currentValue = DestBeanCreator.create(descriptor.getPropertyType());
 86  4
           descriptor.setPropertyValue(intermediateResult, currentValue, fieldMap);          
 87  
         }
 88  12
         intermediateResult = currentValue;
 89  12
       } else { // last one
 90  137
         descriptor.setPropertyValue(intermediateResult, value, fieldMap);
 91  
       }
 92  
     }
 93  137
   }
 94  
 
 95  
   static class ChainedPropertyDescriptor implements DozerPropertyDescriptor {
 96  
 
 97  
     private Field field;
 98  
     private boolean indexed;
 99  
     private int index;
 100  
 
 101  367
     ChainedPropertyDescriptor(Class<?> clazz, String fieldName, boolean indexed, int index) {
 102  367
       this.indexed = indexed;
 103  367
       this.index = index;
 104  367
       field = ReflectionUtils.getFieldFromBean(clazz, fieldName);
 105  366
     }
 106  
 
 107  
     public Class<?> getPropertyType() {
 108  575
       return field.getType();
 109  
     }
 110  
 
 111  
     public Object getPropertyValue(Object bean) {
 112  291
       Object result = null;
 113  
       try {
 114  291
         result = field.get(bean);
 115  0
       } catch (IllegalArgumentException e) {
 116  0
         MappingUtils.throwMappingException(e);
 117  0
       } catch (IllegalAccessException e) {
 118  0
         MappingUtils.throwMappingException(e);
 119  291
       }
 120  291
       if (indexed) {
 121  20
         result = MappingUtils.getIndexedValue(result, index);
 122  
       }
 123  
 
 124  291
       return result;
 125  
     }
 126  
 
 127  
     public void setPropertyValue(Object bean, Object value, FieldMap fieldMap) {
 128  141
       if (value == null && getPropertyType().isPrimitive()) {
 129  0
         return; // do nothing
 130  
       }
 131  
 
 132  
       // Check if dest value is already set and is equal to src value. If true, no need to rewrite the dest value
 133  141
       if (getPropertyValue(bean) == value) {
 134  68
         return;
 135  
       }
 136  
 
 137  
       try {
 138  73
         if (indexed) {
 139  5
           Object existingValue = field.get(bean);
 140  5
           Object collection = MappingUtils.prepareIndexedCollection(getPropertyType(), existingValue, value, index);
 141  5
           field.set(bean, collection);
 142  5
         } else {
 143  68
           field.set(bean, value);
 144  
         }
 145  0
       } catch (IllegalAccessException e) {
 146  0
         MappingUtils.throwMappingException(e);
 147  73
       }
 148  73
     }
 149  
 
 150  
     public Class<?> genericType() {
 151  4
       Type type = field.getGenericType();
 152  4
       return ReflectionUtils.determineGenericsType(type);
 153  
     }
 154  
   }
 155  
 
 156  
 }