KickJava   Java API By Example, From Geeks To Geeks.

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


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.List JavaDoc;
12
13 import org.apache.log4j.Logger;
14 import org.jdom.Element;
15
16 import com.inversoft.config.ConfigurationException;
17 import com.inversoft.config.component.AbstractComponentConfigBuilder;
18 import com.inversoft.error.ErrorList;
19 import com.inversoft.util.StringTools;
20 import com.inversoft.verge.mvc.controller.actionflow.NodeExecutorRegistry;
21 import com.inversoft.verge.repository.config.RepositoryConfigRegistry;
22
23
24 /**
25  * <p>
26  * This class is the abstract base class for all
27  * NodeFactories. This provides methods that assist in
28  * retrieving common attributes from the XML Elements.
29  * However, NodeFactorys do not need to extend this class,
30  * they only need to implement the interface.
31  * </p>
32  *
33  * <p>
34  * This class is a pooled (flyweight) class and therefore
35  * does not hold any state information about Node or Element
36  * objects. Likewise, no sub-class should either.
37  * </p>
38  *
39  * @author Brian Pontarelli
40  * @since 2.0
41  * @version 2.0
42  */

43 public abstract class BaseNodeBuilder extends AbstractComponentConfigBuilder
44 implements NodeBuilder {
45
46     /**
47      * This classes logger
48      */

49     private static final Logger logger = Logger.getLogger(BaseNodeBuilder.class);
50
51
52     /**
53      * Constructs a new <code>BaseNodeBuilder</code>.
54      */

55     public BaseNodeBuilder() {
56         // Empty
57
}
58
59
60     /**
61      * <p>
62      * Constructs a BaseValues object from the given Element. This method
63      * uses the name, className, repositoryId, isEntryPoint, isDefaultEntry,
64      * and isExitPoint attributes from the XML Element to populate the
65      * BaseValues object. This method does not do any validation except
66      * to check if boolean values are correct (true, false).
67      * </p>
68      *
69      * <p>
70      * This means that this method does not check the name, repositoryId,
71      * className or any other XML attribute. These checks need to be done
72      * in sub-classes. The reason for this is because Nodes are implementation
73      * specific and, for example, might need a name and NOT need anything else.
74      * </p>
75      *
76      * <p>
77      * This method also does a NodeExecutor lookup based on the type of the
78      * node which is specified by the type attribute. This NodeExecutor must
79      * be found or this method will throw an exception.
80      * </p>
81      *
82      * <p>
83      * Sub-classes can call this method to build the BaseValues object
84      * and then instantiate their Node and either populate their
85      * Node from the BaseValues or call a copy constructor of some
86      * sort.
87      * </p>
88      *
89      * @param element The Element to build from
90      * @param errors The ErrorList to add any errors to
91      * @return The BaseValues built
92      * @asserts If element or errors is null
93      */

94     public BaseNode.BaseValues buildValues(Element element, ErrorList errors)
95     throws ConfigurationException {
96
97         assert (element != null) : "element == null";
98         assert (errors != null) : "errors == null";
99
100         BaseNode.BaseValues values = new BaseNode.BaseValues();
101         values.name = element.getAttributeValue(Constants.NAME_ATTRIBUTE);
102         values.className = element.getAttributeValue(Constants.CLASS_ATTRIBUTE);
103         values.repositoryId = element.getAttributeValue(Constants.REPOSITORY_ID_ATTRIBUTE);
104         values.type = element.getAttributeValue(Constants.TYPE_ATTRIBUTE);
105
106         String JavaDoc defaultEntry = element.getAttributeValue(Constants.DEFAULT_ATTRIBUTE);
107         String JavaDoc exitPoint = element.getAttributeValue(Constants.EXIT_ATTRIBUTE);
108
109         String JavaDoc longTxnEnabled = element.getAttributeValue(Constants.LONG_TXN_ENABLED_ATTRIBUTE);
110         String JavaDoc longTxnStartURL = element.getAttributeValue(Constants.LONG_TXN_START_URL_ATTRIBUTE);
111         String JavaDoc longTxnEndURL = element.getAttributeValue(Constants.LONG_TXN_END_URL_ATTRIBUTE);
112         String JavaDoc longTxnCategory = element.getAttributeValue(Constants.LONG_TXN_CATEGORY_ATTRIBUTE);
113
114         // Verify the defaultEntry value
115
if (!StringTools.isEmpty(defaultEntry)) {
116             if (!StringTools.isValidBoolean(defaultEntry)) {
117                 errors.addError(Constants.DEFAULT_ATTRIBUTE +
118                     " contains an invalid boolean value");
119             }
120
121             values.defaultEntry = Boolean.valueOf(defaultEntry).booleanValue();
122         }
123
124         // Verify the exitPoint value
125
if (!StringTools.isEmpty(exitPoint)) {
126             if (!StringTools.isValidBoolean(exitPoint)) {
127                 errors.addError(Constants.EXIT_ATTRIBUTE +
128                     " contains an invalid boolean value");
129             }
130
131             values.exitPoint = Boolean.valueOf(exitPoint).booleanValue();
132         }
133
134         // Grab the type of the node so we can lookup the NodeExecutor
135
if (StringTools.isEmpty(values.type)) {
136             errors.addError(Constants.TYPE_ATTRIBUTE + " is a required attribute");
137         } else {
138             values.executor = NodeExecutorRegistry.lookup(values.type);
139             if (values.executor == null) {
140                 errors.addError("No NodeExecutor found for node type " + values.type);
141                 logger.debug("executor is null");
142             }
143         }
144
145         // Verify the longTxnEnabled value
146
if (!StringTools.isEmpty(longTxnEnabled)) {
147             if (!StringTools.isValidBoolean(longTxnEnabled)) {
148                 errors.addError(Constants.LONG_TXN_ENABLED_ATTRIBUTE +
149                     " contains an invalid boolean value");
150             }
151
152             values.longTxnEnabled = Boolean.valueOf(longTxnEnabled).booleanValue();
153             values.longTxnStartURL = longTxnStartURL;
154             values.longTxnEndURL = longTxnEndURL;
155             values.longTxnCategory = longTxnCategory;
156         }
157
158         // Log all the parameters for testing
159
if (logger.isDebugEnabled()) {
160             logger.debug("name: " + values.name);
161             logger.debug("type: " + values.type);
162             logger.debug("class name: " + values.className);
163             logger.debug("repositoryId: " + values.repositoryId);
164             logger.debug("defaultEntry: " + values.defaultEntry);
165             logger.debug("exitPoint: " + values.exitPoint);
166             logger.debug("longTxnEnabled: " + values.longTxnEnabled);
167         }
168
169         return values;
170     }
171
172     /**
173      * Builds the ActionLink objects from the children of the given Element.
174      * The given Element is the Node Element and could contain any number of
175      * actionLink Elements. These are used to construct new ActionLink objects'
176      * which are added to the given Node.
177      *
178      * @param config The Node to add the built ActionLinks to
179      * @param registry The action flow registry used to lookup nodes in another
180      * namespaces
181      * @param repositoryRegistry The repository registry used to lookup and
182      * validate repository items
183      * @throws ConfigurationException If the XML was invalid
184      * @asserts If config is null
185      */

186     public void postBuild(Node config, ActionFlowConfigRegistry registry,
187             RepositoryConfigRegistry repositoryRegistry)
188     throws ConfigurationException {
189
190         assert (config != null) : "config == null";
191
192         // Build the ActionLink objects for the Node
193
BaseNode base = (BaseNode) config;
194         Element element = base.getElement();
195         List JavaDoc links = element.getChildren(Constants.ACTION_LINK_ELEMENT);
196         Iterator JavaDoc iter = links.iterator();
197         ErrorList errors = new ErrorList();
198         Element linkElement;
199         Link link;
200
201         while (iter.hasNext()) {
202             linkElement = (Element) iter.next();
203             link = buildActionLink(linkElement, config, errors, registry);
204             if (link == null) {
205                 continue;
206             }
207
208             base.addLink(link);
209         }
210
211         // Build the RegexLink objects for the Node
212
links = element.getChildren(Constants.REGEX_LINK_ELEMENT);
213         iter = links.iterator();
214
215         while (iter.hasNext()) {
216             linkElement = (Element) iter.next();
217             link = buildRegexLink(linkElement, config, errors, registry);
218             if (link == null) {
219                 continue;
220             }
221
222             base.addLink(link);
223         }
224
225         // Build the Exception Links for the Node
226
links = element.getChildren(Constants.EXCEPTION_LINK_ELEMENT);
227         iter = links.iterator();
228
229         while (iter.hasNext()) {
230             linkElement = (Element) iter.next();
231             link = buildExceptionLink(linkElement, config, errors, registry);
232             if (link == null) {
233                 continue;
234             }
235
236             base.addLink(link);
237         }
238
239         // Release the element
240
base.setElement(null);
241
242         // Check repository ids
243
if (config.getRepositoryId() != null &&
244                 repositoryRegistry.lookup(config.getRepositoryId()) == null) {
245             errors.addError("Invalid repository id: " + config.getRepositoryId() +
246                 " for the node named: " + config.getName());
247         }
248
249         // If there were errors, throw a ConfigurationException
250
if (!errors.isEmpty()) {
251             throw new ConfigurationException(errors);
252         }
253     }
254
255     /**
256      * Builds a single ActionLink object from the given element and returns it
257      *
258      * @param link The Element to build the link from
259      * @param config The Node that this ActionLink belongs to
260      * @param errors The ErrorList to add any errors to
261      * @return The new ActionLink object or null if there were any errors
262      * @asserts If link, config or errors are null
263      */

264     protected ActionLink buildActionLink(Element link, Node config,
265         ErrorList errors, ActionFlowConfigRegistry registry) {
266
267         assert (link != null) : "link == null";
268         assert (config != null) : "config == null";
269         assert (errors != null) : "errors == null";
270
271         String JavaDoc action = link.getAttributeValue(Constants.ACTION_ATTRIBUTE);
272         String JavaDoc node = link.getAttributeValue(Constants.NODE_ATTRIBUTE);
273         String JavaDoc namespace = link.getAttributeValue(Constants.NAMESPACE_ATTRIBUTE);
274         boolean success = true;
275
276         if (StringTools.isEmpty(action)) {
277             errors.addError(Constants.ACTION_ATTRIBUTE +
278                 " is a required attribute of an " + Constants.ACTION_LINK_ELEMENT);
279             success = false;
280         }
281
282         if (StringTools.isEmpty(node)) {
283             errors.addError(Constants.NODE_ATTRIBUTE +
284                 " is a required attribute of an " + Constants.ACTION_LINK_ELEMENT);
285             success = false;
286         }
287
288         // Look up the node referenced by the node attribute
289
Namespace afNamespace = null;
290         if (!StringTools.isEmpty(namespace)) {
291             afNamespace = registry.lookup(namespace);
292         } else {
293             afNamespace = config.getNamespace();
294         }
295
296         if (afNamespace == null) {
297             errors.addError(namespace + " is an invalid namespace");
298             return null;
299         }
300
301         Node dest = afNamespace.getNode(node);
302         if (dest == null) {
303             errors.addError(node + " is an invalid node name");
304             success = false;
305         }
306
307         // If there were any failures, return null
308
if (!success) {
309             return null;
310         }
311
312         return new ActionLink(action, config, dest);
313     }
314
315     /**
316      * Builds a single RegexLink object from the given element and returns it
317      *
318      * @param link The Element to build the link from
319      * @param config The Node that this RegexLink belongs to
320      * @param errors The ErrorList to add any errors to
321      * @return The new RegexLink object or null if there were any errors
322      * @asserts If link, config or errors are null
323      */

324     protected RegexLink buildRegexLink(Element link, Node config,
325         ErrorList errors, ActionFlowConfigRegistry registry) {
326
327         assert (link != null) : "link == null";
328         assert (config != null) : "config == null";
329         assert (errors != null) : "errors == null";
330
331         String JavaDoc regex = link.getAttributeValue(Constants.REGEX_ATTRIBUTE);
332         String JavaDoc node = link.getAttributeValue(Constants.NODE_ATTRIBUTE);
333         String JavaDoc namespace = link.getAttributeValue(Constants.NAMESPACE_ATTRIBUTE);
334         boolean success = true;
335
336         if (StringTools.isEmpty(regex)) {
337             errors.addError(Constants.REGEX_ATTRIBUTE +
338                 " is a required attribute of an " + Constants.REGEX_LINK_ELEMENT);
339             success = false;
340         }
341
342         if (StringTools.isEmpty(node)) {
343             errors.addError(Constants.NODE_ATTRIBUTE +
344                 " is a required attribute of an " + Constants.REGEX_LINK_ELEMENT);
345             success = false;
346         }
347
348         // Look up the node referenced by the node attribute
349
Namespace afNamespace = null;
350         if (!StringTools.isEmpty(namespace)) {
351             afNamespace = registry.lookup(namespace);
352         } else {
353             afNamespace = config.getNamespace();
354         }
355
356         if (afNamespace == null) {
357             errors.addError(namespace + " is an invalid namespace");
358             return null;
359         }
360
361         Node dest = afNamespace.getNode(node);
362         if (dest == null) {
363             errors.addError(node + " is an invalid node name");
364             success = false;
365         }
366
367         // If there were any failures, return null
368
if (!success) {
369             return null;
370         }
371
372         return new RegexLink(regex, config, dest);
373     }
374
375     /**
376      * Builds a single ExceptionLink object from the given element and returns it
377      *
378      * @param link The Element to build the link from
379      * @param config The Node that this ExceptionLink belongs to
380      * @param errors The ErrorList to add any errors to
381      * @return The new ExceptionLink object or null if there were any errors
382      * @asserts If link, config or errors are null
383      */

384     protected ExceptionLink buildExceptionLink(Element link, Node config,
385             ErrorList errors, ActionFlowConfigRegistry registry) {
386
387         assert (link != null) : "link == null";
388         assert (config != null) : "config == null";
389         assert (errors != null) : "errors == null";
390
391         String JavaDoc exception = link.getAttributeValue(Constants.EXCEPTION_ATTRIBUTE);
392         String JavaDoc node = link.getAttributeValue(Constants.NODE_ATTRIBUTE);
393         String JavaDoc namespace = link.getAttributeValue(Constants.NAMESPACE_ATTRIBUTE);
394         boolean success = true;
395
396         if (StringTools.isEmpty(exception)) {
397             errors.addError(Constants.EXCEPTION_ATTRIBUTE +
398                 " is a required attribute of an " + Constants.EXCEPTION_LINK_ELEMENT);
399             success = false;
400         }
401
402         if (StringTools.isEmpty(node)) {
403             errors.addError(Constants.NODE_ATTRIBUTE +
404                 " is a required attribute of an " + Constants.REGEX_LINK_ELEMENT);
405             success = false;
406         }
407
408         // Look up the node referenced by the node attribute
409
Namespace afNamespace = null;
410         if (!StringTools.isEmpty(namespace)) {
411             afNamespace = registry.lookup(namespace);
412         } else {
413             afNamespace = config.getNamespace();
414         }
415
416         if (afNamespace == null) {
417             errors.addError(namespace + " is an invalid namespace");
418             return null;
419         }
420
421         Node dest = afNamespace.getNode(node);
422         if (dest == null) {
423             errors.addError(node + " is an invalid node name");
424             success = false;
425         }
426
427         Exception JavaDoc instance = null;
428         try {
429             Class JavaDoc klass = Class.forName(exception);
430             instance = (Exception JavaDoc) klass.newInstance();
431         } catch (Exception JavaDoc e) {
432             errors.addError(exception + " could not be instantiated: " + e.toString());
433             success = false;
434         }
435
436         // If there were any failures, return null
437
if (!success) {
438             return null;
439         }
440
441         return new ExceptionLink(instance, config, dest);
442     }
443 }
444
445
Popular Tags