KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > riotfamily > forms > factory > ConfigurableElementFactory


1 /* ***** BEGIN LICENSE BLOCK *****
2  * Version: MPL 1.1
3  * The contents of this file are subject to the Mozilla Public License Version
4  * 1.1 (the "License"); you may not use this file except in compliance with
5  * the License. You may obtain a copy of the License at
6  * http://www.mozilla.org/MPL/
7  *
8  * Software distributed under the License is distributed on an "AS IS" basis,
9  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
10  * for the specific language governing rights and limitations under the
11  * License.
12  *
13  * The Original Code is Riot.
14  *
15  * The Initial Developer of the Original Code is
16  * Neteye GmbH.
17  * Portions created by the Initial Developer are Copyright (C) 2006
18  * the Initial Developer. All Rights Reserved.
19  *
20  * Contributor(s):
21  * Felix Gnass [fgnass at neteye dot de]
22  *
23  * ***** END LICENSE BLOCK ***** */

24 package org.riotfamily.forms.factory;
25
26 import java.util.Iterator JavaDoc;
27 import java.util.LinkedList JavaDoc;
28 import java.util.List JavaDoc;
29
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32 import org.riotfamily.common.beans.propertyeditors.IntArrayPropertyEditor;
33 import org.riotfamily.forms.BeanEditor;
34 import org.riotfamily.forms.ContainerElement;
35 import org.riotfamily.forms.Editor;
36 import org.riotfamily.forms.Element;
37 import org.riotfamily.forms.ElementFactory;
38 import org.riotfamily.forms.Form;
39 import org.springframework.beans.BeanUtils;
40 import org.springframework.beans.BeanWrapper;
41 import org.springframework.beans.BeanWrapperImpl;
42 import org.springframework.beans.MutablePropertyValues;
43 import org.springframework.beans.PropertyValue;
44 import org.springframework.beans.PropertyValues;
45 import org.springframework.beans.factory.BeanFactory;
46 import org.springframework.beans.factory.BeanFactoryAware;
47 import org.springframework.beans.factory.config.RuntimeBeanReference;
48
49
50 /**
51  * Configurable element factory that can be used to create arbitary
52  * form elements. This class is used by
53  * {@link org.riotfamily.forms.factory.xml.XmlFormRepositoryDigester}
54  * but could also be useful for custom implementations.
55  */

