You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@click.apache.org by sa...@apache.org on 2010/07/11 17:42:14 UTC
svn commit: r963094 -
/click/trunk/click/framework/src/org/apache/click/ControlRegistry.java
Author: sabob
Date: Sun Jul 11 15:42:13 2010
New Revision: 963094
URL: http://svn.apache.org/viewvc?rev=963094&view=rev
Log:
added a guard against duplicate callbacks and javadoc
Modified:
click/trunk/click/framework/src/org/apache/click/ControlRegistry.java
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=963094&r1=963093&r2=963094&view=diff
==============================================================================
--- click/trunk/click/framework/src/org/apache/click/ControlRegistry.java (original)
+++ click/trunk/click/framework/src/org/apache/click/ControlRegistry.java Sun Jul 11 15:42:13 2010
@@ -27,9 +27,50 @@ import org.apache.click.service.LogServi
import org.apache.commons.lang.Validate;
/**
- * Provides a registry for Controls.
+ * Provides a centralized registry where Controls can be registered, allowing
+ * Click to provide advanced functionality such as AJAX
+ * {@link org.apache.click.Behavior Behaviors} and
+ * {@link org.apache.click.Callback Callbacks}.
+ * <p/>
+ * <b>Please note:</b> the registry is recreated each request and Controls have
+ * to be registered for every request.
*
- * TODO: javadoc
+ * <h3>Behavior Usage</h3>
+ * TODO
+ *
+ * <h3>Callback Usage</h3>
+ * This class will only rarely be used by Control developers who want to create
+ * a custom Control with {@link org.apache.click.Callback Callback} functionality.
+ * <p/>
+ * Example:
+ * <pre class="prettyprint">
+ * public class MyControl extends AbstractControl {
+ *
+ * // The Callback is registered during onInit to cater for both stateless and
+ * // stateful pages
+ * public void onInit() {
+ * Callback callback = getCallback();
+ * ControlRegistry.registerCallback(this, callback);
+ * }
+ *
+ * private Callback getCallback() {
+ * callback = new Callback() {
+ * public void preResponse(Control source) {
+ * // Invoked before the controls are rendered to the client
+ * addIndexToControlNames();
+ * }
+ *
+ * public void preGetHeadElements(Control source) {
+ * // Invoked before the HEAD elements are retrieved for each Control
+ * }
+ *
+ * public void preDestroy(Control source) {
+ * // Invoked before onDestroy event
+ * }
+ * };
+ * return callback;
+ * }
+ * } </pre>
*/
public class ControlRegistry {
@@ -52,6 +93,11 @@ public class ControlRegistry {
// Constructors -----------------------------------------------------------
+ /**
+ * Construct the ControlRegistry with the given ConfigService.
+ *
+ * @param configService the click application configuration service.
+ */
public ControlRegistry(ConfigService configService) {
this.logger = configService.getLogService();
}
@@ -62,16 +108,46 @@ public class ControlRegistry {
* Register the control to be processed by the ClickServlet if the control
* is the Ajax target. A control is an Ajax target if the
* {@link Control#isAjaxTarget(org.apache.click.Context)} method returns true.
- * Target controls have their {@link Control#onProcess()} method invoked.
+ * Once a target control is identified, ClickServlet invokes its
+ * {@link Control#onProcess()} method invoked.
+ * <p/>
+ * <b>Please note:</b> the ControlRegistry is stateless. For each request
+ * a new registry is created. This means a control is only registered for
+ * a single request and must be registered again for subsequent requests.
*
- * @param control the control to register
+ * <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 control the control to register as an Ajax target
*/
public static void registerAjaxTarget(Control control) {
+ if (control == null) {
+ throw new IllegalArgumentException("control cannot be null");
+ }
+
ControlRegistry instance = getThreadLocalRegistry();
instance.internalRegisterAjaxTarget(control);
}
+ /**
+ * Register the source control and associated callback.
+ *
+ * @param source the behavior source control
+ * @param callback the callback to register
+ */
public static void registerCallback(Control control, Callback callback) {
+ if (control == null) {
+ throw new IllegalArgumentException("control cannot be null");
+ }
+ if (callback == null) {
+ throw new IllegalArgumentException("callback cannot be null");
+ }
+
ControlRegistry instance = getThreadLocalRegistry();
instance.internalRegisterCallback(control, callback);
}
@@ -103,9 +179,9 @@ public class ControlRegistry {
}
/**
- * Register the ajax target control.
+ * Register the AJAX target control.
*
- * @param control the ajax target control
+ * @param control the AJAX target control
*/
void internalRegisterAjaxTarget(Control control) {
Validate.notNull(control, "Null control parameter");
@@ -113,16 +189,22 @@ public class ControlRegistry {
}
/**
- * Register the behavior source control.
+ * Register the source control and associated callback.
*
* @param source the behavior source control
+ * @param callback the callback to register
*/
void internalRegisterCallback(Control source, Callback callback) {
Validate.notNull(source, "Null source parameter");
Validate.notNull(callback, "Null callback parameter");
CallbackHolder callbackHolder = new CallbackHolder(source, callback);
- getCallbacks().add(callbackHolder);
+
+ // Guard against adding duplicate callbacks
+ List<CallbackHolder> localCallbacks = getCallbacks();
+ if (!localCallbacks.contains(callbackHolder)) {
+ localCallbacks.add(callbackHolder);
+ }
}
void processPreResponse(Context context) {
@@ -350,5 +432,48 @@ public class ControlRegistry {
public void setControl(Control control) {
this.control = control;
}
+
+ /**
+ * @see Object#equals(java.lang.Object)
+ *
+ * @param o the reference object with which to compare
+ * @return true if this object equals the given object
+ */
+ @Override
+ public boolean equals(Object o) {
+
+ //1. Use the == operator to check if the argument is a reference to this object.
+ if (o == this) {
+ return true;
+ }
+
+ //2. Use the instanceof operator to check if the argument is of the correct type.
+ if (!(o instanceof CallbackHolder)) {
+ return false;
+ }
+
+ //3. Cast the argument to the correct type.
+ CallbackHolder that = (CallbackHolder) 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);
+ }
+
+ /**
+ * @see java.lang.Object#hashCode()
+ *
+ * @return the CallbackHolder hashCode
+ */
+ @Override
+ public int hashCode() {
+ int result = 17;
+ result = 37 * result + (control == null ? 0 : control.hashCode());
+ result = 37 * result + (callback == null ? 0 : callback.hashCode());
+ return result;
+ }
}
}