/* vim: set ts=2 et sw=2 cindent fo=qroca: */ package com.globant.katari.core.web; import java.util.List; import org.apache.commons.lang.Validate; import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.PropertyValue; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; /** Bean post processor that adds additional elements to a target list. * * It is used to compose a list (for example, the list of persistent classes) * with fragments provided by different modules. It is implemented as a bean * factory post processor to make sure that the list is fully created before * any other bean. The target list must be a {@link ListFactoryBean} usually * defined as <util:list> bean on the spring application context. * Multiple ListFactoryAppender instances can target the same list. There is no * guarantee on the order in which fragments are added to the target list.<br> * Sample use: <pre> <bean * class='com.globant.katari.core.web.ListFactoryAppender'> * <constructor-arg value='targetList'/> <constructor-arg> * <list> .... </list> </constructor-arg> </bean> * </pre> @author gerardo.bercovich */ public class ListFactoryAppender implements BeanFactoryPostProcessor { /** The id of the target list to add the elements, it is never null. */ private String targetList; /** The list of elements to add to the target list, it is never null. */ private List<?> elements; /** Indicates if the targetList must exist or not. * * If this parameter is false and the target list does not exist, we throw an * exception. otherwise, it is ignored. This is used to optionally modify an * existing list. The default is false. */ private boolean isOptional = false; /** ListFactoryAppender constructor. * * @param theTargetList the bean name of the target list to add the elements, * it cannot be null. * * @param theElements the list of elements to add to the target list, it * cannot be null. */ public ListFactoryAppender(final String theTargetList, final List<?> theElements) { Validate.notNull(theElements, "the elements cannnot be null."); Validate.notNull(theTargetList, "the target list cannnot be null."); targetList = theTargetList; elements = theElements; } /** ListFactoryAppender constructor. * * @param theTargetList the bean name of the target list to add the elements, * it cannot be null. * * @param optional indicates if the target list must exist. If true, nothing * happens if the target list does not exist. If false, * postProcessBeanFactory throws an exception if the target list does not * exist. * * @param theElements the list of elements to add to the target list, it * cannot be null. */ public ListFactoryAppender(final String theTargetList, final boolean optional, final List<?> theElements) { Validate.notNull(theElements, "the elements cannnot be null."); Validate.notNull(theTargetList, "the target list cannnot be null."); targetList = theTargetList; isOptional = optional; elements = theElements; } /** Adds the elements to the target list definition. * {@inheritDoc} */ @SuppressWarnings("unchecked") public void postProcessBeanFactory( final ConfigurableListableBeanFactory beanFactory) { if (isOptional && !beanFactory.containsBeanDefinition(targetList)) { // We ignore the case that the target list does not exist. return; } BeanDefinition tagetBeanDefinition; tagetBeanDefinition = beanFactory.getBeanDefinition(targetList); MutablePropertyValues propertyValues; propertyValues = tagetBeanDefinition.getPropertyValues(); PropertyValue propertyValue; propertyValue = propertyValues.getPropertyValue("sourceList"); // Warning: we are not explicitly checking that the target list is // effectively a ListFactoryBean, only that it has a sourceList // property. Validate.notNull(propertyValue, "The target list is not a " + "ListFactoryBean definition."); List targetListDefinition = (List) propertyValue.getValue(); targetListDefinition.addAll(elements); } }