56 public class ConfigurableElementFactory implements ContainerElementFactory,
57         EditorElementFactory {
58
59     private Log log = LogFactory.getLog(ConfigurableElementFactory.class);
60     
61     /** The class to create */
62     private Class JavaDoc elementClass;
63     
64     /** Property name the element should be bound to */
65     private String JavaDoc bind;
66     
67     /** Class to be edited by a BeanEditor */
68     private Class JavaDoc beanClass;
69     
70     /** Properties to be set after element creation */
71     private PropertyValues propertyValues;
72     
73     /** List of factories to create optional child elements */
74     private List JavaDoc childFactories = new LinkedList JavaDoc();
75     
76     /** BeanFactory used to lookup bean references */
77     private BeanFactory beanFactory;
78     
79     /**
80      * Creates a new factory for the given element class.
81      */

82     public ConfigurableElementFactory(Class JavaDoc elementClass) {
83         this.elementClass = elementClass;
84     }
85     
86     public Class JavaDoc getElementClass() {
87         return this.elementClass;
88     }
89
90     /**
91      * Sets the BeanFactory that is used to lookup bean references.
92      */

93     public void setBeanFactory(BeanFactory beanFactory) {
94         this.beanFactory = beanFactory;
95     }
96     
97     /**
98      * Sets the PropertyValues that will be set on the element after creation.
99      */

100     public void setPropertyValues(PropertyValues propertyValues) {
101         this.propertyValues = propertyValues;
102     }
103
104     /**
105      * If the factory is set up to create a {@link BeanEditor}, the
106      * type of the bean that is to be edited can be set.
107      *
108      * @throws FormDefinitionException if the element does not implement
109      * {@link BeanEditor}
110      */

111     public void setBeanClass(Class JavaDoc beanClass) {
112         if (beanClass != null && !BeanEditor.class
113                 .isAssignableFrom(elementClass)) {
114             
115             throw new FormDefinitionException("Element class must implement "
116                     + BeanEditor.class.getName());
117         }
118         this.beanClass = beanClass;
119     }
120     
121     /**
122      * @return Returns the beanClass.
123      */

124     public Class JavaDoc getBeanClass() {
125         return beanClass;
126     }
127
128     /**
129      * Sets the name of the property that elements created by this factory
130      * shall be bound to.
131      *
132      * @throws FormDefinitionException if the element does not implement
133      * {@link Editor}
134      */

135     public void setBind(String JavaDoc bind) {
136         if (bind != null && !Editor.class.isAssignableFrom(elementClass)) {
137             throw new FormDefinitionException("Element class must implement "
138                     + Editor.class.getName());
139         }
140         this.bind = bind;
141     }
142     
143     /**
144      * Returns the name of the property that elements created by this factory
145      * shall be bound to or <code>null</code> if no binding should be
146      * performed.
147      *
148      * @see EditorElementFactory#getBind()
149      */

150     public String JavaDoc getBind() {
151         return bind;
152     }
153     
154     /**
155      * Sets a list of element factories that will be used to create child
156      * elements which will be added to the elements beeing created by this
157      * factory.
158      *
159      * @throws FormDefinitionException if the element does not implement
160      * {@link ContainerElement}
161      */

162     public void setChildFactories(List JavaDoc childFactories) {
163         if (childFactories != null && !ContainerElement.class
164                 .isAssignableFrom(elementClass)) {
165             
166             throw new FormDefinitionException("Element class must implement "
167                     + ContainerElement.class.getName());
168         }
169         this.childFactories = childFactories;
170     }
171     
172     /**
173      * Adds an ElementFactory to the list of child factories.
174      * @see #setChildFactories(List)
175      */

176     public void addChildFactory(ElementFactory factory) {
177         if (!ContainerElement.class.isAssignableFrom(elementClass)) {
178             throw new FormDefinitionException("Element class must implement "
179                     + ContainerElement.class.getName());
180         }
181         childFactories.add(factory);
182     }
183     
184     /**
185      * Returns a list of element factories used to create nested elements.
186      * @see #setChildFactories(List)
187      */

188     public List JavaDoc getChildFactories() {
189         return childFactories;
190     }
191     
192     /**
193      * Returns a new instance of the configured element class.
194      * @see ElementFactory#createElement(Element, Form)
195      */

196     public Element createElement(Element parent, Form form) {
197         log.debug("Creating element " + elementClass);
198         Element element = (Element) BeanUtils.instantiateClass(elementClass);
199         element.setParent(parent);
200         if (beanClass != null) {
201             BeanEditor bee = (BeanEditor) element;
202             bee.setBeanClass(beanClass);
203         }
204         if (element instanceof BeanFactoryAware) {
205             BeanFactoryAware bfa = (BeanFactoryAware) element;
206             bfa.setBeanFactory(beanFactory);
207         }
208         populateElement(element);
209         
210         if (element instanceof Editor) {
211             if (bind != null) {
212                 log.debug("Bind: " + bind);
213                 BeanEditor beanEditor = findEditor(parent, form);
214                 Editor editor = (Editor) element;
215                 beanEditor.bind(editor, bind);
216             }
217         }
218         
219         if (element instanceof ContainerElement) {
220             createChildElements((ContainerElement) element, form);
221         }
222                 
223         return element;
224     }
225     
226     /**
227      * Called by {@link #createElement(Element, Form)} to populate the given
228      * element with the property values set via
229      * {@link #setPropertyValues(PropertyValues)}. Values will be resolved if
230      * necessary by calling {@link #resolveValueIfNecessary(Object)}.
231      */

232     protected void populateElement(Element element) {
233         if (propertyValues == null) {
234             return;
235         }
236         BeanWrapper beanWrapper = new BeanWrapperImpl(element);
237         beanWrapper.registerCustomEditor(int[].class, new IntArrayPropertyEditor());
238         MutablePropertyValues pvs = new MutablePropertyValues();
239         PropertyValue[] pvArray = propertyValues.getPropertyValues();
240         for (int i = 0; i < pvArray.length; i++) {
241             PropertyValue pv = pvArray[i];
242             Object JavaDoc resolvedValue = resolveValueIfNecessary(pv.getValue());
243             pvs.addPropertyValue(pvArray[i].getName(), resolvedValue);
244         }
245         beanWrapper.setPropertyValues(pvs);
246     }
247     
248     /**
249      * Called by {@link #populateElement(Element)} to support runtime
250      * references to prototype beans.
251      *
252      * @see RuntimeBeanReference
253      */

254     protected Object JavaDoc resolveValueIfNecessary(Object JavaDoc value) {
255         if (value instanceof RuntimeBeanReference) {
256             RuntimeBeanReference ref = (RuntimeBeanReference) value;
257             return beanFactory.getBean(ref.getBeanName());
258         }
259         return value;
260     }
261     
262     protected void createChildElements(ContainerElement parent, Form form) {
263         if (childFactories != null) {
264             Iterator JavaDoc it = childFactories.iterator();
265             while (it.hasNext()) {
266                 ElementFactory factory = (ElementFactory) it.next();
267                 Element child = factory.createElement(parent, form);
268                 parent.addElement(child);
269             }
270         }
271     }
272     
273     protected BeanEditor findEditor(Element parent, Form form) {
274         while (parent != null) {
275             log.debug("Checking " + parent);
276             if (parent instanceof BeanEditor) {
277                 log.debug("Found.");
278                 return (BeanEditor) parent;
279             }
280             parent = parent.getParent();
281         }
282         return form;
283     }
284             
285 }
286
Popular Tags