org.jdto.spring.BeanWrapperBeanModifier.java Source code

Java tutorial

Introduction

Here is the source code for org.jdto.spring.BeanWrapperBeanModifier.java

Source

/*
 *    Copyright 2012 Juan Alberto Lpez Cavallotti
 *
 * 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.jdto.spring;

import org.apache.commons.lang.StringUtils;
import org.jdto.impl.BaseBeanModifier;
import org.jdto.impl.BeanClassUtils;
import org.jdto.impl.ValueConversionHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.PropertyAccessorFactory;

/**
 * Reads and write property values using the Spring framework {@link BeanWrapper}. <br />
 * When trying to write, this bean will try if possible to make up for missing
 * instances on the association path.
 * @author Juan Alberto Lopez Cavallotti
 */
public class BeanWrapperBeanModifier extends BaseBeanModifier {
    private static final long serialVersionUID = 1L;

    private static Logger logger = LoggerFactory.getLogger(BeanWrapperBeanModifier.class);

    /**
     * Read a property value using the property path by invoking a spring {@link BeanWrapper}
     * @param propertyPath
     * @param instance
     * @return the property value found on the property path applied to the provided instance.
     */
    @Override
    public Object doReadPropertyValue(String propertyPath, Object instance) {
        BeanWrapper beanWrapper = PropertyAccessorFactory.forBeanPropertyAccess(instance);

        //check if it's safe to write the property.
        if (!beanWrapper.isReadableProperty(propertyPath)) {
            return null;
        }

        return beanWrapper.getPropertyValue(propertyPath);
    }

    /**
     * Set a property using the property path invoking a spring framework {@link BeanWrapper}.
     * @param propertyPath
     * @param value
     * @param instance 
     */
    @Override
    public void doWritePropertyValue(String propertyPath, Object value, Object instance) {
        BeanWrapper beanWrapper = PropertyAccessorFactory.forBeanPropertyAccess(instance);

        //check and make up for missing association parts.
        StringBuilder builder = new StringBuilder();

        String[] subProps = StringUtils.split(propertyPath, '.');

        //go through all the parts but one
        for (int i = 0; i < subProps.length - 1; i++) {
            String prop = subProps[i];

            if (i > 0) {
                builder.append(".");
            }

            builder.append(prop);

            Object partialValue = beanWrapper.getPropertyValue(builder.toString());
            if (partialValue == null) {
                //make up for it
                Class propCls = beanWrapper.getPropertyType(builder.toString());
                Object madeUpValue = BeanClassUtils.createInstance(propCls);
                if (madeUpValue != null) {
                    if (beanWrapper.isWritableProperty(builder.toString())) {
                        beanWrapper.setPropertyValue(builder.toString(), madeUpValue);
                    }
                }
            }
        }

        if (!beanWrapper.isWritableProperty(propertyPath)) {
            logger.info("Cannot write property path " + propertyPath + " of bean", instance);
            return;
        }

        //this can be improved by registering property editors on the bean wrapper
        //at moment this approach is not so simple as the current functionality.
        //nevertheless on the future this situation may change.
        Class expectedType = beanWrapper.getPropertyType(propertyPath);
        value = ValueConversionHelper.applyCompatibilityLogic(expectedType, value);

        beanWrapper.setPropertyValue(propertyPath, value);
    }

}