KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > enterprise > tools > jsfext > layout > xml > XMLLayoutDefinitionReader


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23 package com.sun.enterprise.tools.jsfext.layout.xml;
24
25 import com.sun.enterprise.tools.jsfext.event.handlers.Handler;
26 import com.sun.enterprise.tools.jsfext.event.handlers.HandlerDefinition;
27 import com.sun.enterprise.tools.jsfext.event.handlers.IODescriptor;
28 import com.sun.enterprise.tools.jsfext.layout.descriptor.ComponentType;
29 import com.sun.enterprise.tools.jsfext.layout.descriptor.LayoutAttribute;
30 import com.sun.enterprise.tools.jsfext.layout.descriptor.LayoutComponent;
31 import com.sun.enterprise.tools.jsfext.layout.descriptor.LayoutDefinition;
32 import com.sun.enterprise.tools.jsfext.layout.descriptor.LayoutElement;
33 import com.sun.enterprise.tools.jsfext.layout.descriptor.LayoutFacet;
34 import com.sun.enterprise.tools.jsfext.layout.descriptor.LayoutForEach;
35 import com.sun.enterprise.tools.jsfext.layout.descriptor.LayoutIf;
36 import com.sun.enterprise.tools.jsfext.layout.descriptor.LayoutMarkup;
37 import com.sun.enterprise.tools.jsfext.layout.descriptor.LayoutStaticText;
38 import com.sun.enterprise.tools.jsfext.layout.descriptor.LayoutWhile;
39 import com.sun.enterprise.tools.jsfext.layout.descriptor.Resource;
40 import com.sun.enterprise.tools.jsfext.util.IncludeInputStream;
41
42 import java.io.IOException JavaDoc;
43 import java.io.BufferedInputStream JavaDoc;
44 import java.io.InputStream JavaDoc;
45 import java.net.URL JavaDoc;
46 import java.util.ArrayList JavaDoc;
47 import java.util.HashMap JavaDoc;
48 import java.util.Iterator JavaDoc;
49 import java.util.List JavaDoc;
50 import java.util.Map JavaDoc;
51
52 import javax.xml.parsers.DocumentBuilder JavaDoc;
53 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
54 import javax.xml.parsers.ParserConfigurationException JavaDoc;
55
56 import org.w3c.dom.Document JavaDoc;
57 import org.w3c.dom.Node JavaDoc;
58 import org.w3c.dom.NodeList JavaDoc;
59 import org.w3c.dom.NamedNodeMap JavaDoc;
60
61 import org.xml.sax.EntityResolver JavaDoc;
62 import org.xml.sax.ErrorHandler JavaDoc;
63 import org.xml.sax.SAXException JavaDoc;
64
65
66 /**
67  * <p> This class is responsible for doing the actual parsing of an XML
68  * document following the <code>layout.dtd</code>. It produces a
69  * {@link LayoutElement} tree with a {@link LayoutDefinition} object at
70  * the root of the tree.</p>
71  *
72  * @author Ken Paulsen (ken.paulsen@sun.com)
73  */

