KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > inversoft > verge > mvc > controller > actionflow > config > ActionFlowConfigBuilder


1 /*
2  * Copyright (c) 2003, Inversoft
3  *
4  * This software is distribuable under the GNU Lesser General Public License.
5  * For more information visit gnu.org.
6  */

7 package com.inversoft.verge.mvc.controller.actionflow.config;
8
9
10 import java.util.Iterator JavaDoc;
11 import java.util.Map JavaDoc;
12
13 import org.apache.log4j.Logger;
14 import org.jdom.Document;
15 import org.jdom.Element;
16
17 import com.inversoft.config.ConfigBuilder;
18 import com.inversoft.config.ConfigRegistry;
19 import com.inversoft.config.ConfigurationException;
20 import com.inversoft.config.component.ComponentConfigBuilderRegistry;
21 import com.inversoft.error.ErrorList;
22 import com.inversoft.util.StringTools;
23 import com.inversoft.verge.config.VergeConfigConstants;
24 import com.inversoft.verge.mvc.config.BaseFormConfig;
25 import com.inversoft.verge.mvc.config.BaseFormConfigBuilder;
26 import com.inversoft.verge.repository.config.RepositoryConfigRegistry;
27
28
29 /**
30  * <p>
31  * This class builds the configuration object model from the
32  * XML configuration file(s). The names of the configuration
33  * files are stored in the ServletContext under a context
34  * parameter. The context parameter is always named
35  * actionFlowConfigFiles and is a comma separated list of the
36  * configuration files.
37  * </p>
38  *
39  * <p>
40  * Namespace objects are created from the build
41  * operation and are stored in the {@link ActionFlowConfigRegistry
42  * ActionFlowConfigRegistry} class. This builder does not return the
43  * built objects.
44  * </p>
45  *
46  * @author Brian Pontarelli
47  * @since 2.0
48  * @version 2.0
49  */

