next up previous contents
Next: MethodDescriptor Up: BeanInfo Previous: PropertyDescriptor

EventSetDescriptor

EventSetDescriptorは、新しいイベント・モデルに対応して、リスナーの型、 リスナー上のメソッド、add/removeのメソッドの情報を持ちますので、 次のようなフィールドを持ちます。リスナー上のメソッドは、一般には、 複数個存在しえますので、配列になっていることに注意してください。

public class EventSetDescriptor extends FeatureDescriptor {

    private Class listenerType;
    private Method[] listenerMethods;
    private MethodDescriptor[] listenerMethodDescriptors;
    private Method addMethod;
    private Method removeMethod;
    private boolean unicast;
    private boolean inDefaultEventSet = true;
}

次に、このクラスのコンストラクタのsignatureを見てみたいと思います。

==============================================================================
    public EventSetDescriptor(Class sourceClass, String eventSetName,
                Class listenerType, String listenerMethodName) 
                throws IntrospectionException ...
    public EventSetDescriptor(Class sourceClass,
                String eventSetName, 
                Class listenerType,
                String listenerMethodNames[],
                String addListenerMethodName,
                String removeListenerMethodName)
                throws IntrospectionException ...
    public EventSetDescriptor(String eventSetName, 
                Class listenerType,
                Method listenerMethods[],
                Method addListenerMethod,
                Method removeListenerMethod) 
                throws IntrospectionException ...
    public EventSetDescriptor(String eventSetName, 
                Class listenerType,
                MethodDescriptor listenerMethodDescriptors[],
                Method addListenerMethod,
                Method removeListenerMethod) 
                throws IntrospectionException ...
==============================================================================

EventSetDescriptorとIntrospection

実際には、これらのコンストラクタを使わなくても、Introspectorの getTargetEventInfoメソッドの中で、メソッドのreflectionを通じて、 3番目のコンストラクタが呼び出されるのが分かります。 この部分は、reflectionのいい練習ですので、是非、解読に挑戦して下さい。 リスナー・メソッドがどのように決められているのかを考えてください。

==============================================================================
    private EventSetDescriptor[] getTargetEventInfo() throws IntrospectionException {
        .........
        .........
        if (explicit != null) {
            // Add the explicit informant data to our results.
            for (int i = 0 ; i < explicit.length; i++) {
                addEvent(explicit[i]);
            }
        } else {
            Method methodList[] = getDeclaredMethods(beanClass);

            java.util.Hashtable adds = new java.util.Hashtable();
            java.util.Hashtable removes = new java.util.Hashtable();
            for (int i = 0; i < methodList.length; i++) {
                Method method = methodList[i];
                int mods = method.getModifiers();
                if (Modifier.isStatic(mods) || !Modifier.isPublic(mods)) {
                    continue;
                }
                String name = method.getName();

                Class argTypes[] = method.getParameterTypes();
                Class resultType = method.getReturnType();

                if (name.startsWith("add") && argTypes.length == 1 &&
                                    resultType == Void.TYPE) {
                    String compound = name.substring(3) + ":" + argTypes[0];
                    adds.put(compound, method);
                } else if (name.startsWith("remove") && argTypes.length == 1 &&
                                    resultType == Void.TYPE) {
                    String compound = name.substring(6) + ":" + argTypes[0];
                    removes.put(compound, method);
                }
            }

            java.util.Enumeration keys = adds.keys();
            String beanClassName = beanClass.getName();
            while (keys.hasMoreElements()) {
                String compound = (String) keys.nextElement();
                // Skip any "add" which doesn't have a matching "remove".
                if (removes.get(compound) == null) {
                    continue;
                } 
                // Method name has to end in "Listener"
                if (compound.indexOf("Listener:") <= 0) {
                    continue;
                }

                String listenerName = compound.substring(0, compound.indexOf(':'));
                String eventName = decapitalize(listenerName.substring(0, listenerName.length()-8));
                Method addMethod = (Method)adds.get(compound);
                Method removeMethod = (Method)removes.get(compound);
                Class argType = addMethod.getParameterTypes()[0];

                // Check if the argument type is a subtype of EventListener
                if (!Introspector.isSubclass(argType, eventListenerType)) {
                    continue;
                }

                // generate a list of Method objects for each of the target methods:
                Method allMethods[] = argType.getMethods();
                int count = 0;
                for (int i = 0; i < allMethods.length; i++) {
                    if (isEventHandler(allMethods[i])) {
                        count++;
                    } else {
                        allMethods[i] = null;
                    }
                }
                Method methods[] = new Method[count];
                int j = 0;
                for (int i = 0; i < allMethods.length; i++) {
                    if (allMethods[i] != null) {
                        methods[j++] = allMethods[i];
                    }
                 }

                  EventSetDescriptor esd = 
                      new EventSetDescriptor(eventName, argType,
                                             methods, addMethod, removeMethod);

                if (throwsException(addMethod,
                        java.util.TooManyListenersException.class)) {
                    esd.setUnicast(true);
                }

                addEvent(esd);
            }
        }
        .........
        .........
    }
==============================================================================


maruyama@wakhok.ac.jp