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.propertyeditors.domains;
042:
043: import java.util.ArrayList;
044: import java.util.HashMap;
045: import java.util.Iterator;
046: import java.util.Map;
047: import java.util.Set;
048: import java.util.TreeSet;
049: import com.sun.rave.designtime.Constants;
050: import com.sun.rave.designtime.DesignBean;
051: import com.sun.rave.designtime.DesignContext;
052: import com.sun.rave.designtime.DesignProject;
053: import com.sun.rave.designtime.DesignProperty;
054: import com.sun.rave.designtime.faces.FacesDesignProject;
055:
056: /**
057: * Domain of identifiers of all instance variables matching the class type of
058: * the property. If the property's bean is in page or request scope, then
059: * instance variables in session and application scope will be included. If the
060: * property's bean is in session scope context, instance variables from
061: * application scope will be included.
062: */
063: public class InstanceVariableDomain extends AttachedDomain {
064:
065: /**
066: * Allows a component author to specify a subtype to filter the list of
067: * instance variables. This subtype (Class object or String class name)
068: * must be a subtype of the property type - or it will be ignored.
069: */
070: public final static String INSTANCE_VARIABLE_SUBTYPE = "com.sun.rave.propertyeditors.domains.INSTANCE_VARIABLE_DOMAIN_SUBTYPE"; //NOI18N
071:
072: protected final static String SCOPE_REQUEST = "request";
073: protected final static String SCOPE_SESSION = "session";
074: protected final static String SCOPE_APPLICATION = "application";
075:
076: // For performance improvement. No need to get all the contexts in the project
077: private DesignContext[] getDesignContexts(DesignBean designBean) {
078: DesignProject designProject = designBean.getDesignContext()
079: .getProject();
080: DesignContext[] contexts;
081: if (designProject instanceof FacesDesignProject) {
082: contexts = ((FacesDesignProject) designProject)
083: .findDesignContexts(new String[] { "request",
084: "session", "application" });
085: } else {
086: contexts = new DesignContext[0];
087: }
088: DesignContext[] designContexts = new DesignContext[contexts.length + 1];
089: designContexts[0] = designBean.getDesignContext();
090: System.arraycopy(contexts, 0, designContexts, 1,
091: contexts.length);
092: return designContexts;
093: }
094:
095: public Element[] getElements() {
096:
097: DesignProperty designProperty = getDesignProperty();
098: if (designProperty == null)
099: return Element.EMPTY_ARRAY;
100:
101: Class propertyType = designProperty.getPropertyDescriptor()
102: .getPropertyType();
103:
104: FacesDesignProject facesDesignProject = (FacesDesignProject) designProperty
105: .getDesignBean().getDesignContext().getProject();
106:
107: Object subPropertyType = designProperty.getPropertyDescriptor()
108: .getValue(INSTANCE_VARIABLE_SUBTYPE);
109: if (subPropertyType instanceof Class
110: && (propertyType
111: .isAssignableFrom((Class) subPropertyType))) {
112: propertyType = (Class) subPropertyType;
113: } else if (subPropertyType instanceof String) {
114: try {
115: Class subPropertyClass = Class.forName(
116: (String) subPropertyType, false,
117: facesDesignProject.getContextClassLoader());
118: if (propertyType.isAssignableFrom(subPropertyClass))
119: propertyType = subPropertyClass;
120: } catch (Exception e) {
121: e.printStackTrace();
122: }
123: }
124:
125: // Retrieve the valid contexts in which to look for instance variables
126: DesignContext this Context = designProperty.getDesignBean()
127: .getDesignContext();
128:
129: //DesignContext[] scanContexts = getScanContexts(thisContext, thisContext.getProject().getDesignContexts());
130: DesignContext[] scanContexts = getScanContexts(this Context,
131: getDesignContexts(designProperty.getDesignBean()));
132:
133: // Scan all the beans and accumulate instance variables of all of them
134: // that match the property type
135: Set nameSet = new TreeSet();
136: Map elementMap = new HashMap();
137: for (int c = 0; c < scanContexts.length; c++) {
138: DesignContext context = scanContexts[c];
139: DesignBean beans[] = context.getBeansOfType(propertyType);
140: for (int i = 0; i < beans.length; i++) {
141: Object instance = beans[i].getInstance();
142: if ((instance != null)
143: && propertyType.isAssignableFrom(instance
144: .getClass())) {
145: String name;
146: Element element;
147: if (context == this Context) {
148: name = beans[i].getInstanceName();
149: element = new Element(beans[i].getInstance(),
150: name);
151: } else {
152: name = beans[i].getInstanceName() + " ("
153: + context.getDisplayName() + ")";
154: String initString = getInitString(context,
155: beans[i], propertyType);
156: element = new InstanceElement(beans[i]
157: .getInstance(), name, initString);
158: }
159: nameSet.add(name);
160: elementMap.put(name, element);
161: }
162: }
163: }
164:
165: if (nameSet.size() == 0) {
166: return Element.EMPTY_ARRAY;
167: }
168:
169: // Construct a list of elements of the retained identifiers
170: Element elements[] = new Element[nameSet.size()];
171: Iterator names = nameSet.iterator();
172: int n = 0;
173: while (names.hasNext()) {
174: String name = (String) names.next();
175: elements[n++] = (Element) elementMap.get(name);
176: }
177: return elements;
178: }
179:
180: protected DesignContext[] getScanContexts(
181: DesignContext this Context, DesignContext[] allContexts) {
182: ArrayList scanContexts = new ArrayList();
183: scanContexts.add(this Context);
184: Object this Scope = this Context
185: .getContextData(Constants.ContextData.SCOPE);
186: for (int i = 0; i < allContexts.length; i++) {
187: DesignContext context = allContexts[i];
188: if (context == this Context)
189: continue;
190: Object scope = context
191: .getContextData(Constants.ContextData.SCOPE);
192: if (SCOPE_REQUEST.equals(scope)
193: && SCOPE_REQUEST.equals(this Scope)) {
194: // check if this is the RequestBean
195: Object baseClass = context
196: .getContextData(Constants.ContextData.BASE_CLASS);
197: if (baseClass instanceof Class
198: && "com.sun.rave.web.ui.appbase.AbstractRequestBean"
199: .equals(((Class) baseClass).getName())) {
200: scanContexts.add(context);
201: }
202: } else if (SCOPE_SESSION.equals(scope)
203: && (SCOPE_REQUEST.equals(this Scope) || SCOPE_SESSION
204: .equals(this Scope))) {
205: scanContexts.add(context);
206: } else if (SCOPE_APPLICATION.equals(scope)
207: && (SCOPE_REQUEST.equals(this Scope)
208: || SCOPE_SESSION.equals(this Scope) || SCOPE_APPLICATION
209: .equals(this Scope))) {
210: scanContexts.add(context);
211: }
212: }
213: return (DesignContext[]) scanContexts
214: .toArray(new DesignContext[scanContexts.size()]);
215: }
216:
217: protected String getInitString(DesignContext context,
218: DesignBean bean, Class propType) {
219: String typeName = getJavaTypeName(propType.getName());
220: return "(" + typeName + ")getValue(\"#{"
221: + context.getDisplayName() + "."
222: + bean.getInstanceName() + "}\")";
223: }
224:
225: public static class InstanceElement extends Element {
226:
227: protected String javaInitString;
228:
229: public InstanceElement(Object value, String label,
230: String javaInitString) {
231: super (value, label);
232: this .javaInitString = javaInitString;
233: }
234:
235: public String getJavaInitializationString() {
236: return javaInitString;
237: }
238: }
239:
240: private static HashMap arrayTypeKeyHash = new HashMap();
241: static {
242: arrayTypeKeyHash.put("B", "byte"); //NOI18N
243: arrayTypeKeyHash.put("C", "char"); //NOI18N
244: arrayTypeKeyHash.put("D", "double"); //NOI18N
245: arrayTypeKeyHash.put("F", "float"); //NOI18N
246: arrayTypeKeyHash.put("I", "int"); //NOI18N
247: arrayTypeKeyHash.put("J", "long"); //NOI18N
248: arrayTypeKeyHash.put("S", "short"); //NOI18N
249: arrayTypeKeyHash.put("Z", "boolean"); //NOI18N
250: arrayTypeKeyHash.put("V", "void"); //NOI18N
251: }
252:
253: private static String getJavaTypeName(String tn) {
254: if (tn.startsWith("[")) { //NOI18N
255: int depth = 0;
256: while (tn.startsWith("[")) { //NOI18N
257: tn = tn.substring(1);
258: depth++;
259: }
260: if (tn.startsWith("L")) { //NOI18N
261: tn = tn.substring(1);
262: tn = tn.substring(0, tn.length() - 1);
263: } else {
264: char typeKey = tn.charAt(0);
265: tn = (String) arrayTypeKeyHash.get("" + typeKey); //NOI18N
266: }
267: for (int i = 0; i < depth; i++) {
268: tn += "[]"; //NOI18N
269: }
270: }
271: return tn;
272: }
273: }
|