View Javadoc

1   /*
2    ORG Usurper is a random value object generator library 
3    Copyright (C) 2007  Pierre-Antoine Grégoire
4    
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9    
10   This library is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   Lesser General Public License for more details.
14   
15   You should have received a copy of the GNU Lesser General Public
16   License along with this library; if not, write to the Free Software
17   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18   */
19  package org.org.usurper.springframework.namespace;
20  
21  import java.util.ArrayList;
22  import java.util.List;
23  
24  import org.org.usurper.springframework.UsurperFactoryBean;
25  import org.org.usurper.springframework.UsurperGeneratorSetupFactoryBean;
26  import org.org.usurper.springframework.UsurperListFactoryBean;
27  import org.org.usurper.springframework.UsurperMapFactoryBean;
28  import org.org.usurper.springframework.UsurperSetFactoryBean;
29  import org.org.usurper.springframework.aop.UsurperMethodInterceptor;
30  import org.springframework.aop.framework.ProxyFactoryBean;
31  import org.springframework.beans.factory.BeanDefinitionStoreException;
32  import org.springframework.beans.factory.config.BeanDefinitionHolder;
33  import org.springframework.beans.factory.config.RuntimeBeanReference;
34  import org.springframework.beans.factory.parsing.BeanComponentDefinition;
35  import org.springframework.beans.factory.support.AbstractBeanDefinition;
36  import org.springframework.beans.factory.support.BeanDefinitionBuilder;
37  import org.springframework.beans.factory.support.ManagedMap;
38  import org.springframework.beans.factory.support.ManagedSet;
39  import org.springframework.beans.factory.support.RootBeanDefinition;
40  import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
41  import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
42  import org.springframework.beans.factory.xml.BeanDefinitionParser;
43  import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
44  import org.springframework.beans.factory.xml.ParserContext;
45  import org.springframework.core.Conventions;
46  import org.springframework.util.StringUtils;
47  import org.springframework.util.xml.DomUtils;
48  import org.w3c.dom.Element;
49  
50  /**
51   * The Class GeneratorsNamespaceHandler defines the Spring > 2.0 Namespace handler for Usurper.
52   * See schema: {@link http://www.org-libs.org/org-lib-usurper/schema/generators/usurper-1.0.0.xsd}
53   */
54  public class GeneratorsNamespaceHandler extends NamespaceHandlerSupport {
55      private static final String AOP_GENERATOR_TAG = "aop-generator";
56      private static final String MAP_GENERATOR_TAG = "map-generator";
57      private static final String SET_GENERATOR_TAG = "set-generator";
58      private static final String BEAN_GENERATOR_TAG = "bean-generator";
59      private static final String LIST_GENERATOR_TAG = "list-generator";
60      private static final String SETUP_TAG = "setup";
61      private static final String PROPERTY_TYPE_HANDLER_TAG = "property-type-handler";
62      private static final String PROPERTY_TYPE_HANDLER_REF_TAG = "property-type-handler-ref";
63      private static final String SPECIFIC_PROPERTY_HANDLER_TAG = "specific-property-handler";
64      private static final String SPECIFIC_PROPERTY_HANDLER_REF_TAG = "specific-property-handler-ref";
65  
66      private static final String INTERFACE_ATTR = "interface";
67      private static final String CLASS_ATTR = "class";
68      private static final String VALUE_CLASS_ATTR = "value-class";
69      private static final String KEY_CLASS_ATTR = "key-class";
70      private static final String SETUP_REF_ATTR = "setup-ref";
71      private static final String COUNT_ATTR = "count";
72  
73      private static final String SETUP_PARENT_SETUP = "parent-setup";
74  
75      private static final String SETUP_ARRAY_HANDLER_ATTR = "array-handler";
76      private static final String SETUP_ARRAY_HANDLER_REF_ATTR = "array-handler-ref";
77      private static final String SETUP_ENUM_HANDLER_ATTR = "enum-handler";
78      private static final String SETUP_ENUM_HANDLER_REF_ATTR = "enum-handler-ref";
79  
80      private static final String SETUP_ON_MISSING_HANDLERS_ATTR = "on-missing-handlers";
81      private static final String SETUP_PROPERTY_WRITING_MECHANISM_ATTR = "property-writing-mechanism";
82      private static final String SETUP_COUNT_CALLBACK_ATTR = "count-callback";
83      private static final String SETUP_COUNT_CALLBACK_REF_ATTR = "count-callback-ref";
84  
85      private static final String PROPERTY_TYPE_HANDLER_PROPERTY_TYPE_ATTR = "property-type";
86      private static final String PROPERTY_TYPE_HANDLER_HANDLER_CLASS_ATTR = "handler-class";
87      private static final String PROPERTY_TYPE_HANDLER_HANDLER_REF_ATTR = "handler-ref";
88      private static final String SPECIFIC_PROPERTY_HANDLER_TARGET_CLASS_ATTR = "target-class";
89      private static final String SPECIFIC_PROPERTY_HANDLER_TARGET_PROPERTY_ATTR = "target-property";
90      private static final String SPECIFIC_PROPERTY_HANDLER_HANDLER_CLASS_ATTR = "handler-class";
91      private static final String SPECIFIC_PROPERTY_HANDLER_HANDLER_REF_ATTR = "handler-ref";
92  
93      private static final String USURPER_GENERATOR_SETUP_PROP = "usurperGeneratorSetup";
94      private static final String USURPED_CLASS_NAME_PROP = "usurpedClassName";
95      private static final String USURPED_VALUE_CLASS_NAME_PROP = "usurpedValueClassName";
96      private static final String USURPED_KEY_CLASS_NAME_PROP = "usurpedKeyClassName";
97  
98      private static final String PROXYFACTORYBEAN_INTERCEPTOR_NAMES_PROP = "interceptorNames";
99      private static final String PROXYFACTORYBEAN_PROXY_INTERFACES_PROP = "proxyInterfaces";
100     private static final String USURPER_INTERCEPTOR_BEAN_ID = "usurperInterceptor";
101 
102     public void init() {
103         registerBeanDefinitionParser(BEAN_GENERATOR_TAG, new BeanGeneratorBeanDefinitionParser());
104         registerBeanDefinitionParser(LIST_GENERATOR_TAG, new ListOfBeansGeneratorBeanDefinitionParser());
105         registerBeanDefinitionParser(SET_GENERATOR_TAG, new SetOfBeansGeneratorBeanDefinitionParser());
106         registerBeanDefinitionParser(MAP_GENERATOR_TAG, new MapOfBeansGeneratorBeanDefinitionParser());
107         registerBeanDefinitionParser(AOP_GENERATOR_TAG, new AopGeneratorBeanDefinitionParser());
108         registerBeanDefinitionParser(SETUP_TAG, new SetupBeanDefinitionParser());
109     }
110 
111     private static class AopGeneratorBeanDefinitionParser extends AbstractBeanDefinitionParser implements BeanDefinitionParser {
112 
113         @Override
114         protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
115             String interfaceName = element.getAttribute(INTERFACE_ATTR);
116             String setupRef = element.getAttribute(SETUP_REF_ATTR);
117 
118             // Create the Interceptor definition
119             RootBeanDefinition interceptorDefinition = new RootBeanDefinition(UsurperMethodInterceptor.class);
120             if (StringUtils.hasText(setupRef)) {
121                 interceptorDefinition.getPropertyValues().addPropertyValue(USURPER_GENERATOR_SETUP_PROP, setupRef);
122             }
123             try {
124                 BeanDefinitionHolder holder = new BeanDefinitionHolder(interceptorDefinition, USURPER_INTERCEPTOR_BEAN_ID);
125                 registerBeanDefinition(holder, parserContext.getRegistry());
126                 if (shouldFireEvents()) {
127                     BeanComponentDefinition componentDefinition = new BeanComponentDefinition(holder);
128                     postProcessComponentDefinition(componentDefinition);
129                     parserContext.registerComponent(componentDefinition);
130                 }
131             } catch (BeanDefinitionStoreException ex) {
132                 parserContext.getReaderContext().error(ex.getMessage(), element);
133             }
134             List<String> interceptorNames = new ArrayList<String>();
135             interceptorNames.add(USURPER_INTERCEPTOR_BEAN_ID);
136             // Create the target Class definition.
137             RootBeanDefinition targetDefinition = new RootBeanDefinition(ProxyFactoryBean.class);
138             targetDefinition.setSource(parserContext.extractSource(element));
139             targetDefinition.getPropertyValues().addPropertyValue(PROXYFACTORYBEAN_PROXY_INTERFACES_PROP, interfaceName);
140             targetDefinition.getPropertyValues().addPropertyValue(PROXYFACTORYBEAN_INTERCEPTOR_NAMES_PROP, interceptorNames);
141             return targetDefinition;
142         }
143 
144     }
145 
146     private static class BeanGeneratorBeanDefinitionParser extends AbstractSingleBeanDefinitionParser implements BeanDefinitionParser {
147 
148         @SuppressWarnings("unchecked")
149         @Override
150         protected Class getBeanClass(Element element) {
151             return UsurperFactoryBean.class;
152         }
153 
154         @Override
155         protected void doParse(Element element, BeanDefinitionBuilder bean) {
156             String usurpedClass = element.getAttribute(CLASS_ATTR);
157             bean.addPropertyValue(USURPED_CLASS_NAME_PROP, usurpedClass);
158 
159             String setupRef = element.getAttribute(SETUP_REF_ATTR);
160             if (StringUtils.hasText(setupRef)) {
161                 bean.addPropertyReference(USURPER_GENERATOR_SETUP_PROP, setupRef);
162             }
163 
164         }
165     }
166 
167     private static class ListOfBeansGeneratorBeanDefinitionParser extends AbstractSingleBeanDefinitionParser implements BeanDefinitionParser {
168 
169         @SuppressWarnings("unchecked")
170         @Override
171         protected Class getBeanClass(Element element) {
172             return UsurperListFactoryBean.class;
173         }
174 
175         @Override
176         protected void doParse(Element element, BeanDefinitionBuilder bean) {
177             String usurpedClass = element.getAttribute(CLASS_ATTR);
178             bean.addPropertyValue(USURPED_CLASS_NAME_PROP, usurpedClass);
179 
180             String setupRef = element.getAttribute(SETUP_REF_ATTR);
181             if (StringUtils.hasText(setupRef)) {
182                 bean.addPropertyReference(USURPER_GENERATOR_SETUP_PROP, setupRef);
183             }
184             String count = element.getAttribute(COUNT_ATTR);
185             if (StringUtils.hasText(count)) {
186                 bean.addPropertyValue(COUNT_ATTR, Integer.valueOf(count));
187             }
188 
189         }
190     }
191 
192     private static class MapOfBeansGeneratorBeanDefinitionParser extends AbstractSingleBeanDefinitionParser implements BeanDefinitionParser {
193 
194         @SuppressWarnings("unchecked")
195         @Override
196         protected Class getBeanClass(Element element) {
197             return UsurperMapFactoryBean.class;
198         }
199 
200         @Override
201         protected void doParse(Element element, BeanDefinitionBuilder bean) {
202             String usurpedKeyClass = element.getAttribute(KEY_CLASS_ATTR);
203             bean.addPropertyValue(USURPED_KEY_CLASS_NAME_PROP, usurpedKeyClass);
204 
205             String usurpedValueClass = element.getAttribute(VALUE_CLASS_ATTR);
206             bean.addPropertyValue(USURPED_VALUE_CLASS_NAME_PROP, usurpedValueClass);
207 
208             String setupRef = element.getAttribute(SETUP_REF_ATTR);
209             if (StringUtils.hasText(setupRef)) {
210                 bean.addPropertyReference(USURPER_GENERATOR_SETUP_PROP, setupRef);
211             }
212             String count = element.getAttribute(COUNT_ATTR);
213             if (StringUtils.hasText(count)) {
214                 bean.addPropertyValue(COUNT_ATTR, Integer.valueOf(count));
215             }
216 
217         }
218     }
219 
220     private static class SetOfBeansGeneratorBeanDefinitionParser extends AbstractSingleBeanDefinitionParser implements BeanDefinitionParser {
221         @SuppressWarnings("unchecked")
222         @Override
223         protected Class getBeanClass(Element element) {
224             return UsurperSetFactoryBean.class;
225         }
226 
227         @Override
228         protected void doParse(Element element, BeanDefinitionBuilder bean) {
229             String usurpedClass = element.getAttribute(CLASS_ATTR);
230             bean.addPropertyValue(USURPED_CLASS_NAME_PROP, usurpedClass);
231 
232             String setupRef = element.getAttribute(SETUP_REF_ATTR);
233             if (StringUtils.hasText(setupRef)) {
234                 bean.addPropertyReference(USURPER_GENERATOR_SETUP_PROP, setupRef);
235             }
236             String count = element.getAttribute(COUNT_ATTR);
237             if (StringUtils.hasText(count)) {
238                 bean.addPropertyValue(COUNT_ATTR, Integer.valueOf(count));
239             }
240         }
241     }
242 
243     private static class SetupBeanDefinitionParser extends AbstractSingleBeanDefinitionParser implements BeanDefinitionParser {
244         @SuppressWarnings("unchecked")
245         @Override
246         protected Class getBeanClass(Element element) {
247             return UsurperGeneratorSetupFactoryBean.class;
248         }
249 
250         @SuppressWarnings("unchecked")
251         @Override
252         protected void doParse(Element element, BeanDefinitionBuilder bean) {
253             String parentSetup = element.getAttribute(SETUP_PARENT_SETUP);
254             if (StringUtils.hasText(parentSetup)) {
255                 bean.addPropertyReference(Conventions.attributeNameToPropertyName(SETUP_PARENT_SETUP), parentSetup);
256             }
257 
258             String arrayHandler = element.getAttribute(SETUP_ARRAY_HANDLER_ATTR);
259             String arrayHandlerRef = element.getAttribute(SETUP_ARRAY_HANDLER_REF_ATTR);
260             if (StringUtils.hasText(arrayHandler)) {
261                 bean.addPropertyValue(Conventions.attributeNameToPropertyName(SETUP_ARRAY_HANDLER_ATTR) + "Name", arrayHandler);
262             } else if (StringUtils.hasText(arrayHandlerRef)) {
263                 bean.addPropertyReference(Conventions.attributeNameToPropertyName(SETUP_ARRAY_HANDLER_ATTR), arrayHandlerRef);
264             }
265 
266             String enumHandler = element.getAttribute(SETUP_ENUM_HANDLER_ATTR);
267             String enumHandlerRef = element.getAttribute(SETUP_ENUM_HANDLER_REF_ATTR);
268             if (StringUtils.hasText(enumHandler)) {
269                 bean.addPropertyValue(Conventions.attributeNameToPropertyName(SETUP_ENUM_HANDLER_ATTR + "Name"), enumHandler);
270             } else if (StringUtils.hasText(enumHandlerRef)) {
271                 bean.addPropertyReference(Conventions.attributeNameToPropertyName(SETUP_ENUM_HANDLER_ATTR), enumHandlerRef);
272             }
273 
274             String onMissingHandlers = element.getAttribute(SETUP_ON_MISSING_HANDLERS_ATTR);
275             if (StringUtils.hasText(onMissingHandlers)) {
276                 bean.addPropertyValue(Conventions.attributeNameToPropertyName(SETUP_ON_MISSING_HANDLERS_ATTR), onMissingHandlers.toUpperCase());
277             }
278 
279             String propertyWritingMechanism = element.getAttribute(SETUP_PROPERTY_WRITING_MECHANISM_ATTR);
280             if (StringUtils.hasText(propertyWritingMechanism)) {
281                 bean.addPropertyValue(Conventions.attributeNameToPropertyName(SETUP_PROPERTY_WRITING_MECHANISM_ATTR), propertyWritingMechanism.toUpperCase());
282             }
283             String countCallback = element.getAttribute(SETUP_COUNT_CALLBACK_ATTR);
284             String countCallbackRef = element.getAttribute(SETUP_COUNT_CALLBACK_REF_ATTR);
285             if (StringUtils.hasText(countCallback)) {
286                 bean.addPropertyReference(Conventions.attributeNameToPropertyName(SETUP_COUNT_CALLBACK_ATTR + "Name"), countCallback);
287             } else if (StringUtils.hasText(countCallbackRef)) {
288                 bean.addPropertyReference(Conventions.attributeNameToPropertyName(SETUP_COUNT_CALLBACK_ATTR), countCallbackRef);
289             }
290 
291             List propertyTypeHandlersElements = DomUtils.getChildElementsByTagName(element, PROPERTY_TYPE_HANDLER_TAG);
292             ManagedMap propertyTypeHandlersMap = new ManagedMap(propertyTypeHandlersElements.size());
293             for (int i = 0; i < propertyTypeHandlersElements.size(); i++) {
294                 Element propertyTypeHandlerElement = (Element) propertyTypeHandlersElements.get(i);
295                 String propertyType = propertyTypeHandlerElement.getAttribute(PROPERTY_TYPE_HANDLER_PROPERTY_TYPE_ATTR);
296                 String handlerClass = propertyTypeHandlerElement.getAttribute(PROPERTY_TYPE_HANDLER_HANDLER_CLASS_ATTR);
297                 propertyTypeHandlersMap.put(propertyType, handlerClass);
298             }
299             bean.addPropertyValue(Conventions.attributeNameToPropertyName(PROPERTY_TYPE_HANDLER_TAG) + "sClassNames", propertyTypeHandlersMap);
300 
301             List propertyTypeHandlersRefElements = DomUtils.getChildElementsByTagName(element, PROPERTY_TYPE_HANDLER_REF_TAG);
302             ManagedSet propertyTypeHandlersRefSet = new ManagedSet(propertyTypeHandlersRefElements.size());
303             for (int i = 0; i < propertyTypeHandlersRefElements.size(); i++) {
304                 Element propertyTypeHandlersRefElement = (Element) propertyTypeHandlersRefElements.get(i);
305                 // String propertyType = propertyTypeHandlersRefElement.getAttribute(PROPERTY_TYPE_HANDLER_PROPERTY_TYPE_ATTR);
306                 String handlerRef = propertyTypeHandlersRefElement.getAttribute(PROPERTY_TYPE_HANDLER_HANDLER_REF_ATTR);
307                 RuntimeBeanReference runtimeBeanReference = new RuntimeBeanReference(handlerRef);
308                 propertyTypeHandlersRefSet.add(runtimeBeanReference);
309             }
310             bean.addPropertyValue(Conventions.attributeNameToPropertyName(PROPERTY_TYPE_HANDLER_TAG) + "s", propertyTypeHandlersRefSet);
311 
312             List specificPropertyHandlerElements = DomUtils.getChildElementsByTagName(element, SPECIFIC_PROPERTY_HANDLER_TAG);
313             ManagedMap specificPropertyHandlersMap = new ManagedMap(specificPropertyHandlerElements.size());
314             for (int i = 0; i < specificPropertyHandlerElements.size(); i++) {
315                 Element specificPropertyElement = (Element) specificPropertyHandlerElements.get(i);
316                 String targetClass = specificPropertyElement.getAttribute(SPECIFIC_PROPERTY_HANDLER_TARGET_CLASS_ATTR);
317                 String targetProperty = specificPropertyElement.getAttribute(SPECIFIC_PROPERTY_HANDLER_TARGET_PROPERTY_ATTR);
318                 String handlerClass = specificPropertyElement.getAttribute(SPECIFIC_PROPERTY_HANDLER_HANDLER_CLASS_ATTR);
319                 specificPropertyHandlersMap.put(targetClass + "." + targetProperty, handlerClass);
320             }
321             bean.addPropertyValue(Conventions.attributeNameToPropertyName(SPECIFIC_PROPERTY_HANDLER_TAG) + "sClassNames", specificPropertyHandlersMap);
322 
323             List specificPropertyHandlerRefElements = DomUtils.getChildElementsByTagName(element, SPECIFIC_PROPERTY_HANDLER_REF_TAG);
324             ManagedSet specificPropertyHandlersRefSet = new ManagedSet(specificPropertyHandlerRefElements.size());
325             for (int i = 0; i < specificPropertyHandlerRefElements.size(); i++) {
326                 Element specificPropertyRefElement = (Element) specificPropertyHandlerRefElements.get(i);
327                 // String targetClass = specificPropertyRefElement.getAttribute(SPECIFIC_PROPERTY_HANDLER_TARGET_CLASS_ATTR);
328                 // String targetProperty = specificPropertyRefElement.getAttribute(SPECIFIC_PROPERTY_HANDLER_TARGET_PROPERTY_ATTR);
329                 String handlerRef = specificPropertyRefElement.getAttribute(SPECIFIC_PROPERTY_HANDLER_HANDLER_REF_ATTR);
330                 RuntimeBeanReference runtimeBeanReference = new RuntimeBeanReference(handlerRef);
331                 specificPropertyHandlersRefSet.add(runtimeBeanReference);
332             }
333             bean.addPropertyValue(Conventions.attributeNameToPropertyName(SPECIFIC_PROPERTY_HANDLER_TAG) + "s", specificPropertyHandlersRefSet);
334         }
335     }
336 }