001 /*
002 * Copyright 1996-2004 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package java.beans;
027
028 import com.sun.beans.TypeResolver;
029
030 import java.lang.ref.Reference;
031 import java.lang.ref.WeakReference;
032 import java.lang.ref.SoftReference;
033
034 import java.lang.reflect.Method;
035 import java.lang.reflect.Type;
036
037 /**
038 * The FeatureDescriptor class is the common baseclass for PropertyDescriptor,
039 * EventSetDescriptor, and MethodDescriptor, etc.
040 * <p>
041 * It supports some common information that can be set and retrieved for
042 * any of the introspection descriptors.
043 * <p>
044 * In addition it provides an extension mechanism so that arbitrary
045 * attribute/value pairs can be associated with a design feature.
046 */
047
048 public class FeatureDescriptor {
049
050 private Reference<Class> classRef;
051
052 /**
053 * Constructs a <code>FeatureDescriptor</code>.
054 */
055 public FeatureDescriptor() {
056 }
057
058 /**
059 * Gets the programmatic name of this feature.
060 *
061 * @return The programmatic name of the property/method/event
062 */
063 public String getName() {
064 return name;
065 }
066
067 /**
068 * Sets the programmatic name of this feature.
069 *
070 * @param name The programmatic name of the property/method/event
071 */
072 public void setName(String name) {
073 this .name = name;
074 }
075
076 /**
077 * Gets the localized display name of this feature.
078 *
079 * @return The localized display name for the property/method/event.
080 * This defaults to the same as its programmatic name from getName.
081 */
082 public String getDisplayName() {
083 if (displayName == null) {
084 return getName();
085 }
086 return displayName;
087 }
088
089 /**
090 * Sets the localized display name of this feature.
091 *
092 * @param displayName The localized display name for the
093 * property/method/event.
094 */
095 public void setDisplayName(String displayName) {
096 this .displayName = displayName;
097 }
098
099 /**
100 * The "expert" flag is used to distinguish between those features that are
101 * intended for expert users from those that are intended for normal users.
102 *
103 * @return True if this feature is intended for use by experts only.
104 */
105 public boolean isExpert() {
106 return expert;
107 }
108
109 /**
110 * The "expert" flag is used to distinguish between features that are
111 * intended for expert users from those that are intended for normal users.
112 *
113 * @param expert True if this feature is intended for use by experts only.
114 */
115 public void setExpert(boolean expert) {
116 this .expert = expert;
117 }
118
119 /**
120 * The "hidden" flag is used to identify features that are intended only
121 * for tool use, and which should not be exposed to humans.
122 *
123 * @return True if this feature should be hidden from human users.
124 */
125 public boolean isHidden() {
126 return hidden;
127 }
128
129 /**
130 * The "hidden" flag is used to identify features that are intended only
131 * for tool use, and which should not be exposed to humans.
132 *
133 * @param hidden True if this feature should be hidden from human users.
134 */
135 public void setHidden(boolean hidden) {
136 this .hidden = hidden;
137 }
138
139 /**
140 * The "preferred" flag is used to identify features that are particularly
141 * important for presenting to humans.
142 *
143 * @return True if this feature should be preferentially shown to human users.
144 */
145 public boolean isPreferred() {
146 return preferred;
147 }
148
149 /**
150 * The "preferred" flag is used to identify features that are particularly
151 * important for presenting to humans.
152 *
153 * @param preferred True if this feature should be preferentially shown
154 * to human users.
155 */
156 public void setPreferred(boolean preferred) {
157 this .preferred = preferred;
158 }
159
160 /**
161 * Gets the short description of this feature.
162 *
163 * @return A localized short description associated with this
164 * property/method/event. This defaults to be the display name.
165 */
166 public String getShortDescription() {
167 if (shortDescription == null) {
168 return getDisplayName();
169 }
170 return shortDescription;
171 }
172
173 /**
174 * You can associate a short descriptive string with a feature. Normally
175 * these descriptive strings should be less than about 40 characters.
176 * @param text A (localized) short description to be associated with
177 * this property/method/event.
178 */
179 public void setShortDescription(String text) {
180 shortDescription = text;
181 }
182
183 /**
184 * Associate a named attribute with this feature.
185 *
186 * @param attributeName The locale-independent name of the attribute
187 * @param value The value.
188 */
189 public void setValue(String attributeName, Object value) {
190 if (table == null) {
191 table = new java.util.Hashtable();
192 }
193 table.put(attributeName, value);
194 }
195
196 /**
197 * Retrieve a named attribute with this feature.
198 *
199 * @param attributeName The locale-independent name of the attribute
200 * @return The value of the attribute. May be null if
201 * the attribute is unknown.
202 */
203 public Object getValue(String attributeName) {
204 if (table == null) {
205 return null;
206 }
207 return table.get(attributeName);
208 }
209
210 /**
211 * Gets an enumeration of the locale-independent names of this
212 * feature.
213 *
214 * @return An enumeration of the locale-independent names of any
215 * attributes that have been registered with setValue.
216 */
217 public java.util.Enumeration<String> attributeNames() {
218 if (table == null) {
219 table = new java.util.Hashtable();
220 }
221 return table.keys();
222 }
223
224 /**
225 * Package-private constructor,
226 * Merge information from two FeatureDescriptors.
227 * The merged hidden and expert flags are formed by or-ing the values.
228 * In the event of other conflicts, the second argument (y) is
229 * given priority over the first argument (x).
230 *
231 * @param x The first (lower priority) MethodDescriptor
232 * @param y The second (higher priority) MethodDescriptor
233 */
234 FeatureDescriptor(FeatureDescriptor x, FeatureDescriptor y) {
235 expert = x.expert | y.expert;
236 hidden = x.hidden | y.hidden;
237 preferred = x.preferred | y.preferred;
238 name = y.name;
239 shortDescription = x.shortDescription;
240 if (y.shortDescription != null) {
241 shortDescription = y.shortDescription;
242 }
243 displayName = x.displayName;
244 if (y.displayName != null) {
245 displayName = y.displayName;
246 }
247 classRef = x.classRef;
248 if (y.classRef != null) {
249 classRef = y.classRef;
250 }
251 addTable(x.table);
252 addTable(y.table);
253 }
254
255 /*
256 * Package-private dup constructor
257 * This must isolate the new object from any changes to the old object.
258 */
259 FeatureDescriptor(FeatureDescriptor old) {
260 expert = old.expert;
261 hidden = old.hidden;
262 preferred = old.preferred;
263 name = old.name;
264 shortDescription = old.shortDescription;
265 displayName = old.displayName;
266 classRef = old.classRef;
267
268 addTable(old.table);
269 }
270
271 private void addTable(java.util.Hashtable t) {
272 if (t == null) {
273 return;
274 }
275 java.util.Enumeration keys = t.keys();
276 while (keys.hasMoreElements()) {
277 String key = (String) keys.nextElement();
278 Object value = t.get(key);
279 setValue(key, value);
280 }
281 }
282
283 // Package private methods for recreating the weak/soft referent
284
285 void setClass0(Class cls) {
286 this .classRef = getWeakReference(cls);
287 }
288
289 Class getClass0() {
290 return (this .classRef != null) ? this .classRef.get() : null;
291 }
292
293 /**
294 * Create a Reference wrapper for the object.
295 *
296 * @param obj object that will be wrapped
297 * @param soft true if a SoftReference should be created; otherwise Soft
298 * @return a Reference or null if obj is null.
299 */
300 static Reference createReference(Object obj, boolean soft) {
301 Reference ref = null;
302 if (obj != null) {
303 if (soft) {
304 ref = new SoftReference(obj);
305 } else {
306 ref = new WeakReference(obj);
307 }
308 }
309 return ref;
310 }
311
312 // Convenience method which creates a WeakReference.
313 static Reference createReference(Object obj) {
314 return createReference(obj, false);
315 }
316
317 /**
318 * Returns an object from a Reference wrapper.
319 *
320 * @return the Object in a wrapper or null.
321 */
322 static Object getObject(Reference ref) {
323 return (ref == null) ? null : (Object) ref.get();
324 }
325
326 /**
327 * Creates a new soft reference that refers to the given object.
328 *
329 * @return a new soft reference or <code>null</code> if object is <code>null</code>
330 *
331 * @see SoftReference
332 */
333 static <T> Reference<T> getSoftReference(T object) {
334 return (object != null) ? new SoftReference<T>(object) : null;
335 }
336
337 /**
338 * Creates a new weak reference that refers to the given object.
339 *
340 * @return a new weak reference or <code>null</code> if object is <code>null</code>
341 *
342 * @see WeakReference
343 */
344 static <T> Reference<T> getWeakReference(T object) {
345 return (object != null) ? new WeakReference<T>(object) : null;
346 }
347
348 /**
349 * Resolves the return type of the method.
350 *
351 * @param base the class that contains the method in the hierarchy
352 * @param method the object that represents the method
353 * @return a class identifying the return type of the method
354 *
355 * @see Method#getGenericReturnType
356 * @see Method#getReturnType
357 */
358 static Class getReturnType(Class base, Method method) {
359 if (base == null) {
360 base = method.getDeclaringClass();
361 }
362 return TypeResolver.erase(TypeResolver.resolveInClass(base,
363 method.getGenericReturnType()));
364 }
365
366 /**
367 * Resolves the parameter types of the method.
368 *
369 * @param base the class that contains the method in the hierarchy
370 * @param method the object that represents the method
371 * @return an array of classes identifying the parameter types of the method
372 *
373 * @see Method#getGenericParameterTypes
374 * @see Method#getParameterTypes
375 */
376 static Class[] getParameterTypes(Class base, Method method) {
377 if (base == null) {
378 base = method.getDeclaringClass();
379 }
380 return TypeResolver.erase(TypeResolver.resolveInClass(base,
381 method.getGenericParameterTypes()));
382 }
383
384 private boolean expert;
385 private boolean hidden;
386 private boolean preferred;
387 private String shortDescription;
388 private String name;
389 private String displayName;
390 private java.util.Hashtable table;
391 }
|