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.component.util.descriptors;
042:
043: import com.sun.rave.web.ui.component.util.event.DecodeEvent;
044:
045: import java.util.ArrayList;
046: import java.util.HashMap;
047: import java.util.Iterator;
048: import java.util.List;
049: import java.util.Map;
050:
051: import javax.faces.context.FacesContext;
052: import javax.faces.component.UIComponent;
053:
054: /**
055: * <P> This represents the top-level {@link LayoutElement}, it is the
056: * container for every other {@link LayoutElement}. By itself, it has no
057: * functionality. Its purpose in life is to group all top-level child
058: * {@link LayoutElement}s. LayoutDefintion objects can be registered
059: * with the {@link com.sun.rave.web.ui.renderer.template.LayoutDefinitionManager}.
060: * This class does provide a useful method
061: * {@link #getChildLayoutElementById(FacesContext, String, LayoutElement, UIComponent)}
062: * which will search recursively for the given child id.</P>
063: *
064: * @author Ken Paulsen (ken.paulsen@sun.com)
065: */
066: public class LayoutDefinition extends LayoutElementBase {
067:
068: /**
069: * This is a hard-coded LayoutComponent type. By default it corresponds
070: * to com.sun.rave.web.ui.component.util.factories.StaticTextFactory.
071: */
072: public static final String STATIC_TEXT_TYPE = "staticText";
073:
074: /**
075: * This is the full class name of the default StaticTextFactory
076: */
077: public static final String STATIC_TEXT_FACTORY_CLASS_NAME = "com.sun.rave.web.ui.component.util.factories.StaticTextFactory";
078:
079: /**
080: * This is a list of Resource objects. These Resources are to be added
081: * to the Request scope when this LayoutDefinition is used.
082: */
083: private List _resources = new ArrayList();
084:
085: /**
086: * Map of types. This information is needed to instantiate UIComponents.
087: */
088: private Map _types = new HashMap();
089:
090: /**
091: * Map of attributes. Attributes can be used to store extra information
092: * about the LayoutDefinition.
093: */
094: private Map _attributes = new HashMap();
095:
096: /**
097: * Constructor
098: */
099: public LayoutDefinition(String id) {
100: // LayoutDefinition objects do not have a parent or an id
101: super (null, id);
102:
103: // Set the default StaticText ComponentType
104: addComponentType(new ComponentType(STATIC_TEXT_TYPE,
105: STATIC_TEXT_FACTORY_CLASS_NAME));
106: }
107:
108: /**
109: * Retrieve a ComponentType by typeID
110: *
111: * @param typeID The key used to retrieve the ComponentType
112: *
113: * @return The requested ComponentType or null
114: */
115: public ComponentType getComponentType(String typeID) {
116: return (ComponentType) _types.get(typeID);
117: }
118:
119: /**
120: * This will add the given ComponentType to the map of registered
121: * ComponentTypes. It will use the ComponentType ID as the key to the
122: * Map. This means that if a ComponentType with the same ID had
123: * previously been registered, it will be replaced with the ComponentType
124: * passed in.
125: *
126: * @param type The ComponentType.
127: */
128: public void addComponentType(ComponentType type) {
129: _types.put(type.getId(), type);
130: }
131:
132: /**
133: * This method adds a Resource. These resources should be added to the
134: * request scope when this component is used. This is mainly used for
135: * ResourceBundles (at this time).
136: *
137: * @param res The Resource to associate with the LayoutDefinition
138: */
139: public void addResource(Resource res) {
140: _resources.add(res);
141: }
142:
143: /**
144: * This method returns a List of Resource objects.
145: *
146: * @return This method returns a List of Resource objects.
147: */
148: public List getResources() {
149: return _resources;
150: }
151:
152: /**
153: * This method searches for the requested LayoutComponent by id.
154: *
155: * @param context <code>FacesContext</code>
156: * @param id id to look for
157: * @param parent Search starts from this
158: * <code>LayoutElement</code>
159: * @param parentComponent Parent <code>UIComponent</code>
160: *
161: * @return The matching LayoutElement if found, null otherwise.
162: */
163: public static LayoutElement getChildLayoutElementById(
164: FacesContext context, String id, LayoutElement parent,
165: UIComponent parentComponent) {
166: // NOTE: I may want to optimize this by putting all values in a Map so
167: // NOTE: that I don't have to do this search.
168:
169: // Make sure this isn't what we're looking for
170: if (parent.getId(context, parentComponent).equals(id)) {
171: return parent;
172: }
173:
174: // Not 'this' so lets check the children
175: Iterator it = parent.getChildLayoutElements().iterator();
176: LayoutElement elt = null;
177: while (it.hasNext()) {
178: elt = getChildLayoutElementById(context, id,
179: (LayoutElement) it.next(), parentComponent);
180: if (elt != null) {
181: // Found it!
182: return elt;
183: }
184: }
185:
186: // Not found...
187: return null;
188: }
189:
190: /**
191: * Retrieve an attribute by key
192: *
193: * @param key The key used to retrieve the attribute
194: *
195: * @return The requested attribute or null
196: */
197: public Object getAttribute(String key) {
198: return _attributes.get(key);
199: }
200:
201: /**
202: * Associate the given key with the given Object as an attribute.
203: *
204: * @param key The key associated with the given object (if this key
205: * is already in use, it will replace the previously set attribute
206: * object).
207: *
208: * @param value The Object to store.
209: */
210: public void setAttribute(String key, Object value) {
211: _attributes.put(key, value);
212: }
213:
214: /**
215: * <P> The LayoutDefinition does not encode anything for itself, this
216: * method simply returns true.</P>
217: *
218: * @param context The FacesContext
219: * @param component The UIComponent
220: *
221: * @return true
222: */
223: protected boolean encodeThis(FacesContext context,
224: UIComponent component) {
225: return true;
226: }
227:
228: /**
229: * <P> This decode method invokes any registered DECODE handlers.</P>
230: *
231: * @param context The FacesContext
232: * @param component The Template
233: */
234: public void decode(FacesContext context, UIComponent component) {
235: // Invoke "decode" handlers
236: dispatchHandlers(context, DECODE, new DecodeEvent(component));
237: }
238:
239: /**
240: * <P> This is the "type" for handlers to be invoked to handle "decode"
241: * functionality for this element.</P>
242: */
243: public static final String DECODE = "decode";
244: }
|