/* * Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com * The software in this package is published under the terms of the CPAL v1.0 * license, a copy of which has been included with this distribution in the * LICENSE.txt file. */ package org.mule.runtime.config.spring.parsers.generic; import org.mule.runtime.config.spring.parsers.assembly.BeanAssembler; import org.mule.runtime.config.spring.parsers.assembly.BeanAssemblerFactory; import org.mule.runtime.config.spring.parsers.assembly.DefaultBeanAssembler; import org.mule.runtime.config.spring.parsers.assembly.DefaultBeanAssemblerFactory; import org.mule.runtime.config.spring.parsers.assembly.configuration.PropertyConfiguration; import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.PropertyValue; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.ManagedList; import org.w3c.dom.Element; import java.util.List; /** * A child definition parser that wraps the child object */ public class WrappingChildDefinitionParser extends ChildDefinitionParser { private final Class wrapperClass; private final String propertyNameInWrapper; private final String unwrappedPropertyName; private final WrappingController wrappingController; public WrappingChildDefinitionParser(String setterMethod, Class clazz, Class constraint, boolean allowClassAttribute, Class wrapperClass, String propertyNameInWrapper, String unwrappedPropertyName, WrappingController wrappingController) { super(setterMethod, clazz, constraint, allowClassAttribute); this.wrapperClass = wrapperClass; this.propertyNameInWrapper = propertyNameInWrapper; this.unwrappedPropertyName = unwrappedPropertyName; this.wrappingController = wrappingController; } @Override public String getPropertyName(Element e) { if (!wrappingController.shouldWrap(e)) { return unwrappedPropertyName; } else { return super.getPropertyName(e); } } @Override protected void preProcess(Element element) { super.preProcess(element); if (wrappingController.shouldWrap(element)) { setBeanAssemblerFactory(new MessageProcessorWrappingBeanAssemblerFactory(wrapperClass, propertyNameInWrapper)); } else { setBeanAssemblerFactory(new DefaultBeanAssemblerFactory()); } } /** * Determines whether to wrap the child based on the where it appears in the DOM. */ public interface WrappingController { boolean shouldWrap(Element elm); } private static class MessageProcessorWrappingBeanAssemblerFactory implements BeanAssemblerFactory { private final Class wrapperClass; private final String propertyNameInWrapper; public MessageProcessorWrappingBeanAssemblerFactory(Class wrapperClass, String propertyNameInWrapper) { this.wrapperClass = wrapperClass; this.propertyNameInWrapper = propertyNameInWrapper; } public BeanAssembler newBeanAssembler(PropertyConfiguration beanConfig, BeanDefinitionBuilder bean, PropertyConfiguration targetConfig, BeanDefinition target) { return new MessageProcessorWrappingBeanAssembler(beanConfig, bean, targetConfig, target, wrapperClass, propertyNameInWrapper); } } private static class MessageProcessorWrappingBeanAssembler extends DefaultBeanAssembler { private final Class wrapperClass; private final String propertyNameInWrapper; public MessageProcessorWrappingBeanAssembler(PropertyConfiguration beanConfig, BeanDefinitionBuilder bean, PropertyConfiguration targetConfig, BeanDefinition target, Class wrapperClass, String propertyNameInWrapper) { super(beanConfig, bean, targetConfig, target); this.wrapperClass = wrapperClass; this.propertyNameInWrapper = propertyNameInWrapper; } public void insertBeanInTarget(String oldName) { if (target == null) { // TODO MULE-9638 - This is possible when the parent node is parsed by the new mechanism return; } String newName = bestGuessName(targetConfig, oldName, target.getBeanClassName()); MutablePropertyValues targetProperties = target.getPropertyValues(); PropertyValue pv = targetProperties.getPropertyValue(newName); Object oldValue = null == pv ? null : pv.getValue(); BeanDefinitionBuilder wrapper = BeanDefinitionBuilder.genericBeanDefinition(wrapperClass); wrapper.addPropertyValue(propertyNameInWrapper, bean.getBeanDefinition()); if (oldValue == null) { oldValue = new ManagedList(); pv = new PropertyValue(newName, oldValue); targetProperties.addPropertyValue(pv); } if (targetConfig.isCollection(oldName)) { List list = retrieveList(oldValue); list.add(wrapper.getBeanDefinition()); } else { targetProperties.addPropertyValue(newName, wrapper.getBeanDefinition()); } } } }