Uploaded image for project: 'Groovy'
  1. Groovy
  2. GROOVY-4509

ASTTransformation @ListenerList - Java-style listener support

    XMLWordPrintableJSON

Details

    • New Feature
    • Status: Closed
    • Minor
    • Resolution: Fixed
    • 1.7.5
    • 1.8-beta-3
    • None
    • None
    • All systems
    • Patch

    Description

      The Annotation @ListenerList adds Java-style listener support to a class based on the annotated Collection-property.

      Given the following example:

      interface TestListener {
          void eventOccurred(TestEvent event)
      }
      
      class TestEvent {
          def source
          String message
      
          TestEvent(def source, String message) {
              this.source = source
              this.message = message
          }
      }
      
      class TestClass {
          @ListenerList
          List<TestListener> listeners
      }
      

      It adds the following methods:

      synchronized void addTestListener(TestListener listener)
      synchronized void removeTestListener(TestListener listener)
      synchronized TestListener[] getTestListeners()
      void fireEventOccurred(TestEvent event)
      void fireEventOccurred(Object source, String message)
      

      The @ListenerList can get the following parameters:
      listener = type of the Listener instance.
      Default:
      If the annotated collection has a single, concrete (not wildcarded) generic subtype this subtype is
      used as listener type.
      Otherwise java.util.Map is used.
      event = type of the Event to fire
      Default:
      If the listener type has a single abstract method with a single parameter, this is used as event type
      Otherwise java.lang.Object is used.
      fire = One or many names of event-methods to fire
      Format: <suffix for fire-method>[-><event-method to be called>]?
      e.g. fire="eventOccurred" or fire="eventOccurred2->eventOccurred"
      If the second part is omitted, the first part is used for both.
      Default:
      All abstract methods with a single parameter derived from type of event
      name = name as suffix for creating the add, remove and get Methods
      Default:
      Name of the listener type

      More info on fire-method creation:
      For each entry in the given or default created list a fire-method name will be created: "fire${suffix.capitalize()}".
      For each fire-method name a set of fire-methods will be created with the event type as single parameter and all the
      parameterlists from the declared constructors of the event type.

        interface ObjectEventListener {
          void eventOccurred(Object event)
        }
      
        interface SingleMethodListener {
          void eventOccurred(TestEvent event)
        }
      
        interface MultiMethodListener {
          void eventOccurred1(TestEvent event)
          void eventOccurred2(TestEvent event)
        }
      
        class TestEvent {
          def source
          String message
      
          TestEvent(def source, String message) {
            this.source = source
            this.message = message
          }
        }
      
        /* Methods created for the following class:
          synchronized void addSingleMethodListener(SingleMethodListener listener)
          synchronized void removeSingleMethodListener(SingleMethodListener listener)
          synchronized SingleMethodListener[] getSingleMethodListeners()
          void fireEventOccurred(TestEvent event)
          void fireEventOccurred(Object source, String message)
        */
        class DefaultFireAndNames {
          @ListenerList(listener = SingleMethodListener, event = TestEvent)
          def listeners
        }
      
        /* Methods created for the following class:
          synchronized void addSingleMethodListener2(SingleMethodListener listener)
          synchronized void removeSingleMethodListener2(SingleMethodListener listener)
          synchronized SingleMethodListener[] getSingleMethodListener2s()
          void fireEventOccurred2(TestEvent event)
          void fireEventOccurred2(Object source, String message)
        */
        class CustomFireAndName {
          @ListenerList(listener = SingleMethodListener, event = TestEvent, fire = "eventOccurred2", name = "testListener2")
          def listeners
        }
      
        /* Methods created for the following class:
          synchronized void addMultiMethodListener(MultiMethodListener listener)
          synchronized void removeMultiMethodListener(MultiMethodListener listener)
          synchronized MultiMethodListener[] getMultiMethodListeners()
          void fireEventOccurred1(TestEvent event)
          void fireEventOccurred1(Object source, String message)
          void fireEventOccurred2(TestEvent event)
          void fireEventOccurred2(Object source, String message)
        */
        class MultipleMethodListener {
          @ListenerList(listener = MultiMethodListener, event = TestEvent)
          def listeners
        }
      
        /* Methods created for the following class:
          synchronized void addSingleMethodListener(SingleMethodListener listener)
          synchronized void removeSingleMethodListener(SingleMethodListener listener)
          synchronized SingleMethodListener[] getSingleMethodListeners()
          void fireEventOccurred(TestEvent event)
          void fireEventOccurred(Object source, String message)
          synchronized void addSingleMethodListener2(SingleMethodListener listener)
          synchronized void removeSingleMethodListener2(SingleMethodListener listener)
          synchronized SingleMethodListener[] getSingleMethodListener2s()
          void fireEventOccurred2(TestEvent event)
          void fireEventOccurred2(Object source, String message)
        */
        class MultipleListsOfSameEvent {
          @ListenerList(listener = SingleMethodListener, event = TestEvent)
          def listeners
          @ListenerList(listener = SingleMethodListener, event = TestEvent, fire = "eventOccurred2->eventOccurred", name = "testListener2")
          def listeners2
        }
      
        /* Methods created for the following class:
          synchronized void addMultiMethodListener(MultiMethodListener listener)
          synchronized void removeMultiMethodListener(MultiMethodListener listener)
          synchronized MultiMethodListener[] getMultiMethodListeners()
          void fireEventOccurred(TestEvent event)
          void fireEventOccurred(Object source, String message)
          void fireNextEventOccurred(TestEvent event)
          void fireNextEventOccurred(Object source, String message)
        */
        class MultipleMethodListenerWithCustomFire {
          @ListenerList(listener = MultiMethodListener, event = TestEvent, fire = ["eventOccurred->eventOccurred1", "nextEventOccurred->eventOccurred2"])
          def listeners
        }
      
        /* Methods created for the following class:
          synchronized void addSingleMethodListener(SingleMethodListener listener)
          synchronized void removeSingleMethodListener(SingleMethodListener listener)
          synchronized SingleMethodListener[] getSingleMethodListeners()
          void fireEventOccurred(Map event)
        */
        class MapEvent {
          @ListenerList(listener = SingleMethodListener, event = Map)
          def listeners
        }
      
        /* Methods created for the following class:
          synchronized void addTestListener(Map listener)
          synchronized void removeTestListener(Map listener)
          synchronized Map[] getTestListeners()
          void fireEventOccurred(TestEvent event)
          void fireEventOccurred(Object source, String message)
        */
        class MapListener {
          @ListenerList(event = TestEvent, name = "testListener", fire = "eventOccurred")
          def listeners
        }
      
        /* Methods created for the following class:
          synchronized void addTestListener(Map listener)
          synchronized void removeTestListener(Map listener)
          synchronized Map[] getTestListeners()
          void fireEventOccurred(TestEvent event)
          void fireEventOccurred(Object source, String message)
          void fireEventOccurred2(TestEvent event)
          void fireEventOccurred2(Object source, String message)
        */
        class MultipleMapListener {
          @ListenerList(event = TestEvent, name = "testListener", fire = ["eventOccurred", "eventOccurred2"])
          def listeners
        }
      
        /* Methods created for the following class:
          synchronized void addTestListener(Map listener)
          synchronized void removeTestListener(Map listener)
          synchronized Map[] getTestListeners()
          void fireEventOccurred(Map event)
        */
        class MapListenerAndMapEvent {
          @ListenerList(name = "testListener", fire = "eventOccurred", event = Map)
          def listeners
        }
      
        /* Methods created for the following class:
          synchronized void addSingleMethodListener(SingleMethodListener listener)
          synchronized void removeSingleMethodListener(SingleMethodListener listener)
          synchronized SingleMethodListener[] getSingleMethodListeners()
          void fireEventOccurred(Object event)
        */
        class ObjectEvent {
          @ListenerList(listener = SingleMethodListener)
          def listeners
        }
      
        /* Methods created for the following class:
          synchronized void addTestListener(Map listener)
          synchronized void removeTestListener(Map listener)
          synchronized Map[] getTestListeners()
          void fireEventOccurred(Object event)
        */
        class MapListenerAndObjectEvent {
          @ListenerList(name = "testListener", fire = "eventOccurred")
          def listeners
        }
      
        /* Methods created for the following class:
          synchronized void addObjectEventListener(ObjectEventListener listener)
          synchronized void removeObjectEventListener(ObjectEventListener listener)
          synchronized ObjectEventListener[] getObjectEventListeners()
          void fireEventOccurred(String event)
        */
        class ListenerSubtypeList {
          @ListenerList(event = String)
          List<ObjectEventListener> listeners
        }
      
        /* Methods created for the following class:
          synchronized void addSingleMethodListener(SingleMethodListener listener)
          synchronized void removeSingleMethodListener(SingleMethodListener listener)
          synchronized SingleMethodListener[] getSingleMethodListeners()
          void fireEventOccurred(TestEvent event)
          void fireEventOccurred(Object source, String message)
        */
        class ListenerSubtypeWithSingleMethodList {
          @ListenerList
          List<SingleMethodListener> listeners
        }
      

      Attachments

        1. ListenerListASTTransformation1.patch
          38 kB
          Alexander Klein
        2. ListenerListASTTransformation.txt
          12 kB
          Alexander Klein
        3. ListenerListASTTransformation.patch
          33 kB
          Alexander Klein

        Activity

          People

            hamletdrc Hamlet D'Arcy
            saschaklein Alexander Klein
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: