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.datadictionary;
017
018import org.apache.commons.lang.StringUtils;
019import org.kuali.rice.krad.service.DataDictionaryService;
020import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
021import org.springframework.beans.MutablePropertyValues;
022import org.springframework.beans.PropertyValue;
023import org.springframework.beans.factory.config.BeanDefinition;
024import org.springframework.beans.factory.config.BeanDefinitionHolder;
025import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
026import org.springframework.beans.factory.config.TypedStringValue;
027
028/**
029 * Base class for dictionary bean processors that provides utility methods
030 *
031 * @author Kuali Rice Team (rice.collab@kuali.org)
032 */
033public abstract class DictionaryBeanProcessorBase implements DictionaryBeanProcessor {
034
035    /**
036     * Retrieves the class for the object that will be created from the bean definition. Since the class might not
037     * be configured on the bean definition, but by a parent, each parent bean definition is recursively checked for
038     * a class until one is found
039     *
040     * @param beanDefinition bean definition to get class for
041     * @param beanFactory bean factory that contains the bean definition
042     * @return Class<?> class configured for the bean definition, or null
043     */
044    protected Class<?> getBeanClass(BeanDefinition beanDefinition, ConfigurableListableBeanFactory beanFactory) {
045        if (StringUtils.isNotBlank(beanDefinition.getBeanClassName())) {
046            try {
047                return Class.forName(beanDefinition.getBeanClassName());
048            } catch (ClassNotFoundException e) {
049                // swallow exception and return null so bean is not processed
050                return null;
051            }
052        } else if (StringUtils.isNotBlank(beanDefinition.getParentName())) {
053            BeanDefinition parentBeanDefinition = beanFactory.getBeanDefinition(beanDefinition.getParentName());
054            if (parentBeanDefinition != null) {
055                return getBeanClass(parentBeanDefinition, beanFactory);
056            }
057        }
058
059        return null;
060    }
061
062    /**
063     * Determines whether the given value is of String type and if so returns the string value
064     *
065     * @param value object value to check
066     * @return String string value for object or null if object is not a string type
067     */
068    protected String getStringValue(Object value) {
069        if (value instanceof TypedStringValue) {
070            TypedStringValue typedStringValue = (TypedStringValue) value;
071            return typedStringValue.getValue();
072        } else if (value instanceof String) {
073            return (String) value;
074        }
075
076        return null;
077    }
078
079    /**
080     * Applies the given property name and value to the bean definition
081     *
082     * @param propertyPath name of the property to add value for
083     * @param propertyValue value for the property
084     * @param beanDefinition bean definition to add property value to
085     */
086    protected void applyPropertyValueToBean(String propertyPath, String propertyValue, BeanDefinition beanDefinition) {
087        applyPropertyValueToBean(propertyPath, propertyValue, beanDefinition.getPropertyValues());
088    }
089
090    /**
091     * Applies the given property name and value to given property values
092     *
093     * @param propertyPath name of the property to add value for
094     * @param propertyValue value for the property
095     * @param pvs property values to add property to
096     */
097    protected void applyPropertyValueToBean(String propertyPath, String propertyValue, MutablePropertyValues pvs) {
098        pvs.addPropertyValue(propertyPath, propertyValue);
099    }
100
101    /**
102     * Determines if the given property value is a bean definition or bean definition holder and if
103     * so returns the value as a bean definintion
104     *
105     * @param propertyValue property value to get bean definition from
106     * @return property value as a bean definition or null if value does not contain a bean definition
107     */
108    protected BeanDefinition getPropertyValueBeanDefinition(PropertyValue propertyValue) {
109        BeanDefinition beanDefinition = null;
110
111        Object value = propertyValue.getValue();
112        if ((value instanceof BeanDefinition) || (value instanceof BeanDefinitionHolder)) {
113            if (propertyValue instanceof BeanDefinition) {
114                beanDefinition = (BeanDefinition) propertyValue;
115            } else {
116                beanDefinition = ((BeanDefinitionHolder) value).getBeanDefinition();
117            }
118        }
119
120        return beanDefinition;
121    }
122
123    /**
124     * Indicates whether the given bean name was generated by spring
125     *
126     * @param beanName bean name to check
127     * @return boolean true if bean name is generated, false if not
128     */
129    protected boolean isGeneratedBeanName(String beanName) {
130        return StringUtils.isNotBlank(beanName) && (StringUtils.contains(beanName, "$") || StringUtils.contains(
131                beanName, "#"));
132    }
133
134    /**
135     * Returns an instance of the data dictionary service
136     *
137     * @return DataDictionaryService instance
138     */
139    protected DataDictionaryService getDataDictionaryService() {
140        return KRADServiceLocatorWeb.getDataDictionaryService();
141    }
142}