KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > enterprise > tools > jsfext > component > factory > basic > DynamicTreeNodeFactory


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.component.factory.basic;
24
25 import com.sun.enterprise.tools.jsfext.component.ComponentUtil;
26 import com.sun.enterprise.tools.jsfext.util.Util;
27
28 import com.sun.enterprise.tools.jsfext.component.factory.ComponentFactoryBase;
29 import com.sun.enterprise.tools.jsfext.layout.descriptor.LayoutComponent;
30
31 import java.lang.reflect.InvocationTargetException JavaDoc;
32 import java.util.Iterator JavaDoc;
33 import java.util.List JavaDoc;
34 import java.util.Map JavaDoc;
35 import java.util.Properties JavaDoc;
36
37 import javax.faces.context.FacesContext;
38 import javax.faces.component.UIComponent;
39
40
41 /**
42  * <p> Portions of many trees are non-static, or Dynamic. By this it is meant
43  * that some of the nodes can only be determined at Runtime. The goal of
44  * this factory is to provide a means for dynamic tree nodes to be
45  * defined. This implementation allows a portion or an entire tree to be
46  * defined.</p>
47  *
48  * <p> It relies on the supplied {@link TreeAdaptor} to drive the creation
49  * of the "root" tree node. The "root" node is a single Tree or TreeNode
50  * that is returned from the {@see #create(FacesContext, LayoutComponent,
51  * UIComponent)} method. Since this is a factory class for creating a
52  * single UIComponent, it is expected that a single UIComponent is
53  * returned from this method. However, the returned UIComponent may
54  * contain 0 or more children (other TreeNodes). The {@link TreeAdaptor}
55  * facilitates this.</p>
56  *
57  * <p> The {@link TreeAdaptor} implemenation is respsonsible for traversing
58  * the tree data and providing the necessary information about that data
59  * to this factory. The tree data can be stored in any format, a specific
60  * TreeAdaptor must be written to interpret each unique type of data
61  * format. When this factory interacts with the {@link TreeAdaptor}, it
62  * passes an <code>Object</code> that represents a tree node in the
63  * arbitrary data format. This <code>Object</code> is obtained originally
64  * from the {@link TreeAdaptor}, so the developer has control over what
65  * object is used to identify tree nodes in their own data format.</p>
66  *
67  * <p> See {@link TreeAdaptor} to see the necessary methods to implement in
68  * order for this factory to be capable of populating
69  * <code>TreeNode</code>s based on your data.</p>
70  *
71  * @author Ken Paulsen (ken.paulsen@sun.com)
72  */

