001: /* ====================================================================
002: * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
003: *
004: * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * 3. The end-user documentation included with the redistribution,
019: * if any, must include the following acknowledgment:
020: * "This product includes software developed by Jcorporate Ltd.
021: * (http://www.jcorporate.com/)."
022: * Alternately, this acknowledgment may appear in the software itself,
023: * if and wherever such third-party acknowledgments normally appear.
024: *
025: * 4. "Jcorporate" and product names such as "Expresso" must
026: * not be used to endorse or promote products derived from this
027: * software without prior written permission. For written permission,
028: * please contact info@jcorporate.com.
029: *
030: * 5. Products derived from this software may not be called "Expresso",
031: * or other Jcorporate product names; nor may "Expresso" or other
032: * Jcorporate product names appear in their name, without prior
033: * written permission of Jcorporate Ltd.
034: *
035: * 6. No product derived from this software may compete in the same
036: * market space, i.e. framework, without prior written permission
037: * of Jcorporate Ltd. For written permission, please contact
038: * partners@jcorporate.com.
039: *
040: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
041: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
042: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
043: * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
044: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
045: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
046: * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
047: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
048: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
049: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
050: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
051: * SUCH DAMAGE.
052: * ====================================================================
053: *
054: * This software consists of voluntary contributions made by many
055: * individuals on behalf of the Jcorporate Ltd. Contributions back
056: * to the project(s) are encouraged when you make modifications.
057: * Please send them to support@jcorporate.com. For more information
058: * on Jcorporate Ltd. and its products, please see
059: * <http://www.jcorporate.com/>.
060: *
061: * Portions of this software are based upon other open source
062: * products and are subject to their respective licenses.
063: */
064:
065: /**
066: * Copyright 1999, 2000, 2001 Jcorporate Ltd.
067: */package com.jcorporate.expresso.core.controller;
068:
069: import com.jcorporate.expresso.core.misc.StringUtil;
070: import com.jcorporate.expresso.kernel.util.ClassLocator;
071: import com.jcorporate.expresso.kernel.util.FastStringBuffer;
072: import org.w3c.dom.NamedNodeMap;
073: import org.w3c.dom.Node;
074: import org.w3c.dom.NodeList;
075:
076: import java.util.Enumeration;
077: import java.util.HashMap;
078: import java.util.Iterator;
079: import java.util.Map;
080: import java.util.Vector;
081:
082: /**
083: * A ControllerElement is the superclass for the three types of objects that are
084: * produced by a Controller when it transitions from one state to another.
085: * Output, Input and Transition objects all extend this class, and share the
086: * behaviors specified here.
087: * IMPORTANT NOTE: We don't use Logging (e.g. log4j) in this object, as it
088: * is sometimes stored in session when the server shuts down, and must be able
089: * to re-instantiate from the serialized form without needing to wait for
090: * ConfigManager to be initialized.
091: */
092: public class ControllerElement implements Cloneable,
093: java.io.Serializable {
094:
095: /**
096: * Short name for the element
097: */
098: private String name;
099:
100: /**
101: * Label to identify the element
102: */
103: private String label;
104:
105: /**
106: * Type - a descriptive categorization of the output type so that
107: * automatic formatters have a chance of figuring out how to render
108: * the element.
109: */
110: private String type;
111:
112: /**
113: * Longer description of the element (optional)
114: */
115: private String description;
116:
117: /**
118: * How many lines does this element consist of?
119: */
120: private int lines = 1;
121:
122: /**
123: * Nested items, if any
124: */
125: private Vector nested = null;
126:
127: /**
128: * Parent object within which this object is nested
129: */
130: private ControllerElement parent = null;
131:
132: /**
133: * Display length of the item
134: */
135: private int displayLength = 60;
136:
137: /**
138: * The attributes of this ControllerElement object
139: */
140: private HashMap attributes = null;
141:
142: /* The ControllerResponse that contains this ControllerElement */
143: private ControllerResponse myResponse = null;
144:
145: /**
146: * A map of nested elements keyed by name. May be incomplete if the
147: * developer does not use unique names.
148: */
149: private Map mappedNested = null;
150:
151: /**
152: * Returns the contents of this controller element
153: *
154: * @return Vector of nested content
155: */
156: public Vector getContents() {
157: return getNested();
158: } /* getContents() */
159:
160: /**
161: * Default constructor
162: */
163: protected ControllerElement() {
164: }
165:
166: /**
167: * Add a nested item to this element
168: *
169: * @param e A ControllerElement to nest inside this element
170: */
171: public void addNested(ControllerElement e) {
172: if (nested == null) {
173: nested = new Vector(3);
174: }
175:
176: if (mappedNested == null) {
177: mappedNested = new HashMap(3);
178: }
179:
180: nested.addElement(e);
181: mappedNested.put(e.getName(), e);
182:
183: e.setParent(this );
184: ControllerResponse cr = getControllerResponse();
185: if (cr != null) {
186: e.setControllerResponse(getControllerResponse());
187: }
188: } /* addNested(ControllerElement) */
189:
190: /**
191: * Internal method used by allNested to gather all of the items nested
192: * within an item recursively.
193: *
194: * @param t the source ControllerElement to return from
195: * @return java.util.Vector
196: */
197: private Vector addNestedFrom(ControllerElement t) {
198: Vector v = new Vector();
199:
200: Vector tVec = t.getNestedOrNull();
201: if (tVec == null) {
202: return v;
203: }
204:
205: ControllerElement oneElement = null;
206:
207: for (Enumeration e = tVec.elements(); e.hasMoreElements();) {
208: oneElement = (ControllerElement) e.nextElement();
209: v.addElement(oneElement);
210:
211: for (Enumeration e2 = addNestedFrom(oneElement).elements(); e2
212: .hasMoreElements();) {
213: v.addElement(e2.nextElement());
214: }
215: } /* for each nested element */
216:
217: return v;
218: } /* addNestedFrom(ControllerElement) */
219:
220: /**
221: * Return the nested items from this item
222: *
223: * @return java.util.Vector
224: */
225: public Vector allNested() {
226: Vector v = new Vector();
227:
228: for (Enumeration e = addNestedFrom(this ).elements(); e
229: .hasMoreElements();) {
230: v.addElement(e.nextElement());
231: }
232:
233: return v;
234: } /* allNested() */
235:
236: /**
237: * Shouldn't be normally called directly.
238: *
239: * @return created or null of the creation fails.
240: * @throws CloneNotSupportedException as per the API spec.
241: */
242: public Object clone() throws java.lang.CloneNotSupportedException {
243: Object o = null;
244: String className = getClass().getName();
245:
246: try {
247: Class c = ClassLocator.loadClass(className);
248: o = c.newInstance();
249: } catch (ClassNotFoundException cn) {
250: throw new IllegalArgumentException("State object '"
251: + className + "' not found");
252: } catch (InstantiationException ie) {
253: throw new IllegalArgumentException("State object '"
254: + className + "' cannot be instantiated");
255: } catch (IllegalArgumentException e) {
256: throw new IllegalArgumentException(
257: "State object '"
258: + className
259: + "' cannot be instantiated (IllegalArgumentException)");
260: } catch (IllegalAccessException iae) {
261: throw new IllegalArgumentException("llegal access loading "
262: + "State object '" + className + "'");
263: }
264: synchronized (this ) {
265: ControllerElement ce = (ControllerElement) o;
266: Vector v = this .getNestedOrNull();
267: if (v != null) {
268: for (Enumeration e = v.elements(); e.hasMoreElements();) {
269: ControllerElement oneNested = (ControllerElement) e
270: .nextElement();
271: ce.addNested((ControllerElement) oneNested.clone());
272: }
273: }
274:
275: String oneKey = null;
276: HashMap attribs = getAttributes();
277:
278: if (attribs != null) {
279: for (Iterator e2 = attribs.keySet().iterator(); e2
280: .hasNext();) {
281: oneKey = (String) e2.next();
282: ce.setAttribute(oneKey, (String) attribs
283: .get(oneKey));
284: }
285: }
286:
287: ce.description = description;
288: ce.displayLength = displayLength;
289: ce.label = label;
290: ce.lines = lines;
291: ce.name = name;
292: ce.parent = parent;
293: ce.type = type;
294: }
295:
296: return o;
297: } /* clone() */
298:
299: /**
300: * Base Class 'deserialization' from XML given a DOM Node N.
301: *
302: * @param n A <code>DOM Node</code> object.
303: * @return an instantiated ControllerElement
304: */
305: public static ControllerElement fromXML(Node n)
306: throws ControllerException {
307: ControllerElement ce = new ControllerElement();
308:
309: return fromXML(n, ce);
310: }
311:
312: /**
313: * Return a controller element based upon the xml fragment
314: *
315: * @param n The DOM node that represents the controller-element
316: * @param ce The created controller element subclass
317: * @return an instantiated ControllerElement
318: * @throws ControllerException if fragment is not a controller element
319: */
320: protected static ControllerElement fromXML(Node n,
321: ControllerElement ce) throws ControllerException {
322: if (!n.getNodeName().equals("controller-element")) {
323: throw new ControllerException("Failed To Get DOM Node of "
324: + " type 'controller-element' Got "
325: + n.getNodeName() + " instead.");
326: }
327:
328: NamedNodeMap nm = n.getAttributes();
329:
330: /**
331: * Load up all the Controller Element Attributes
332: */
333: Node attribute;
334: attribute = nm.getNamedItem("name");
335:
336: if (attribute != null) {
337: ce.name = attribute.getNodeValue();
338: }
339:
340: attribute = nm.getNamedItem("description");
341:
342: if (attribute != null) {
343: ce.description = attribute.getNodeValue();
344: }
345:
346: attribute = nm.getNamedItem("display-length");
347:
348: if (attribute != null) {
349: try {
350: ce.displayLength = Integer.parseInt(attribute
351: .getNodeValue());
352: } catch (NumberFormatException nfe) {
353: }
354: }
355:
356: attribute = nm.getNamedItem("label");
357:
358: if (attribute != null) {
359: ce.label = attribute.getNodeValue();
360: }
361:
362: attribute = nm.getNamedItem("lines");
363:
364: if (attribute != null) {
365: try {
366: ce.lines = Integer.parseInt(attribute.getNodeValue());
367: } catch (NumberFormatException nfe) {
368: }
369: }
370:
371: attribute = nm.getNamedItem("name");
372:
373: if (attribute != null) {
374: ce.name = attribute.getNodeValue();
375: }
376:
377: attribute = nm.getNamedItem("type");
378:
379: if (attribute != null) {
380: ce.type = attribute.getNodeValue();
381: }
382:
383: NodeList nl = n.getChildNodes();
384:
385: /**
386: * Iterate through all the child nodes and get the element-attributes
387: * nodes
388: */
389: for (int i = 0; i < nl.getLength(); i++) {
390: Node currentNode = nl.item(i);
391:
392: if (currentNode.getNodeName().equals("element-attributes")) {
393: NodeList attrnl = currentNode.getChildNodes();
394:
395: for (int j = 0; j < attrnl.getLength(); j++) {
396: Node oneNode = attrnl.item(j);
397:
398: if (oneNode.getNodeName().equals(
399: "element-attribute")) {
400: NamedNodeMap attrs = oneNode.getAttributes();
401: String key = attrs.getNamedItem("name")
402: .getNodeValue();
403: String value = attrs.getNamedItem("value")
404: .getNodeValue();
405:
406: if (key != null) {
407: if (value == null) {
408: value = ("");
409: }
410: if (ce.attributes == null) {
411: ce.attributes = new HashMap();
412: }
413:
414: ce.attributes.put(key, value);
415: }
416: }
417: }
418: } else if (currentNode.getNodeName().equals(
419: "nested-outputs")) {
420: NodeList nestedNodes = currentNode.getChildNodes();
421:
422: for (int k = 0; k < nestedNodes.getLength(); k++) {
423: Node oneNode = nestedNodes.item(k);
424:
425: if (oneNode.getNodeName().equals("output")) {
426: ce.addNested(Output
427: .fromXML(nestedNodes.item(k)));
428: }
429: }
430: } else if (currentNode.getNodeName()
431: .equals("nested-inputs")) {
432: NodeList nestedNodes = currentNode.getChildNodes();
433:
434: for (int k = 0; k < nestedNodes.getLength(); k++) {
435: Node oneNode = nestedNodes.item(k);
436:
437: if (oneNode.getNodeName().equals("input")) {
438: ce
439: .addNested(Input.fromXML(nestedNodes
440: .item(k)));
441: }
442: }
443: } else if (currentNode.getNodeName()
444: .equals("nested-blocks")) {
445: NodeList nestedNodes = currentNode.getChildNodes();
446:
447: for (int k = 0; k < nestedNodes.getLength(); k++) {
448: Node oneNode = nestedNodes.item(k);
449:
450: if (oneNode.getNodeName().equals("block")) {
451: ce
452: .addNested(Block.fromXML(nestedNodes
453: .item(k)));
454: }
455: }
456: } else if (currentNode.getNodeName().equals(
457: "nested-transitions")) {
458: NodeList nestedNodes = currentNode.getChildNodes();
459:
460: for (int k = 0; k < nestedNodes.getLength(); k++) {
461: Node oneNode = nestedNodes.item(k);
462:
463: if (oneNode.getNodeName().equals("transition")) {
464: ce.addNested(Transition.fromXML(nestedNodes
465: .item(k)));
466: }
467: }
468: }
469: } /* For each Child Node */
470:
471: return ce;
472: }
473:
474: /**
475: * Get the value of an "attribute" for this ControllerElement item.
476: * The attributes can
477: * be any set of named values that the client and Controller are
478: * both aware of.
479: *
480: * @param att The name of the attribute whose value is wanted
481: * @return The value of the specified attribtue, if it exists, else
482: * null
483: */
484: public String getAttribute(String att) {
485: if (attributes == null) {
486: return "";
487: }
488: return StringUtil.notNull((String) attributes.get(att));
489: } /* getAttribute(String) */
490:
491: /**
492: * Return the entire Hashtable of attribute values for this ControllerElement
493: *
494: * @return A Hashtable of name/value pairs for this ControllerElement object
495: */
496: public HashMap getAttributes() {
497: if (attributes == null) {
498: attributes = new HashMap();
499: }
500: return attributes;
501: } /* getAttributes() */
502:
503: /**
504: * Same as above but will return null if no attributes have ever been set.
505: *
506: * @return HashMap or <i>null</i>
507: */
508: public HashMap getAttributesOrNull() {
509: return attributes;
510: }
511:
512: /*
513: * get the contained item of this name
514: * @param name name of item to be fetched
515: * @return content associated with name, or null
516: */
517: public ControllerElement getContent(String name) {
518: ControllerElement t = null;
519: Vector v = this .getNestedOrNull();
520: if (v != null) {
521: for (Enumeration e = v.elements(); e.hasMoreElements();) {
522: t = (ControllerElement) e.nextElement();
523:
524: if (t.getName().equals(name)) {
525: return t;
526: }
527: }
528: }
529:
530: return null;
531: } /* getContent(String) */
532:
533: /**
534: * Get the description of this element
535: *
536: * @return A String description of this element as specified by the
537: * controller
538: */
539: public String getDescription() {
540: return StringUtil.notNull(description);
541: } /* getDescription() */
542:
543: /**
544: * Get the display length suggested by the controller for this
545: * item.
546: *
547: * @return The display length suggested for this item
548: */
549: public int getDisplayLength() {
550: return displayLength;
551: } /* getDisplayLength() */
552:
553: /**
554: * Get the label of this element
555: *
556: * @return The label of this element
557: */
558: public String getLabel() {
559: return StringUtil.notNull(label);
560: } /* getLabel() */
561:
562: /**
563: * Get the suggested number of lines for this item
564: *
565: * @return integer
566: */
567: public int getLines() {
568: return lines;
569: } /* getLines() */
570:
571: /**
572: * Get the name of this element.
573: * title and name are synonymous--easier for JSTL
574: *
575: * @return The name of this element
576: */
577: public String getName() {
578: return StringUtil.notNull(name);
579: } /* getName() */
580:
581: /**
582: * Get the name of this element.
583: * title and name are synonymous--easier for JSTL
584: *
585: * @return The name of this element
586: */
587: public String getTitle() {
588: return StringUtil.notNull(name);
589: }
590:
591: /**
592: * Return the entire Vector of nested elements in this element
593: *
594: * @return A Vector of the objects nested within this element
595: */
596: public Vector getNested() {
597: if (nested == null) {
598: nested = new Vector();
599: }
600:
601: return nested;
602: } /* getNested() */
603:
604: /**
605: * A method to support JSTL 1.0 usage; returns the size of the
606: * nested controller elements.
607: * <p/>
608: * <p> In JSTL 1.0 it is not possible to the retrieve sizes of
609: * collections directly without using a wrapper or a custom tag
610: * action. </p>
611: *
612: * @return size of all nested controller elements
613: */
614: public int getNestedCount() {
615: return getNested().size();
616: } /* getNestedCount() */
617:
618: /**
619: * Same as getNested. <b>But</b> does not allocate a Vector if there aren't
620: * any values.
621: *
622: * @return java.util.Vector or null if nested Vector doesn't exist yet.
623: */
624: public Vector getNestedOrNull() {
625: if (nested == null) {
626: return null;
627: }
628:
629: return nested;
630: }
631:
632: /**
633: * Retrieve the iterator to all tested objects.
634: *
635: * @return
636: */
637: public Iterator getNestedIterator() {
638: return getNested().iterator();
639: }
640:
641: /**
642: * Return the "parent" of this element - e.g. the element that this
643: * element is nested within
644: *
645: * @return the parent element or possibly null if there is no parent
646: */
647: public ControllerElement getParent() {
648: return parent;
649: } /* getParent() */
650:
651: /**
652: * Returns whatever the type is
653: *
654: * @return java.lang.String
655: */
656: public String getType() {
657: return type;
658: }
659:
660: /**
661: * Remove this item from the "nested" items of it's parent. After
662: * this method, the item is still valid, but is no longer nested within
663: * it's parent
664: *
665: * @throws ControllerException if the current item is not nested
666: */
667: public void remove() throws ControllerException {
668: if (parent == null) {
669: String myName = (this .getClass().getName() + ".remove()");
670: throw new ControllerException(myName
671: + " :This item is not nested "
672: + "in another item - cannot remove");
673: }
674:
675: parent.removeNested(this );
676: } /* remove() */
677:
678: /**
679: * Remove an element from the nested elements for this item
680: *
681: * @param elementToRemove The element to be removed from the list of
682: * nested items.
683: * @throws ControllerException if there is no such item nested in this item
684: */
685: public void removeNested(ControllerElement elementToRemove)
686: throws ControllerException {
687: if (nested.removeElement(elementToRemove)) {
688: return;
689: }
690:
691: String myName = (this .getClass().getName() + ".removeNested(ControllerElement)");
692: throw new ControllerException(myName
693: + "No such nested element as '"
694: + elementToRemove.getName() + "' in Output "
695: + getName());
696: } /* removeNested(ControllerElement) */
697:
698: /**
699: * Set the named attribute of this Output to the given value
700: *
701: * @param attrib The name of an "attribtue" for this ControllerElement item
702: * @param val The value for this attribute
703: */
704: public void setAttribute(String attrib, String val) {
705: if (attributes == null) {
706: attributes = new HashMap();
707: }
708: attributes.put(attrib, val);
709: } /* setAttributes(String, String) */
710:
711: /**
712: * Used by the controller to set the description of this element
713: *
714: * @param newDescription The description being set by this object
715: */
716: public void setDescription(String newDescription) {
717: description = newDescription;
718: } /* setDescription(String) */
719:
720: /**
721: * Set the suggested display length (in caracters) for this
722: * Controller element
723: *
724: * @param newLength The specified length for display of this element
725: */
726: public void setDisplayLength(int newLength) {
727: displayLength = newLength;
728: } /* setDisplayLength(int) */
729:
730: /**
731: * Set a label for this element
732: *
733: * @param newLabel The new label for this element
734: */
735: public void setLabel(String newLabel) {
736: label = newLabel;
737: } /* setLabel(String) */
738:
739: /**
740: * Set the display number of lines suggested for this item
741: *
742: * @param newLines The number of lines to specify
743: */
744: public void setLines(int newLines) {
745: lines = newLines;
746: } /* setLines(int) */
747:
748: /**
749: * Used by the controller to set the name of this element
750: *
751: * @param newName The new name for this element
752: */
753: public void setName(String newName) {
754: name = newName;
755: } /* setName(String) */
756:
757: /**
758: * Set the "parent" of this element - e.g. the element that this
759: * element is nested within
760: *
761: * @param t The ControllerElement that has this element as a nested item
762: */
763: public void setParent(ControllerElement t) {
764: parent = t;
765: } /* setParent(ControllerElement) */
766:
767: /**
768: * Sets the descriptive data type for this ControllerElement
769: *
770: * @param s a new java.lang.String
771: */
772: public void setType(String s) {
773: type = s;
774: }
775:
776: /**
777: * Convert the object to an xml fragment.
778: *
779: * @param stream a pre-allocated FastStringBuffer to append to
780: * @return the in parameter stream.
781: */
782: public FastStringBuffer toXML(FastStringBuffer stream) {
783: stream.append("<controller-element");
784:
785: if (name != null && name.length() > 0) {
786: stream.append(" name=\"");
787: stream.append(StringUtil.xmlEscape(name));
788: stream.append("\"");
789: }
790: if (label != null && label.length() > 0) {
791: stream.append(" label=\"");
792: stream.append(StringUtil.xmlEscape(label));
793: stream.append("\"");
794: }
795: if (type != null && type.length() > 0) {
796: stream.append(" type=\"");
797: stream.append(StringUtil.xmlEscape(type));
798: stream.append("\"");
799: }
800: if (description != null && description.length() > 0) {
801: stream.append(" description=\"");
802: stream.append(StringUtil.xmlEscape(description));
803: stream.append("\"");
804: }
805: if (displayLength > 0) {
806: stream.append(" display-length=\"");
807: stream.append(displayLength);
808: stream.append("\"");
809: }
810: if (lines > 0) {
811: stream.append(" lines=\"");
812: stream.append(lines);
813: stream.append("\"");
814: }
815:
816: stream.append(">\n");
817:
818: if (attributes != null && !attributes.isEmpty()) {
819: stream.append("\t<element-attributes>\n");
820:
821: for (Iterator i = attributes.keySet().iterator(); i
822: .hasNext();) {
823: String key = (String) i.next();
824: String value = null;
825:
826: if (key != null) {
827: value = (String) attributes.get(key);
828:
829: //
830: //All null values go to empty strings
831: //
832: if (value == null) {
833: value = "";
834: }
835:
836: stream.append("\t<element-attribute name=\"");
837: stream.append(StringUtil.xmlEscape(key));
838: stream.append("\" value=\"");
839: stream.append(StringUtil.xmlEscape(value));
840: stream.append("\"/>\n");
841: }
842: }
843:
844: stream.append("\t</element-attributes>\n");
845: }
846:
847: /* Now deal with nested elements */
848: Vector nestedBlocks = new Vector();
849: Vector nestedOutputs = new Vector();
850: Vector nestedTransitions = new Vector();
851: Vector nestedInputs = new Vector();
852: Vector nested = this .getNestedOrNull();
853: ControllerElement ce = null;
854: if (nested != null) {
855: for (Enumeration en = nested.elements(); en
856: .hasMoreElements();) {
857: ce = (ControllerElement) en.nextElement();
858:
859: if (ce instanceof Input) {
860: nestedInputs.addElement(ce);
861: }
862: if (ce instanceof Output) {
863: nestedOutputs.addElement(ce);
864: }
865: if (ce instanceof Transition) {
866: nestedTransitions.addElement(ce);
867: }
868: if (ce instanceof Block) {
869: nestedBlocks.addElement(ce);
870: }
871: }
872: }
873: if (nestedOutputs.size() > 0) {
874: stream.append(" <nested-outputs>\n");
875:
876: Output oneOutput = null;
877:
878: for (Enumeration eno = nestedOutputs.elements(); eno
879: .hasMoreElements();) {
880: oneOutput = (Output) eno.nextElement();
881: stream = oneOutput.toXML(stream);
882: }
883:
884: stream.append(" </nested-outputs>\n");
885: }
886: if (nestedInputs.size() > 0) {
887: stream.append(" <nested-inputs>\n");
888:
889: Input oneInput = null;
890:
891: for (Enumeration eni = nestedInputs.elements(); eni
892: .hasMoreElements();) {
893: oneInput = (Input) eni.nextElement();
894: stream = oneInput.toXML(stream);
895: }
896:
897: stream.append(" </nested-inputs>\n");
898: }
899: if (nestedTransitions.size() > 0) {
900: stream.append(" <nested-transitions>\n");
901:
902: Transition oneTransition = null;
903:
904: for (Enumeration ent = nestedTransitions.elements(); ent
905: .hasMoreElements();) {
906: oneTransition = (Transition) ent.nextElement();
907: stream = oneTransition.toXML(stream);
908: }
909:
910: stream.append(" </nested-transitions>\n");
911: }
912: if (nestedBlocks.size() > 0) {
913: stream.append(" <nested-blocks>\n");
914:
915: Block oneBlock = null;
916:
917: for (Enumeration enb = nestedBlocks.elements(); enb
918: .hasMoreElements();) {
919: oneBlock = (Block) enb.nextElement();
920: stream = oneBlock.toXML(stream);
921: }
922:
923: stream.append(" </nested-blocks>\n");
924: }
925:
926: stream.append("</controller-element>\n");
927:
928: return stream;
929: }
930:
931: /**
932: * Return a specific Element nested within this Element
933: *
934: * @param nestedName the name of the element to retrieve
935: * @return An Element with the specified name or null if it doesn't exist
936: */
937: public ControllerElement getNested(String nestedName)
938: throws ControllerException {
939: ControllerElement oneElement = null;
940: Vector v = getNestedOrNull();
941:
942: if (v == null) {
943: return null;
944: }
945:
946: for (Enumeration e = v.elements(); e.hasMoreElements();) {
947: oneElement = (ControllerElement) e.nextElement();
948:
949: if (oneElement.getName().equals(nestedName)) {
950: return oneElement;
951: }
952: } /* for each element nested */
953:
954: return null;
955: } /* getNested(String) */
956:
957: /**
958: * Return a Map of all nested elements keyed by controllerElement name.
959: * Useful for JSTL iteration of the Map.
960: */
961: public Map getNestedMap() {
962: if (mappedNested == null) {
963: mappedNested = new HashMap();
964: }
965: return mappedNested;
966: }
967:
968: /**
969: * Called by the ControllerResponse to hand itself back to this
970: * element so that it can be accessed by the elements as required
971: *
972: * @param newResponse the new Response.
973: */
974: public synchronized void setControllerResponse(
975: ControllerResponse newResponse) {
976: myResponse = newResponse;
977:
978: Vector allNested = getNestedOrNull();
979:
980: if (allNested == null) {
981: return;
982: }
983:
984: ControllerElement ce = null;
985:
986: int size = allNested.size();
987: for (int i = 0; i < size; i++) {
988: ce = (ControllerElement) allNested.get(i);
989: ce.setControllerResponse(newResponse);
990: }
991: }
992:
993: protected ControllerResponse getControllerResponse() {
994: return myResponse;
995: }
996: }
997:
998: /* ControllerElement */
|