Source code: com/sun/facelets/tag/jsf/ComponentSupport.java
1 /**
2 * Licensed under the Common Development and Distribution License,
3 * you may not use this file except in compliance with the License.
4 * You may obtain a copy of the License at
5 *
6 * http://www.sun.com/cddl/
7 *
8 * Unless required by applicable law or agreed to in writing, software
9 * distributed under the License is distributed on an "AS IS" BASIS,
10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
11 * implied. See the License for the specific language governing
12 * permissions and limitations under the License.
13 */
14
15 package com.sun.facelets.tag.jsf;
16
17 import java.io.IOException;
18 import java.util.ArrayList;
19 import java.util.Collection;
20 import java.util.Collections;
21 import java.util.Iterator;
22 import java.util.List;
23 import java.util.Locale;
24
25 import javax.faces.FacesException;
26 import javax.faces.component.UIComponent;
27 import javax.faces.component.UIViewRoot;
28 import javax.faces.context.FacesContext;
29
30 import com.sun.facelets.FaceletContext;
31 import com.sun.facelets.FaceletHandler;
32 import com.sun.facelets.tag.TagAttribute;
33 import com.sun.facelets.tag.TagAttributeException;
34
35 /**
36 *
37 * @author Jacob Hookom
38 * @version $Id: ComponentSupport.java,v 1.6 2006/05/31 04:11:58 jhook Exp $
39 */
40 public final class ComponentSupport {
41
42 private final static String MARK_DELETED = "com.sun.facelets.MARK_DELETED";
43 public final static String MARK_CREATED = "com.sun.facelets.MARK_ID";
44
45 /**
46 * Used in conjunction with markForDeletion where any UIComponent marked
47 * will be removed.
48 *
49 * @param c
50 * UIComponent to finalize
51 */
52 public static final void finalizeForDeletion(UIComponent c) {
53 // remove any existing marks of deletion
54 c.getAttributes().remove(MARK_DELETED);
55
56 // finally remove any children marked as deleted
57 int sz = c.getChildCount();
58 if (sz > 0) {
59 UIComponent cc = null;
60 List cl = c.getChildren();
61 while (--sz >= 0) {
62 cc = (UIComponent) cl.get(sz);
63 if (cc.getAttributes().containsKey(MARK_DELETED)) {
64 cl.remove(sz);
65 }
66 }
67 }
68
69 // remove any facets marked as deleted
70 if (c.getFacets().size() > 0) {
71 Collection col = c.getFacets().values();
72 UIComponent fc;
73 for (Iterator itr = col.iterator(); itr.hasNext();) {
74 fc = (UIComponent) itr.next();
75 if (fc.getAttributes().containsKey(MARK_DELETED)) {
76 itr.remove();
77 }
78 }
79 }
80 }
81
82
83 /**
84 * A lighter-weight version of UIComponent's findChild.
85 *
86 * @param parent
87 * parent to start searching from
88 * @param id
89 * to match to
90 * @return UIComponent found or null
91 */
92 public static final UIComponent findChild(UIComponent parent, String id) {
93 int sz = parent.getChildCount();
94 if (sz > 0) {
95 UIComponent c = null;
96 List cl = parent.getChildren();
97 while (--sz >= 0) {
98 c = (UIComponent) cl.get(sz);
99 if (id.equals(c.getId())) {
100 return c;
101 }
102 }
103 }
104 return null;
105 }
106
107 /**
108 * By TagId, find Child
109 * @param parent
110 * @param id
111 * @return
112 */
113 public static final UIComponent findChildByTagId(UIComponent parent, String id) {
114 int sz = parent.getChildCount();
115 if (sz > 0) {
116 UIComponent c = null;
117 List cl = parent.getChildren();
118 String cid = null;
119 while (--sz >= 0) {
120 c = (UIComponent) cl.get(sz);
121 cid = (String) c.getAttributes().get(MARK_CREATED);
122 if (id.equals(cid)) {
123 return c;
124 }
125 }
126 }
127 return null;
128 }
129
130 /**
131 * According to JSF 1.2 tag specs, this helper method will use the
132 * TagAttribute passed in determining the Locale intended.
133 *
134 * @param ctx
135 * FaceletContext to evaluate from
136 * @param attr
137 * TagAttribute representing a Locale
138 * @return Locale found
139 * @throws TagAttributeException
140 * if the Locale cannot be determined
141 */
142 public static final Locale getLocale(FaceletContext ctx, TagAttribute attr)
143 throws TagAttributeException {
144 Object obj = attr.getObject(ctx);
145 if (obj instanceof Locale) {
146 return (Locale) obj;
147 }
148 if (obj instanceof String) {
149 String s = (String) obj;
150 if (s.length() == 2) {
151 return new Locale(s);
152 }
153 if (s.length() == 5) {
154 return new Locale(s.substring(0, 2), s.substring(3, 5)
155 .toUpperCase());
156 }
157 if (s.length() >= 7) {
158 return new Locale(s.substring(0, 2), s.substring(3, 5)
159 .toUpperCase(), s.substring(6, s.length()));
160 }
161 throw new TagAttributeException(attr, "Invalid Locale Specified: "
162 + s);
163 } else {
164 throw new TagAttributeException(attr,
165 "Attribute did not evaluate to a String or Locale: " + obj);
166 }
167 }
168
169 /**
170 * Tries to walk up the parent to find the UIViewRoot, if not found, then go
171 * to FaceletContext's FacesContext for the view root.
172 *
173 * @param ctx
174 * FaceletContext
175 * @param parent
176 * UIComponent to search from
177 * @return UIViewRoot instance for this evaluation
178 */
179 public static final UIViewRoot getViewRoot(FaceletContext ctx,
180 UIComponent parent) {
181 UIComponent c = parent;
182 do {
183 if (c instanceof UIViewRoot) {
184 return (UIViewRoot) c;
185 } else {
186 c = c.getParent();
187 }
188 } while (c != null);
189 return ctx.getFacesContext().getViewRoot();
190 }
191
192 /**
193 * Marks all direct children and Facets with an attribute for deletion.
194 *
195 * @see #finalizeForDeletion(UIComponent)
196 * @param c
197 * UIComponent to mark
198 */
199 public static final void markForDeletion(UIComponent c) {
200 // flag this component as deleted
201 c.getAttributes().put(MARK_DELETED, Boolean.TRUE);
202
203 // mark all children to be deleted
204 int sz = c.getChildCount();
205 if (sz > 0) {
206 UIComponent cc = null;
207 List cl = c.getChildren();
208 while (--sz >= 0) {
209 cc = (UIComponent) cl.get(sz);
210 if (cc.getAttributes().containsKey(MARK_CREATED)) {
211 cc.getAttributes().put(MARK_DELETED, Boolean.TRUE);
212 }
213 }
214 }
215
216 // mark all facets to be deleted
217 if (c.getFacets().size() > 0) {
218 Collection col = c.getFacets().values();
219 UIComponent fc;
220 for (Iterator itr = col.iterator(); itr.hasNext();) {
221 fc = (UIComponent) itr.next();
222 if (fc.getAttributes().containsKey(MARK_CREATED)) {
223 fc.getAttributes().put(MARK_DELETED, Boolean.TRUE);
224 }
225 }
226 }
227 }
228
229 public final static void encodeRecursive(FacesContext context,
230 UIComponent viewToRender) throws IOException, FacesException {
231 if (viewToRender.isRendered()) {
232 viewToRender.encodeBegin(context);
233 if (viewToRender.getRendersChildren()) {
234 viewToRender.encodeChildren(context);
235 } else if (viewToRender.getChildCount() > 0) {
236 Iterator kids = viewToRender.getChildren().iterator();
237 while (kids.hasNext()) {
238 UIComponent kid = (UIComponent) kids.next();
239 encodeRecursive(context, kid);
240 }
241 }
242 viewToRender.encodeEnd(context);
243 }
244 }
245
246 public static void removeTransient(UIComponent c) {
247 UIComponent d, e;
248 if (c.getChildCount() > 0) {
249 for (Iterator itr = c.getChildren().iterator(); itr.hasNext();) {
250 d = (UIComponent) itr.next();
251 if (d.getFacets().size() > 0) {
252 for (Iterator jtr = d.getFacets().values().iterator(); jtr
253 .hasNext();) {
254 e = (UIComponent) jtr.next();
255 if (e.isTransient()) {
256 jtr.remove();
257 } else {
258 removeTransient(e);
259 }
260 }
261 }
262 if (d.isTransient()) {
263 itr.remove();
264 } else {
265 removeTransient(d);
266 }
267 }
268 }
269 if (c.getFacets().size() > 0) {
270 for (Iterator itr = c.getFacets().values().iterator(); itr
271 .hasNext();) {
272 d = (UIComponent) itr.next();
273 if (d.isTransient()) {
274 itr.remove();
275 } else {
276 removeTransient(d);
277 }
278 }
279 }
280 }
281
282 /**
283 * Determine if the passed component is not null and if it's new
284 * to the tree. This operation can be used for determining if attributes
285 * should be wired to the component.
286 *
287 * @param component the component you wish to modify
288 * @return true if it's new
289 */
290 public final static boolean isNew(UIComponent component) {
291 return component != null && component.getParent() == null;
292 }
293 }