74 public class XMLLayoutDefinitionReader {
75
76     /**
77      * <p> Constructor.</p>
78      *
79      * @param url A URL pointing to the {@link LayoutDefinition}
80      * @param entityResolver EntityResolver to use, may be (null)
81      * @param errorHandler ErrorHandler to use, may be (null)
82      * @param baseURI The base URI passed to DocumentBuilder.parse()
83      */

84     public XMLLayoutDefinitionReader(URL JavaDoc url, EntityResolver JavaDoc entityResolver, ErrorHandler JavaDoc errorHandler, String JavaDoc baseURI) {
85     _url = url;
86     _entityResolver = entityResolver;
87     _errorHandler = errorHandler;
88     _baseURI = baseURI;
89     }
90
91     /**
92      * <p> Accessor for the URL.</p>
93      */

94     public URL JavaDoc getURL() {
95     return _url;
96     }
97
98     /**
99      * <p> Accessor for the entityResolver.</p>
100      */

101     public EntityResolver JavaDoc getEntityResolver() {
102     return _entityResolver;
103     }
104
105     /**
106      * <p> Accessor for the ErrorHandler.</p>
107      */

108     public ErrorHandler JavaDoc getErrorHandler() {
109     return _errorHandler;
110     }
111
112     /**
113      * <p> Accessor for the base URI.</p>
114      */

115     public String JavaDoc getBaseURI() {
116     return _baseURI;
117     }
118
119     /**
120      * <p> The read method opens the given URL and parses the XML document
121      * that it points to. It then walks the DOM and populates a
122      * {@link LayoutDefinition} structure, which is returned.</p>
123      *
124      * @return The {@link LayoutDefinition}
125      *
126      * @throws IOException
127      */

128     public LayoutDefinition read() throws IOException JavaDoc {
129     // Open the URL
130
InputStream inputStream = new IncludeInputStream(
131         new BufferedInputStream JavaDoc(getURL().openStream()));
132     Document JavaDoc doc = null;
133
134     try {
135         // Get a DocumentBuilderFactory and set it up
136
DocumentBuilderFactory JavaDoc dbf = DocumentBuilderFactory.newInstance();
137         dbf.setNamespaceAware(true);
138         dbf.setValidating(true);
139         dbf.setIgnoringComments(true);
140         dbf.setIgnoringElementContentWhitespace(false);
141         dbf.setCoalescing(false);
142         // The opposite of creating entity ref nodes is expanding inline
143
dbf.setExpandEntityReferences(true);
144
145         // Get a DocumentBuilder...
146
DocumentBuilder JavaDoc db = null;
147         try {
148         db = dbf.newDocumentBuilder();
149         } catch (ParserConfigurationException JavaDoc ex) {
150         throw new RuntimeException JavaDoc(ex);
151         }
152         if (getEntityResolver() != null) {
153         db.setEntityResolver(getEntityResolver());
154         }
155         if (getErrorHandler() != null) {
156         db.setErrorHandler(getErrorHandler());
157         }
158
159         // Parse the XML file
160
try {
161         doc = db.parse(inputStream, getBaseURI());
162         } catch (SAXException JavaDoc ex) {
163         throw new RuntimeException JavaDoc(ex);
164         }
165     } finally {
166         try {
167         inputStream.close();
168         } catch (Exception JavaDoc ex) {
169         // Ignore...
170
}
171     }
172
173     // Populate the LayoutDefinition from the Document
174
return createLayoutDefinition(doc);
175     }
176
177     /**
178      * <p> This method is responsible for extracting all the information out
179      * of the supplied document and filling the {@link LayoutDefinition}
180      * structure.</p>
181      *
182      * @param doc The <code>Document</code> object to read.
183      *
184      * @return The new {@link LayoutDefinition} Object.
185      */

186     private LayoutDefinition createLayoutDefinition(Document JavaDoc doc) {
187     // Get the document element (LAYOUT_DEFINITION_ELEMENT)
188
Node JavaDoc node = doc.getDocumentElement();
189     if (!node.getNodeName().equalsIgnoreCase(LAYOUT_DEFINITION_ELEMENT)) {
190         throw new RuntimeException JavaDoc("Document Element must be '"
191             + LAYOUT_DEFINITION_ELEMENT + "'");
192     }
193
194     // Create a new LayoutDefinition (the id is not propagated here)
195
LayoutDefinition ld = new LayoutDefinition("");
196
197     // Do "resources" first, they are defined at the top of the document
198
List JavaDoc childElements = getChildElements(node, RESOURCES_ELEMENT);
199     Iterator JavaDoc it = childElements.iterator();
200     if (it.hasNext()) {
201         // Found the RESOURCES_ELEMENT, there is at most 1
202
addResources(ld, (Node JavaDoc) it.next());
203     }
204
205     // Do "types", they need to be defined before parsing the layout
206
childElements = getChildElements(node, TYPES_ELEMENT);
207     it = childElements.iterator();
208     if (it.hasNext()) {
209         // Found the TYPES_ELEMENT, there is at most 1
210
addTypes(ld, (Node JavaDoc) it.next());
211     }
212
213     // Do "handlers" next, they need to be defined before parsing the layout
214
childElements = getChildElements(node, HANDLERS_ELEMENT);
215     it = childElements.iterator();
216     if (it.hasNext()) {
217         // Found the HANDLERS_ELEMENT, there is at most 1
218
cacheHandlerDefs((Node JavaDoc) it.next());
219     }
220
221     // Look to see if there is an EVENT_ELEMENT defined
222
childElements = getChildElements(node, EVENT_ELEMENT);
223     it = childElements.iterator();
224     if (it.hasNext()) {
225         // Found the EVENT_ELEMENT, there is at most 1
226
// Get the event type
227
Node JavaDoc eventNode = (Node JavaDoc) it.next();
228         String JavaDoc type = (String JavaDoc) getAttributes(eventNode).
229         get(TYPE_ATTRIBUTE);
230
231         // Set the Handlers for the given event type (name)
232
List JavaDoc handlers = ld.getHandlers(type);
233         ld.setHandlers(type, getHandlers(eventNode, handlers));
234     }
235
236     // Next look for "layout", there is exactly 1
237
childElements = getChildElements(node, LAYOUT_ELEMENT);
238     it = childElements.iterator();
239     if (it.hasNext()) {
240         // Found the LAYOUT_ELEMENT, there is only 1
241
addChildLayoutElements(ld, (Node JavaDoc) it.next());
242     } else {
243         throw new RuntimeException JavaDoc("A '" + LAYOUT_ELEMENT
244             + "' element is required in the XML document!");
245     }
246
247     // Return the LayoutDefinition
248
return ld;
249     }
250
251     /**
252      * <p> This method iterates throught the child RESOURCE_ELEMENT nodes and
253      * adds new resource objects to the {@link LayoutDefinition}.</p>
254      *
255      * @param ld The {@link LayoutDefinition}
256      * @param node Parent <code>Node</code> containing the
257      * {@link RESOURCE_ELEMENT} nodes.
258      */

259     private void addResources(LayoutDefinition ld, Node JavaDoc node) {
260     // Get the child nodes
261
Iterator JavaDoc it = getChildElements(node, RESOURCE_ELEMENT).iterator();
262
263     // Walk children (we only care about RESOURCE_ELEMENT)
264
while (it.hasNext()) {
265         // Found a RESOURCE_ELEMENT
266
ld.addResource(createResource((Node JavaDoc) it.next()));
267     }
268     }
269
270     /**
271      * <p> This method takes the given Resource Element node and reads the
272      * {@link ID_ATTRIBUTE}, {@link EXTRA_INFO_ATTRIBUTE} and
273      * {@link FACTORY_CLASS_ATTRIBUTE} attributes. It then instantiates
274      * a new {@link Resource} with the values of these two attributes.</p>
275      *
276      * @param node The {@link Resource} node to extract information from
277      * when creating the {@link Resource}.
278      */

279     private Resource createResource(Node JavaDoc node) {
280     // Pull off the attributes
281
Map JavaDoc attributes = getAttributes(node);
282     String JavaDoc id = (String JavaDoc) attributes.get(ID_ATTRIBUTE);
283     String JavaDoc extraInfo =
284         (String JavaDoc) attributes.get(EXTRA_INFO_ATTRIBUTE);
285     String JavaDoc factoryClass =
286         (String JavaDoc) attributes.get(FACTORY_CLASS_ATTRIBUTE);
287
288     // Make sure required values are present
289
if ((factoryClass == null) || (id == null) || (extraInfo == null)
290         || (factoryClass.trim().equals("")) || (id.trim().equals(""))
291         || (extraInfo.trim().equals(""))) {
292         throw new RuntimeException JavaDoc("'" + ID_ATTRIBUTE + "', '"
293             + EXTRA_INFO_ATTRIBUTE + "', and '"
294             + FACTORY_CLASS_ATTRIBUTE + "' are required attributes of '"
295             + RESOURCE_ELEMENT + "' Element!");
296     }
297
298     // Create the new Resource
299
return new Resource(id, extraInfo, factoryClass);
300     }
301
302     /**
303      * <p> This method iterates through the child
304      * {@link COMPONENT_TYPE_ELEMENT} nodes and adds new
305      * {@link ComponentTypes} to the {@link LayoutDefinition}.</p>
306      *
307      * @param ld The {@link LayoutDefinition}
308      * @param node Parent <code>Node</code> containing the
309      * {@link COMPONENT_TYPE_ELEMENT} nodes
310      */

311     private void addTypes(LayoutDefinition ld, Node JavaDoc node) {
312     // Get the child nodes
313
Iterator JavaDoc it = getChildElements(node, COMPONENT_TYPE_ELEMENT).iterator();
314
315     // Walk the COMPONENT_TYPE_ELEMENT elements
316
while (it.hasNext()) {
317         ld.addComponentType(createComponentType((Node JavaDoc) it.next()));
318     }
319     }
320
321     /**
322      * <p> This method takes the given {@link ComponentType} Element node and
323      * reads the {@link ID_ATTRIBUTE} and {@link FACTORY_CLASS_ATTRIBUTE}
324      * attributes. It then instantiates a new {@link ComponentType} with
325      * the values of these two attributes.</p>
326      *
327      * @param node The {@link ComponentType} node to extract information
328      * from when creating the {@link ComponentType}.
329      */

330     private ComponentType createComponentType(Node JavaDoc node) {
331     // Pull off the attributes
332
Map JavaDoc attributes = getAttributes(node);
333     String JavaDoc id = (String JavaDoc) attributes.get(ID_ATTRIBUTE);
334     String JavaDoc factoryClass =
335         (String JavaDoc) attributes.get(FACTORY_CLASS_ATTRIBUTE);
336
337     // Make sure required values are present
338
if ((factoryClass == null) || (id == null)
339         || (factoryClass.trim().equals("")) || (id.trim().equals(""))) {
340         throw new RuntimeException JavaDoc("Both '" + ID_ATTRIBUTE + "' and '"
341             + FACTORY_CLASS_ATTRIBUTE + "' are required attributes of '"
342             + COMPONENT_TYPE_ELEMENT + "' Element!");
343     }
344
345     // Create the new ComponentType
346
return new ComponentType(id, factoryClass);
347     }
348
349     /**
350      * <p> This method iterates through the child
351      * {@link HANDLER_DEFINITION_ELEMENT} nodes and caches them, so they
352      * may be retrieved later by {@link Handlers} referring to them.</p>
353      *
354      * @param node Parent <code>Node</code> containing
355      * {@link HANDLER_DEFINITION_ELEMENT} nodes.
356      */

357     private void cacheHandlerDefs(Node JavaDoc node) {
358     HandlerDefinition def = null;
359
360     // Get the child nodes
361
Iterator JavaDoc it =
362         getChildElements(node, HANDLER_DEFINITION_ELEMENT).iterator();
363     while (it.hasNext()) {
364         // Found a HANDLER_DEFINITION_ELEMENT, cache it
365
def = createHandlerDefinition((Node JavaDoc) it.next());
366         _handlerDefs.put(def.getId(), def);
367     }
368     }
369
370     /**
371      * <p> This method takes the given {@link HANDLER_DEFINITION_ELEMENT}
372      * node and reads the {@link ID_ATTRIBUTE},
373      * {@link CLASS_NAME_ATTRIBUTE}, and {@link METHOD_NAME_ATTRIBUTE}
374      * attributes. It then instantiates a new {@link HandlerDefinition}
375      * object.</p>
376      *
377      * <p> Next it looks to see if the {@link HandlerDefinition} has child
378      * inputDef, outputDef, and/or nested handler elements. If so it
379      * processes them.</p>
380      *
381      * @param node The {@link HANDLER_DEFINITION_ELEMENT} node to extract
382      * information from when creating the
383      * {@link HandlerDefinition}.
384      *
385      * @return The newly created {@link HandlerDefinition}.
386      */

387     public HandlerDefinition createHandlerDefinition(Node JavaDoc node) {
388
389     // Create he HandlerDefinition
390
Map JavaDoc attributes = getAttributes(node);
391     String JavaDoc value = (String JavaDoc) attributes.get(ID_ATTRIBUTE);
392     HandlerDefinition hd = new HandlerDefinition(value);
393
394 // hd.setDescription(_description)
395

396     // Check for a className
397
value = (String JavaDoc) attributes.get(CLASS_NAME_ATTRIBUTE);
398     if ((value != null) && !value.equals("")) {
399         // Found a className, now get the methodName
400
String JavaDoc tmpStr =
401         (String JavaDoc) attributes.get(METHOD_NAME_ATTRIBUTE);
402         if ((tmpStr == null) || tmpStr.equals("")) {
403         throw new IllegalArgumentException JavaDoc("You must provide a '"
404             + METHOD_NAME_ATTRIBUTE + "' attribute on the '"
405             + HANDLER_DEFINITION_ELEMENT + "' element with "
406             + CLASS_NAME_ATTRIBUTE + " atttribute equal to '"
407             + value + "'.");
408         }
409         hd.setHandlerMethod(value, tmpStr);
410     }
411
412     // Add child handlers to this HandlerDefinition. This allows a
413
// HandlerDefinition to define handlers that should be invoked before
414
// the method defined by this handler definition is invoked.
415
List JavaDoc handlers = hd.getChildHandlers();
416     hd.setChildHandlers(getHandlers(node, handlers));
417
418     // Add InputDef objects to the HandlerDefinition
419
addInputDefs(hd, node);
420
421     // Add OutputDef objects to the HandlerDefinition
422
addOutputDefs(hd, node);
423
424     // Return the newly created HandlerDefinition object
425
return hd;
426     }
427
428     /**
429      * <p> This method creates a <code>List</code> of {@link Handler}s from
430      * the provided <code>Node</code>. It will look at the child
431      * <code>Element</code>s for {@link HANDLER_ELEMENT} elements. When
432      * found, it will create a new {@link Handler} object and add it to a
433      * <code>List</code> that is created internally. This
434      * <code>List</code> is returned.</p>
435      *
436      * @param node <code>Node</code> containing
437      * {@link HANDLER_ELEMENT} elements.
438      * @param handlers <code>List</code> of existing {@link Handler}s.
439      *
440      * @return A <code>List</code> of {@link Handler} objects, empty
441      * <code>List</code> if no {@link Handler}s found
442      */

443     private List JavaDoc getHandlers(Node JavaDoc node, List JavaDoc handlers) {
444     // Get the child nodes
445
Iterator JavaDoc it = getChildElements(node, HANDLER_ELEMENT).iterator();
446
447     // Walk children (we only care about HANDLER_ELEMENT)
448
if (handlers == null) {
449         handlers = new ArrayList JavaDoc();
450     }
451     while (it.hasNext()) {
452         // Found a HANDLER_ELEMENT
453
handlers.add(createHandler((Node JavaDoc) it.next()));
454     }
455
456     // Return the handlers
457
return handlers;
458     }
459
460     /**
461      * <p> This method creates a {@link Handler} from the given handler
462      * <code>Node</code>. It will add input and/or output mappings
463      * specified by any child Elements named {@link INPUT_ELEMENT} or
464      * {@link OUTPUT_MAPPING_ELEMENT}.</p>
465      *
466      * @param handlerNode The <code>Node</code> describing the
467      * {@link Handler} to be created.
468      *
469      * @return The newly created {@link Handler}.
470      */

471     private Handler createHandler(Node JavaDoc handlerNode) {
472     // Pull off attributes...
473
String JavaDoc id = (String JavaDoc) getAttributes(handlerNode).
474         get(ID_ATTRIBUTE);
475     if ((id == null) || (id.trim().equals(""))) {
476         throw new RuntimeException JavaDoc("'" + ID_ATTRIBUTE
477             + "' attribute not found on '" + HANDLER_ELEMENT
478             + "' Element!");
479     }
480
481     // Find the HandlerDefinition associated with this Handler
482
HandlerDefinition handlerDef = (HandlerDefinition) _handlerDefs.get(id);
483     if (handlerDef == null) {
484         throw new IllegalArgumentException JavaDoc(HANDLER_ELEMENT + " elements "
485             + ID_ATTRIBUTE + " attribute must match the "
486             + ID_ATTRIBUTE + " attribute of a "
487             + HANDLER_DEFINITION_ELEMENT + ". A HANDLER_ELEMENT with '"
488             + id + "' was specified, however there is no cooresponding "
489             + HANDLER_DEFINITION_ELEMENT + " with a matching "
490             + ID_ATTRIBUTE + " attribute.");
491     }
492
493     // Create new Handler
494
Handler handler = new Handler(handlerDef);
495
496     // Add the inputs
497
Map JavaDoc attributes = null;
498     Node JavaDoc inputNode = null;
499     Iterator JavaDoc it = getChildElements(handlerNode, INPUT_ELEMENT).iterator();
500     while (it.hasNext()) {
501         // Processing an INPUT_ELEMENT
502
inputNode = (Node JavaDoc) it.next();
503         attributes = getAttributes(inputNode);
504         handler.setInputValue(
505         (String JavaDoc) attributes.get(NAME_ATTRIBUTE),
506         getValueFromNode(inputNode, attributes));
507     }
508
509     // Add the OutputMapping objects
510
it = getChildElements(handlerNode, OUTPUT_MAPPING_ELEMENT).iterator();
511     while (it.hasNext()) {
512         // Processing an OUTPUT_MAPPING_ELEMENT
513
attributes = getAttributes((Node JavaDoc) it.next());
514         handler.setOutputMapping(
515         (String JavaDoc) attributes.get(OUTPUT_NAME_ATTRIBUTE),
516         (String JavaDoc) attributes.get(TARGET_KEY_ATTRIBUTE),
517         (String JavaDoc) attributes.get(TARGET_TYPE_ATTRIBUTE));
518     }
519
520     // Return the newly created handler
521
return handler;
522     }
523
524     /**
525      * <p> This method adds InputDefs to the given {@link HandlerDefinition}
526      * object. It will look at the child elements for those named
527      * {@link INPUT_DEF_ELEMENT}. It will create an {@link IODescriptor}
528      * for each and add it to the {@link HandlerDefinition}.</p>
529      *
530      * @param hd {@link HandlerDefinition}.
531      * @param hdNode {@link HandlerDefinition} <code>Node</code>, its
532      * children will be searched
533      */

534     private void addInputDefs(HandlerDefinition hd, Node JavaDoc hdNode) {
535     // Get the child nodes
536
Iterator JavaDoc it = getChildElements(hdNode, INPUT_DEF_ELEMENT).iterator();
537
538     // Walk children (we only care about INPUT_DEF_ELEMENT)
539
while (it.hasNext()) {
540         // Found a INPUT_DEF_ELEMENT
541
hd.addInputDef(createIODescriptor((Node JavaDoc) it.next()));
542     }
543     }
544
545     /**
546      * <p> This method adds OutputDefs to the given {@link HandlerDefinition}
547      * object. It will look at the child elements for those named
548      * {@link OUTPUT_DEF_ELEMENT}. It will create an {@link IODescriptor}
549      * for each and add it to the {@link HandlerDefinition}.</p>
550      *
551      * @param hd {@link HandlerDefinition}.
552      * @param hdNode {@link HandlerDefinition} <code>Node</code>, its
553      * children will be searched.
554      */

555     private void addOutputDefs(HandlerDefinition hd, Node JavaDoc hdNode) {
556     // Get the child nodes
557
Iterator JavaDoc it = getChildElements(hdNode, OUTPUT_DEF_ELEMENT).iterator();
558
559     // Walk children (we only care about OUTPUT_DEF_ELEMENT)
560
while (it.hasNext()) {
561         // Found a OUTPUT_DEF_ELEMENT
562
hd.addOutputDef(createIODescriptor((Node JavaDoc) it.next()));
563     }
564     }
565
566     /**
567      * <p> This method will create an {@link IODescriptor} from the given
568      * node. The node must contain atleast a {@link NAME_ATTRIBUTE} and a
569      * {@link TYPE_ATTRIBUTE} attribute. It may also contain a
570      * {@link DEFAULT_ATTRIBUTE} and a {@link REQUIRED_ATTRIBUTE}. These
571      * are only meaningful for input {@link IODescriptors}, however --
572      * this method does not know the difference between input and output
573      * descriptors.</p>
574      *
575      * @param node The <code>Node</code> holding info used to create an
576      * {@link IODescriptor}.
577      *
578      * @return A newly created {@link IODescriptor}.
579      */

580     private IODescriptor createIODescriptor(Node JavaDoc node) {
581     // Get the attributes
582
Map JavaDoc attributes = getAttributes(node);
583     String JavaDoc name = (String JavaDoc) attributes.get(NAME_ATTRIBUTE);
584     if ((name == null) || name.equals("")) {
585         throw new IllegalArgumentException JavaDoc("Name must be provided!");
586     }
587     String JavaDoc type = (String JavaDoc) attributes.get(TYPE_ATTRIBUTE);
588     if ((type == null) || type.equals("")) {
589         throw new IllegalArgumentException JavaDoc("Type must be provided!");
590     }
591     Object JavaDoc def = attributes.get(DEFAULT_ATTRIBUTE);
592     String JavaDoc req = (String JavaDoc) attributes.get(REQUIRED_ATTRIBUTE);
593
594     // Create the IODescriptor
595
IODescriptor ioDesc = new IODescriptor(name, type);
596     ioDesc.setDefault(def);
597     if (req != null) {
598         ioDesc.setRequired(Boolean.valueOf(req).booleanValue());
599     }
600 // ioDesc.setDescription(attributes.get(DESCRIPTION_ATTRIBUTE))
601

602     // Return the new IODescriptor
603
return ioDesc;
604     }
605
606     /**
607      * <p> This method adds child LayoutElements.</p>
608      *
609      * @param ld
610      * @param node
611      */

612     private void addChildLayoutElements(LayoutElement layElt, Node JavaDoc node) {
613     // Get the child nodes
614
Iterator JavaDoc it = getChildElements(node).iterator();
615
616     // Walk children (we care about IF_ELEMENT, ATTRIBUTE_ELEMENT,
617
// MARKUP_ELEMENT, FACET_ELEMENT, STATIC_TEXT_ELEMENT,
618
// COMPONENT_ELEMENT, EVENT_ELEMENT, FOREACH_ELEMENT, EDIT_ELEMENT, and
619
// WHILE_ELEMENT)
620
Node JavaDoc childNode = null;
621     String JavaDoc name = null;
622     while (it.hasNext()) {
623         childNode = (Node JavaDoc) it.next();
624         name = childNode.getNodeName();
625         if (name.equalsIgnoreCase(IF_ELEMENT)) {
626         // Found a IF_ELEMENT
627
layElt.addChildLayoutElement(
628             createLayoutIf(layElt, childNode));
629         } else if (name.equalsIgnoreCase(ATTRIBUTE_ELEMENT)) {
630         // Found a ATTRIBUTE_ELEMENT
631
LayoutElement childElt =
632             createLayoutAttribute(layElt, childNode);
633         if (childElt != null) {
634             layElt.addChildLayoutElement(childElt);
635         }
636         } else if (name.equalsIgnoreCase(MARKUP_ELEMENT)) {
637         // Found a MARKUP_ELEMENT
638
layElt.addChildLayoutElement(
639             createLayoutMarkup(layElt, childNode));
640         } else if (name.equalsIgnoreCase(FACET_ELEMENT)) {
641         // Found a FACET_ELEMENT
642
layElt.addChildLayoutElement(
643             createLayoutFacet(layElt, childNode));
644         } else if (name.equalsIgnoreCase(STATIC_TEXT_ELEMENT)) {
645         // Found a STATIC_TEXT_ELEMENT
646
layElt.addChildLayoutElement(
647             createLayoutStaticText(layElt, childNode));
648         } else if (name.equalsIgnoreCase(COMPONENT_ELEMENT)) {
649         // Found a COMPONENT_ELEMENT
650
layElt.addChildLayoutElement(
651             createLayoutComponent(layElt, childNode));
652         } else if (name.equalsIgnoreCase(EVENT_ELEMENT)) {
653         // Found a EVENT_ELEMENT
654
// Get the event type
655
name = (String JavaDoc) getAttributes(childNode).
656             get(TYPE_ATTRIBUTE);
657         // Set the Handlers for the given event type (name)
658
List JavaDoc handlers = layElt.getHandlers(name);
659         layElt.setHandlers(name, getHandlers(childNode, handlers));
660         } else if (name.equalsIgnoreCase(FOREACH_ELEMENT)) {
661         // Found a FOREACH_ELEMENT
662
layElt.addChildLayoutElement(
663             createLayoutForEach(layElt, childNode));
664         } else if (name.equalsIgnoreCase(WHILE_ELEMENT)) {
665         // Found a WHILE_ELEMENT
666
layElt.addChildLayoutElement(
667             createLayoutWhile(layElt, childNode));
668         } else if (name.equalsIgnoreCase(EDIT_ELEMENT)) {
669         // Found an EDIT_ELEMENT
670
layElt.addChildLayoutElement(
671             createEditLayoutComponent(layElt, childNode));
672         } else {
673         throw new RuntimeException JavaDoc("Unknown Element Found: '"
674             + childNode.getNodeName() + "' under '"
675             + node.getNodeName() + "'.");
676         }
677     }
678     }
679
680     /**
681      * <p> This method creates a new {@link LayoutIf}
682      * {@link LayoutElement}.</p>
683      *
684      * @param parent The parent {@link LayoutElement}.
685      * @param node The {@link IF_ELEMENT} node to extract information from
686      * when creating the {@link LayoutIf}
687      */

688     private LayoutElement createLayoutIf(LayoutElement parent, Node JavaDoc node) {
689     // Pull off attributes...
690
String JavaDoc condition = (String JavaDoc) getAttributes(node).get(
691         CONDITION_ATTRIBUTE);
692     if ((condition == null) || (condition.trim().equals(""))) {
693         throw new RuntimeException JavaDoc("'" + CONDITION_ATTRIBUTE
694             + "' attribute not found on '" + IF_ELEMENT + "' Element!");
695     }
696
697     // Create new LayoutIf
698
LayoutElement ifElt = new LayoutIf(parent, condition);
699
700     // Add children...
701
addChildLayoutElements(ifElt, node);
702
703     // Return the if
704
return ifElt;
705     }
706
707     /**
708      * <p> This method creates a new {@link LayoutForEach}
709      * {@link LayoutElement}.</p>
710      *
711      * @param parent The parent {@link LayoutElement}.
712      * @param node The {@link #FOREACH_ELEMENT} node to extract
713      * information from when creating the
714      * {@link LayoutForEach}.
715      *
716      * @return The new {@link LayoutForEach} {@link LayoutElement}.
717      */

718     private LayoutElement createLayoutForEach(LayoutElement parent, Node JavaDoc node) {
719     // Pull off attributes...
720
String JavaDoc list = (String JavaDoc) getAttributes(node).get(
721         LIST_ATTRIBUTE);
722     if ((list == null) || (list.trim().equals(""))) {
723         throw new RuntimeException JavaDoc("'" + LIST_ATTRIBUTE
724             + "' attribute not found on '" + FOREACH_ELEMENT
725             + "' Element!");
726     }
727     String JavaDoc key = (String JavaDoc) getAttributes(node).get(
728         KEY_ATTRIBUTE);
729     if ((key == null) || (key.trim().equals(""))) {
730         throw new RuntimeException JavaDoc("'" + KEY_ATTRIBUTE
731             + "' attribute not found on '" + FOREACH_ELEMENT
732             + "' Element!");
733     }
734
735     // Create new LayoutForEach
736
LayoutElement forEachElt = new LayoutForEach(parent, list, key);
737
738     // Add children...
739
addChildLayoutElements(forEachElt, node);
740
741     // Return the forEach
742
return forEachElt;
743     }
744
745     /**
746      * <p> This method creates a new {@link LayoutWhile}
747      * {@link LayoutElement}.</p>
748      *
749      * @param parent The parent {@link LayoutElement}.
750      * @param node The {@link #WHILE_ELEMENT} node to extract information
751      * from when creating the LayoutWhile.
752      *
753      * @return The new {@link LayoutWhile} {@link LayoutElement}.
754      */

755     private LayoutElement createLayoutWhile(LayoutElement parent, Node JavaDoc node) {
756     // Pull off attributes...
757
String JavaDoc condition = (String JavaDoc) getAttributes(node).get(
758         CONDITION_ATTRIBUTE);
759     if ((condition == null) || (condition.trim().equals(""))) {
760         throw new RuntimeException JavaDoc("'" + CONDITION_ATTRIBUTE
761             + "' attribute not found on '" + WHILE_ELEMENT
762             + "' Element!");
763     }
764
765     // Create new LayoutWhile
766
LayoutElement whileElt = new LayoutWhile(parent, condition);
767
768     // Add children...
769
addChildLayoutElements(whileElt, node);
770
771     // Return the while
772
return whileElt;
773     }
774
775     /**
776      *
777      *
778      * @param parent The parent {@link LayoutElement}.
779      * @param node The {@link #ATTRIBUTE_ELEMENT} node to extract
780      * information from when creating the
781      * {@link LayoutAttribute}
782      */

783     private LayoutElement createLayoutAttribute(LayoutElement parent, Node JavaDoc node) {
784     // Pull off attributes...
785
Map JavaDoc attributes = getAttributes(node);
786     String JavaDoc name = (String JavaDoc) attributes.get(NAME_ATTRIBUTE);
787     if ((name == null) || (name.trim().equals(""))) {
788         throw new RuntimeException JavaDoc("'" + NAME_ATTRIBUTE
789             + "' attribute not found on '" + ATTRIBUTE_ELEMENT
790             + "' Element!");
791     }
792     LayoutElement attributeElt = null;
793
794     // Check if we're setting this on a LayoutComponent vs. LayoutMarkup
795
// Do this after checking for "name" to show correct error message
796
LayoutComponent comp = null;
797     if (parent instanceof LayoutComponent) {
798         comp = (LayoutComponent) parent;
799     } else {
800         comp = getParentLayoutComponent(parent);
801     }
802     if (comp != null) {
803         // Treat this as a LayoutComponent "option" instead of "attribute"
804
addOption(comp, node);
805     } else {
806         String JavaDoc value = (String JavaDoc) attributes.get(VALUE_ATTRIBUTE);
807         String JavaDoc property = (String JavaDoc) attributes.get(PROPERTY_ATTRIBUTE);
808
809         // Create new LayoutAttribute
810
attributeElt = new LayoutAttribute(parent, name, value, property);
811
812         // Add children... (event children are supported)
813
addChildLayoutElements(attributeElt, node);
814     }
815
816     // Return the LayoutAttribute (or null if inside LayoutComponent)
817
return attributeElt;
818     }
819
820     /**
821      * <p> This method creates a new {@link LayoutMarkup}.
822      *
823      * @param parent The parent {@link LayoutElement}.
824      * @param node The {@link MARKUP_ELEMENT} node to extract information
825      * from when creating the {@link LayoutMarkup}.
826      */

827     private LayoutElement createLayoutMarkup(LayoutElement parent, Node JavaDoc node) {
828     // Pull off attributes...
829
Map JavaDoc attributes = getAttributes(node);
830     String JavaDoc tag = (String JavaDoc) attributes.get(TAG_ATTRIBUTE);
831     if ((tag == null) || (tag.trim().equals(""))) {
832         throw new RuntimeException JavaDoc("'" + TAG_ATTRIBUTE
833             + "' attribute not found on '" + MARKUP_ELEMENT
834             + "' Element!");
835     }
836
837     // Check to see if this is inside a LayoutComponent, if so, we must
838
// use a LayoutComponent for it to get rendered
839
LayoutElement markupElt = null;
840     if ((parent instanceof LayoutComponent)
841         || isNestedLayoutComponent(parent)) {
842         // Make a "markup" LayoutComponent..
843
ComponentType type = ensureMarkupType(parent);
844         markupElt = new LayoutComponent(
845             parent, MARKUP_ELEMENT + _markupCount++, type);
846         LayoutComponent markupComp = ((LayoutComponent) markupElt);
847         markupComp.addOption("tag", tag);
848         markupComp.setNested(true);
849         markupComp.setFacetChild(false);
850
851         // Add children...
852
addChildLayoutComponentChildren(markupComp, node);
853     } else {
854         // Create new LayoutMarkup
855
String JavaDoc type = (String JavaDoc) attributes.get(TYPE_ATTRIBUTE);
856         markupElt = new LayoutMarkup(parent, tag, type);
857
858         // Add children...
859
addChildLayoutElements(markupElt, node);
860     }
861
862     // Return the LayoutMarkup
863
return markupElt;
864     }
865
866     /**
867      * <p> This method is responsible for Creating a {@link LayoutFacet}
868      * {@link LayoutElement}.</p>
869      *
870      * @param parent The parent {@link LayoutElement}.
871      * @param node The {@link #FACET_ELEMENT} node to extract information
872      * from when creating the {@link LayoutFacet}.
873      *
874      * @return The new {@link LayoutFacet} {@link LayoutElement}.
875      */

876     private LayoutElement createLayoutFacet(LayoutElement parent, Node JavaDoc node) {
877     // Pull off attributes...
878
// id
879
String JavaDoc id = (String JavaDoc) getAttributes(node).get(ID_ATTRIBUTE);
880     if ((id == null) || (id.trim().equals(""))) {
881         throw new RuntimeException JavaDoc("'" + ID_ATTRIBUTE
882             + "' attribute not found on '" + FACET_ELEMENT
883             + "' Element!");
884     }
885
886     // Create new LayoutFacet
887
LayoutFacet facetElt = new LayoutFacet(parent, id);
888
889     // Set isRendered
890
String JavaDoc rendered = (String JavaDoc) getAttributes(node).get(RENDERED_ATTRIBUTE);
891     boolean isRendered = true;
892     if ((rendered == null) || rendered.trim().equals("")
893         || rendered.equals(AUTO_RENDERED)) {
894         // Automatically determine if this LayoutFacet should be rendered
895
isRendered = !isNestedLayoutComponent(facetElt);
896     } else {
897         isRendered = Boolean.getBoolean(rendered);
898     }
899     facetElt.setRendered(isRendered);
900
901     // Add children...
902
addChildLayoutElements(facetElt, node);
903
904     // Return the LayoutFacet
905
return facetElt;
906     }
907
908     /**
909      * <p> This method returns true if any of the parent
910      * {@link LayoutElement}s are {@link LayoutComponent}s. If a
911      * {@link LayoutFacet} is encountered first, false is automatically
912      * returned. This method is specific to processing needed for
913      * creating a {@link LayoutComponent}. Do not use this for general
914      * cases when you need to find if a {@link LayoutElement} is embedded
915      * within a {@link LayoutComponent} (which should ignore
916      * {@link LayoutFacet} elements).</p>
917      *
918      * @param elt The {@link LayoutElement} to check.
919      *
920      * @return true if it has a {@link LayoutComponent} ancestor.
921      */

922     private static boolean isLayoutComponentChild(LayoutElement elt) {
923     elt = elt.getParent();
924     while (elt != null) {
925         if (elt instanceof LayoutComponent) {
926         return true;
927         } else if (elt instanceof LayoutFacet) {
928         // Don't consider it a child if it is a facet
929
return false;
930         }
931         elt = elt.getParent();
932     }
933
934     // Not found
935
return false;
936     }
937
938     /**
939      * <p> This method determines if the given {@link LayoutElement} is
940      * inside a {@link LayoutComponent}. It will look at all the
941      * parents, if any of them are {@link LayoutComponent} instances,
942      * this method will return <code>true</code>.</p>
943      *
944      * @param elt The {@link LayoutElement} to check.
945      *
946      * @return true If a {@link LayoutComponent} exists as an ancestor.
947      */

948     public static boolean isNestedLayoutComponent(LayoutElement elt) {
949     return (getParentLayoutComponent(elt) != null);
950     }
951
952     /**
953      *
954      * @param node The {@link #COMPONENT_ELEMENT} node to extract
955      * information from when creating the
956      * {@link LayoutComponent}.
957      */

958     private LayoutElement createLayoutComponent(LayoutElement parent, Node JavaDoc node) {
959     // Pull off attributes...
960
Map JavaDoc attributes = getAttributes(node);
961     String JavaDoc id = (String JavaDoc) attributes.get(ID_ATTRIBUTE);
962     String JavaDoc type = (String JavaDoc) attributes.get(TYPE_ATTRIBUTE);
963     if ((type == null) || (type.trim().equals(""))) {
964         throw new RuntimeException JavaDoc("'" + TYPE_ATTRIBUTE
965             + "' attribute not found on '" + COMPONENT_ELEMENT
966             + "' Element!");
967     }
968
969     // Create new LayoutComponent
970
LayoutComponent component = new LayoutComponent(parent, id,
971         getComponentType(parent, type));
972
973     // Check for overwrite flag
974
String JavaDoc overwrite = (String JavaDoc) attributes.get(OVERWRITE_ATTRIBUTE);
975     if ((overwrite != null) && (overwrite.length() > 0)) {
976         component.setOverwrite(Boolean.valueOf(overwrite).booleanValue());
977     }
978
979     // Set flag to indicate if this LayoutComponent is nested in another
980
// LayoutComponent. This is significant b/c during rendering, events
981
// will need to be fired differently (the TemplateRenderer /
982
// LayoutElements will not have any control). The strategy used will
983
// rely on "instance" handlers, this flag indicates that "instance"
984
// handlers should be used.
985
// NOTE: While this could be implemented on the LayoutComponent
986
// itself, I decided not to for performance reasons and to
987
// allow this value to be overruled if desired.
988
component.setNested(isNestedLayoutComponent(component));
989
990     // Figure out if this should be stored as a facet, if so under what id
991
if (isLayoutComponentChild(component)) {
992         component.setFacetChild(false);
993     } else {
994         // Need to add this so that it has the correct facet name
995
// Check to see if this LayoutComponent is inside a LayoutFacet
996
while (parent != null) {
997         if (parent instanceof LayoutFacet) {
998             // Inside a LayoutFacet, use its id... only if this facet
999
// is a child of a LayoutComponent (otherwise, it is a
1000
// layout facet used for layout, not for defining a facet
1001
// of a UIComponent)
1002
if (isLayoutComponentChild(parent)) {
1003            id = parent.getUnevaluatedId();
1004            }
1005            break;
1006        }
1007        parent = parent.getParent();
1008        }
1009        // Set the facet name
1010
component.addOption(LayoutComponent.FACET_NAME, id);
1011    }
1012
1013    // Add children... (different for component LayoutElements)
1014
addChildLayoutComponentChildren(component, node);
1015
1016    // Return the LayoutComponent
1017
return component;
1018    }
1019
1020    /**
1021     *
1022     */

1023    private void addChildLayoutComponentChildren(LayoutComponent component, Node JavaDoc node) {
1024    // Get the child nodes
1025
Iterator JavaDoc it = getChildElements(node).iterator();
1026
1027    // Walk children (we care about COMPONENT_ELEMENT, FACET_ELEMENT,
1028
// OPTION_ELEMENT, EVENT_ELEMENT, MARKUP_ELEMENT, and EDIT_ELEMENT)
1029
Node JavaDoc childNode = null;
1030    String JavaDoc name = null;
1031    while (it.hasNext()) {
1032        childNode = (Node JavaDoc) it.next();
1033        name = childNode.getNodeName();
1034        if (name.equalsIgnoreCase(COMPONENT_ELEMENT)) {
1035        // Found a COMPONENT_ELEMENT
1036
component.addChildLayoutElement(
1037            createLayoutComponent(component, childNode));
1038        } else if (name.equalsIgnoreCase(FACET_ELEMENT)) {
1039        // Found a FACET_ELEMENT
1040
component.addChildLayoutElement(
1041            createLayoutFacet(component, childNode));
1042        } else if (name.equalsIgnoreCase(OPTION_ELEMENT)) {
1043        // Found a OPTION_ELEMENT
1044
addOption(component, childNode);
1045        } else if (name.equalsIgnoreCase(EVENT_ELEMENT)) {
1046        // Found a EVENT_ELEMENT
1047
// Get the event type
1048
name = (String JavaDoc) getAttributes(childNode).
1049            get(TYPE_ATTRIBUTE);
1050
1051        // Set the Handlers for the given event type (name)
1052
List JavaDoc handlers = component.getHandlers(name);
1053        component.setHandlers(name, getHandlers(childNode, handlers));
1054        } else if (name.equalsIgnoreCase(EDIT_ELEMENT)) {
1055        // Found an EDIT_ELEMENT
1056
component.addChildLayoutElement(
1057            createEditLayoutComponent(component, childNode));
1058        } else if (name.equalsIgnoreCase(MARKUP_ELEMENT)) {
1059        // Found an MARKUP_ELEMENT
1060
component.addChildLayoutElement(
1061            createLayoutMarkup(component, childNode));
1062        } else if (name.equalsIgnoreCase(ATTRIBUTE_ELEMENT)) {
1063        // Found a ATTRIBUTE_ELEMENT (actually in this case it will
1064
// just add an "option" to the LayoutComponent), technically
1065
// this case should only happen for LayoutMarkup components...
1066
// this mess is caused by trying to support 2 .dtd's w/ 1 .dtd
1067
// file... perhaps it's time to split.
1068
createLayoutAttribute(component, childNode);
1069        } else {
1070        throw new RuntimeException JavaDoc("Unknown Element Found: '"
1071            + childNode.getNodeName() + "' under '"
1072            + COMPONENT_ELEMENT + "'.");
1073        }
1074    }
1075    }
1076
1077    /**
1078     * <p> This adds a special {@link LayoutComponent} to the
1079     * <code>UIComponent</code> tree that serves as a marker indicating
1080     * that it is OK to edit this block of code. Editors can take
1081     * advantage of this to know what is safe to edit. The type will be
1082     * "markup" the id will be prefixed by {@link #EDITABLE} and an
1083     * "option" named {@link EDITABLE}, value == <code>true</code> will
1084     * be added.</p>
1085     *
1086     * @param node The {@link #COMPONENT_ELEMENT} node to extract
1087     * information from when creating the <em>Edit</em>
1088     * {@link LayoutComponent}.
1089     */

1090    private LayoutElement createEditLayoutComponent(LayoutElement parent, Node JavaDoc node) {
1091    // First Add a popupMenu around this component... use it as the parent
1092
parent = createEditPopupMenuLayoutComponent(parent, node);
1093
1094    // Pull off attributes...
1095
Map JavaDoc attributes = getAttributes(node);
1096    String JavaDoc id = (String JavaDoc) attributes.get(ID_ATTRIBUTE);
1097
1098    // Create the LayoutComponent
1099
ComponentType type = ensureEditAreaType(parent);
1100    LayoutComponent component =
1101        new LayoutComponent(parent, EDITABLE + id, type);
1102    parent.addChildLayoutElement(component);
1103
1104    // Configure it...
1105
component.setNested(isNestedLayoutComponent(component));
1106    component.setFacetChild(false);
1107    component.addOption(EDITABLE, Boolean.TRUE); // Flag
1108

1109    // Add children... (different for component LayoutElements)
1110
addChildLayoutComponentChildren(component, node);
1111
1112    return parent;
1113    }
1114
1115    /**
1116     * <p> This method creates a PopupMenu component w/ the Editor
1117     * commands.</p>
1118     */

1119    private LayoutElement createEditPopupMenuLayoutComponent(LayoutElement parent, Node JavaDoc node) {
1120    // Pull off attributes...
1121
Map JavaDoc attributes = getAttributes(node);
1122    String JavaDoc id = (String JavaDoc) attributes.get(ID_ATTRIBUTE);
1123
1124    // Create the LayoutComponent
1125
ComponentType type = ensurePopupMenuType(parent);
1126    LayoutComponent popupMenu =
1127        new LayoutComponent(parent, EDIT_MENU + id, type);
1128
1129    // Configure it...
1130
popupMenu.setNested(isNestedLayoutComponent(popupMenu));
1131    popupMenu.setFacetChild(false);
1132
1133    // Could add "menu" facet here, however, I decided to do it in the xml
1134

1135    // Return the result
1136
return popupMenu;
1137    }
1138
1139    /**
1140     * <p> This method ensures that a "popupMenu" {@link ComponentType} has
1141     * been defined so that it can be used implicitly.</p>
1142     */

1143    private ComponentType ensurePopupMenuType(LayoutElement elt) {
1144    // See if it is defined
1145
LayoutDefinition ld = elt.getLayoutDefinition();
1146    ComponentType type = ld.getComponentType(POPUP_MENU_TYPE);
1147    if (type == null) {
1148        // Nope, define it...
1149
type = new ComponentType(POPUP_MENU_TYPE, POPUP_MENU_TYPE_CLASS);
1150        ld.addComponentType(type);
1151    }
1152
1153    // Return the type
1154
return type;
1155    }
1156
1157    /**
1158     * <p> This method ensures that a "editArea" {@link ComponentType} has
1159     * been defined so that it can be used implicitly.</p>
1160     */

1161    private ComponentType ensureEditAreaType(LayoutElement elt) {
1162    // See if it is defined
1163
LayoutDefinition ld = elt.getLayoutDefinition();
1164    ComponentType type = ld.getComponentType(EDIT_AREA_TYPE);
1165    if (type == null) {
1166        // Nope, define it...
1167
type = new ComponentType(EDIT_AREA_TYPE, EDIT_AREA_TYPE_CLASS);
1168        ld.addComponentType(type);
1169    }
1170
1171    // Return the type
1172
return type;
1173    }
1174
1175    /**
1176     * <p> This method ensures that a "markup" {@link ComponentType} has been
1177     * defined so that it can be used implicitly.</p>
1178     */

1179    private ComponentType ensureMarkupType(LayoutElement elt) {
1180    // See if it is defined
1181
LayoutDefinition ld = elt.getLayoutDefinition();
1182    ComponentType type = ld.getComponentType(MARKUP_ELEMENT);
1183    if (type == null) {
1184        // Nope, define it...
1185
type = new ComponentType(MARKUP_ELEMENT, MARKUP_FACTORY_CLASS);
1186        ld.addComponentType(type);
1187    }
1188
1189    // Return the type
1190
return type;
1191    }
1192
1193    /**
1194     * <p> This method adds an option to the given {@link LayoutComponent}
1195     * based on the information in the given {@link #OPTION_ELEMENT}
1196     * <code>Node</code>.</p>
1197     *
1198     * @param component The {@link LayoutComponent}.
1199     * @param node The {@link #OPTION_ELEMENT} <code>Node</code>.
1200     */

1201    private void addOption(LayoutComponent component, Node JavaDoc node) {
1202    // Pull off the attributes
1203
Map JavaDoc attributes = getAttributes(node);
1204
1205    // Get the name
1206
String JavaDoc name = (String JavaDoc) attributes.get(NAME_ATTRIBUTE);
1207    if ((name == null) || (name.trim().equals(""))) {
1208        throw new RuntimeException JavaDoc("'" + NAME_ATTRIBUTE
1209            + "' attribute not found on '" + OPTION_ELEMENT
1210            + "' Element!");
1211    }
1212    name = name.trim();
1213
1214    // Get the value
1215
Object JavaDoc value = getValueFromNode(node, attributes);
1216
1217    // Add the option to the component (value may be null)
1218
component.addOption(name, value);
1219    }
1220
1221    /**
1222     * <p> This method reads obtains the {@link #VALUE_ATTRIBUTE} from the
1223     * given node, or from the child {@link #LIST_ELEMENT} element. If
1224     * neither are provided, <code>(null)</code> is returned. The
1225     * attribute takes precedence over the child {@link #LIST_ELEMENT}
1226     * element.</p>
1227     *
1228     * @param node <code>Node</code> containing the value attribute
1229     * or {@link #LIST_ELEMENT}
1230     * @param attributes <code>Map</code> of attributes which may contain
1231     * {@link #VALUE_ATTRIBUTE}
1232     *
1233     * @return The value (as a <code>String</code> or <code>List</code>), or
1234     * <code>(null)</code> if not specified.
1235     */

1236    private Object JavaDoc getValueFromNode(Node JavaDoc node, Map JavaDoc attributes) {
1237    Object JavaDoc value = attributes.get(VALUE_ATTRIBUTE);
1238    if (value == null) {
1239        // The value attribute may be null if multiple values are supplied.
1240
// Walk children (we only care about LIST_ELEMENT)
1241
List JavaDoc list = new ArrayList JavaDoc();
1242        Iterator JavaDoc it = getChildElements(node, LIST_ELEMENT).iterator();
1243        while (it.hasNext()) {
1244        // Add a value to the List
1245
list.add(getAttributes((Node JavaDoc) it.next()).
1246            get(VALUE_ATTRIBUTE));
1247        }
1248        if (list.size() > 0) {
1249        // Only use the list if it has values
1250
value = list;
1251        }
1252    }
1253    return value;
1254    }
1255
1256    /**
1257     *
1258     * @param node The {@link #STATIC_TEXT_ELEMENT} node to extract
1259     * information from when creating the
1260     * {@link LayoutStaticText}.
1261     */

1262    private LayoutElement createLayoutStaticText(LayoutElement parent, Node JavaDoc node) {
1263    // Create new LayoutComponent
1264
LayoutStaticText text =
1265        new LayoutStaticText(parent, "", getTextNodesAsString(node));
1266
1267    // Add all the attributes from the static text as options
1268
// component.addOptions(getAttributes(node));
1269

1270    // Add escape... FIXME
1271

1272    // Return the LayoutStaticText
1273
return text;
1274    }
1275
1276
1277
1278    //////////////////////////////////////////////////////////////////////
1279
// Utility Methods
1280
//////////////////////////////////////////////////////////////////////
1281

1282    /**
1283     * <p> This method returns a <code>List</code> of all child
1284     * <code>Element</code>s below the given <code>Node</code>.</p>
1285     *
1286     * @param node The <code>Node</code> to pull child elements from.
1287     *
1288     * @return <code>List</code> of child <code>Element</code>s found below
1289     * the given <code>Node</code>.
1290     */

1291    public List JavaDoc getChildElements(Node JavaDoc node) {
1292    return getChildElements(node, null);
1293    }
1294
1295    /**
1296     * <p> This method returns a List of all child Elements below the given
1297     * Node matching the given name. If name equals null, all Elements
1298     * below this node will be returned.</p>
1299     *
1300     * @param node The node to pull child elements from.
1301     * @param name The name of the Elements to return.
1302     *
1303     * @return List of child elements found below the given node matching
1304     * the name (if provided).
1305     */

1306    public List JavaDoc getChildElements(Node JavaDoc node, String JavaDoc name) {
1307    // Get the child nodes
1308
NodeList JavaDoc nodes = node.getChildNodes();
1309    if (nodes == null) {
1310        // No children, just return an empty List
1311
return new ArrayList JavaDoc(0);
1312    }
1313
1314    // Create a new List to store the child Elements
1315
List JavaDoc list = new ArrayList JavaDoc();
1316
1317    // Add all the child Elements to the List
1318
Node JavaDoc childNode = null;
1319    for (int idx = 0; idx < nodes.getLength(); idx++) {
1320        childNode = nodes.item(idx);
1321        if (childNode.getNodeType() != Node.ELEMENT_NODE) {
1322        // Skip TEXT_NODE and other Node types
1323
continue;
1324        }
1325
1326        // Add to the list if name is null, or it matches the node name
1327
if ((name == null) || childNode.getNodeName().equalsIgnoreCase(name)) {
1328        list.add(childNode);
1329        }
1330    }
1331
1332    // Return the list of Elements
1333
return list;
1334    }
1335
1336
1337    /**
1338     * <p> This method returns the <code>String</code> representation of all
1339     * the <code>Node.TEXT_NODE</code> nodes that are children of the
1340     * given <code>Node</code>.
1341     *
1342     * @param node The <code>Node</code> to pull child
1343     * <code>Element</code>s from.
1344     *
1345     * @return The <code>String</code> representation of all the
1346     * <code>Node.TEXT_NODE</code> type nodes under the given
1347     * <code>Node</code>.
1348     */

1349    public String JavaDoc getTextNodesAsString(Node JavaDoc node) {
1350    // Get the child nodes
1351
NodeList JavaDoc nodes = node.getChildNodes();
1352    if (nodes == null) {
1353        // No children, return null
1354
return null;
1355    }
1356
1357    // Create a StringBuffer
1358
StringBuffer JavaDoc buf = new StringBuffer JavaDoc("");
1359
1360    // Add all the child Element values to the StringBuffer
1361
Node JavaDoc childNode = null;
1362    for (int idx = 0; idx < nodes.getLength(); idx++) {
1363        childNode = nodes.item(idx);
1364        if ((childNode.getNodeType() != Node.TEXT_NODE)
1365            && (childNode.getNodeType() != Node.CDATA_SECTION_NODE)) {
1366        // Skip all other Node types
1367
continue;
1368        }
1369        buf.append(childNode.getNodeValue());
1370    }
1371
1372    // Return the String
1373
return buf.toString();
1374    }
1375
1376
1377
1378    /**
1379     * <p> This method returns a <code>Map</code> of all attributes for the
1380     * given <code>Node</code>. Each attribute name will be stored in the
1381     * <code>Map</code> in lower case so case can be ignored.</p>
1382     *
1383     * @param node The node to pull attributes from.
1384     *
1385     * @return <code>Map</code> of attributes found on the given
1386     * <code>Node</code>.
1387     */

1388    public Map JavaDoc getAttributes(Node JavaDoc node) {
1389    // Get the attributes
1390
NamedNodeMap JavaDoc attributes = node.getAttributes();
1391    if ((attributes == null) || (attributes.getLength() == 0)) {
1392        // No attributes, just return an empty Map
1393
return new HashMap JavaDoc(0);
1394    }
1395
1396    // Create a Map to contain the attributes
1397
Map JavaDoc map = new HashMap JavaDoc();
1398
1399    // Add all the attributes to the Map
1400
Node JavaDoc attNode = null;
1401    for (int idx = 0; idx < attributes.getLength(); idx++) {
1402        attNode = attributes.item(idx);
1403        map.put(attNode.getNodeName().toLowerCase(),
1404            attNode.getNodeValue());
1405    }
1406
1407    // Return the map
1408
return map;
1409    }
1410
1411
1412    /**
1413     * <p> This utility method returns the requested {@link ComponentType}.
1414     * If it is not found, it throws an
1415     * <code>IllegalArgumentException</code>.</p>
1416     *
1417     * @param elt A {@link LayoutElement} whose root is a
1418     * {@link LayoutDefinition}.
1419     * @param type The <code>String</code> type to lookup.
1420     *
1421     * @return The {@link ComponentType}.
1422     */

1423    public ComponentType getComponentType(LayoutElement elt, String JavaDoc type) {
1424    // Find the ComponentType
1425
ComponentType componentType =
1426        elt.getLayoutDefinition().getComponentType(type);
1427    if (componentType == null) {
1428        throw new IllegalArgumentException JavaDoc("ComponentType '" + type
1429            + "' not defined!");
1430    }
1431    return componentType;
1432    }
1433
1434    /**
1435     * <p> This method returns the nearest {@link LayoutComponent} that
1436     * contains the given {@link LayoutElement}, null if none.</p>
1437     *
1438     * @param elt The {@link LayoutElement} to start with.
1439     *
1440     * @return The containing {@link LayoutComponent} if one exists.
1441     */

1442    public static LayoutComponent getParentLayoutComponent(LayoutElement elt) {
1443    elt = elt.getParent();
1444    while (elt != null) {
1445        if (elt instanceof LayoutComponent) {
1446        return (LayoutComponent) elt;
1447        }
1448        elt = elt.getParent();
1449    }
1450    return null;
1451    }
1452
1453
1454    //////////////////////////////////////////////////////////////////////
1455
// Constants
1456
//////////////////////////////////////////////////////////////////////
1457

1458    public static final String JavaDoc ATTRIBUTE_ELEMENT =
1459    "attribute";
1460    public static final String JavaDoc COMPONENT_ELEMENT =
1461    "component";
1462    public static final String JavaDoc COMPONENT_TYPE_ELEMENT =
1463    "componenttype";
1464    public static final String JavaDoc EDIT_ELEMENT =
1465    "edit";
1466    public static final String JavaDoc EVENT_ELEMENT =
1467    "event";
1468    public static final String JavaDoc FACET_ELEMENT =
1469    "facet";
1470    public static final String JavaDoc FOREACH_ELEMENT =
1471    "foreach";
1472    public static final String JavaDoc HANDLER_ELEMENT =
1473    "handler";
1474    public static final String JavaDoc HANDLERS_ELEMENT =
1475    "handlers";
1476    public static final String JavaDoc HANDLER_DEFINITION_ELEMENT =
1477    "handlerdefinition";
1478    public static final String JavaDoc IF_ELEMENT =
1479    "if";
1480    public static final String JavaDoc INPUT_DEF_ELEMENT =
1481    "inputdef";
1482    public static final String JavaDoc INPUT_ELEMENT =
1483    "input";
1484    public static final String JavaDoc LAYOUT_DEFINITION_ELEMENT =
1485    "layoutdefinition";
1486    public static final String JavaDoc LAYOUT_ELEMENT =
1487    "layout";
1488    public static final String JavaDoc LIST_ELEMENT =
1489    "list";
1490    public static final String JavaDoc MARKUP_ELEMENT =
1491    "markup";
1492    public static final String JavaDoc OPTION_ELEMENT =
1493    "option";
1494    public static final String JavaDoc OUTPUT_DEF_ELEMENT =
1495    "outputdef";
1496    public static final String JavaDoc OUTPUT_MAPPING_ELEMENT =
1497    "outputmapping";
1498    public static final String JavaDoc STATIC_TEXT_ELEMENT =
1499    "statictext";
1500    public static final String JavaDoc TYPES_ELEMENT =
1501    "types";
1502    public static final String JavaDoc RESOURCES_ELEMENT =
1503    "resources";
1504    public static final String JavaDoc RESOURCE_ELEMENT =
1505    "resource";
1506    public static final String JavaDoc WHILE_ELEMENT =
1507    "while";
1508
1509    public static final String JavaDoc CLASS_NAME_ATTRIBUTE =
1510    "classname";
1511    public static final String JavaDoc CONDITION_ATTRIBUTE =
1512    "condition";
1513    public static final String JavaDoc DEFAULT_ATTRIBUTE =
1514    "default";
1515    public static final String JavaDoc DESCRIPTION_ATTRIBUTE =
1516    "description";
1517    public static final String JavaDoc EXTRA_INFO_ATTRIBUTE =
1518    "extrainfo";
1519    public static final String JavaDoc FACTORY_CLASS_ATTRIBUTE =
1520    "factoryclass";
1521    public static final String JavaDoc ID_ATTRIBUTE =
1522    "id";
1523    public static final String JavaDoc KEY_ATTRIBUTE =
1524    "key";
1525    public static final String JavaDoc LIST_ATTRIBUTE =
1526    "list";
1527    public static final String JavaDoc METHOD_NAME_ATTRIBUTE =
1528    "methodname";
1529    public static final String JavaDoc NAME_ATTRIBUTE =
1530    "name";
1531    public static final String JavaDoc OUTPUT_NAME_ATTRIBUTE =
1532    "outputname";
1533    public static final String JavaDoc OVERWRITE_ATTRIBUTE =
1534    "overwrite";
1535    public static final String JavaDoc PROPERTY_ATTRIBUTE =
1536    "property";
1537    public static final String JavaDoc RENDERED_ATTRIBUTE =
1538    "rendered";
1539    public static final String JavaDoc REQUIRED_ATTRIBUTE =
1540    "required";
1541    public static final String JavaDoc TAG_ATTRIBUTE =
1542    "tag";
1543    public static final String JavaDoc TARGET_KEY_ATTRIBUTE =
1544    "targetkey";
1545    public static final String JavaDoc TARGET_TYPE_ATTRIBUTE =
1546    "targettype";
1547    public static final String JavaDoc TYPE_ATTRIBUTE =
1548    "type";
1549    public static final String JavaDoc VALUE_ATTRIBUTE =
1550    "value";
1551
1552    public static final String JavaDoc AUTO_RENDERED =
1553    "auto";
1554    public static final String JavaDoc EDITABLE =
1555    "editableContent";
1556    public static final String JavaDoc EDIT_MENU =
1557    "editMenu";
1558
1559    public static final String JavaDoc EDIT_AREA_TYPE =
1560    "editArea";
1561    public static final String JavaDoc POPUP_MENU_TYPE =
1562    "popupMenu";
1563    public static final String JavaDoc EDIT_AREA_TYPE_CLASS =
1564    "com.sun.enterprise.tools.jsfext.component.factory.basic.EditAreaFactory";
1565    public static final String JavaDoc MARKUP_FACTORY_CLASS =
1566    "com.sun.enterprise.tools.jsfext.component.factory.basic.MarkupFactory";
1567    public static final String JavaDoc POPUP_MENU_TYPE_CLASS =
1568    "com.sun.enterprise.tools.jsfext.component.factory.basic.PopupMenuFactory";
1569
1570
1571    /**
1572     * This is used to set the "value" option for static text fields.
1573     */

1574// public static final String VALUE_OPTION = "value";
1575

1576    private URL JavaDoc _url = null;
1577    private EntityResolver JavaDoc _entityResolver = null;
1578    private ErrorHandler JavaDoc _errorHandler = null;
1579    private String JavaDoc _baseURI = null;
1580
1581    private Map JavaDoc _handlerDefs = new HashMap JavaDoc();
1582    private int _markupCount = 1;
1583}
1584
Popular Tags