73 public class DynamicTreeNodeFactory extends ComponentFactoryBase {
74
75     /**
76      * Constructor
77      */

78     public DynamicTreeNodeFactory() {
79     }
80
81
82     /**
83      * <p> This is the factory method responsible for creating the
84      * <code>UIComponent</code>.</p>
85      *
86      * @param context The <code>FacesContext</code>
87      * @param descriptor The {@link LayoutComponent} descriptor associated
88      * with the requested <code>UIComponent</code>.
89      * @param parent The parent <code>UIComponent</code>
90      *
91      * @return The newly created component.
92      */

93     public UIComponent create(FacesContext context, LayoutComponent descriptor, UIComponent parent) {
94     // Get the TreeAdaptor which should be used
95
TreeAdaptor treeAdaptor = getTreeAdaptor(context, descriptor, parent);
96
97     // Initialize the TreeAdaptor instance
98
treeAdaptor.init();
99
100     // First pull off the root...
101
Object JavaDoc currentObj = treeAdaptor.getTreeNodeObject();
102
103     // Return the root TreeNode
104
return processNode(context, treeAdaptor, currentObj, parent);
105     }
106
107     /**
108      * <p> This method gets the <code>TreeAdaptor</code> by looking at the
109      * {@link #TREE_ADAPTOR_CLASS} option and invoking
110      * <code>getInstance</code> on the specified <code>TreeAdaptor</code>
111      * implementation.</p>
112      */

113     protected TreeAdaptor getTreeAdaptor(FacesContext ctx, LayoutComponent desc, UIComponent parent) {
114     TreeAdaptor adaptor = null;
115     Object JavaDoc cls = desc.getEvaluatedOption(ctx, TREE_ADAPTOR_CLASS, parent);
116     if (cls == null) {
117         throw new IllegalArgumentException JavaDoc("'" + TREE_ADAPTOR_CLASS
118             + "' must be specified!");
119     }
120     try {
121         Class JavaDoc adaptorClass = Util.getClass(cls);
122         adaptor = (TreeAdaptor) adaptorClass.getMethod("getInstance",
123             (Class JavaDoc []) new Class JavaDoc[] {FacesContext.class,
124             LayoutComponent.class, UIComponent.class}).
125                 invoke((Object JavaDoc) null,
126                     (Object JavaDoc []) new Object JavaDoc[] {ctx,
127                     desc, parent});
128     } catch (ClassNotFoundException JavaDoc ex) {
129         throw new RuntimeException JavaDoc(ex);
130     } catch (NoSuchMethodException JavaDoc ex) {
131         throw new RuntimeException JavaDoc(ex);
132     } catch (IllegalAccessException JavaDoc ex) {
133         throw new RuntimeException JavaDoc(ex);
134     } catch (InvocationTargetException JavaDoc ex) {
135         throw new RuntimeException JavaDoc(ex);
136     }
137
138     // Return the TreeAdaptor
139
return adaptor;
140     }
141
142     /**
143      * <p> This method is responsible for creating and configuring a
144      * <code>TreeNode</code> given its <code>TreeNode</code> object. It
145      * then recurses for each child <code>TreeNode</code> object.</p>
146      */

147     protected UIComponent processNode(FacesContext ctx, TreeAdaptor adaptor, Object JavaDoc currentObj, UIComponent parent) {
148     // Pull off the important information...
149
String JavaDoc id = adaptor.getId(currentObj);
150     String JavaDoc factoryClass = adaptor.getFactoryClass(currentObj);
151     // NOTE: Properties specify things such as:
152
// URL, Text, Image, Action, Expanded, ActionListener, etc.
153
Map JavaDoc props = adaptor.getFactoryOptions(currentObj);
154     Properties JavaDoc properties = Util.mapToProperties(props);
155
156     // Create TreeNode
157
UIComponent node = ComponentUtil.getChild(
158         (UIComponent) parent, id, factoryClass, properties);
159
160     // The above util method defaults to using a facet... change to child
161
// NOTE: The above needs "parent" to correctly evaluate ${}
162
// NOTE: expressions, in the future find a way to make it store as a
163
// NOTE: child vs. facet (possible if I create the LayoutComponent).
164
if (parent != null) {
165         parent.getFacets().remove(id);
166         parent.getChildren().add(node);
167     }
168
169     // Configure TreeNode
170
configureTreeNode(ctx, adaptor, node, currentObj);
171
172     // Walk TreeAdaptor and Create child TreeNodes
173
List JavaDoc children = adaptor.getChildTreeNodeObjects(currentObj);
174     if (children != null) {
175         Iterator JavaDoc it = children.iterator();
176         while (it.hasNext()) {
177         currentObj = it.next();
178         // We can ignore the return value b/c the factory should
179
// automatically set the parent
180
processNode(ctx, adaptor, currentObj, node);
181         }
182     }
183
184     // Return the recently created TreeNode (or whatever it is)
185
return node;
186     }
187
188     /**
189      * <p> Adds on facets and handlers.</p>
190      */

191     protected void configureTreeNode(FacesContext ctx, TreeAdaptor adaptor, UIComponent treeNode, Object JavaDoc currentObj) {
192     // Add facets (such as "content" and "image")
193
Map JavaDoc facets = adaptor.getFacets(treeNode, currentObj);
194     Map JavaDoc treeNodeFacets = treeNode.getFacets();
195     if (facets != null) {
196         Iterator JavaDoc it = facets.keySet().iterator();
197         String JavaDoc facetName;
198         Object JavaDoc facetValue;
199         while (it.hasNext()) {
200         facetName = (String JavaDoc) it.next();
201         facetValue = facets.get(facetName);
202         if (facetValue != null) {
203             treeNodeFacets.put(facetName, facetValue);
204         }
205         }
206     }
207
208     // Add instance handlers
209
Map JavaDoc handlersByType = adaptor.getHandlersByType(treeNode, currentObj);
210     if (handlersByType != null) {
211         Iterator JavaDoc it = handlersByType.keySet().iterator();
212         if (it.hasNext()) {
213         String JavaDoc eventType = null;
214         Map JavaDoc compAttrs = treeNode.getAttributes();
215         while (it.hasNext()) {
216             // Assign instance handlers to attribute for retrieval later
217
// (Retrieval must be explicit, see LayoutElementBase)
218
eventType = (String JavaDoc) it.next();
219             compAttrs.put(eventType, handlersByType.get(eventType));
220         }
221         }
222     }
223     }
224
225     /**
226      * <p> This is the option that must be supplied when using this factory
227      * in order to specify which TreeAdaptor instance should be used.
228      * The value should be a fully qualified class name of a valid
229      * TreeAdaptor instance. The TreeAdaptor instance must have a
230      * <code>public static TreeAdaptor getInstance(FacesContext,
231      * LayoutComponent, UIComponent)</code> method in order to get access
232      * to an instance of the TreeAdaptor instance.</p>
233      */

234     public static final String JavaDoc TREE_ADAPTOR_CLASS = "treeAdaptorClass";
235 }
236
Popular Tags