KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > enterprise > tools > jsfext > layout > descriptor > LayoutForEach


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.descriptor;
24
25 import com.sun.enterprise.tools.jsfext.el.VariableResolver;
26 import com.sun.enterprise.tools.jsfext.event.AfterLoopEvent;
27 import com.sun.enterprise.tools.jsfext.event.BeforeLoopEvent;
28
29 import java.io.IOException JavaDoc;
30 import java.util.Iterator JavaDoc;
31 import java.util.List JavaDoc;
32 import java.util.Map JavaDoc;
33
34 import javax.faces.component.UIComponent;
35 import javax.faces.context.FacesContext;
36 import javax.faces.el.ValueBinding;
37 import javax.faces.webapp.UIComponentTag;
38
39
40 /**
41  * <p> This class defines a LayoutForEach {@link LayoutElement}. The
42  * LayoutForEach provides the functionality necessary to iteratively
43  * display a portion of the layout tree. The list property contains
44  * the <code>List</code> of items to iterate over.</p>
45  *
46  * @see VariableResolver
47  *
48  * @author Ken Paulsen (ken.paulsen@sun.com)
49  */

50 public class LayoutForEach extends LayoutElementBase implements LayoutElement {
51
52     /**
53      * <p> Constructor.</p>
54      *
55      * @param parent The parent {@link LayoutElement}
56      * @param listBinding The <code>List</code> to iterate over
57      * @param key The <code>ServletRequest</code> attribute key
58      * used to store the object being processed
59      */

60     public LayoutForEach(LayoutElement parent, String JavaDoc listBinding, String JavaDoc key) {
61     super(parent, null);
62     if ((listBinding == null) || listBinding.equals("")) {
63         throw new IllegalArgumentException JavaDoc("'listBinding' is required!");
64     }
65     if ((key == null) || key.equals("")) {
66         throw new IllegalArgumentException JavaDoc("'key' is required!");
67     }
68     _listBinding = listBinding;
69     _key = key;
70     }
71
72
73     /**
74      * <p> This method always returns true. The condition is based on an
75      * <code>Iterator.hasNext()</code> call instead of here because
76      * the {@link #encode(FacesContext, TemplateComponent)} method
77      * evaluates this and then calls the super. Performing the check
78      * here would cause the condition to be evaluated twice.</p>
79      *
80      * @param context The FacesContext
81      * @param component The UIComponent
82      *
83      * @return true
84      */

85     protected boolean encodeThis(FacesContext context, UIComponent component) {
86     return true;
87     }
88
89     /**
90      * <p> This method evaluates the list binding for this
91      * <code>LayoutForEach</code>. This is expected to evaulate to a
92      * <code>List</code> object. If it doesn't, this method will throw a
93      * <code>NullPointerException</code> (if it evaulates to
94      * <code>null</code>), or an <code>IllegalArgumentException</code> if
95      * it doesn't evaluate to a <code>List</code>.</p>
96      *
97      * @param context The <code>FacesContext</code>
98      *
99      * return The <code>List</code> of objects to iterate over
100      */

101     protected List JavaDoc getList(FacesContext context) {
102     // Invoke our own EL. This is needed b/c JSF's EL is designed for
103
// Bean getters only. It does not get CONSTANTS or pull data from
104
// other sources (such as session, request attributes, etc., etc.)
105
// Resolve our variables now because we cannot depend on the
106
// individual components to do this. We may want to find a way to
107
// make this work as a regular ValueBinding expression... but for
108
// now, we'll just resolve it this way.
109
Object JavaDoc value = VariableResolver.resolveVariables(
110         context, this, null /* FIXME: component */, _listBinding);
111
112     // Next check to see if the value contains a JSF ValueBinding
113
if (value != null) {
114         String JavaDoc strVal = value.toString();
115         if (UIComponentTag.isValueReference(strVal)) {
116         ValueBinding vb =
117             context.getApplication().createValueBinding(strVal);
118         value = vb.getValue(context);
119         }
120     }
121
122     // Make sure we found something...
123
if (value == null) {
124         throw new NullPointerException JavaDoc("List not found via expression: '"
125             + _listBinding + "'.");
126     }
127
128     // Make sure we have a List...
129
if (!(value instanceof List JavaDoc)) {
130         throw new IllegalArgumentException JavaDoc("Expression '" + _listBinding
131             + "' did not resolve to a List! Found: '" + value + "'");
132     }
133
134     // Return the List
135
return (List JavaDoc) value;
136     }
137
138     /**
139      * <p> This method sets the <code>Object</code> that is currently being
140      * processed by this <code>LayoutForEach</code>. This implementation
141      * stores this value in the request attribute map undert the key
142      * provided to this <code>LayoutForEach</code>.</p>
143      *
144      * <p> As an added convenience, this method will also set an attribute
145      * that contains the current index number. The attribute key will be
146      * the same key the <code>Object</code> is stored under plus "-index".
147      * The index is stored as a String.</p>
148      *
149      * @param context The <code>FacesContext</code>
150      * @param value The <code>Object</code> to store
151      * @param index The current index number of the <code>Object</code>
152      */

153     protected void setCurrentForEachValue(FacesContext context, Object JavaDoc value, int index, String JavaDoc key) {
154     Map JavaDoc map = context.getExternalContext().getRequestMap();
155     map.put(key, value);
156     map.put(key + "-index", "" + index);
157     }
158
159     /**
160      * <p> This implementation overrides the parent <code>encode</code>
161      * method. It does this to cause the encode process to loop as long
162      * as there are more <code>List</code> entries to process.</p>
163      *
164      * @param context The FacesContext
165      * @param component The UIComponent
166      */

167     public void encode(FacesContext context, UIComponent component) throws IOException JavaDoc {
168     // Before events..
169
Object JavaDoc result = dispatchHandlers(context, BEFORE_LOOP,
170         new BeforeLoopEvent(component));
171
172     String JavaDoc key = resolveValue(
173         context, component, _key).toString();
174
175     // Iterate over the values in the list and perform the requested
176
// action(s) per the body of the LayoutForEach
177
Iterator JavaDoc it = getList(context).iterator();
178     for (int index = 1; it.hasNext(); index++) {
179         setCurrentForEachValue(context, it.next(), index, key);
180         super.encode(context, component);
181     }
182
183     // Invoke any "after" handlers
184
result = dispatchHandlers(context, AFTER_LOOP,
185         new AfterLoopEvent(component));
186     }
187
188
189     private String JavaDoc _listBinding = null;
190     private String JavaDoc _key = null;
191
192
193     /**
194      * <p> This is the event "type" for
195      * {@link com.sun.enterprise.tools.jsfext.event.handler.Handler}
196      * elements to be invoked after this LayoutForEach is processed
197      * (outside loop).</p>
198      */

199      public static final String JavaDoc AFTER_LOOP = "afterLoop";
200
201     /**
202      * <p> This is the event "type" for
203      * {@link com.sun.enterprise.tools.jsfext.event.handler.Handler}
204      * elements to be invoked before this LayoutForEach is processed
205      * (outside loop).</p>
206      */

207      public static final String JavaDoc BEFORE_LOOP = "beforeLoop";
208 }
209
Popular Tags