All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.dozer.propertydescriptor.FieldPropertyDescriptor Maven / Gradle / Ivy

Go to download

Dozer is a powerful Java Bean to Java Bean mapper that recursively copies data from one object to another

There is a newer version: 5.5.1
Show newest version
/*
 * Copyright 2005-2010 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.dozer.propertydescriptor;

import org.dozer.factory.DestBeanCreator;
import org.dozer.fieldmap.FieldMap;
import org.dozer.fieldmap.HintContainer;
import org.dozer.util.DozerConstants;
import org.dozer.util.MappingUtils;
import org.dozer.util.ReflectionUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Type;


/**
 * Internal class that directly accesses the field via reflection. The getter/setter methods for the field are bypassed
 * and will NOT be invoked. Private fields are accessible by Dozer. Only intended for internal use.
 *
 * @author garsombke.franz
 * @author tierney.matt
 * @author dmitry.buzdin
 */
public class FieldPropertyDescriptor extends AbstractPropertyDescriptor implements DozerPropertyDescriptor {

  private final DozerPropertyDescriptor[] descriptorChain;

  public FieldPropertyDescriptor(Class clazz, String fieldName, boolean isIndexed, int index,
                                 HintContainer srcDeepIndexHintContainer, HintContainer destDeepIndexHintContainer) {
    super(clazz, fieldName, isIndexed, index, srcDeepIndexHintContainer, destDeepIndexHintContainer);

    String[] tokens = fieldName.split(DozerConstants.DEEP_FIELD_DELIMITER_REGEXP);
    descriptorChain = new DozerPropertyDescriptor[tokens.length];

    Class currentType = clazz;
    for (int i = 0, tokensLength = tokens.length; i < tokensLength; i++) {
      String token = tokens[i];
      descriptorChain[i] = new ChainedPropertyDescriptor(currentType, token, isIndexed, index);
      if (i < tokensLength) {
        Field field = ReflectionUtils.getFieldFromBean(currentType, tokens[i]);
        currentType = field.getType();
      }
    }
  }

  public Class getPropertyType() {
    return descriptorChain[descriptorChain.length - 1].getPropertyType();
  }

  public Class genericType() {
    return descriptorChain[descriptorChain.length - 1].genericType();
  }

  public Object getPropertyValue(Object bean) {
    Object intermediateResult = bean;
    for (DozerPropertyDescriptor descriptor : descriptorChain) {
      intermediateResult = descriptor.getPropertyValue(intermediateResult);
      if (intermediateResult == null) {
        return null;
      }
    }
    return intermediateResult;
  }

  public void setPropertyValue(Object bean, Object value, FieldMap fieldMap) {
    Object intermediateResult = bean;
    for (int i = 0; i < descriptorChain.length; i++) {
      DozerPropertyDescriptor descriptor = descriptorChain[i];
      if (i != descriptorChain.length - 1) {
        Object currentValue = descriptor.getPropertyValue(intermediateResult);
        if (currentValue == null) {
          currentValue = DestBeanCreator.create(descriptor.getPropertyType());
          descriptor.setPropertyValue(intermediateResult, currentValue, fieldMap);          
        }
        intermediateResult = currentValue;
      } else { // last one
        descriptor.setPropertyValue(intermediateResult, value, fieldMap);
      }
    }
  }

  static class ChainedPropertyDescriptor implements DozerPropertyDescriptor {

    private Field field;
    private boolean indexed;
    private int index;

    ChainedPropertyDescriptor(Class clazz, String fieldName, boolean indexed, int index) {
      this.indexed = indexed;
      this.index = index;
      field = ReflectionUtils.getFieldFromBean(clazz, fieldName);
    }

    public Class getPropertyType() {
      return field.getType();
    }

    public Object getPropertyValue(Object bean) {
      Object result = null;
      try {
        result = field.get(bean);
      } catch (IllegalArgumentException e) {
        MappingUtils.throwMappingException(e);
      } catch (IllegalAccessException e) {
        MappingUtils.throwMappingException(e);
      }
      if (indexed) {
        result = MappingUtils.getIndexedValue(result, index);
      }

      return result;
    }

    public void setPropertyValue(Object bean, Object value, FieldMap fieldMap) {
      if (value == null && getPropertyType().isPrimitive()) {
        return; // do nothing
      }

      // Check if dest value is already set and is equal to src value. If true, no need to rewrite the dest value
      if (getPropertyValue(bean) == value) {
        return;
      }

      try {
        if (indexed) {
          Object existingValue = field.get(bean);
          Object collection = MappingUtils.prepareIndexedCollection(getPropertyType(), existingValue, value, index);
          field.set(bean, collection);
        } else {
          field.set(bean, value);
        }
      } catch (IllegalAccessException e) {
        MappingUtils.throwMappingException(e);
      }
    }

    public Class genericType() {
      Type type = field.getGenericType();
      return ReflectionUtils.determineGenericsType(type);
    }
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy