001: /**
002: * Licensed under the Common Development and Distribution License,
003: * you may not use this file except in compliance with the License.
004: * You may obtain a copy of the License at
005: *
006: * http://www.sun.com/cddl/
007: *
008: * Unless required by applicable law or agreed to in writing, software
009: * distributed under the License is distributed on an "AS IS" BASIS,
010: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
011: * implied. See the License for the specific language governing
012: * permissions and limitations under the License.
013: */package com.sun.facelets.tag.jsf;
014:
015: import java.io.IOException;
016: import java.util.ArrayList;
017: import java.util.Collection;
018: import java.util.Collections;
019: import java.util.Iterator;
020: import java.util.List;
021: import java.util.Locale;
022:
023: import javax.faces.FacesException;
024: import javax.faces.component.UIComponent;
025: import javax.faces.component.UIViewRoot;
026: import javax.faces.context.FacesContext;
027:
028: import com.sun.facelets.FaceletContext;
029: import com.sun.facelets.FaceletHandler;
030: import com.sun.facelets.tag.TagAttribute;
031: import com.sun.facelets.tag.TagAttributeException;
032:
033: /**
034: *
035: * @author Jacob Hookom
036: * @version $Id: ComponentSupport.java,v 1.7 2006/12/01 07:01:59 jhook Exp $
037: */
038: public final class ComponentSupport {
039:
040: private final static String MARK_DELETED = "com.sun.facelets.MARK_DELETED";
041: public final static String MARK_CREATED = "com.sun.facelets.MARK_ID";
042:
043: /**
044: * Used in conjunction with markForDeletion where any UIComponent marked
045: * will be removed.
046: *
047: * @param c
048: * UIComponent to finalize
049: */
050: public static final void finalizeForDeletion(UIComponent c) {
051: // remove any existing marks of deletion
052: c.getAttributes().remove(MARK_DELETED);
053:
054: // finally remove any children marked as deleted
055: int sz = c.getChildCount();
056: if (sz > 0) {
057: UIComponent cc = null;
058: List cl = c.getChildren();
059: while (--sz >= 0) {
060: cc = (UIComponent) cl.get(sz);
061: if (cc.getAttributes().containsKey(MARK_DELETED)) {
062: cl.remove(sz);
063: }
064: }
065: }
066:
067: // remove any facets marked as deleted
068: if (c.getFacets().size() > 0) {
069: Collection col = c.getFacets().values();
070: UIComponent fc;
071: for (Iterator itr = col.iterator(); itr.hasNext();) {
072: fc = (UIComponent) itr.next();
073: if (fc.getAttributes().containsKey(MARK_DELETED)) {
074: itr.remove();
075: }
076: }
077: }
078: }
079:
080: /**
081: * A lighter-weight version of UIComponent's findChild.
082: *
083: * @param parent
084: * parent to start searching from
085: * @param id
086: * to match to
087: * @return UIComponent found or null
088: */
089: public static final UIComponent findChild(UIComponent parent,
090: String id) {
091: int sz = parent.getChildCount();
092: if (sz > 0) {
093: UIComponent c = null;
094: List cl = parent.getChildren();
095: while (--sz >= 0) {
096: c = (UIComponent) cl.get(sz);
097: if (id.equals(c.getId())) {
098: return c;
099: }
100: }
101: }
102: return null;
103: }
104:
105: /**
106: * By TagId, find Child
107: * @param parent
108: * @param id
109: * @return
110: */
111: public static final UIComponent findChildByTagId(
112: UIComponent parent, String id) {
113: Iterator itr = parent.getFacetsAndChildren();
114: UIComponent c = null;
115: String cid = null;
116: while (itr.hasNext()) {
117: c = (UIComponent) itr.next();
118: cid = (String) c.getAttributes().get(MARK_CREATED);
119: if (id.equals(cid)) {
120: return c;
121: }
122: }
123: // int sz = parent.getChildCount();
124: // if (sz > 0) {
125: // UIComponent c = null;
126: // List cl = parent.getChildren();
127: // String cid = null;
128: // while (--sz >= 0) {
129: // c = (UIComponent) cl.get(sz);
130: // cid = (String) c.getAttributes().get(MARK_CREATED);
131: // if (id.equals(cid)) {
132: // return c;
133: // }
134: // }
135: // }
136: return null;
137: }
138:
139: /**
140: * According to JSF 1.2 tag specs, this helper method will use the
141: * TagAttribute passed in determining the Locale intended.
142: *
143: * @param ctx
144: * FaceletContext to evaluate from
145: * @param attr
146: * TagAttribute representing a Locale
147: * @return Locale found
148: * @throws TagAttributeException
149: * if the Locale cannot be determined
150: */
151: public static final Locale getLocale(FaceletContext ctx,
152: TagAttribute attr) throws TagAttributeException {
153: Object obj = attr.getObject(ctx);
154: if (obj instanceof Locale) {
155: return (Locale) obj;
156: }
157: if (obj instanceof String) {
158: String s = (String) obj;
159: if (s.length() == 2) {
160: return new Locale(s);
161: }
162: if (s.length() == 5) {
163: return new Locale(s.substring(0, 2), s.substring(3, 5)
164: .toUpperCase());
165: }
166: if (s.length() >= 7) {
167: return new Locale(s.substring(0, 2), s.substring(3, 5)
168: .toUpperCase(), s.substring(6, s.length()));
169: }
170: throw new TagAttributeException(attr,
171: "Invalid Locale Specified: " + s);
172: } else {
173: throw new TagAttributeException(attr,
174: "Attribute did not evaluate to a String or Locale: "
175: + obj);
176: }
177: }
178:
179: /**
180: * Tries to walk up the parent to find the UIViewRoot, if not found, then go
181: * to FaceletContext's FacesContext for the view root.
182: *
183: * @param ctx
184: * FaceletContext
185: * @param parent
186: * UIComponent to search from
187: * @return UIViewRoot instance for this evaluation
188: */
189: public static final UIViewRoot getViewRoot(FaceletContext ctx,
190: UIComponent parent) {
191: UIComponent c = parent;
192: do {
193: if (c instanceof UIViewRoot) {
194: return (UIViewRoot) c;
195: } else {
196: c = c.getParent();
197: }
198: } while (c != null);
199: return ctx.getFacesContext().getViewRoot();
200: }
201:
202: /**
203: * Marks all direct children and Facets with an attribute for deletion.
204: *
205: * @see #finalizeForDeletion(UIComponent)
206: * @param c
207: * UIComponent to mark
208: */
209: public static final void markForDeletion(UIComponent c) {
210: // flag this component as deleted
211: c.getAttributes().put(MARK_DELETED, Boolean.TRUE);
212:
213: // mark all children to be deleted
214: int sz = c.getChildCount();
215: if (sz > 0) {
216: UIComponent cc = null;
217: List cl = c.getChildren();
218: while (--sz >= 0) {
219: cc = (UIComponent) cl.get(sz);
220: if (cc.getAttributes().containsKey(MARK_CREATED)) {
221: cc.getAttributes().put(MARK_DELETED, Boolean.TRUE);
222: }
223: }
224: }
225:
226: // mark all facets to be deleted
227: if (c.getFacets().size() > 0) {
228: Collection col = c.getFacets().values();
229: UIComponent fc;
230: for (Iterator itr = col.iterator(); itr.hasNext();) {
231: fc = (UIComponent) itr.next();
232: if (fc.getAttributes().containsKey(MARK_CREATED)) {
233: fc.getAttributes().put(MARK_DELETED, Boolean.TRUE);
234: }
235: }
236: }
237: }
238:
239: public final static void encodeRecursive(FacesContext context,
240: UIComponent viewToRender) throws IOException,
241: FacesException {
242: if (viewToRender.isRendered()) {
243: viewToRender.encodeBegin(context);
244: if (viewToRender.getRendersChildren()) {
245: viewToRender.encodeChildren(context);
246: } else if (viewToRender.getChildCount() > 0) {
247: Iterator kids = viewToRender.getChildren().iterator();
248: while (kids.hasNext()) {
249: UIComponent kid = (UIComponent) kids.next();
250: encodeRecursive(context, kid);
251: }
252: }
253: viewToRender.encodeEnd(context);
254: }
255: }
256:
257: public static void removeTransient(UIComponent c) {
258: UIComponent d, e;
259: if (c.getChildCount() > 0) {
260: for (Iterator itr = c.getChildren().iterator(); itr
261: .hasNext();) {
262: d = (UIComponent) itr.next();
263: if (d.getFacets().size() > 0) {
264: for (Iterator jtr = d.getFacets().values()
265: .iterator(); jtr.hasNext();) {
266: e = (UIComponent) jtr.next();
267: if (e.isTransient()) {
268: jtr.remove();
269: } else {
270: removeTransient(e);
271: }
272: }
273: }
274: if (d.isTransient()) {
275: itr.remove();
276: } else {
277: removeTransient(d);
278: }
279: }
280: }
281: if (c.getFacets().size() > 0) {
282: for (Iterator itr = c.getFacets().values().iterator(); itr
283: .hasNext();) {
284: d = (UIComponent) itr.next();
285: if (d.isTransient()) {
286: itr.remove();
287: } else {
288: removeTransient(d);
289: }
290: }
291: }
292: }
293:
294: /**
295: * Determine if the passed component is not null and if it's new
296: * to the tree. This operation can be used for determining if attributes
297: * should be wired to the component.
298: *
299: * @param component the component you wish to modify
300: * @return true if it's new
301: */
302: public final static boolean isNew(UIComponent component) {
303: return component != null && component.getParent() == null;
304: }
305: }
|