blob: eea5a29d81c13ca61b82f08499d9755905e82caf [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1996-2004 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package java.beans;
27
28import com.sun.beans.TypeResolver;
29
30import java.lang.ref.Reference;
31import java.lang.ref.WeakReference;
32import java.lang.ref.SoftReference;
33
34import java.lang.reflect.Method;
35import java.lang.reflect.Type;
36
37/**
38 * The FeatureDescriptor class is the common baseclass for PropertyDescriptor,
39 * EventSetDescriptor, and MethodDescriptor, etc.
40 * <p>
41 * It supports some common information that can be set and retrieved for
42 * any of the introspection descriptors.
43 * <p>
44 * In addition it provides an extension mechanism so that arbitrary
45 * attribute/value pairs can be associated with a design feature.
46 */
47
48public class FeatureDescriptor {
49
50 private Reference<Class> classRef;
51
52 /**
53 * Constructs a <code>FeatureDescriptor</code>.
54 */
55 public FeatureDescriptor() {
56 }
57
58 /**
59 * Gets the programmatic name of this feature.
60 *
61 * @return The programmatic name of the property/method/event
62 */
63 public String getName() {
64 return name;
65 }
66
67 /**
68 * Sets the programmatic name of this feature.
69 *
70 * @param name The programmatic name of the property/method/event
71 */
72 public void setName(String name) {
73 this.name = name;
74 }
75
76 /**
77 * Gets the localized display name of this feature.
78 *
79 * @return The localized display name for the property/method/event.
80 * This defaults to the same as its programmatic name from getName.
81 */
82 public String getDisplayName() {
83 if (displayName == null) {
84 return getName();
85 }
86 return displayName;
87 }
88
89 /**
90 * Sets the localized display name of this feature.
91 *
92 * @param displayName The localized display name for the
93 * property/method/event.
94 */
95 public void setDisplayName(String displayName) {
96 this.displayName = displayName;
97 }
98
99 /**
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)
291 ? this.classRef.get()
292 : null;
293 }
294
295 /**
296 * Create a Reference wrapper for the object.
297 *
298 * @param obj object that will be wrapped
299 * @param soft true if a SoftReference should be created; otherwise Soft
300 * @return a Reference or null if obj is null.
301 */
302 static Reference createReference(Object obj, boolean soft) {
303 Reference ref = null;
304 if (obj != null) {
305 if (soft) {
306 ref = new SoftReference(obj);
307 } else {
308 ref = new WeakReference(obj);
309 }
310 }
311 return ref;
312 }
313
314 // Convenience method which creates a WeakReference.
315 static Reference createReference(Object obj) {
316 return createReference(obj, false);
317 }
318
319 /**
320 * Returns an object from a Reference wrapper.
321 *
322 * @return the Object in a wrapper or null.
323 */
324 static Object getObject(Reference ref) {
325 return (ref == null) ? null : (Object)ref.get();
326 }
327
328 /**
329 * Creates a new soft reference that refers to the given object.
330 *
331 * @return a new soft reference or <code>null</code> if object is <code>null</code>
332 *
333 * @see SoftReference
334 */
335 static <T> Reference<T> getSoftReference(T object) {
336 return (object != null)
337 ? new SoftReference<T>(object)
338 : null;
339 }
340
341 /**
342 * Creates a new weak reference that refers to the given object.
343 *
344 * @return a new weak reference or <code>null</code> if object is <code>null</code>
345 *
346 * @see WeakReference
347 */
348 static <T> Reference<T> getWeakReference(T object) {
349 return (object != null)
350 ? new WeakReference<T>(object)
351 : null;
352 }
353
354 /**
355 * Resolves the return type of the method.
356 *
357 * @param base the class that contains the method in the hierarchy
358 * @param method the object that represents the method
359 * @return a class identifying the return type of the method
360 *
361 * @see Method#getGenericReturnType
362 * @see Method#getReturnType
363 */
364 static Class getReturnType(Class base, Method method) {
365 if (base == null) {
366 base = method.getDeclaringClass();
367 }
368 return TypeResolver.erase(TypeResolver.resolveInClass(base, method.getGenericReturnType()));
369 }
370
371 /**
372 * Resolves the parameter types of the method.
373 *
374 * @param base the class that contains the method in the hierarchy
375 * @param method the object that represents the method
376 * @return an array of classes identifying the parameter types of the method
377 *
378 * @see Method#getGenericParameterTypes
379 * @see Method#getParameterTypes
380 */
381 static Class[] getParameterTypes(Class base, Method method) {
382 if (base == null) {
383 base = method.getDeclaringClass();
384 }
385 return TypeResolver.erase(TypeResolver.resolveInClass(base, method.getGenericParameterTypes()));
386 }
387
388 private boolean expert;
389 private boolean hidden;
390 private boolean preferred;
391 private String shortDescription;
392 private String name;
393 private String displayName;
394 private java.util.Hashtable table;
395}