< prev index next >
src/java.desktop/share/classes/java/beans/EventHandler.java
Print this page
*** 34,119 ****
import sun.reflect.misc.MethodUtil;
import sun.reflect.misc.ReflectUtil;
/**
! * The <code>EventHandler</code> class provides
* support for dynamically generating event listeners whose methods
* execute a simple statement involving an incoming event object
* and a target object.
* <p>
! * The <code>EventHandler</code> class is intended to be used by interactive tools, such as
* application builders, that allow developers to make connections between
* beans. Typically connections are made from a user interface bean
* (the event <em>source</em>)
* to an application logic bean (the <em>target</em>). The most effective
* connections of this kind isolate the application logic from the user
! * interface. For example, the <code>EventHandler</code> for a
! * connection from a <code>JCheckBox</code> to a method
* that accepts a boolean value can deal with extracting the state
* of the check box and passing it directly to the method so that
* the method is isolated from the user interface layer.
* <p>
* Inner classes are another, more general way to handle events from
! * user interfaces. The <code>EventHandler</code> class
* handles only a subset of what is possible using inner
! * classes. However, <code>EventHandler</code> works better
* with the long-term persistence scheme than inner classes.
! * Also, using <code>EventHandler</code> in large applications in
* which the same interface is implemented many times can
* reduce the disk and memory footprint of the application.
* <p>
! * The reason that listeners created with <code>EventHandler</code>
* have such a small
! * footprint is that the <code>Proxy</code> class, on which
! * the <code>EventHandler</code> relies, shares implementations
* of identical
* interfaces. For example, if you use
! * the <code>EventHandler</code> <code>create</code> methods to make
! * all the <code>ActionListener</code>s in an application,
* all the action listeners will be instances of a single class
! * (one created by the <code>Proxy</code> class).
* In general, listeners based on
! * the <code>Proxy</code> class require one listener class
* to be created per <em>listener type</em> (interface),
* whereas the inner class
* approach requires one class to be created per <em>listener</em>
* (object that implements the interface).
*
* <p>
! * You don't generally deal directly with <code>EventHandler</code>
* instances.
! * Instead, you use one of the <code>EventHandler</code>
! * <code>create</code> methods to create
* an object that implements a given listener interface.
! * This listener object uses an <code>EventHandler</code> object
* behind the scenes to encapsulate information about the
* event, the object to be sent a message when the event occurs,
* the message (method) to be sent, and any argument
* to the method.
* The following section gives examples of how to create listener
! * objects using the <code>create</code> methods.
*
* <h2>Examples of Using EventHandler</h2>
*
! * The simplest use of <code>EventHandler</code> is to install
* a listener that calls a method on the target object with no arguments.
! * In the following example we create an <code>ActionListener</code>
! * that invokes the <code>toFront</code> method on an instance
! * of <code>javax.swing.JFrame</code>.
*
* <blockquote>
*<pre>
*myButton.addActionListener(
* (ActionListener)EventHandler.create(ActionListener.class, frame, "toFront"));
*</pre>
* </blockquote>
*
! * When <code>myButton</code> is pressed, the statement
! * <code>frame.toFront()</code> will be executed. One could get
* the same effect, with some additional compile-time type safety,
! * by defining a new implementation of the <code>ActionListener</code>
* interface and adding an instance of it to the button:
*
* <blockquote>
*<pre>
//Equivalent code using an inner class instead of EventHandler.
--- 34,119 ----
import sun.reflect.misc.MethodUtil;
import sun.reflect.misc.ReflectUtil;
/**
! * The {@code EventHandler} class provides
* support for dynamically generating event listeners whose methods
* execute a simple statement involving an incoming event object
* and a target object.
* <p>
! * The {@code EventHandler} class is intended to be used by interactive tools, such as
* application builders, that allow developers to make connections between
* beans. Typically connections are made from a user interface bean
* (the event <em>source</em>)
* to an application logic bean (the <em>target</em>). The most effective
* connections of this kind isolate the application logic from the user
! * interface. For example, the {@code EventHandler} for a
! * connection from a {@code JCheckBox} to a method
* that accepts a boolean value can deal with extracting the state
* of the check box and passing it directly to the method so that
* the method is isolated from the user interface layer.
* <p>
* Inner classes are another, more general way to handle events from
! * user interfaces. The {@code EventHandler} class
* handles only a subset of what is possible using inner
! * classes. However, {@code EventHandler} works better
* with the long-term persistence scheme than inner classes.
! * Also, using {@code EventHandler} in large applications in
* which the same interface is implemented many times can
* reduce the disk and memory footprint of the application.
* <p>
! * The reason that listeners created with {@code EventHandler}
* have such a small
! * footprint is that the {@code Proxy} class, on which
! * the {@code EventHandler} relies, shares implementations
* of identical
* interfaces. For example, if you use
! * the {@code EventHandler create} methods to make
! * all the {@code ActionListener}s in an application,
* all the action listeners will be instances of a single class
! * (one created by the {@code Proxy} class).
* In general, listeners based on
! * the {@code Proxy} class require one listener class
* to be created per <em>listener type</em> (interface),
* whereas the inner class
* approach requires one class to be created per <em>listener</em>
* (object that implements the interface).
*
* <p>
! * You don't generally deal directly with {@code EventHandler}
* instances.
! * Instead, you use one of the {@code EventHandler}
! * {@code create} methods to create
* an object that implements a given listener interface.
! * This listener object uses an {@code EventHandler} object
* behind the scenes to encapsulate information about the
* event, the object to be sent a message when the event occurs,
* the message (method) to be sent, and any argument
* to the method.
* The following section gives examples of how to create listener
! * objects using the {@code create} methods.
*
* <h2>Examples of Using EventHandler</h2>
*
! * The simplest use of {@code EventHandler} is to install
* a listener that calls a method on the target object with no arguments.
! * In the following example we create an {@code ActionListener}
! * that invokes the {@code toFront} method on an instance
! * of {@code javax.swing.JFrame}.
*
* <blockquote>
*<pre>
*myButton.addActionListener(
* (ActionListener)EventHandler.create(ActionListener.class, frame, "toFront"));
*</pre>
* </blockquote>
*
! * When {@code myButton} is pressed, the statement
! * {@code frame.toFront()} will be executed. One could get
* the same effect, with some additional compile-time type safety,
! * by defining a new implementation of the {@code ActionListener}
* interface and adding an instance of it to the button:
*
* <blockquote>
*<pre>
//Equivalent code using an inner class instead of EventHandler.
*** 123,138 ****
* }
*});
*</pre>
* </blockquote>
*
! * The next simplest use of <code>EventHandler</code> is
* to extract a property value from the first argument
* of the method in the listener interface (typically an event object)
* and use it to set the value of a property in the target object.
! * In the following example we create an <code>ActionListener</code> that
! * sets the <code>nextFocusableComponent</code> property of the target
* (myButton) object to the value of the "source" property of the event.
*
* <blockquote>
*<pre>
*EventHandler.create(ActionListener.class, myButton, "nextFocusableComponent", "source")
--- 123,138 ----
* }
*});
*</pre>
* </blockquote>
*
! * The next simplest use of {@code EventHandler} is
* to extract a property value from the first argument
* of the method in the listener interface (typically an event object)
* and use it to set the value of a property in the target object.
! * In the following example we create an {@code ActionListener} that
! * sets the {@code nextFocusableComponent} property of the target
* (myButton) object to the value of the "source" property of the event.
*
* <blockquote>
*<pre>
*EventHandler.create(ActionListener.class, myButton, "nextFocusableComponent", "source")
*** 150,162 ****
* }
*}
*</pre>
* </blockquote>
*
! * It's also possible to create an <code>EventHandler</code> that
* just passes the incoming event object to the target's action.
! * If the fourth <code>EventHandler.create</code> argument is
* an empty string, then the event is just passed along:
*
* <blockquote>
*<pre>
*EventHandler.create(ActionListener.class, target, "doActionEvent", "")
--- 150,162 ----
* }
*}
*</pre>
* </blockquote>
*
! * It's also possible to create an {@code EventHandler} that
* just passes the incoming event object to the target's action.
! * If the fourth {@code EventHandler.create} argument is
* an empty string, then the event is just passed along:
*
* <blockquote>
*<pre>
*EventHandler.create(ActionListener.class, target, "doActionEvent", "")
*** 174,188 ****
* }
*}
*</pre>
* </blockquote>
*
! * Probably the most common use of <code>EventHandler</code>
* is to extract a property value from the
* <em>source</em> of the event object and set this value as
* the value of a property of the target object.
! * In the following example we create an <code>ActionListener</code> that
* sets the "label" property of the target
* object to the value of the "text" property of the
* source (the value of the "source" property) of the event.
*
* <blockquote>
--- 174,188 ----
* }
*}
*</pre>
* </blockquote>
*
! * Probably the most common use of {@code EventHandler}
* is to extract a property value from the
* <em>source</em> of the event object and set this value as
* the value of a property of the target object.
! * In the following example we create an {@code ActionListener} that
* sets the "label" property of the target
* object to the value of the "text" property of the
* source (the value of the "source" property) of the event.
*
* <blockquote>
*** 248,268 ****
* target.getA().setB(e.getC().isD());
* }
*}
*</pre>
* <p>
! * As <code>EventHandler</code> ultimately relies on reflection to invoke
* a method we recommend against targeting an overloaded method. For example,
! * if the target is an instance of the class <code>MyTarget</code> which is
* defined as:
* <pre>
* public class MyTarget {
* public void doIt(String);
* public void doIt(Object);
* }
* </pre>
! * Then the method <code>doIt</code> is overloaded. EventHandler will invoke
* the method that is appropriate based on the source. If the source is
* null, then either method is appropriate and the one that is invoked is
* undefined. For that reason we recommend against targeting overloaded
* methods.
*
--- 248,268 ----
* target.getA().setB(e.getC().isD());
* }
*}
*</pre>
* <p>
! * As {@code EventHandler} ultimately relies on reflection to invoke
* a method we recommend against targeting an overloaded method. For example,
! * if the target is an instance of the class {@code MyTarget} which is
* defined as:
* <pre>
* public class MyTarget {
* public void doIt(String);
* public void doIt(Object);
* }
* </pre>
! * Then the method {@code doIt} is overloaded. EventHandler will invoke
* the method that is appropriate based on the source. If the source is
* null, then either method is appropriate and the one that is invoked is
* undefined. For that reason we recommend against targeting overloaded
* methods.
*
*** 282,307 ****
private final String eventPropertyName;
private final String listenerMethodName;
private final AccessControlContext acc = AccessController.getContext();
/**
! * Creates a new <code>EventHandler</code> object;
! * you generally use one of the <code>create</code> methods
* instead of invoking this constructor directly. Refer to
* {@link java.beans.EventHandler#create(Class, Object, String, String)
* the general version of create} for a complete description of
! * the <code>eventPropertyName</code> and <code>listenerMethodName</code>
* parameter.
*
* @param target the object that will perform the action
* @param action the name of a (possibly qualified) property or method on
* the target
* @param eventPropertyName the (possibly qualified) name of a readable property of the incoming event
* @param listenerMethodName the name of the method in the listener interface that should trigger the action
*
! * @throws NullPointerException if <code>target</code> is null
! * @throws NullPointerException if <code>action</code> is null
*
* @see EventHandler
* @see #create(Class, Object, String, String, String)
* @see #getTarget
* @see #getAction
--- 282,307 ----
private final String eventPropertyName;
private final String listenerMethodName;
private final AccessControlContext acc = AccessController.getContext();
/**
! * Creates a new {@code EventHandler} object;
! * you generally use one of the {@code create} methods
* instead of invoking this constructor directly. Refer to
* {@link java.beans.EventHandler#create(Class, Object, String, String)
* the general version of create} for a complete description of
! * the {@code eventPropertyName} and {@code listenerMethodName}
* parameter.
*
* @param target the object that will perform the action
* @param action the name of a (possibly qualified) property or method on
* the target
* @param eventPropertyName the (possibly qualified) name of a readable property of the incoming event
* @param listenerMethodName the name of the method in the listener interface that should trigger the action
*
! * @throws NullPointerException if {@code target} is null
! * @throws NullPointerException if {@code action} is null
*
* @see EventHandler
* @see #create(Class, Object, String, String, String)
* @see #getTarget
* @see #getAction
*** 357,367 ****
return eventPropertyName;
}
/**
* Returns the name of the method that will trigger the action.
! * A return value of <code>null</code> signifies that all methods in the
* listener interface trigger the action.
*
* @return the name of the method that will trigger the action
*
* @see #EventHandler(Object, String, String, String)
--- 357,367 ----
return eventPropertyName;
}
/**
* Returns the name of the method that will trigger the action.
! * A return value of {@code null} signifies that all methods in the
* listener interface trigger the action.
*
* @return the name of the method that will trigger the action
*
* @see #EventHandler(Object, String, String, String)
*** 410,420 ****
}
/**
* Extract the appropriate property value from the event and
* pass it to the action associated with
! * this <code>EventHandler</code>.
*
* @param proxy the proxy object
* @param method the method in the listener interface
* @return the result of applying the action to the target
*
--- 410,420 ----
}
/**
* Extract the appropriate property value from the event and
* pass it to the action associated with
! * this {@code EventHandler}.
*
* @param proxy the proxy object
* @param method the method in the listener interface
* @return the result of applying the action to the target
*
*** 493,515 ****
}
return null;
}
/**
! * Creates an implementation of <code>listenerInterface</code> in which
* <em>all</em> of the methods in the listener interface apply
! * the handler's <code>action</code> to the <code>target</code>. This
* method is implemented by calling the other, more general,
! * implementation of the <code>create</code> method with both
! * the <code>eventPropertyName</code> and the <code>listenerMethodName</code>
! * taking the value <code>null</code>. Refer to
* {@link java.beans.EventHandler#create(Class, Object, String, String)
* the general version of create} for a complete description of
! * the <code>action</code> parameter.
* <p>
! * To create an <code>ActionListener</code> that shows a
! * <code>JDialog</code> with <code>dialog.show()</code>,
* one can write:
*
*<blockquote>
*<pre>
*EventHandler.create(ActionListener.class, dialog, "show")
--- 493,515 ----
}
return null;
}
/**
! * Creates an implementation of {@code listenerInterface} in which
* <em>all</em> of the methods in the listener interface apply
! * the handler's {@code action} to the {@code target}. This
* method is implemented by calling the other, more general,
! * implementation of the {@code create} method with both
! * the {@code eventPropertyName} and the {@code listenerMethodName}
! * taking the value {@code null}. Refer to
* {@link java.beans.EventHandler#create(Class, Object, String, String)
* the general version of create} for a complete description of
! * the {@code action} parameter.
* <p>
! * To create an {@code ActionListener} that shows a
! * {@code JDialog} with {@code dialog.show()},
* one can write:
*
*<blockquote>
*<pre>
*EventHandler.create(ActionListener.class, dialog, "show")
*** 519,533 ****
* @param <T> the type to create
* @param listenerInterface the listener interface to create a proxy for
* @param target the object that will perform the action
* @param action the name of a (possibly qualified) property or method on
* the target
! * @return an object that implements <code>listenerInterface</code>
*
! * @throws NullPointerException if <code>listenerInterface</code> is null
! * @throws NullPointerException if <code>target</code> is null
! * @throws NullPointerException if <code>action</code> is null
*
* @see #create(Class, Object, String, String)
*/
public static <T> T create(Class<T> listenerInterface,
Object target, String action)
--- 519,533 ----
* @param <T> the type to create
* @param listenerInterface the listener interface to create a proxy for
* @param target the object that will perform the action
* @param action the name of a (possibly qualified) property or method on
* the target
! * @return an object that implements {@code listenerInterface}
*
! * @throws NullPointerException if {@code listenerInterface} is null
! * @throws NullPointerException if {@code target} is null
! * @throws NullPointerException if {@code action} is null
*
* @see #create(Class, Object, String, String)
*/
public static <T> T create(Class<T> listenerInterface,
Object target, String action)
*** 535,559 ****
return create(listenerInterface, target, action, null, null);
}
/**
/**
! * Creates an implementation of <code>listenerInterface</code> in which
* <em>all</em> of the methods pass the value of the event
! * expression, <code>eventPropertyName</code>, to the final method in the
! * statement, <code>action</code>, which is applied to the <code>target</code>.
* This method is implemented by calling the
! * more general, implementation of the <code>create</code> method with
! * the <code>listenerMethodName</code> taking the value <code>null</code>.
* Refer to
* {@link java.beans.EventHandler#create(Class, Object, String, String)
* the general version of create} for a complete description of
! * the <code>action</code> and <code>eventPropertyName</code> parameters.
* <p>
! * To create an <code>ActionListener</code> that sets the
! * the text of a <code>JLabel</code> to the text value of
! * the <code>JTextField</code> source of the incoming event,
* you can use the following code:
*
*<blockquote>
*<pre>
*EventHandler.create(ActionListener.class, label, "text", "source.text");
--- 535,559 ----
return create(listenerInterface, target, action, null, null);
}
/**
/**
! * Creates an implementation of {@code listenerInterface} in which
* <em>all</em> of the methods pass the value of the event
! * expression, {@code eventPropertyName}, to the final method in the
! * statement, {@code action}, which is applied to the {@code target}.
* This method is implemented by calling the
! * more general, implementation of the {@code create} method with
! * the {@code listenerMethodName} taking the value {@code null}.
* Refer to
* {@link java.beans.EventHandler#create(Class, Object, String, String)
* the general version of create} for a complete description of
! * the {@code action} and {@code eventPropertyName} parameters.
* <p>
! * To create an {@code ActionListener} that sets the
! * the text of a {@code JLabel} to the text value of
! * the {@code JTextField} source of the incoming event,
* you can use the following code:
*
*<blockquote>
*<pre>
*EventHandler.create(ActionListener.class, label, "text", "source.text");
*** 577,591 ****
* @param target the object that will perform the action
* @param action the name of a (possibly qualified) property or method on
* the target
* @param eventPropertyName the (possibly qualified) name of a readable property of the incoming event
*
! * @return an object that implements <code>listenerInterface</code>
*
! * @throws NullPointerException if <code>listenerInterface</code> is null
! * @throws NullPointerException if <code>target</code> is null
! * @throws NullPointerException if <code>action</code> is null
*
* @see #create(Class, Object, String, String, String)
*/
public static <T> T create(Class<T> listenerInterface,
Object target, String action,
--- 577,591 ----
* @param target the object that will perform the action
* @param action the name of a (possibly qualified) property or method on
* the target
* @param eventPropertyName the (possibly qualified) name of a readable property of the incoming event
*
! * @return an object that implements {@code listenerInterface}
*
! * @throws NullPointerException if {@code listenerInterface} is null
! * @throws NullPointerException if {@code target} is null
! * @throws NullPointerException if {@code action} is null
*
* @see #create(Class, Object, String, String, String)
*/
public static <T> T create(Class<T> listenerInterface,
Object target, String action,
*** 593,657 ****
{
return create(listenerInterface, target, action, eventPropertyName, null);
}
/**
! * Creates an implementation of <code>listenerInterface</code> in which
! * the method named <code>listenerMethodName</code>
! * passes the value of the event expression, <code>eventPropertyName</code>,
! * to the final method in the statement, <code>action</code>, which
! * is applied to the <code>target</code>. All of the other listener
* methods do nothing.
* <p>
! * The <code>eventPropertyName</code> string is used to extract a value
* from the incoming event object that is passed to the target
* method. The common case is the target method takes no arguments, in
* which case a value of null should be used for the
! * <code>eventPropertyName</code>. Alternatively if you want
* the incoming event object passed directly to the target method use
* the empty string.
! * The format of the <code>eventPropertyName</code> string is a sequence of
* methods or properties where each method or
* property is applied to the value returned by the preceding method
* starting from the incoming event object.
! * The syntax is: <code>propertyName{.propertyName}*</code>
! * where <code>propertyName</code> matches a method or
! * property. For example, to extract the <code>point</code>
! * property from a <code>MouseEvent</code>, you could use either
! * <code>"point"</code> or <code>"getPoint"</code> as the
! * <code>eventPropertyName</code>. To extract the "text" property from
! * a <code>MouseEvent</code> with a <code>JLabel</code> source use any
! * of the following as <code>eventPropertyName</code>:
! * <code>"source.text"</code>,
! * <code>"getSource.text"</code> <code>"getSource.getText"</code> or
! * <code>"source.getText"</code>. If a method can not be found, or an
* exception is generated as part of invoking a method a
! * <code>RuntimeException</code> will be thrown at dispatch time. For
* example, if the incoming event object is null, and
! * <code>eventPropertyName</code> is non-null and not empty, a
! * <code>RuntimeException</code> will be thrown.
* <p>
! * The <code>action</code> argument is of the same format as the
! * <code>eventPropertyName</code> argument where the last property name
* identifies either a method name or writable property.
* <p>
! * If the <code>listenerMethodName</code> is <code>null</code>
! * <em>all</em> methods in the interface trigger the <code>action</code> to be
! * executed on the <code>target</code>.
! * <p>
! * For example, to create a <code>MouseListener</code> that sets the target
! * object's <code>origin</code> property to the incoming <code>MouseEvent</code>'s
! * location (that's the value of <code>mouseEvent.getPoint()</code>) each
* time a mouse button is pressed, one would write:
*<blockquote>
*<pre>
*EventHandler.create(MouseListener.class, target, "origin", "point", "mousePressed");
*</pre>
*</blockquote>
*
! * This is comparable to writing a <code>MouseListener</code> in which all
! * of the methods except <code>mousePressed</code> are no-ops:
*
*<blockquote>
*<pre>
//Equivalent code using an inner class instead of EventHandler.
*new MouseAdapter() {
--- 593,657 ----
{
return create(listenerInterface, target, action, eventPropertyName, null);
}
/**
! * Creates an implementation of {@code listenerInterface} in which
! * the method named {@code listenerMethodName}
! * passes the value of the event expression, {@code eventPropertyName},
! * to the final method in the statement, {@code action}, which
! * is applied to the {@code target}. All of the other listener
* methods do nothing.
* <p>
! * The {@code eventPropertyName} string is used to extract a value
* from the incoming event object that is passed to the target
* method. The common case is the target method takes no arguments, in
* which case a value of null should be used for the
! * {@code eventPropertyName}. Alternatively if you want
* the incoming event object passed directly to the target method use
* the empty string.
! * The format of the {@code eventPropertyName} string is a sequence of
* methods or properties where each method or
* property is applied to the value returned by the preceding method
* starting from the incoming event object.
! * The syntax is: {@code propertyName{.propertyName}*}
! * where {@code propertyName} matches a method or
! * property. For example, to extract the {@code point}
! * property from a {@code MouseEvent}, you could use either
! * {@code "point"} or {@code "getPoint"} as the
! * {@code eventPropertyName}. To extract the "text" property from
! * a {@code MouseEvent} with a {@code JLabel} source use any
! * of the following as {@code eventPropertyName}:
! * {@code "source.text"},
! * {@code "getSource.text" "getSource.getText"} or
! * {@code "source.getText"}. If a method can not be found, or an
* exception is generated as part of invoking a method a
! * {@code RuntimeException} will be thrown at dispatch time. For
* example, if the incoming event object is null, and
! * {@code eventPropertyName} is non-null and not empty, a
! * {@code RuntimeException} will be thrown.
* <p>
! * The {@code action} argument is of the same format as the
! * {@code eventPropertyName} argument where the last property name
* identifies either a method name or writable property.
* <p>
! * If the {@code listenerMethodName} is {@code null}
! * <em>all</em> methods in the interface trigger the {@code action} to be
! * executed on the {@code target}.
! * <p>
! * For example, to create a {@code MouseListener} that sets the target
! * object's {@code origin} property to the incoming {@code MouseEvent}'s
! * location (that's the value of {@code mouseEvent.getPoint()}) each
* time a mouse button is pressed, one would write:
*<blockquote>
*<pre>
*EventHandler.create(MouseListener.class, target, "origin", "point", "mousePressed");
*</pre>
*</blockquote>
*
! * This is comparable to writing a {@code MouseListener} in which all
! * of the methods except {@code mousePressed} are no-ops:
*
*<blockquote>
*<pre>
//Equivalent code using an inner class instead of EventHandler.
*new MouseAdapter() {
*** 668,682 ****
* @param action the name of a (possibly qualified) property or method on
* the target
* @param eventPropertyName the (possibly qualified) name of a readable property of the incoming event
* @param listenerMethodName the name of the method in the listener interface that should trigger the action
*
! * @return an object that implements <code>listenerInterface</code>
*
! * @throws NullPointerException if <code>listenerInterface</code> is null
! * @throws NullPointerException if <code>target</code> is null
! * @throws NullPointerException if <code>action</code> is null
*
* @see EventHandler
*/
public static <T> T create(Class<T> listenerInterface,
Object target, String action,
--- 668,682 ----
* @param action the name of a (possibly qualified) property or method on
* the target
* @param eventPropertyName the (possibly qualified) name of a readable property of the incoming event
* @param listenerMethodName the name of the method in the listener interface that should trigger the action
*
! * @return an object that implements {@code listenerInterface}
*
! * @throws NullPointerException if {@code listenerInterface} is null
! * @throws NullPointerException if {@code target} is null
! * @throws NullPointerException if {@code action} is null
*
* @see EventHandler
*/
public static <T> T create(Class<T> listenerInterface,
Object target, String action,
< prev index next >