click-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sa...@apache.org
Subject svn commit: r963694 - in /click/trunk/click: framework/src/org/apache/click/ mock/src/org/apache/click/ mock/test/org/apache/click/
Date Tue, 13 Jul 2010 12:40:06 GMT
Author: sabob
Date: Tue Jul 13 12:40:05 2010
New Revision: 963694

URL: http://svn.apache.org/viewvc?rev=963694&view=rev
Log:
reduce API by merging callback and behavior

Removed:
    click/trunk/click/framework/src/org/apache/click/Callback.java
Modified:
    click/trunk/click/framework/src/org/apache/click/Behavior.java
    click/trunk/click/framework/src/org/apache/click/ControlRegistry.java
    click/trunk/click/mock/src/org/apache/click/MockContext.java
    click/trunk/click/mock/test/org/apache/click/MockContextTest.java

Modified: click/trunk/click/framework/src/org/apache/click/Behavior.java
URL: http://svn.apache.org/viewvc/click/trunk/click/framework/src/org/apache/click/Behavior.java?rev=963694&r1=963693&r2=963694&view=diff
==============================================================================
--- click/trunk/click/framework/src/org/apache/click/Behavior.java (original)
+++ click/trunk/click/framework/src/org/apache/click/Behavior.java Tue Jul 13 12:40:05 2010
@@ -19,16 +19,41 @@
 package org.apache.click;
 
 /**
- * Behaviors are added to Controls to provide enhanced features such as
- * Ajax. Behaviors extend the {@link Callback} interface which
- * allows them to <tt>decorate</tt> their associated Controls.
- *
+ * Behaviors are added to Controls to provide more advanced features such as
+ * Ajax support.
+ * <p/>
+ * To handle an Ajax request, Behaviors expose a listener method,
+ * {@link #onAction(org.apache.click.Control) onAction}, which Click will
+ * invoke if the Behavior method {@link #isRequestTarget(org.apache.click.Context) isRequestTarget}
+ * returns true.
+ * <p/>
+ * <b>Please note:</b> a behavior <tt>onAction</tt> method is only
invoked if the
+ * Control is the Ajax target, in other words,
+ * {@link org.apache.click.Control#isAjaxTarget(org.apache.click.Context) isAjaxTarget}
+ * must return true.
  * <p/>
- * Behaviors expose a listener method through
- * {@link #onAction(org.apache.click.Control)}, which Click will invoke if
- * the method {@link #isRequestTarget(org.apache.click.Context)} returns true.
+ * Behaviors also provide interceptor methods for specific Control life
+ * cycle events. These interceptor methods can be used to further process the
+ * control or the control children.
+ * <p/>
+ * The following interceptor methods are defined:
+ *
+ * <ul>
+ * <li>preResponse - occurs before the control markup is written to the response</li>
+ * <li>preGetHeadElements - occurs after <tt>preResponse</tt> but before
the control
+ * {@link Control#getHeadElements() HEAD elements} are written to the response</li>
+ * <li>preDestroy - occurs before the Control {@link Control#onDestroy() onDestroy}
+ * event handler.</li>
+ * </ul>
+ *
+ * These events allow the Behavior to <tt>decorate</tt> a control, for example:
+ * <ul>
+ * <li>add/remove Control HEAD elements such as JavaScript and CSS dependencies
+ * and setup scripts</li>
+ * <li>add/remove Control attributes such as <tt>"class"</tt>, <tt>"style"</tt>
etc</li>
+ * </ul>
  */
-public interface Behavior extends Callback {
+public interface Behavior {
 
     /**
      * The behavior action method.
@@ -41,7 +66,7 @@ public interface Behavior extends Callba
     public Partial onAction(Control source);
 
     /**
-     * Return true if the behavior is the requeset target, false otherwise.
+     * Return true if the behavior is the request target, false otherwise.
      * <p/>
      * This method is queried by Click to determine if the behavior's
      * {@link #onAction(org.apache.click.Control)} method should be called in
@@ -82,6 +107,29 @@ public interface Behavior extends Callba
      * @param context the request context
      * @return true if the behavior is the request target, false otherwise
      */
-    // TODO move this method to another interface/class?
     public boolean isRequestTarget(Context context);
-}
+
+    /**
+     * This event occurs before the markup is written to the HttpServletResponse.
+     *
+     * @param source the control the behavior is registered with
+     */
+    public void preResponse(Control source);
+
+    /**
+     * This event occurs after {@link #preResponse(org.apache.click.Control)},
+     * but before the Control's {@link Control#getHeadElements()} is called.
+     *
+     * @param source the control the behavior is registered with
+     */
+    public void preGetHeadElements(Control source);
+
+    /**
+     * This event occurs before the Control {@link Control#onDestroy() onDestroy}
+     * event handler. This event allows the behavior to cleanup or store Control
+     * state in the Session.
+     *
+     * @param source the control the behavior is registered with
+     */
+    public void preDestroy(Control source);
+}

