Coverage Report - org.apache.commons.lang3.event.EventUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
EventUtils
85%
12/14
N/A
3,2
EventUtils$EventBindingInvocationHandler
100%
11/11
100%
8/8
3,2
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  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  
 
 18  
 package org.apache.commons.lang3.event;
 19  
 
 20  
 import java.lang.reflect.InvocationHandler;
 21  
 import java.lang.reflect.InvocationTargetException;
 22  
 import java.lang.reflect.Method;
 23  
 import java.lang.reflect.Proxy;
 24  
 import java.util.Arrays;
 25  
 import java.util.HashSet;
 26  
 import java.util.Set;
 27  
 
 28  
 import org.apache.commons.lang3.reflect.MethodUtils;
 29  
 
 30  
 /**
 31  
  * Provides some useful event-based utility methods.
 32  
  *
 33  
  * @since 3.0
 34  
  * @version $Id: EventUtils.java 1436770 2013-01-22 07:09:45Z ggregory $
 35  
  */
 36  1
 public class EventUtils {
 37  
 
 38  
     /**
 39  
      * Adds an event listener to the specified source.  This looks for an "add" method corresponding to the event
 40  
      * type (addActionListener, for example).
 41  
      * @param eventSource   the event source
 42  
      * @param listenerType  the event listener type
 43  
      * @param listener      the listener
 44  
      * @param <L>           the event listener type
 45  
      *
 46  
      * @throws IllegalArgumentException if the object doesn't support the listener type
 47  
      */
 48  
     public static <L> void addEventListener(final Object eventSource, final Class<L> listenerType, final L listener) {
 49  
         try {
 50  7
             MethodUtils.invokeMethod(eventSource, "add" + listenerType.getSimpleName(), listener);
 51  2
         } catch (final NoSuchMethodException e) {
 52  2
             throw new IllegalArgumentException("Class " + eventSource.getClass().getName()
 53  
                     + " does not have a public add" + listenerType.getSimpleName()
 54  
                     + " method which takes a parameter of type " + listenerType.getName() + ".");
 55  0
         } catch (final IllegalAccessException e) {
 56  0
             throw new IllegalArgumentException("Class " + eventSource.getClass().getName()
 57  
                     + " does not have an accessible add" + listenerType.getSimpleName ()
 58  
                     + " method which takes a parameter of type " + listenerType.getName() + ".");
 59  1
         } catch (final InvocationTargetException e) {
 60  1
             throw new RuntimeException("Unable to add listener.", e.getCause());
 61  4
         }
 62  4
     }
 63  
 
 64  
     /**
 65  
      * Binds an event listener to a specific method on a specific object.
 66  
      *
 67  
      * @param <L>          the event listener type
 68  
      * @param target       the target object
 69  
      * @param methodName   the name of the method to be called
 70  
      * @param eventSource  the object which is generating events (JButton, JList, etc.)
 71  
      * @param listenerType the listener interface (ActionListener.class, SelectionListener.class, etc.)
 72  
      * @param eventTypes   the event types (method names) from the listener interface (if none specified, all will be
 73  
      *                     supported)
 74  
      */
 75  
     public static <L> void bindEventsToMethod(final Object target, final String methodName, final Object eventSource,
 76  
             final Class<L> listenerType, final String... eventTypes) {
 77  3
         final L listener = listenerType.cast(Proxy.newProxyInstance(target.getClass().getClassLoader(),
 78  
                 new Class[] { listenerType }, new EventBindingInvocationHandler(target, methodName, eventTypes)));
 79  3
         addEventListener(eventSource, listenerType, listener);
 80  3
     }
 81  
 
 82  1
     private static class EventBindingInvocationHandler implements InvocationHandler {
 83  
         private final Object target;
 84  
         private final String methodName;
 85  
         private final Set<String> eventTypes;
 86  
 
 87  
         /**
 88  
          * Creates a new instance of {@code EventBindingInvocationHandler}.
 89  
          *
 90  
          * @param target the target object for method invocations
 91  
          * @param methodName the name of the method to be invoked
 92  
          * @param eventTypes the names of the supported event types
 93  
          */
 94  3
         EventBindingInvocationHandler(final Object target, final String methodName, final String[] eventTypes) {
 95  3
             this.target = target;
 96  3
             this.methodName = methodName;
 97  3
             this.eventTypes = new HashSet<String>(Arrays.asList(eventTypes));
 98  3
         }
 99  
 
 100  
         /**
 101  
          * Handles a method invocation on the proxy object.
 102  
          *
 103  
          * @param proxy the proxy instance
 104  
          * @param method the method to be invoked
 105  
          * @param parameters the parameters for the method invocation
 106  
          * @return the result of the method call
 107  
          * @throws Throwable if an error occurs
 108  
          */
 109  
         @Override
 110  
         public Object invoke(final Object proxy, final Method method, final Object[] parameters) throws Throwable {
 111  4
             if (eventTypes.isEmpty() || eventTypes.contains(method.getName())) {
 112  3
                 if (hasMatchingParametersMethod(method)) {
 113  1
                     return MethodUtils.invokeMethod(target, methodName, parameters);
 114  
                 } else {
 115  2
                     return MethodUtils.invokeMethod(target, methodName);
 116  
                 }
 117  
             }
 118  1
             return null;
 119  
         }
 120  
 
 121  
         /**
 122  
          * Checks whether a method for the passed in parameters can be found.
 123  
          *
 124  
          * @param method the listener method invoked
 125  
          * @return a flag whether the parameters could be matched
 126  
          */
 127  
         private boolean hasMatchingParametersMethod(final Method method) {
 128  3
             return MethodUtils.getAccessibleMethod(target.getClass(), methodName, method.getParameterTypes()) != null;
 129  
         }
 130  
     }
 131  
 }