001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package com.sun.rave.web.ui.faces;
042:
043: import com.sun.rave.web.ui.util.LogUtil;
044:
045: import java.util.List;
046: import javax.faces.component.UIComponent;
047: import javax.faces.el.PropertyNotFoundException;
048: import javax.faces.el.PropertyResolver;
049:
050: /**
051: * <p>Custom JSF <code>PropertyResolver that, when the <code>base</code>
052: * object is a <code>UIComponent</code>, scans for a child with the
053: * <code>id</code> specified by the property name.</p>
054: */
055: public class UIComponentPropertyResolver extends PropertyResolver {
056:
057: // -------------------------------------------------------- Static Variables
058:
059: // ------------------------------------------------------ Instance Variables
060:
061: /**
062: * <p>The original <code>PropertyResolver</code> to which we
063: * will delegate unrecognized base objects.</p>
064: */
065: private PropertyResolver original = null;
066:
067: // ------------------------------------------------------------ Constructors
068:
069: public UIComponentPropertyResolver() {
070: LogUtil.warning(UIComponentPropertyResolver.class,
071: "UIComponentPropertyResolver(" + "NONE" + ")");
072: }
073:
074: /**
075: * <p>Construct a new {@link UIComponentPropertyResolver} that decorates
076: * the specified <code>PropertyResolver</code>.</p>
077: *
078: * @param original Original <code>PropertyResolver</code> to decorate
079: */
080: public UIComponentPropertyResolver(PropertyResolver original) {
081:
082: this .original = original;
083: if (LogUtil.fineEnabled(UIComponentPropertyResolver.class)) {
084: LogUtil.fine(UIComponentPropertyResolver.class,
085: "UIComponentPropertyResolver(" + original + ")"); // NOI18N
086: }
087:
088: }
089:
090: // ------------------------------------------------ PropertyResolver Methods
091:
092: /**
093: * <p>When the base object is a <code>UIComponent</code>, treat the
094: * property name as the <code>id</code> of a child component to be
095: * returned. If there is no such child, delegate to the rest of
096: * the chain (so that properties of a component may be accessed).</p>
097: *
098: * @param base Base object
099: * @param property Property name
100: */
101: public Object getValue(Object base, Object property) {
102:
103: if (LogUtil.finestEnabled(UIComponentPropertyResolver.class)) {
104: LogUtil.finest(UIComponentPropertyResolver.class,
105: "getValue(" + base + "," + property + ")"); // NOI18N
106: }
107:
108: if ((base == null) || (!(base instanceof UIComponent))
109: || (property == null)) {
110: if (LogUtil
111: .finestEnabled(UIComponentPropertyResolver.class)) {
112: LogUtil.finest(UIComponentPropertyResolver.class,
113: " Delegated to decorated PropertyResolver");
114: }
115: return original.getValue(base, property);
116: }
117:
118: // Try to resolve to facet or child UIComponent
119: UIComponent component = (UIComponent) base;
120: String id = property.toString();
121:
122: // First check for a facet w/ that name
123: UIComponent kid = (UIComponent) component.getFacets().get(id);
124: if (kid != null) {
125: return kid;
126: }
127:
128: // Now check for child component w/ that id
129: if (component.getChildCount() < 1) {
130: return original.getValue(base, property);
131: }
132: List kids = component.getChildren();
133: for (int i = 0; i < kids.size(); i++) {
134: kid = (UIComponent) kids.get(i);
135: if (id.equals(kid.getId())) {
136: if (LogUtil
137: .finestEnabled(UIComponentPropertyResolver.class)) {
138: LogUtil.finest(UIComponentPropertyResolver.class,
139: " Returning child " + kid);
140: }
141: return kid;
142: }
143: }
144:
145: // Not found, delegate to original...
146: return original.getValue(base, property);
147: }
148:
149: /**
150: * <p>When the base object is a <code>UIComponent</code>, treat the
151: * index as the zero-relative index of the child to be returned.</p>
152: *
153: * @param base Base object
154: * @param index Zero-relative child index
155: */
156: public Object getValue(Object base, int index) {
157:
158: if ((base == null) || (!(base instanceof UIComponent))) {
159: return original.getValue(base, index);
160: }
161:
162: UIComponent component = (UIComponent) base;
163: if (component.getChildCount() < 1) {
164: throw new PropertyNotFoundException("" + index);
165: }
166: try {
167: return component.getChildren().get(index);
168: } catch (IndexOutOfBoundsException e) {
169: throw new PropertyNotFoundException("" + index);
170: }
171:
172: }
173:
174: /**
175: * <p>When the base object is a <code>UIComponent</code>, treat the
176: * property name as the <code>id</code> of a child component to be
177: * replaced. If there is no such child, delegate to the rest of the
178: * chain (so that properties of a component may be accessed).</p>
179: *
180: * @param base Base object
181: * @param property Property name
182: * @param value Replacement component
183: */
184: public void setValue(Object base, Object property, Object value) {
185:
186: if ((base == null) || (!(base instanceof UIComponent))
187: || (property == null) || (value == null)
188: || (!(value instanceof UIComponent))) {
189: original.setValue(base, property, value);
190: return;
191: }
192:
193: UIComponent component = (UIComponent) base;
194: String id = property.toString();
195: // First check to for facet w/ this name
196: if (component.getFacets().get(id) != null) {
197: component.getFacets().put(id, value);
198: return;
199: }
200: // Not a facet, see if it's a child
201: if (component.getChildCount() < 1) {
202: original.setValue(base, property, value);
203: return;
204: }
205: List kids = component.getChildren();
206: for (int i = 0; i < kids.size(); i++) {
207: UIComponent kid = (UIComponent) kids.get(i);
208: if (id.equals(kid.getId())) {
209: kids.set(i, value);
210: return;
211: }
212: }
213: original.setValue(base, property, value);
214:
215: }
216:
217: /**
218: * <p>When the base object is a <code>UIComponent</code>, treat the
219: * index as the zero-relative index of the child to be replaced.</p>
220: *
221: * @param base Base object
222: * @param index Zero-relative child index
223: * @param value Replacement component
224: */
225: public void setValue(Object base, int index, Object value) {
226:
227: if ((base == null) || (!(base instanceof UIComponent))
228: || (value == null) || (!(value instanceof UIComponent))) {
229: original.setValue(base, index, value);
230: return;
231: }
232:
233: UIComponent component = (UIComponent) base;
234: if (component.getChildCount() < 1) {
235: throw new PropertyNotFoundException("" + index);
236: }
237: try {
238: component.getChildren().set(index, value);
239: } catch (IndexOutOfBoundsException e) {
240: throw new PropertyNotFoundException("" + index);
241: }
242:
243: }
244:
245: /**
246: * <p>When the base object is a <code>UIComponent</code>, treat the
247: * property name as the <code>id</code> of a child component to be
248: * retrieved. If the specified child actually exists, return
249: * <code>false</code> (because replacement is allowed). If there
250: * is no such child, delegate to the rest of the chain (so that
251: * component properties may be accessed).</p>
252: *
253: * @param base Base object
254: * @param property Property name
255: */
256: public boolean isReadOnly(Object base, Object property) {
257:
258: if ((base == null) || (!(base instanceof UIComponent))
259: || (property == null)) {
260: return original.isReadOnly(base, property);
261: }
262:
263: UIComponent component = (UIComponent) base;
264: String id = property.toString();
265: if (component.getFacets().get(id) != null) {
266: return false;
267: }
268: if (component.getChildCount() < 1) {
269: return original.isReadOnly(base, property);
270: }
271: List kids = component.getChildren();
272: for (int i = 0; i < kids.size(); i++) {
273: UIComponent kid = (UIComponent) kids.get(i);
274: if (id.equals(kid.getId())) {
275: return false;
276: }
277: }
278: return original.isReadOnly(base, property);
279:
280: }
281:
282: /**
283: * <p>When the base object is a <code>UIComponent</code>, treat the
284: * index as the zero-relative index of the child to be retrieved.
285: * If the specified child actually exists, return <code>false</code>
286: * (because replacement is allowed).</p>
287: *
288: * @param base Base object
289: * @param index Zero-relative child index
290: */
291: public boolean isReadOnly(Object base, int index) {
292:
293: if ((base == null) || (!(base instanceof UIComponent))) {
294: return original.isReadOnly(base, index);
295: }
296:
297: UIComponent component = (UIComponent) base;
298: if (component.getChildCount() < 1) {
299: throw new PropertyNotFoundException("" + index);
300: }
301: try {
302: component.getChildren().get(index);
303: return false;
304: } catch (IndexOutOfBoundsException e) {
305: throw new PropertyNotFoundException("" + index);
306: }
307:
308: }
309:
310: /**
311: * <p>When the base object is a <code>UIComponent</code>, treat the
312: * property name as the <code>id</code> of a child component to be
313: * retrieved. If the specified child actually exists, return
314: * <code>javax.faces.component.UIComponent</code>. If there is
315: * no such child, delegate to the rest of the chain (so that component
316: * properties may be accessed).</p>
317: *
318: * @param base Base object
319: * @param property Property name
320: */
321: public Class getType(Object base, Object property) {
322:
323: if ((base == null) || (!(base instanceof UIComponent))
324: || (property == null)) {
325: return original.getType(base, property);
326: }
327:
328: UIComponent component = (UIComponent) base;
329: String id = property.toString();
330: if (component.getFacets().get(id) != null) {
331: return UIComponent.class;
332: }
333: if (component.getChildCount() < 1) {
334: return original.getType(base, property);
335: }
336: List kids = component.getChildren();
337: for (int i = 0; i < kids.size(); i++) {
338: UIComponent kid = (UIComponent) kids.get(i);
339: if (id.equals(kid.getId())) {
340: return UIComponent.class;
341: }
342: }
343: return original.getType(base, property);
344:
345: }
346:
347: /**
348: * <p>When the base object is a <code>UIComponent</code>, treat the
349: * index as the zero-relative index of the child to be retrieved.
350: * If the specified child actually exists,
351: * return <code>javax.faces.component.UIComponent</code>.</p>
352: *
353: * @param base Base object
354: * @param index Zero-relative child index
355: */
356: public Class getType(Object base, int index) {
357:
358: if ((base == null) || (!(base instanceof UIComponent))) {
359: return original.getType(base, index);
360: }
361:
362: UIComponent component = (UIComponent) base;
363: if (component.getChildCount() < 1) {
364: throw new PropertyNotFoundException("" + index);
365: }
366: try {
367: component.getChildren().get(index);
368: return UIComponent.class;
369: } catch (IndexOutOfBoundsException e) {
370: throw new PropertyNotFoundException("" + index);
371: }
372:
373: }
374:
375: }
|