001/**
002 * Copyright 2005-2018 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.rice.krad.web.bind;
017
018import org.springframework.beans.*;
019
020/**
021 * Bean wrapper that will auto grow paths for setting the value but not grow paths for getting
022 * a value.
023 *
024 * @author Kuali Rice Team (rice.collab@kuali.org)
025 */
026public class UifBeanWrapper extends BeanWrapperImpl {
027
028    private BeanWrapperImpl rootBeanWrapper;
029
030    public UifBeanWrapper(Object object) {
031        super(object);
032    }
033
034    public UifBeanWrapper(Object object, String nestedPath, UifBeanWrapper superBw) {
035        super(object, nestedPath, superBw);
036
037        setRootBeanWrapper(superBw.getRootBeanWrapper());
038    }
039
040    /**
041     * Overridden to set auto grow nested paths to false for getting the value.
042     *
043     * {@inheritDoc}
044     */
045    @Override
046    public Object getPropertyValue(String propertyName) throws BeansException {
047        return getPropertyValue(propertyName, false);
048    }
049
050    /**
051     * Returns the value for the given property growing nested paths depending on the parameter.
052     *
053     * @param propertyName name of the property to get value for
054     * @param autoGrowNestedPaths whether nested paths should be grown (initialized if null)
055     * @return value for property
056     */
057    protected Object getPropertyValue(String propertyName, boolean autoGrowNestedPaths) {
058        setAutoGrowNestedPaths(autoGrowNestedPaths);
059
060        Object value = null;
061        try {
062            value = super.getPropertyValue(propertyName);
063        } catch (NullValueInNestedPathException e) {
064            // swallow null values in path and return null as the value
065        } catch (InvalidPropertyException e1) {
066            if (!(e1.getRootCause() instanceof NullValueInNestedPathException)) {
067                throw e1;
068            }
069        }
070
071        return value;
072    }
073
074    /**
075     * Override to set auto grow to true for setting property values.
076     *
077     * {@inheritDoc}
078     */
079    @Override
080    public void setPropertyValue(PropertyValue pv) throws BeansException {
081        setAutoGrowNestedPaths(true);
082
083        super.setPropertyValue(pv);
084    }
085
086    /**
087     * Override to set auto grow to true for setting property values.
088     *
089     * {@inheritDoc}
090     */
091    @Override
092    public void setPropertyValue(String propertyName, Object value) throws BeansException {
093        setAutoGrowNestedPaths(true);
094
095        super.setPropertyValue(propertyName, value);
096    }
097
098    /**
099     * Override to instantiate a UIF bean wrapper for nested bean wrappers.
100     *
101     * {@inheritDoc}
102     */
103    @Override
104    protected BeanWrapperImpl newNestedPropertyAccessor(Object object, String nestedPath) {
105        return new UifBeanWrapper(object, nestedPath, this);
106    }
107
108    /**
109     * Override to set auto grown on the nested bean wrapper to the setting of the root bean wrapper.
110     *
111     * <p>This is necessary because the nested bean wrapper could have been cached, and its auto-grow
112     * setting reflect an earler get or set call</p>
113     *
114     * {@inheritDoc}
115     */
116    @Override
117    protected AbstractNestablePropertyAccessor getPropertyAccessorForPropertyPath(String propertyPath) {
118        if (this.rootBeanWrapper != null) {
119            setAutoGrowNestedPaths(this.rootBeanWrapper.isAutoGrowNestedPaths());
120        }
121
122        return super.getPropertyAccessorForPropertyPath(propertyPath);
123    }
124
125
126
127    /**
128     * Bean wrapper for the root data object, used for setting auto grows on nested bean wrappers.
129     *
130     * @return bean wrapper impl for root data object
131     */
132    public BeanWrapperImpl getRootBeanWrapper() {
133        if (rootBeanWrapper == null) {
134            return this;
135        }
136
137        return rootBeanWrapper;
138    }
139
140    /**
141     * @see UifBeanWrapper#getRootBeanWrapper()
142     */
143    public void setRootBeanWrapper(BeanWrapperImpl rootBeanWrapper) {
144        this.rootBeanWrapper = rootBeanWrapper;
145    }
146}