ListenerEventDispatcher.java

  1. /**
  2.  *
  3.  * Copyright 2003-2007 Jive Software.
  4.  *
  5.  * Licensed under the Apache License, Version 2.0 (the "License");
  6.  * you may not use this file except in compliance with the License.
  7.  * You may obtain a copy of the License at
  8.  *
  9.  *     http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.jivesoftware.smackx.workgroup.util;

  18. import java.lang.reflect.Method;
  19. import java.util.ArrayList;
  20. import java.util.ListIterator;
  21. import java.util.logging.Level;
  22. import java.util.logging.Logger;

  23. /**
  24.  * This class is a very flexible event dispatcher which implements Runnable so that it can
  25.  * dispatch easily from a newly created thread. The usage of this in code is more or less:
  26.  * create a new instance of this class, use addListenerTriplet to add as many listeners
  27.  * as desired to be messaged, create a new Thread using the instance of this class created
  28.  * as the argument to the constructor, start the new Thread instance.<p>
  29.  *
  30.  * Also, this is intended to be used to message methods that either return void, or have
  31.  * a return which the developer using this class is uninterested in receiving.
  32.  *
  33.  * @author loki der quaeler
  34.  */
  35. public class ListenerEventDispatcher implements Runnable {
  36.     private static final Logger LOGGER = Logger.getLogger(ListenerEventDispatcher.class.getName());

  37.     protected transient ArrayList<TripletContainer> triplets;

  38.     protected transient boolean hasFinishedDispatching;
  39.     protected transient boolean isRunning;

  40.     public ListenerEventDispatcher () {
  41.         super();

  42.         this.triplets = new ArrayList<TripletContainer>();

  43.         this.hasFinishedDispatching = false;
  44.         this.isRunning = false;
  45.     }

  46.     /**
  47.      * Add a listener triplet - the instance of the listener to be messaged, the Method on which
  48.      *  the listener should be messaged, and the Object array of arguments to be supplied to the
  49.      *  Method. No attempts are made to determine whether this triplet was already added.<br>
  50.      *
  51.      * Messages are dispatched in the order in which they're added via this method; so if triplet
  52.      *  X is added after triplet Z, then triplet Z will undergo messaging prior to triplet X.<br>
  53.      *
  54.      * This method should not be called once the owning Thread instance has been started; if it
  55.      *  is called, the triplet will not be added to the messaging queue.<br>
  56.      *
  57.      * @param listenerInstance the instance of the listener to receive the associated notification
  58.      * @param listenerMethod the Method instance representing the method through which notification
  59.      *                          will occur
  60.      * @param methodArguments the arguments supplied to the notification method
  61.      */
  62.     public void addListenerTriplet(Object listenerInstance, Method listenerMethod,
  63.             Object[] methodArguments)
  64.     {
  65.         if (!this.isRunning) {
  66.             this.triplets.add(new TripletContainer(listenerInstance, listenerMethod,
  67.                     methodArguments));
  68.         }
  69.     }

  70.     /**
  71.      * @return whether this instance has finished dispatching its messages
  72.      */
  73.     public boolean hasFinished() {
  74.         return this.hasFinishedDispatching;
  75.     }

  76.     public void run() {
  77.         ListIterator<TripletContainer> li = null;

  78.         this.isRunning = true;

  79.         li = this.triplets.listIterator();
  80.         while (li.hasNext()) {
  81.             TripletContainer tc = li.next();

  82.             try {
  83.                 tc.getListenerMethod().invoke(tc.getListenerInstance(), tc.getMethodArguments());
  84.             } catch (Exception e) {
  85.                 LOGGER.log(Level.SEVERE, "Exception dispatching an event", e);
  86.             }
  87.         }

  88.         this.hasFinishedDispatching = true;
  89.     }


  90.     protected class TripletContainer {

  91.         protected Object listenerInstance;
  92.         protected Method listenerMethod;
  93.         protected Object[] methodArguments;

  94.         protected TripletContainer (Object inst, Method meth, Object[] args) {
  95.             super();

  96.             this.listenerInstance = inst;
  97.             this.listenerMethod = meth;
  98.             this.methodArguments = args;
  99.         }

  100.         protected Object getListenerInstance() {
  101.             return this.listenerInstance;
  102.         }

  103.         protected Method getListenerMethod() {
  104.             return this.listenerMethod;
  105.         }

  106.         protected Object[] getMethodArguments() {
  107.             return this.methodArguments;
  108.         }
  109.     }
  110. }