001: /*
002: * Copyright 2001-2007 Geert Bevin <gbevin[remove] at uwyn dot com>
003: * Distributed under the terms of either:
004: * - the common development and distribution license (CDDL), v1.0; or
005: * - the GNU Lesser General Public License, v2.1 or later
006: * $Id: Recursion.java 3634 2007-01-08 21:42:24Z gbevin $
007: */
008: package tutorial.recursion;
009:
010: import com.uwyn.rife.engine.Element;
011: import com.uwyn.rife.template.InternalValue;
012: import com.uwyn.rife.template.Template;
013: import java.util.ArrayList;
014: import java.util.Iterator;
015:
016: /**
017: * Demonstrates how the template engine can be used to construct complex
018: * recursive content through the use of <code>InternalValue</code> objects and
019: * internal template construction.
020: *
021: * @author Geert Bevin (gbevin[remove] at uwyn dot com)
022: * @version $Revision: 3634 $
023: */
024: public class Recursion extends Element {
025: /**
026: * The element's entry point.
027: */
028: public void processElement() {
029: /* Generate a tree with the following structure :
030: *
031: * +- node1
032: * | |
033: * | +- node1a
034: * | +- node1b
035: * | +- node1c
036: * |
037: * +- node2
038: * | |
039: * | +- node2a
040: * | | |
041: * | | +- node2a1
042: * | | +- node2a2
043: * | |
044: * | +- node2b
045: * |
046: * +- node3
047: * |
048: * +- node3a
049: * +- node3b
050: */
051: TreeNode tree = new TreeNode();
052: TreeNode node1 = new TreeNode(tree, "node1");
053: TreeNode node2 = new TreeNode(tree, "node2");
054: TreeNode node3 = new TreeNode(tree, "node3");
055: new TreeNode(node1, "node1a");
056: new TreeNode(node1, "node1b");
057: new TreeNode(node1, "node1c");
058: TreeNode node2a = new TreeNode(node2, "node2a");
059: new TreeNode(node2, "node2b");
060: new TreeNode(node3, "node3a");
061: new TreeNode(node3, "node3b");
062: new TreeNode(node2a, "node2a1");
063: new TreeNode(node2a, "node2a2");
064:
065: // obtain an instance of the template that will output the tree
066: Template template = getHtmlTemplate("tutorial.recursion");
067:
068: // process the tree for output to the template
069: tree.output(template);
070:
071: // print the template
072: print(template);
073: }
074:
075: /**
076: * A node in the tree structure that will output itself to a provided
077: * template instance.
078: *
079: * @author Geert Bevin (gbevin[remove] at uwyn dot com)
080: */
081: class TreeNode {
082: private String title = null;
083: private ArrayList children = new ArrayList();
084: private TreeNode parent = null;
085:
086: /**
087: * Constructs the root node from which all others will branch.
088: */
089: public TreeNode() {
090: }
091:
092: /**
093: * Add a child node to the provided parent node.
094: * Each child has a mandatory <code>title</code>.
095: *
096: * @param parent the parent node
097: * @param title the title of the child node
098: *
099: */
100: public TreeNode(TreeNode parent, String title) {
101: if (null == title)
102: throw new IllegalArgumentException(
103: "title can't be null.");
104:
105: parent.addChild(this );
106: this .title = title;
107: }
108:
109: /**
110: * Outputs the tree structure to a provided <code>Template</code>
111: * instance.
112: * <p>
113: * Each node will be appended to the <code>nodes</code> value and obtain
114: * from the <code>node</code> block. This block contains a
115: * <code>title</code> value that will contain the title of the node.
116: * <p>
117: * Each new depth level will be obtained from the <code>level</code>
118: * block and assigned to the <code>level</code> value. This value
119: * contains the <code>nodes</code> value to output a collection of
120: * sibling nodes and the <code>level</code> is present in the
121: * <code>node</code> block to allow child nodes to be inserted.
122: * <p>
123: * The complete tree is displayed by a top-level <code>level</code>
124: * value that will contain all first-level nodes, who will thus in their
125: * turn contain their own direct child nodes, and so on ...
126: *
127: * @param template the <code>Template</code> instance in which the
128: * tree structure should be output
129: *
130: */
131: public void output(Template template) {
132: // if no children are present, clear the level value
133: if (0 == children.size()) {
134: template.setValue("level", "");
135: } else {
136: // obtain a new internal value to construct a collection
137: // of sibling child nodes in the local scope
138: InternalValue nodes = template.createInternalValue();
139:
140: // iterete over the children
141: Iterator child_it = children.iterator();
142: TreeNode child = null;
143: while (child_it.hasNext()) {
144: // obtain the next child
145: child = (TreeNode) child_it.next();
146: // and output it before the processing continues
147: child.output(template);
148: // set the child's title value
149: template.setValue("title", encodeHtml(child
150: .getTitle()));
151: // and append it to the local internal value
152: nodes.appendBlock("node");
153: }
154: // when all children have been processed, set to nodes value
155: // to the locally constructed internal value
156: template.setValue("nodes", nodes);
157: // set the level value which includes the sibling nodes in the
158: // same level
159: template.setBlock("level", "level");
160: }
161: }
162:
163: /**
164: * Adds a child to the current <code>TreeNode</code> instance.
165: *
166: * @param child the child <code>TreeNode</code>
167: *
168: */
169: private void addChild(TreeNode child) {
170: child.parent = this ;
171: children.add(child);
172: }
173:
174: /**
175: * Retrieves the title of the current <code>TreeNode</code> instance.
176: *
177: * @return a <code>String</code> instance with the title; or
178: * <p>
179: * <code>null</code> if this is the root node.
180: */
181: public String getTitle() {
182: return title;
183: }
184:
185: /**
186: * Retrieves the parent of the current <code>TreeNode</code> instance.
187: *
188: * @return a <code>TreeNode</code> instance with the parent; or
189: * <p>
190: * <code>null</code> if this is the root node.
191: */
192: public TreeNode getParent() {
193: return parent;
194: }
195: }
196: }
|