View Javadoc
1   /*
2    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
3    * The software in this package is published under the terms of the CPAL v1.0
4    * license, a copy of which has been included with this distribution in the
5    * LICENSE.txt file.
6    */
7   package org.mule.config.spring.parsers.generic;
8   
9   import org.mule.config.spring.parsers.assembly.BeanAssembler;
10  import org.mule.config.spring.parsers.assembly.BeanAssemblerFactory;
11  import org.mule.config.spring.parsers.assembly.DefaultBeanAssembler;
12  import org.mule.config.spring.parsers.assembly.DefaultBeanAssemblerFactory;
13  import org.mule.config.spring.parsers.assembly.configuration.PropertyConfiguration;
14  import org.springframework.beans.MutablePropertyValues;
15  import org.springframework.beans.PropertyValue;
16  import org.springframework.beans.factory.config.BeanDefinition;
17  import org.springframework.beans.factory.support.BeanDefinitionBuilder;
18  import org.springframework.beans.factory.support.ManagedList;
19  import org.w3c.dom.Element;
20  
21  import java.util.List;
22  
23  /**
24   * A child definition parser that wraps the child object
25   */
26  public class WrappingChildDefinitionParser extends ChildDefinitionParser
27  {
28      private final Class wrapperClass;
29      private final String propertyNameInWrapper;
30      private final String unwrappedPropertyName;
31      private final WrappingController wrappingController;
32  
33      public WrappingChildDefinitionParser(String setterMethod,
34                                           Class clazz,
35                                           Class constraint,
36                                           boolean allowClassAttribute,
37                                           Class wrapperClass,
38                                           String propertyNameInWrapper,
39                                           String unwrappedPropertyName,
40                                           WrappingController wrappingController)
41      {
42          super(setterMethod, clazz, constraint, allowClassAttribute);
43          this.wrapperClass = wrapperClass;
44          this.propertyNameInWrapper = propertyNameInWrapper;
45          this.unwrappedPropertyName = unwrappedPropertyName;
46          this.wrappingController = wrappingController;
47      }
48  
49      @Override
50      public String getPropertyName(Element
51          e)
52      {
53          if (!wrappingController.shouldWrap(e))
54          {
55              return unwrappedPropertyName;
56          }
57          else
58          {
59              return super.getPropertyName(e);
60          }
61      }
62  
63      @Override
64      protected void preProcess(Element
65          element)
66      {
67          super.preProcess(element);
68          if (wrappingController.shouldWrap(element))
69          {
70              setBeanAssemblerFactory(new MessageProcessorWrappingBeanAssemblerFactory(wrapperClass, propertyNameInWrapper));
71          }
72          else
73          {
74              setBeanAssemblerFactory(new DefaultBeanAssemblerFactory());
75          }
76      }
77  
78      /**
79       * Determines whether to wrap the child based on the where it appears in the DOM.
80       */
81      public interface WrappingController
82      {
83          boolean shouldWrap(Element elm);
84      }
85  
86      private static class MessageProcessorWrappingBeanAssemblerFactory implements BeanAssemblerFactory
87      {
88          private final Class wrapperClass;
89          private final String propertyNameInWrapper;
90  
91          public MessageProcessorWrappingBeanAssemblerFactory(Class wrapperClass, String propertyNameInWrapper)
92          {
93              this.wrapperClass = wrapperClass;
94              this.propertyNameInWrapper = propertyNameInWrapper;
95          }
96  
97          public BeanAssembler newBeanAssembler(PropertyConfiguration beanConfig,
98                                                BeanDefinitionBuilder bean,
99                                                PropertyConfiguration targetConfig,
100                                               BeanDefinition target)
101         {
102             return new MessageProcessorWrappingBeanAssembler(beanConfig, bean, targetConfig, target, wrapperClass, propertyNameInWrapper);
103         }
104     }
105 
106     private static class MessageProcessorWrappingBeanAssembler extends DefaultBeanAssembler
107     {
108         private final Class wrapperClass;
109         private final String propertyNameInWrapper;
110 
111         public MessageProcessorWrappingBeanAssembler(PropertyConfiguration beanConfig,
112                                                      BeanDefinitionBuilder bean,
113                                                      PropertyConfiguration targetConfig,
114                                                      BeanDefinition target,
115                                                      Class wrapperClass,
116                                                      String propertyNameInWrapper)
117         {
118             super(beanConfig, bean, targetConfig, target);
119             this.wrapperClass = wrapperClass;
120             this.propertyNameInWrapper = propertyNameInWrapper;
121         }
122 
123         public void insertBeanInTarget(String oldName)
124         {
125             assertTargetPresent();
126             String newName = bestGuessName(targetConfig, oldName, target.getBeanClassName());
127             MutablePropertyValues targetProperties = target.getPropertyValues();
128             PropertyValue pv = targetProperties.getPropertyValue(newName);
129             Object oldValue = null == pv ? null : pv.getValue();
130 
131             BeanDefinitionBuilder wrapper = BeanDefinitionBuilder.genericBeanDefinition(wrapperClass);
132             wrapper.addPropertyValue(propertyNameInWrapper, bean.getBeanDefinition());
133 
134             if (oldValue == null)
135             {
136                 oldValue = new ManagedList();
137                 pv = new PropertyValue(newName, oldValue);
138                 targetProperties.addPropertyValue(pv);
139             }
140             if (targetConfig.isCollection(oldName))
141             {
142                 List list = retrieveList(oldValue);
143                 list.add(wrapper.getBeanDefinition());
144             }
145             else
146             {
147                 targetProperties.addPropertyValue(newName, wrapper.getBeanDefinition());
148             }
149         }
150     }
151 }