50 public class ActionFlowConfigBuilder implements ConfigBuilder {
51
52     /**
53      * This classes logger
54      */

55     private static final Logger logger = Logger.getLogger(ActionFlowConfigBuilder.class);
56
57
58     /**
59      * The ResourceBundle that stores all the ComponentConfigBuilder information
60      */

61     public static final String JavaDoc BUILDERS_BUNDLE =
62         "com.inversoft.verge.mvc.controller.actionflow.config.ActionFlowConfigBuilders";
63
64     /**
65      * The namespace prefix in the component configuration properties file
66      */

67     public static final String JavaDoc NAMESPACE_PREFIX = "namespace_";
68
69     /**
70      * The node prefix in the component configuration properties file
71      */

72     public static final String JavaDoc NODE_PREFIX = "node_";
73
74     /**
75      * This is the component ComponentConfigBuilderRegistry that stores the individual
76      * ConfigBuilders for this package
77      */

78     private ComponentConfigBuilderRegistry builderRegistry;
79
80
81     /**
82      * Constructs a new <code>ActionFlowConfigBuilder</code>.
83      *
84      * @throws ConfigurationException If the ComponentConfigBuilderRegistry could not be
85      * initialized properly
86      */

87     public ActionFlowConfigBuilder() throws ConfigurationException {
88         builderRegistry = new ComponentConfigBuilderRegistry(BUILDERS_BUNDLE);
89     }
90
91
92     /**
93      * <p>
94      * Builds the configuration object model using the names of the xml configuration
95      * files from the servlet context parameter. Therefore, this method does not
96      * need any additional information.
97      * </p>
98      *
99      * <p>
100      * The configuration objects that are built are stored in the given instance of
101      * the {@link ActionFlowConfigRegistry ActionFlowConfigRegistry} class
102      * </p>
103      *
104      * <p>
105      * This method, like all the configuration methods, is synchronized. This is
106      * not to prevent multiple thread usage but to enforce a proper write of the
107      * ConfigRegistry Object from Thread local memory to the JVM heap memory.
108      * This will ensure that when the ConfigRegistry is later set into the
109      * singleton, which is an atomic operation, it will be correctly populated.
110      * </p>
111
112      * @param document The XML document to parse the configuration from
113      * @param registry The ActionFlowConfigRegistry to store the objects in
114      * @throws ConfigurationException If anything went wrong during the build
115      */

116     public synchronized void build(Document document, ConfigRegistry registry)
117     throws ConfigurationException {
118
119         ActionFlowConfigRegistry actionRegistry = (ActionFlowConfigRegistry) registry;
120         ErrorList errors = new ErrorList();
121         Namespace namespace = buildNamespace(document, errors);
122
123         if (namespace != null) {
124             if (actionRegistry.lookup(namespace.getName()) != null) {
125                 logger.error("There are two or more namespaces named: " +
126                     namespace.getName());
127                 errors.addError("There are two or more namespaces named: " +
128                     namespace.getName());
129             } else if (logger.isDebugEnabled()) {
130                 logger.debug("Stored namespace named '" + namespace.getName() + "'");
131             }
132
133             actionRegistry.register(namespace);
134         }
135
136         if (!errors.isEmpty()) {
137             throw new ConfigurationException(errors);
138         }
139     }
140
141     /**
142      * Since the Portal configuration is dumped and completely reloaded on
143      * refreshes, this calls build because the registry should be fresh.
144      *
145      * @param document The Document to parse and build from
146      * @param registry The registry to store the objects in
147      * @throws ConfigurationException If there were any errors
148      */

149     public void rebuild(Document document, ConfigRegistry registry)
150     throws ConfigurationException {
151         build(document, registry);
152     }
153
154     /**
155      * Finishes the build process. This creates the links, looks up repository
156      * items, etc.
157      */

158     public void validate(ConfigRegistry registry, Map JavaDoc registries)
159     throws ConfigurationException {
160
161         // Call post process on every Namespace and Node built
162
ErrorList errors = new ErrorList();
163         ActionFlowConfigRegistry actionRegistry = (ActionFlowConfigRegistry) registry;
164         RepositoryConfigRegistry repository =
165             (RepositoryConfigRegistry) registries.get(VergeConfigConstants.REPOSITORY_KEY);
166         assert (repository != null) : "RepositoryConfigRegistry not found";
167
168         Iterator JavaDoc iter = actionRegistry.iterator();
169         NamespaceBuilder namespaceBuilder;
170         Namespace namespace;
171
172         while (iter.hasNext()) {
173             namespace = (Namespace) iter.next();
174
175             // Call postBuild on the Namespace AFTER all the Nodes are done
176
namespaceBuilder =
177                 (NamespaceBuilder) builderRegistry.lookup(NAMESPACE_PREFIX +
178                     namespace.getType());
179             try {
180                 namespaceBuilder.validate(namespace, actionRegistry, registries,
181                     builderRegistry);
182             } catch (ConfigurationException ce) {
183                 errors.addErrorList(ce.getErrors());
184             }
185         }
186
187         // If there were any errors during the build process, throw an exception
188
if (!errors.isEmpty()) {
189             throw new ConfigurationException(errors);
190         }
191     }
192
193     /**
194      * If the validation was successfull, the registry should be all setup so we
195      * can go ahead and set the singleton instance.
196      *
197      * @param registry The ActionFlowConfigRegistry that was just built
198      * @param otherRegistries not used
199      */

200     public void commit(ConfigRegistry registry, Map JavaDoc otherRegistries) {
201         ActionFlowConfigRegistry.setInstance((ActionFlowConfigRegistry) registry);
202     }
203
204     /**
205      * Parses the namespace out of the file given.
206      *
207      * @param namespace The Document to parse
208      * @param errors An ErrorList to add all the errors to
209      * @return The Namespace parsed from the document or null if there were errors
210      */

211     protected Namespace buildNamespace(Document namespace, ErrorList errors) {
212
213         // Get the factory and build the Namespace
214
Element root = namespace.getRootElement();
215         String JavaDoc type = root.getAttributeValue(Constants.TYPE_ATTRIBUTE);
216         if (StringTools.isEmpty(type)) {
217             type = DefaultTypes.NAMESPACE;
218         }
219
220         NamespaceBuilder nsFactory = (NamespaceBuilder) builderRegistry.lookup(
221             NAMESPACE_PREFIX + type);
222         if (nsFactory == null) {
223             errors.addError("Can not locate factory to build namespace of type " + type);
224             return null;
225         }
226
227         Namespace ns = null;
228         try {
229             ns = nsFactory.build(root);
230         } catch (ConfigurationException ce) {
231             errors.addErrorList(ce.getErrors());
232             return ns;
233         }
234
235         // Build the Nodes from the children
236
Iterator JavaDoc iter = root.getChildren().iterator();
237         Element element;
238         String JavaDoc name;
239         Node node;
240         BaseFormConfig form;
241         boolean failed = false;
242
243         while (iter.hasNext()) {
244             element = (Element) iter.next();
245             name = element.getName();
246
247             if (name.equals(Constants.NODE_ELEMENT)) {
248                 node = buildNode(ns, element, errors);
249                 if (node == null) {
250                     failed = true;
251                     continue;
252                 }
253
254                 if (logger.isDebugEnabled()) {
255                     logger.debug("Adding node named '" + node.getName() +
256                         "' to namespace named '" + ns.getName() + "'");
257                 }
258
259                 ns.addNode(node);
260             } else if (name.equals(Constants.FORM_ELEMENT)) {
261                 form = buildForm(ns, element, errors);
262                 if (form == null) {
263                     failed = true;
264                     continue;
265                 }
266
267                 if (logger.isDebugEnabled()) {
268                     logger.debug("Adding form named '" + form.getName() +
269                         "' to namespace named '" + ns.getName() + "'");
270                 }
271
272                 ns.addForm(form);
273             } else {
274                 errors.addError("Element type: " + name + " not supported");
275             }
276         }
277
278         if (failed) {
279             ns = null;
280         }
281
282         return ns;
283     }
284
285     /**
286      * Parses a Node from the given element using the correct Factory for the
287      * Node type
288      *
289      * @param element The Element to parse the Node from
290      * @param errors An ErrorList to add the errors to
291      * @return The Node built or null if there were errors
292      */

293     protected Node buildNode(Namespace namespace, Element element, ErrorList errors) {
294
295         String JavaDoc type = element.getAttributeValue(Constants.TYPE_ATTRIBUTE);
296         if (StringTools.isEmpty(type)) {
297             errors.addError("A node is missing the type attribute");
298             return null;
299         }
300
301         NodeBuilder factory = (NodeBuilder) builderRegistry.lookup(
302             NODE_PREFIX + type);
303         if (factory == null) {
304             errors.addError("Unable to locate a factory for Node type " + type);
305             return null;
306         }
307
308         Node node = null;
309         try {
310             node = factory.build(namespace, element);
311         } catch (ConfigurationException ce) {
312             errors.addErrorList(ce.getErrors());
313         }
314
315         return node;
316     }
317
318     /**
319      * Parses a Form from the given element using the correct Factory for the
320      * form type.
321      *
322      * @param element The Element to parse the form from
323      * @param errors An ErrorList to add the errors to
324      * @return The Node built or null if there were errors
325      */

326     protected BaseFormConfig buildForm(Namespace namespace, Element element,
327             ErrorList errors) {
328
329         BaseFormConfigBuilder builder = (BaseFormConfigBuilder)
330             builderRegistry.lookup("form");
331         if (builder == null) {
332             errors.addError("Unable to locate a builder for forms");
333             return null;
334         }
335
336         BaseFormConfig formConfig = null;
337         try {
338             formConfig = (BaseFormConfig) builder.build(element);
339         } catch (ConfigurationException ce) {
340             errors.addErrorList(ce.getErrors());
341         }
342
343         return formConfig;
344     }
345 }
346
Popular Tags