KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > beans > EventSetDescriptor


1 /*
2  * @(#)EventSetDescriptor.java 1.65 05/10/14
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.beans;
9
10 import java.lang.ref.Reference JavaDoc;
11
12 import java.lang.reflect.Method JavaDoc;
13
14 /**
15  * An EventSetDescriptor describes a group of events that a given Java
16  * bean fires.
17  * <P>
18  * The given group of events are all delivered as method calls on a single
19  * event listener interface, and an event listener object can be registered
20  * via a call on a registration method supplied by the event source.
21  */

22 public class EventSetDescriptor extends FeatureDescriptor JavaDoc {
23
24     private MethodDescriptor JavaDoc[] listenerMethodDescriptors;
25     private MethodDescriptor JavaDoc addMethodDescriptor;
26     private MethodDescriptor JavaDoc removeMethodDescriptor;
27     private MethodDescriptor JavaDoc getMethodDescriptor;
28
29     private Reference JavaDoc listenerMethodsRef;
30     private Reference JavaDoc listenerTypeRef;
31
32     private boolean unicast;
33     private boolean inDefaultEventSet = true;
34
35     /**
36      * Creates an <TT>EventSetDescriptor</TT> assuming that you are
37      * following the most simple standard design pattern where a named
38      * event &quot;fred&quot; is (1) delivered as a call on the single method of
39      * interface FredListener, (2) has a single argument of type FredEvent,
40      * and (3) where the FredListener may be registered with a call on an
41      * addFredListener method of the source component and removed with a
42      * call on a removeFredListener method.
43      *
44      * @param sourceClass The class firing the event.
45      * @param eventSetName The programmatic name of the event. E.g. &quot;fred&quot;.
46      * Note that this should normally start with a lower-case character.
47      * @param listenerType The target interface that events
48      * will get delivered to.
49      * @param listenerMethodName The method that will get called when the event gets
50      * delivered to its target listener interface.
51      * @exception IntrospectionException if an exception occurs during
52      * introspection.
53      */

54     public EventSetDescriptor(Class JavaDoc<?> sourceClass, String JavaDoc eventSetName,
55         Class JavaDoc<?> listenerType, String JavaDoc listenerMethodName)
56         throws IntrospectionException JavaDoc {
57     this(sourceClass, eventSetName, listenerType,
58          new String JavaDoc[] { listenerMethodName },
59          "add" + getListenerClassName(listenerType),
60          "remove" + getListenerClassName(listenerType),
61          "get" + getListenerClassName(listenerType) + "s");
62
63     String JavaDoc eventName = capitalize(eventSetName) + "Event";
64     Method JavaDoc[] listenerMethods = getListenerMethods();
65     if (listenerMethods.length > 0) {
66         Class JavaDoc[] args = listenerMethods[0].getParameterTypes();
67         // Check for EventSet compliance. Special case for vetoableChange. See 4529996
68
if (!"vetoableChange".equals(eventSetName) && !args[0].getName().endsWith(eventName)) {
69                 throw new IntrospectionException JavaDoc("Method \"" + listenerMethodName +
70                          "\" should have argument \"" +
71                          eventName + "\"");
72         }
73     }
74     }
75
76     private static String JavaDoc getListenerClassName(Class JavaDoc cls) {
77     String JavaDoc className = cls.getName();
78     return className.substring(className.lastIndexOf('.') + 1);
79     }
80
81     /**
82      * Creates an <TT>EventSetDescriptor</TT> from scratch using
83      * string names.
84      *
85      * @param sourceClass The class firing the event.
86      * @param eventSetName The programmatic name of the event set.
87      * Note that this should normally start with a lower-case character.
88      * @param listenerType The Class of the target interface that events
89      * will get delivered to.
90      * @param listenerMethodNames The names of the methods that will get called
91      * when the event gets delivered to its target listener interface.
92      * @param addListenerMethodName The name of the method on the event source
93      * that can be used to register an event listener object.
94      * @param removeListenerMethodName The name of the method on the event source
95      * that can be used to de-register an event listener object.
96      * @exception IntrospectionException if an exception occurs during
97      * introspection.
98      */

99     public EventSetDescriptor(Class JavaDoc<?> sourceClass,
100         String JavaDoc eventSetName,
101         Class JavaDoc<?> listenerType,
102         String JavaDoc listenerMethodNames[],
103         String JavaDoc addListenerMethodName,
104         String JavaDoc removeListenerMethodName)
105         throws IntrospectionException JavaDoc {
106     this(sourceClass, eventSetName, listenerType,
107          listenerMethodNames, addListenerMethodName,
108          removeListenerMethodName, null);
109     }
110
111     /**
112      * This constructor creates an EventSetDescriptor from scratch using
113      * string names.
114      *
115      * @param sourceClass The class firing the event.
116      * @param eventSetName The programmatic name of the event set.
117      * Note that this should normally start with a lower-case character.
118      * @param listenerType The Class of the target interface that events
119      * will get delivered to.
120      * @param listenerMethodNames The names of the methods that will get called
121      * when the event gets delivered to its target listener interface.
122      * @param addListenerMethodName The name of the method on the event source
123      * that can be used to register an event listener object.
124      * @param removeListenerMethodName The name of the method on the event source
125      * that can be used to de-register an event listener object.
126      * @param getListenerMethodName The method on the event source that
127      * can be used to access the array of event listener objects.
128      * @exception IntrospectionException if an exception occurs during
129      * introspection.
130      * @since 1.4
131      */

132     public EventSetDescriptor(Class JavaDoc<?> sourceClass,
133         String JavaDoc eventSetName,
134         Class JavaDoc<?> listenerType,
135         String JavaDoc listenerMethodNames[],
136         String JavaDoc addListenerMethodName,
137         String JavaDoc removeListenerMethodName,
138         String JavaDoc getListenerMethodName)
139         throws IntrospectionException JavaDoc {
140     if (sourceClass == null || eventSetName == null || listenerType == null) {
141         throw new NullPointerException JavaDoc();
142     }
143     setName(eventSetName);
144     setClass0(sourceClass);
145     setListenerType(listenerType);
146     
147     Method JavaDoc[] listenerMethods = new Method JavaDoc[listenerMethodNames.length];
148     for (int i = 0; i < listenerMethodNames.length; i++) {
149         // Check for null names
150
if (listenerMethodNames[i] == null) {
151         throw new NullPointerException JavaDoc();
152         }
153         listenerMethods[i] = getMethod(listenerType, listenerMethodNames[i], 1);
154     }
155     setListenerMethods(listenerMethods);
156
157     setAddListenerMethod(getMethod(sourceClass, addListenerMethodName, 1));
158     setRemoveListenerMethod(getMethod(sourceClass, removeListenerMethodName, 1));
159
160     // Be more forgiving of not finding the getListener method.
161
Method JavaDoc method = Introspector.findMethod(sourceClass,
162                         getListenerMethodName, 0);
163     if (method != null) {
164         setGetListenerMethod(method);
165     }
166     }
167
168     private static Method JavaDoc getMethod(Class JavaDoc cls, String JavaDoc name, int args)
169     throws IntrospectionException JavaDoc {
170     if (name == null) {
171         return null;
172     }
173     Method JavaDoc method = Introspector.findMethod(cls, name, args);
174     if (method == null) {
175         throw new IntrospectionException JavaDoc("Method not found: " + name +
176                          " on class " + cls.getName());
177     }
178     return method;
179     }
180
181     /**
182      * Creates an <TT>EventSetDescriptor</TT> from scratch using
183      * <TT>java.lang.reflect.Method</TT> and <TT>java.lang.Class</TT> objects.
184      *
185      * @param eventSetName The programmatic name of the event set.
186      * @param listenerType The Class for the listener interface.
187      * @param listenerMethods An array of Method objects describing each
188      * of the event handling methods in the target listener.
189      * @param addListenerMethod The method on the event source
190      * that can be used to register an event listener object.
191      * @param removeListenerMethod The method on the event source
192      * that can be used to de-register an event listener object.
193      * @exception IntrospectionException if an exception occurs during
194      * introspection.
195      */

196     public EventSetDescriptor(String JavaDoc eventSetName,
197         Class JavaDoc<?> listenerType,
198         Method JavaDoc listenerMethods[],
199         Method JavaDoc addListenerMethod,
200         Method JavaDoc removeListenerMethod)
201         throws IntrospectionException JavaDoc {
202     this(eventSetName, listenerType, listenerMethods,
203          addListenerMethod, removeListenerMethod, null);
204     }
205
206     /**
207      * This constructor creates an EventSetDescriptor from scratch using
208      * java.lang.reflect.Method and java.lang.Class objects.
209      *
210      * @param eventSetName The programmatic name of the event set.
211      * @param listenerType The Class for the listener interface.
212      * @param listenerMethods An array of Method objects describing each
213      * of the event handling methods in the target listener.
214      * @param addListenerMethod The method on the event source
215      * that can be used to register an event listener object.
216      * @param removeListenerMethod The method on the event source
217      * that can be used to de-register an event listener object.
218      * @param getListenerMethod The method on the event source
219      * that can be used to access the array of event listener objects.
220      * @exception IntrospectionException if an exception occurs during
221      * introspection.
222      * @since 1.4
223      */

224     public EventSetDescriptor(String JavaDoc eventSetName,
225         Class JavaDoc<?> listenerType,
226         Method JavaDoc listenerMethods[],
227         Method JavaDoc addListenerMethod,
228         Method JavaDoc removeListenerMethod,
229         Method JavaDoc getListenerMethod)
230         throws IntrospectionException JavaDoc {
231     setName(eventSetName);
232     setListenerMethods(listenerMethods);
233     setAddListenerMethod(addListenerMethod);
234     setRemoveListenerMethod( removeListenerMethod);
235     setGetListenerMethod(getListenerMethod);
236     setListenerType(listenerType);
237     }
238
239     /**
240      * Creates an <TT>EventSetDescriptor</TT> from scratch using
241      * <TT>java.lang.reflect.MethodDescriptor</TT> and <TT>java.lang.Class</TT>
242      * objects.
243      *
244      * @param eventSetName The programmatic name of the event set.
245      * @param listenerType The Class for the listener interface.
246      * @param listenerMethodDescriptors An array of MethodDescriptor objects
247      * describing each of the event handling methods in the
248      * target listener.
249      * @param addListenerMethod The method on the event source
250      * that can be used to register an event listener object.
251      * @param removeListenerMethod The method on the event source
252      * that can be used to de-register an event listener object.
253      * @exception IntrospectionException if an exception occurs during
254      * introspection.
255      */

256     public EventSetDescriptor(String JavaDoc eventSetName,
257         Class JavaDoc<?> listenerType,
258         MethodDescriptor JavaDoc listenerMethodDescriptors[],
259         Method JavaDoc addListenerMethod,
260         Method JavaDoc removeListenerMethod)
261         throws IntrospectionException JavaDoc {
262     setName(eventSetName);
263     this.listenerMethodDescriptors = listenerMethodDescriptors;
264     setAddListenerMethod(addListenerMethod);
265     setRemoveListenerMethod(removeListenerMethod);
266     setListenerType(listenerType);
267     }
268
269     /**
270      * Gets the <TT>Class</TT> object for the target interface.
271      *
272      * @return The Class object for the target interface that will
273      * get invoked when the event is fired.
274      */

275     public Class JavaDoc<?> getListenerType() {
276     return (Class JavaDoc)getObject(listenerTypeRef);
277     }
278
279     private void setListenerType(Class JavaDoc cls) {
280     listenerTypeRef = createReference(cls);
281     }
282
283     /**
284      * Gets the methods of the target listener interface.
285      *
286      * @return An array of <TT>Method</TT> objects for the target methods
287      * within the target listener interface that will get called when
288      * events are fired.
289      */

290     public synchronized Method JavaDoc[] getListenerMethods() {
291     Method JavaDoc[] methods = getListenerMethods0();
292     if (methods == null) {
293             if (listenerMethodDescriptors != null) {
294                 methods = new Method JavaDoc[listenerMethodDescriptors.length];
295         for (int i = 0; i < methods.length; i++) {
296                     methods[i] = listenerMethodDescriptors[i].getMethod();
297         }
298         }
299         setListenerMethods(methods);
300     }
301     return methods;
302     }
303
304     private void setListenerMethods(Method JavaDoc[] methods) {
305     if (methods == null) {
306         return;
307     }
308         if (listenerMethodDescriptors == null) {
309             listenerMethodDescriptors = new MethodDescriptor JavaDoc[methods.length];
310         for (int i = 0; i < methods.length; i++) {
311                 listenerMethodDescriptors[i] = new MethodDescriptor JavaDoc(methods[i]);
312         }
313     }
314     listenerMethodsRef = createReference(methods, true);
315     }
316
317     private Method JavaDoc[] getListenerMethods0() {
318     return (Method JavaDoc[])getObject(listenerMethodsRef);
319     }
320
321     /**
322      * Gets the <code>MethodDescriptor</code>s of the target listener interface.
323      *
324      * @return An array of <code>MethodDescriptor</code> objects for the target methods
325      * within the target listener interface that will get called when
326      * events are fired.
327      */

328     public synchronized MethodDescriptor JavaDoc[] getListenerMethodDescriptors() {
329     return listenerMethodDescriptors;
330     }
331
332     /**
333      * Gets the method used to add event listeners.
334      *
335      * @return The method used to register a listener at the event source.
336      */

337     public synchronized Method JavaDoc getAddListenerMethod() {
338         return (addMethodDescriptor != null ?
339                     addMethodDescriptor.getMethod() : null);
340     }
341
342     private synchronized void setAddListenerMethod(Method JavaDoc method) {
343     if (method == null) {
344         return;
345     }
346     if (getClass0() == null) {
347         setClass0(method.getDeclaringClass());
348     }
349         addMethodDescriptor = new MethodDescriptor JavaDoc(method);
350     }
351
352     /**
353      * Gets the method used to remove event listeners.
354      *
355      * @return The method used to remove a listener at the event source.
356      */

357     public synchronized Method JavaDoc getRemoveListenerMethod() {
358         return (removeMethodDescriptor != null ?
359                     removeMethodDescriptor.getMethod() : null);
360     }
361
362     private synchronized void setRemoveListenerMethod(Method JavaDoc method) {
363     if (method == null) {
364         return;
365     }
366     if (getClass0() == null) {
367         setClass0(method.getDeclaringClass());
368     }
369         removeMethodDescriptor = new MethodDescriptor JavaDoc(method);
370     }
371
372     /**
373      * Gets the method used to access the registered event listeners.
374      *
375      * @return The method used to access the array of listeners at the event
376      * source or null if it doesn't exist.
377      * @since 1.4
378      */

379     public synchronized Method JavaDoc getGetListenerMethod() {
380         return (getMethodDescriptor != null ?
381                     getMethodDescriptor.getMethod() : null);
382     }
383
384     private synchronized void setGetListenerMethod(Method JavaDoc method) {
385     if (method == null) {
386         return;
387     }
388     if (getClass0() == null) {
389         setClass0(method.getDeclaringClass());
390     }
391         getMethodDescriptor = new MethodDescriptor JavaDoc(method);
392     }
393
394     /**
395      * Mark an event set as unicast (or not).
396      *
397      * @param unicast True if the event set is unicast.
398      */

399     public void setUnicast(boolean unicast) {
400     this.unicast = unicast;
401     }
402     
403     /**
404      * Normally event sources are multicast. However there are some
405      * exceptions that are strictly unicast.
406      *
407      * @return <TT>true</TT> if the event set is unicast.
408      * Defaults to <TT>false</TT>.
409      */

410     public boolean isUnicast() {
411     return unicast;
412     }
413
414     /**
415      * Marks an event set as being in the &quot;default&quot; set (or not).
416      * By default this is <TT>true</TT>.
417      *
418      * @param inDefaultEventSet <code>true</code> if the event set is in
419      * the &quot;default&quot; set,
420      * <code>false</code> if not
421      */

422     public void setInDefaultEventSet(boolean inDefaultEventSet) {
423     this.inDefaultEventSet = inDefaultEventSet;
424     }
425     
426     /**
427      * Reports if an event set is in the &quot;default&quot; set.
428      *
429      * @return <TT>true</TT> if the event set is in
430      * the &quot;default&quot; set. Defaults to <TT>true</TT>.
431      */

432     public boolean isInDefaultEventSet() {
433     return inDefaultEventSet;
434     }
435
436     /*
437      * Package-private constructor
438      * Merge two event set descriptors. Where they conflict, give the
439      * second argument (y) priority over the first argument (x).
440      *
441      * @param x The first (lower priority) EventSetDescriptor
442      * @param y The second (higher priority) EventSetDescriptor
443      */

444     EventSetDescriptor(EventSetDescriptor JavaDoc x, EventSetDescriptor JavaDoc y) {
445     super(x,y);
446     listenerMethodDescriptors = x.listenerMethodDescriptors;
447     if (y.listenerMethodDescriptors != null) {
448         listenerMethodDescriptors = y.listenerMethodDescriptors;
449     }
450
451         listenerTypeRef = x.listenerTypeRef;
452     if (y.listenerTypeRef != null) {
453         listenerTypeRef = y.listenerTypeRef;
454     }
455
456         addMethodDescriptor = x.addMethodDescriptor;
457         if (y.addMethodDescriptor != null) {
458             addMethodDescriptor = y.addMethodDescriptor;
459         }
460
461         removeMethodDescriptor = x.removeMethodDescriptor;
462         if (y.removeMethodDescriptor != null) {
463             removeMethodDescriptor = y.removeMethodDescriptor;
464         }
465
466         getMethodDescriptor = x.getMethodDescriptor;
467         if (y.getMethodDescriptor != null) {
468             getMethodDescriptor = y.getMethodDescriptor;
469         }
470
471     unicast = y.unicast;
472     if (!x.inDefaultEventSet || !y.inDefaultEventSet) {
473         inDefaultEventSet = false;
474     }
475     }
476
477     /*
478      * Package-private dup constructor
479      * This must isolate the new object from any changes to the old object.
480      */

481     EventSetDescriptor(EventSetDescriptor JavaDoc old) {
482     super(old);
483     if (old.listenerMethodDescriptors != null) {
484         int len = old.listenerMethodDescriptors.length;
485         listenerMethodDescriptors = new MethodDescriptor JavaDoc[len];
486         for (int i = 0; i < len; i++) {
487         listenerMethodDescriptors[i] = new MethodDescriptor JavaDoc(
488                     old.listenerMethodDescriptors[i]);
489         }
490     }
491     listenerTypeRef = old.listenerTypeRef;
492
493         addMethodDescriptor = old.addMethodDescriptor;
494         removeMethodDescriptor = old.removeMethodDescriptor;
495         getMethodDescriptor = old.getMethodDescriptor;
496
497     unicast = old.unicast;
498     inDefaultEventSet = old.inDefaultEventSet;
499     }
500 }
501
Popular Tags