Modified: click/trunk/click/framework/src/org/apache/click/ControlRegistry.java
URL: http://svn.apache.org/viewvc/click/trunk/click/framework/src/org/apache/click/ControlRegistry.java?rev=963694&r1=963693&r2=963694&view=diff
==============================================================================
--- click/trunk/click/framework/src/org/apache/click/ControlRegistry.java (original)
+++ click/trunk/click/framework/src/org/apache/click/ControlRegistry.java Tue Jul 13 12:40:05
2010
@@ -85,8 +85,8 @@ public class ControlRegistry {
     /** The set of Ajax target controls. */
     Set<Control> ajaxTargetControls;
 
-    /** The list of registered callbacks. */
-    List<CallbackHolder> callbacks;
+    /** The list of registered behaviors. */
+    List<BehaviorHolder> behaviors;
 
     /** The application log service. */
     LogService logger;
@@ -96,7 +96,7 @@ public class ControlRegistry {
     /**
      * Construct the ControlRegistry with the given ConfigService.
      *
-     * @param configService the click application configuration service.
+     * @param configService the click application configuration service
      */
     public ControlRegistry(ConfigService configService) {
         this.logger = configService.getLogService();
@@ -135,21 +135,39 @@ public class ControlRegistry {
     }
 
     /**
-     * Register the source control and associated callback.
+     * Register a control event interceptor for the given control and behavior.
+     * The control will be passed as the source control to the Behavior
+     * interception methods:
+     * {@link org.apache.click.Behavior#preGetHeadElements(org.apache.click.Control) preGetHeadElements(Control)},
+     * {@link org.apache.click.Behavior#preResponse(org.apache.click.Control) preResponse(Control)
and
+     * {@link org.apache.click.Behavior#preDestroy()}.
+     * <p/>
+     * <b>Please note:</b> the ControlRegistry is stateless. For each request
+     * a new registry is created. This means a control and behavior is only
+     * registered for a single request and must be registered again for subsequent
+     * requests.
+     *
+     * <b>Stateful Page note:</b> when invoking this method directly from a stateful
+     * page, ensure the control is registered on every request. Generally this
+     * means that for stateful pages this method should be used in the Page
+     * <tt>onInit</tt> method (which is invoked for every request) instead of
the
+     * Page constructor (which is invoked only once). This warning can be ignored
+     * for stateless pages since both the constructor and onInit method is invoked
+     * every request.
      *
      * @param source the behavior source control
-     * @param callback the callback to register
+     * @param behavior the behavior to register
      */
-    public static void registerCallback(Control control, Callback callback) {
+    public static void registerInterceptor(Control control, Behavior behavior) {
         if (control == null) {
             throw new IllegalArgumentException("control cannot be null");
         }
-        if (callback == null) {
-            throw new IllegalArgumentException("callback cannot be null");
+        if (behavior == null) {
+            throw new IllegalArgumentException("behavior cannot be null");
         }
 
         ControlRegistry instance = getThreadLocalRegistry();
-        instance.internalRegisterCallback(control, callback);
+        instance.internalRegisterCallback(control, behavior);
     }
 
     // Protected Methods ------------------------------------------------------
@@ -166,11 +184,11 @@ public class ControlRegistry {
     // Package Private Methods ------------------------------------------------
 
     /**
-     * Remove all callbacks and controls from this registry.
+     * Remove all behaviors and controls from this registry.
      */
     void clear() {
-        if (hasCallbacks()) {
-            getCallbacks().clear();
+        if (hasBehaviors()) {
+            getBehaviors().clear();
         }
 
         if (hasAjaxTargetControls()) {
@@ -189,21 +207,21 @@ public class ControlRegistry {
     }
 
     /**
-     * Register the source control and associated callback.
+     * Register the source control and associated behavior.
      *
      * @param source the behavior source control
-     * @param callback the callback to register
+     * @param behavior the behavior to register
      */
-    void internalRegisterCallback(Control source, Callback callback) {
+    void internalRegisterCallback(Control source, Behavior behavior) {
         Validate.notNull(source, "Null source parameter");
-        Validate.notNull(callback, "Null callback parameter");
+        Validate.notNull(behavior, "Null behavior parameter");
 
-        CallbackHolder callbackHolder = new CallbackHolder(source, callback);
+        BehaviorHolder behaviorHolder = new BehaviorHolder(source, behavior);
 
-        // Guard against adding duplicate callbacks
-        List<CallbackHolder> localCallbacks = getCallbacks();
-        if (!localCallbacks.contains(callbackHolder)) {
-            localCallbacks.add(callbackHolder);
+        // Guard against adding duplicate behaviors
+        List<BehaviorHolder> localBehaviors = getBehaviors();
+        if (!localBehaviors.contains(behaviorHolder)) {
+            localBehaviors.add(behaviorHolder);
         }
     }
 
@@ -216,11 +234,11 @@ public class ControlRegistry {
             }
         }
 
-        if (hasCallbacks()) {
-            for (CallbackHolder callbackHolder : getCallbacks()) {
-                Callback callback = callbackHolder.getCallback();
-                Control control = callbackHolder.getControl();
-                callback.preResponse(control);
+        if (hasBehaviors()) {
+            for (BehaviorHolder behaviorHolder : getBehaviors()) {
+                Behavior behavior = behaviorHolder.getBehavior();
+                Control control = behaviorHolder.getControl();
+                behavior.preResponse(control);
             }
         }
     }
@@ -234,11 +252,11 @@ public class ControlRegistry {
             }
         }
 
-        if (hasCallbacks()) {
-            for (CallbackHolder callbackHolder : getCallbacks()) {
-                Callback callback = callbackHolder.getCallback();
-                Control control = callbackHolder.getControl();
-                callback.preGetHeadElements(control);
+        if (hasBehaviors()) {
+            for (BehaviorHolder behaviorHolder : getBehaviors()) {
+                Behavior behavior = behaviorHolder.getBehavior();
+                Control control = behaviorHolder.getControl();
+                behavior.preGetHeadElements(control);
             }
         }
     }
@@ -252,17 +270,17 @@ public class ControlRegistry {
             }
         }
 
-        if (hasCallbacks()) {
-            for (CallbackHolder callbackHolder : getCallbacks()) {
-                Callback callback = callbackHolder.getCallback();
-                Control control = callbackHolder.getControl();
-                callback.preDestroy(control);
+        if (hasBehaviors()) {
+            for (BehaviorHolder behaviorHolder : getBehaviors()) {
+                Behavior behavior = behaviorHolder.getBehavior();
+                Control control = behaviorHolder.getControl();
+                behavior.preDestroy(control);
             }
         }
     }
 
     /**
-     * Checks if any control callbacks have been registered.
+     * Checks if any AJAX target control have been registered.
      */
     boolean hasAjaxTargetControls() {
         if (ajaxTargetControls == null || ajaxTargetControls.isEmpty()) {
@@ -284,25 +302,25 @@ public class ControlRegistry {
     }
 
     /**
-     * Checks if any control callbacks have been registered.
+     * Checks if any control behaviors have been registered.
      */
-    boolean hasCallbacks() {
-        if (callbacks == null || callbacks.isEmpty()) {
+    boolean hasBehaviors() {
+        if (behaviors == null || behaviors.isEmpty()) {
             return false;
         }
         return true;
     }
 
     /**
-     * Return the set of registered callbacks.
+     * Return the set of registered behaviors.
      *
-     * @return set of registered callbacks
+     * @return set of registered behaviors
      */
-    List<CallbackHolder> getCallbacks() {
-        if (callbacks == null) {
-            callbacks = new ArrayList<CallbackHolder>();
+    List<BehaviorHolder> getBehaviors() {
+        if (behaviors == null) {
+            behaviors = new ArrayList<BehaviorHolder>();
         }
-        return callbacks;
+        return behaviors;
     }
 
     static ControlRegistry getThreadLocalRegistry() {
@@ -406,23 +424,23 @@ public class ControlRegistry {
         }
     }
 
-    static class CallbackHolder {
+    static class BehaviorHolder {
 
-        private Callback callback;
+        private Behavior behavior;
 
         private Control control;
 
-        public CallbackHolder(Control control, Callback callback) {
+        public BehaviorHolder(Control control, Behavior behavior) {
             this.control = control;
-            this.callback = callback;
+            this.behavior = behavior;
         }
 
-        public Callback getCallback() {
-            return callback;
+        public Behavior getBehavior() {
+            return behavior;
         }
 
-        public void setCallback(Callback callback) {
-            this.callback = callback;
+        public void setBehavior(Behavior behavior) {
+            this.behavior = behavior;
         }
 
         public Control getControl() {
@@ -448,31 +466,31 @@ public class ControlRegistry {
             }
 
             //2. Use the instanceof operator to check if the argument is of the correct type.
-            if (!(o instanceof CallbackHolder)) {
+            if (!(o instanceof BehaviorHolder)) {
                 return false;
             }
 
             //3. Cast the argument to the correct type.
-            CallbackHolder that = (CallbackHolder) o;
+            BehaviorHolder that = (BehaviorHolder) o;
 
             boolean equals = this.control == null ? that.control == null : this.control.equals(that.control);
             if (!equals) {
                 return false;
             }
 
-            return this.callback == null ? that.callback == null : this.callback.equals(that.callback);
+            return this.behavior == null ? that.behavior == null : this.behavior.equals(that.behavior);
         }
 
         /**
          * @see java.lang.Object#hashCode()
          *
-         * @return the CallbackHolder hashCode
+         * @return the BehaviorHolder hashCode
          */
         @Override
         public int hashCode() {
             int result = 17;
             result = 37 * result + (control == null ? 0 : control.hashCode());
-            result = 37 * result + (callback == null ? 0 : callback.hashCode());
+            result = 37 * result + (behavior == null ? 0 : behavior.hashCode());
             return result;
         }
     }

Modified: click/trunk/click/mock/src/org/apache/click/MockContext.java
URL: http://svn.apache.org/viewvc/click/trunk/click/mock/src/org/apache/click/MockContext.java?rev=963694&r1=963693&r2=963694&view=diff
==============================================================================
--- click/trunk/click/mock/src/org/apache/click/MockContext.java (original)
+++ click/trunk/click/mock/src/org/apache/click/MockContext.java Tue Jul 13 12:40:05 2010
@@ -70,7 +70,7 @@ import org.apache.click.util.ClickUtils;
  *     // Check that nameField value is null
  *     Assert.assertNull(nameField.getValueObject());
  *
- *     // Simulate a form onProcess callback
+ *     // Simulate a form onProcess event
  *     form.onProcess();
  *
  *     // Check that nameField value is now bound to request value
@@ -330,27 +330,27 @@ public class MockContext extends Context
     }
 
     /**
-     * Execute the preResponse callback event for all registered callbacks.
+     * Execute the preResponse method for all registered behaviors.
      */
-    public void executePreResponseCallbackEvent() {
+    public void executePreResponse() {
         ControlRegistry registry = ControlRegistry.getThreadLocalRegistry();
 
         registry.processPreResponse(this);
     }
 
     /**
-     * Execute the preGetHeadElements callback event for all registered callbacks.
+     * Execute the preGetHeadElements method for all registered behaviors.
      */
-    public void executePreGetHeadElementsCallbackEvent() {
+    public void executePreGetHeadElements() {
         ControlRegistry registry = ControlRegistry.getThreadLocalRegistry();
 
         registry.processPreGetHeadElements(this);
     }
 
     /**
-     * Execute the preDestroy callback event for all registered callbacks.
+     * Execute the preDestroy method for all registered behaviors.
      */
-    public void executePreDestroyCallbackEvent() {
+    public void executePreDestroy() {
         ControlRegistry registry = ControlRegistry.getThreadLocalRegistry();
 
         registry.processPreDestroy(this);

Modified: click/trunk/click/mock/test/org/apache/click/MockContextTest.java
URL: http://svn.apache.org/viewvc/click/trunk/click/mock/test/org/apache/click/MockContextTest.java?rev=963694&r1=963693&r2=963694&view=diff
==============================================================================
--- click/trunk/click/mock/test/org/apache/click/MockContextTest.java (original)
+++ click/trunk/click/mock/test/org/apache/click/MockContextTest.java Tue Jul 13 12:40:05
2010
@@ -36,7 +36,7 @@ public class MockContextTest extends Tes
     /** Indicates that an actionListener was invoked. */
     private boolean submitCalled = false;
 
-    /** Indicators that callback events was invoked. */
+    /** Indicators that behavior events was invoked. */
     private boolean preGetHeadElementsCalled = false;
     private boolean preResponseCalled = false;
     private boolean preDestroyCalled = false;
@@ -169,7 +169,7 @@ public class MockContextTest extends Tes
      * Test that registered behaviors are removed through the method
      * MockContext.reset().
      */
-    public void testResetBehaviors() {
+    public void testResetAjaxBehaviors() {
         MockContext context = MockContext.initContext();
         MockRequest request = context.getMockRequest();
         request.setParameter("save", "save");
@@ -199,12 +199,12 @@ public class MockContextTest extends Tes
         assertEquals(0, dispatcher.getBehaviorSourceSet().size());
     }
 
-    // Test Callbacks ---------------------------------------------------------
+    // Test Behavior Interceptor Methods --------------------------------------
 
     /**
-     * Test that context can properly process callbacks.
+     * Test that context can properly process Behavior interceptor methods.
      */
-    public void testProcessCallbacks() {
+    public void testProcessBehaviorInterceptorMethods() {
         MockContext context = MockContext.initContext();
 
         Submit submit = new Submit("save");
@@ -213,7 +213,15 @@ public class MockContextTest extends Tes
         preResponseCalled = false;
         preDestroyCalled = false;
 
-        ControlRegistry.registerCallback(submit, new Callback() {
+        ControlRegistry.registerInterceptor(submit, new Behavior() {
+
+            public boolean isRequestTarget(Context context) {
+                return false;
+            }
+
+            public Partial onAction(Control source) {
+                return null;
+            }
 
             public void preDestroy(Control source) {
                 preDestroyCalled = true;
@@ -230,32 +238,32 @@ public class MockContextTest extends Tes
 
         ControlRegistry registry = ControlRegistry.getThreadLocalRegistry();
 
-        // Assert there is one callback registered
-        assertEquals(1, registry.getCallbacks().size());
+        // Assert there is one behavior registered
+        assertEquals(1, registry.getBehaviors().size());
 
-        // Process the preResponse callback event
-        context.executePreResponseCallbackEvent();
-        assertTrue("preResponse callback event was not processed", preResponseCalled);
-
-        // Process the preGetHeadElements callback event
-        context.executePreGetHeadElementsCallbackEvent();
-        assertTrue("preGetHeadElements callback event was not processed", preGetHeadElementsCalled);
-
-        // Process the preGetHeadElements callback event
-        context.executePreDestroyCallbackEvent();
-        assertTrue("preDestroy callback event was not processed", preDestroyCalled);
-
-        // Assert that the callback was not removed after all events was processed
-        // The reason the callbacks are not automatically removed is because the
-        // last callback is onDestroy, which is right before the request goes out
-        // of scope
-        assertEquals(1, registry.getCallbacks().size());
+        // Process the preResponse interceptor methods
+        context.executePreResponse();
+        assertTrue("preResponse was not processed", preResponseCalled);
+
+        // Process the preGetHeadElements interceptor methods
+        context.executePreGetHeadElements();
+        assertTrue("preGetHeadElements was not processed", preGetHeadElementsCalled);
+
+        // Process the preGetHeadElements interceptor methods
+        context.executePreDestroy();
+        assertTrue("preDestroy was not processed", preDestroyCalled);
+
+        // Assert that the behavior was not removed after all events was processed
+        // The reason the behaviors are not automatically removed is because the
+        // last behavior is onDestroy, which is right before the request goes out
+        // of scope anyway
+        assertEquals(1, registry.getBehaviors().size());
     }
 
     /**
-     * Test that context can properly fire callbacks.
+     * Test that context can properly fire and reset behavior interceptors.
      */
-    public void testResetCallbacks() {
+    public void testResetControlInterceptors() {
         MockContext context = MockContext.initContext();
 
         Submit submit = new Submit("save");
@@ -264,7 +272,15 @@ public class MockContextTest extends Tes
         preResponseCalled = false;
         preDestroyCalled = false;
 
-        ControlRegistry.registerCallback(submit, new Callback() {
+        ControlRegistry.registerInterceptor(submit, new Behavior() {
+
+            public boolean isRequestTarget(Context context) {
+                return false;
+            }
+
+            public Partial onAction(Control source) {
+                return null;
+            }
 
             public void preDestroy(Control source) {
                 preDestroyCalled = true;
@@ -281,25 +297,25 @@ public class MockContextTest extends Tes
 
         ControlRegistry registry = ControlRegistry.getThreadLocalRegistry();
 
-        // Assert there is one callback registered
-        assertEquals(1, registry.getCallbacks().size());
+        // Assert there is one behavior registered
+        assertEquals(1, registry.getBehaviors().size());
 
         // Context reset should clear the dispatcher
         context.reset();
 
-        // Assert that the callback was not removed after all events was processed
-        // The reason the callbacks are not automatically removed is because the
-        // last callback is onDestroy, which is right before the request goes out
-        // of scope
-        assertEquals(0, registry.getCallbacks().size());
+        // Assert that the behavior was not removed after all events was processed
+        // The reason the behaviors are not automatically removed is because the
+        // last behavior is onDestroy, which is right before the request goes out
+        // of scope anyway
+        assertEquals(0, registry.getBehaviors().size());
     }
 
-    // Callback + Behavior tests ----------------------------------------------
+    // Behavior tests ---------------------------------------------------------
 
     /**
-     * Test that context can properly process callbacks and behaviors.
+     * Test that context can properly process behaviors.
      */
-    public void testProcessBehaviorAndCallbacks() {
+    public void testProcessBehaviors() {
         MockContext context = MockContext.initContext();
         MockRequest request = context.getMockRequest();
         request.setParameter("save", "save");
@@ -355,29 +371,29 @@ public class MockContextTest extends Tes
 
         ControlRegistry registry = ControlRegistry.getThreadLocalRegistry();
 
-        // Assert that the submit control is registered as a callback
+        // Assert that the submit control is registered as an AJAX target
         assertEquals(1, registry.getAjaxTargetControls().size());
         assertSame(submit, registry.getAjaxTargetControls().iterator().next());
 
-        // Process the preResponse callback event
-        context.executePreResponseCallbackEvent();
-        assertTrue("preResponse callback event was not processed", preResponseCalled);
-
-        // Process the preGetHeadElements callback event
-        context.executePreGetHeadElementsCallbackEvent();
-        assertTrue("preGetHeadElements callback event was not processed", preGetHeadElementsCalled);
-
-        // Process the preGetHeadElements callback event
-        context.executePreDestroyCallbackEvent();
-        assertTrue("preDestroy callback event was not processed", preDestroyCalled);
+        // Process the preResponse interceptor methods
+        context.executePreResponse();
+        assertTrue("preResponse was not processed", preResponseCalled);
+
+        // Process the preGetHeadElements interceptor methods
+        context.executePreGetHeadElements();
+        assertTrue("preGetHeadElements was not processed", preGetHeadElementsCalled);
+
+        // Process the preGetHeadElements interceptor methods
+        context.executePreDestroy();
+        assertTrue("preDestroy was not processed", preDestroyCalled);
 
-        // Assert that the callback was not removed after all events was processed
+        // Assert that the behaviors was not removed after all events was processed
         assertEquals(1, registry.getAjaxTargetControls().size());
 
-        // Test that reset will clear the callback dispatcher
+        // Test that reset will clear the ControlRegistry
         context.reset();
 
-        // Assert that the callback was removed after reset
+        // Assert that the behavior was removed after reset
         assertEquals(0, registry.getAjaxTargetControls().size());
     }
 }



Mime
View raw message