Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
interface MyListener {
    void eventOccurred(MyEvent event)
}
class MyEvent {    def source
    String message

    TestEventMyEvent(def source, String message) {
        this.source = source
        this.message = message
    }
}
class MyBeanClass {
    @ListenerList
    List<MyListener> listeners
}
  • + addMyListener(MyListener) : void - This method is created based on the generic type of your annotated List field. The name and parameter type is are based on the List field's generic parameter.
  • + removeMyListener(MyListener) : void- This method is created based on the generic type of your annotated List field. The name and parameter type is are based on the List field's generic parameter.
  • + getMyListeners() : MyListener[] - This method is created based on the generic type of your annotated List field.The name is the plural form of the List field's generic parameter, and the return type is an array of the generic parameter.
  • + fireEventOccurred(MyEvent) : void - This method is created based on the type that the List's generic type points to. In this case, MyListener is a one method interface with an eventOccurred(MyEvent) method. The method name is fire[MethodName of the interface] and the parameter is the parameter list from the interface. (Note: what happens where there are two parameters on the method?)+ fireEventOccurred(Object, String) : void - This should be removed as it is too complex to generate a proper parameter list. What if the object has 2 constructors? Are there two methods generated? 10 constructors = 10 methods? Yuck.

Gets turned into:

  • Code Block
    public class MyBeanClass {
    
        @groovy.beans.ListenerList
        private List<MyListener> listeners
    
        public void addMyListener(MyListener listener) {
            if (listener == null) { return }
            if ( listeners == null) { listeners = [] }
            listeners.add(listener)
        }
    
        public void removeMyListener(MyListener listener) {
            if (listener == null) { return }
            if ( listeners == null) { listeners = [] }
            listeners.remove(listener)
        }
    
        public MyListener[] getMyListeners() {
            def __result = []
            if ( listeners != null) {
                __result.addAll(listeners)
            }
            __result as MyListener[]
        }
    
        public void fireEventOccurred(MyEvent p0) {
            if ( listeners != null) {
                def __list = new ArrayList(listeners)
                for (listener : __list ) {
                    listener.eventOccurred(p0)
                }
            }
        }
    
        public void fireEventOccurred(java.lang.Object p0, java.lang.String p1) {
            if ( listeners != null) {
                def __list = new ArrayList(listeners)
                for (listener : __list ) {
                    listener.eventOccurred(new MyEvent(p0, p1))
                }
            }
        }
    }
    
    Notes - 1) add listener and remove listener have conflicting code. There is a guard clause that returns null when parameter is null and a guard clause that lazy instantiates the listener. Can't have both. 2) The fireEvent methods do not seem to be part of the bean spec. To simplify, let's remove the 2nd one with 2 parameters.

...

  • We considered allowing @ListenerList to be a Class/Type annotation. The benefit was terseness. You don't even need to declare a field in that case. However, we decided it brings too much complexity. We are searching for ways to simplify this, and removing this option reduces the complexity with no real loss in functionality.
  • We considered adding fire* methods based on the declared constructors of the Event class. This means that if the Event class has 5 constructors then there would be 6 fire events on the target class. This is too complex, too verbose, and not part of the bean spec. To simplify we removed it. We can add it back in later if we want. 

Advanced Examples

The following examples have not been analyzed yet and may be inconsistent. All of these examples assume the following:

...