org.apache.click.control
Class AbstractControl

java.lang.Object
  extended by org.apache.click.control.AbstractControl
All Implemented Interfaces:
Serializable, Control
Direct Known Subclasses:
AbstractContainer, AbstractLink, Field, Table

public abstract class AbstractControl
extends Object
implements Control

Provides a default implementation of the Control interface to make it easier for developers to create their own controls.

Subclasses are expected to at least override getTag() to differentiate the control. However some controls do not map cleanly to an html tag, in which case you can override render(org.apache.click.util.HtmlStringBuffer) for complete control over the output.

Below is an example of creating a new control called MyField:

 public class MyField extends AbstractControl {

     private String value;

     public void setValue(String value) {
         this.value = value;
     }

     public String getValue() {
         return value;
     }

     public String getTag() {
         // Return the HTML tag
         return "input";
     }

     public boolean onProcess() {
         // Bind the request parameter to the field value
         String requestValue = getContext().getRequestParameter(getName());
         setValue(requestValue);

         // Invoke any listener of MyField
         return dispatchActionEvent();
     }
 }
 
By overriding getTag() one can specify the html tag to render.

Overriding onProcess() allows one to bind the servlet request parameter to MyField value. The dispatchActionEvent() method registers the listener for this control on the Context. Once the onProcess event has finished, all registered listeners will be fired.

To view the html rendered by MyField invoke the control's toString() method:

 public class Test {
     public static void main (String args[]) {
         // Create mock context in which to test the control.
         MockContext.initContext();

         String fieldName = "myfield";
         MyField myfield = new MyField(fieldName);
         String output = myfield.toString();
         System.out.println(output);
     }
 } 
Executing the above test results in the following output:
 <input name="myfield" id="myfield"/>
Also see Control javadoc for an explanation of the Control execution sequence.

Message Resources and Internationalization (i18n)

Controls support a hierarchy of resource bundles for displaying messages. These localized messages can be accessed through the methods: The order in which localized messages resolve are described in the user guide.

See Also:
Serialized Form

Field Summary
protected  ActionListener actionListener
          The control's action listener.
protected  Map<String,String> attributes
          The Control attributes Map.
protected  Set<Behavior> behaviors
          The control's list of behaviors.
protected  List<Element> headElements
          The list of page HTML HEAD elements including: Javascript imports, Css imports, inline Javascript and inline Css.
protected  Object listener
          The listener target object.
protected  String listenerMethod
          The listener method name.
protected  Map<String,String> messages
          The Control localized messages Map.
protected  String name
          The Control name.
protected  Object parent
          The control's parent.
protected  Map<String,String> styles
          Deprecated. use addStyleClass(String) and removeStyleClass(String) instead.
 
Fields inherited from interface org.apache.click.Control
CONTROL_MESSAGES
 
Constructor Summary
AbstractControl()
          Create a control with no name defined.
AbstractControl(String name)
          Create a control with the given name.
 
Method Summary
 void addBehavior(Behavior behavior)
          Add the given Behavior to the control's Set of Behaviors.
 void addStyleClass(String value)
          Add the CSS class attribute.
protected  void appendAttributes(HtmlStringBuffer buffer)
          Append all the controls attributes to the specified buffer.
protected  void dispatchActionEvent()
          Dispatch an action event to the ActionEventDispatcher.
 ActionListener getActionListener()
          Return the control's action listener.
 String getAttribute(String name)
          Return the control HTML attribute with the given name, or null if the attribute does not exist.
 Map<String,String> getAttributes()
          Return the control's attributes Map.
 Set<Behavior> getBehaviors()
          Returns the Set of Behaviors for this control.
 Context getContext()
          Return the Page request Context of the Control.
protected  int getControlSizeEst()
          Return the estimated rendered control size in characters.
 List<Element> getHeadElements()
          Return the list of HEAD elements to be included in the page.
 String getHtmlImports()
          Deprecated. use the new getHeadElements() instead
 String getId()
          Return the "id" attribute value if defined, or the control name otherwise.
 String getMessage(String name)
          Return the localized message for the given key or null if not found.
 String getMessage(String name, Object... args)
          Return the formatted message for the given resource name and message format arguments or null if no message was found.
 Map<String,String> getMessages()
          Return a Map of localized messages for the control.
 String getName()
          Return the name of the Control.
 Page getPage()
          Return the parent page of this control, or null if not defined.
 Object getParent()
          Return the parent of the Control.
 String getStyle(String name)
          Return the control CSS style for the given name.
 Map<String,String> getStyles()
          Deprecated. use getAttribute(String) instead
 String getTag()
          Returns the controls html tag.
 boolean hasAttribute(String name)
          Returns true if specified attribute is defined, false otherwise.
 boolean hasAttributes()
          Return true if the control has attributes or false otherwise.
 boolean hasBehaviors()
          Returns true if this control has any Behaviors registered, false otherwise.
 boolean hasStyles()
          Deprecated. use hasAttribute(String) instead
 boolean isAjaxTarget(Context context)
          Returns true if this control is an AJAX target, false otherwise.
 void onDeploy(ServletContext servletContext)
          This method does nothing.
 void onDestroy()
          This method does nothing.
 void onInit()
          This method does nothing.
 boolean onProcess()
          The on process event handler.
 void onRender()
          This method does nothing.
 void removeBehavior(Behavior behavior)
          Remove the given Behavior from the Control's Set of Behaviors.
 void removeStyleClass(String value)
          Removes the CSS class attribute.
 void render(HtmlStringBuffer buffer)
          Render the control's output to the specified buffer.
protected  void renderTagBegin(String tagName, HtmlStringBuffer buffer)
          Render the tag and common attributes including id, class and style.
protected  void renderTagEnd(String tagName, HtmlStringBuffer buffer)
          Closes the specified tag.
 void setActionListener(ActionListener listener)
          Set the control's action listener.
 void setAttribute(String name, String value)
          Set the control attribute with the given attribute name and value.
 void setId(String id)
          Set the HTML id attribute for the control with the given value.
 void setListener(Object listener, String method)
          Set the controls event listener.
 void setName(String name)
          Set the name of the Control.
 void setParent(Object parent)
          Set the parent of the Control.
 void setStyle(String name, String value)
          Set the control CSS style name and value pair.
 String toString()
          Returns the HTML representation of this control.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

actionListener

protected ActionListener actionListener
The control's action listener.


behaviors

protected Set<Behavior> behaviors
The control's list of behaviors.


headElements

protected List<Element> headElements
The list of page HTML HEAD elements including: Javascript imports, Css imports, inline Javascript and inline Css.


attributes

protected Map<String,String> attributes
The Control attributes Map.


messages

protected transient Map<String,String> messages
The Control localized messages Map.


name

protected String name
The Control name.


parent

protected Object parent
The control's parent.


styles

protected Map<String,String> styles
Deprecated. use addStyleClass(String) and removeStyleClass(String) instead.
The Map of CSS style attributes.


listener

protected Object listener
The listener target object.


listenerMethod

protected String listenerMethod
The listener method name.

Constructor Detail

AbstractControl

public AbstractControl()
Create a control with no name defined.


AbstractControl

public AbstractControl(String name)
Create a control with the given name.

Parameters:
name - the control name
Method Detail

getTag

public String getTag()
Returns the controls html tag.

Subclasses should override this method and return the correct tag.

This method returns null by default.

Example tags include table, form, a and input.

Returns:
this controls html tag

getActionListener

public ActionListener getActionListener()
Return the control's action listener. If the control has a listener target and listener method defined, this method will return an ActionListener instance.

Returns:
the control's action listener

setActionListener

public void setActionListener(ActionListener listener)
Set the control's action listener.

Parameters:
listener - the control's action listener

hasBehaviors

public boolean hasBehaviors()
Returns true if this control has any Behaviors registered, false otherwise.

Specified by:
hasBehaviors in interface Control
Returns:
true if this control has any Behaviors registered, false otherwise

addBehavior

public void addBehavior(Behavior behavior)
Add the given Behavior to the control's Set of Behaviors.

In addition, the Control will be registered with the ControlRegistry as a potential Ajax target control and to have it's Behaviors processed by the Click runtime.

Parameters:
behavior - the Behavior to add

removeBehavior

public void removeBehavior(Behavior behavior)
Remove the given Behavior from the Control's Set of Behaviors.

Parameters:
behavior - the Behavior to remove

getBehaviors

public Set<Behavior> getBehaviors()
Returns the Set of Behaviors for this control.

Specified by:
getBehaviors in interface Control
Returns:
the Set of Behaviors for this control

isAjaxTarget

public boolean isAjaxTarget(Context context)
Returns true if this control is an AJAX target, false otherwise.

The control is defined as an Ajax target if the control ID is send as a request parameter.

Specified by:
isAjaxTarget in interface Control
Parameters:
context - the request context
Returns:
true if this control is an AJAX target, false otherwise

getAttribute

public String getAttribute(String name)
Return the control HTML attribute with the given name, or null if the attribute does not exist.

Parameters:
name - the name of link HTML attribute
Returns:
the link HTML attribute

setAttribute

public void setAttribute(String name,
                         String value)
Set the control attribute with the given attribute name and value. You would generally use attributes if you were creating the entire Control programmatically and rendering it with the toString() method.

For example given the ActionLink:

 ActionLink addLink = new ActionLink("addLink", "Add");
 addLink.setAttribute("target", "_blank"); 
Will render the HTML as:
 <a href=".." target="_blank">Add</a> 
Note: for style and class attributes you can also use the methods setStyle(String, String) and addStyleClass(String).

Parameters:
name - the attribute name
value - the attribute value
Throws:
IllegalArgumentException - if name parameter is null
See Also:
setStyle(String, String), addStyleClass(String), removeStyleClass(String)

getAttributes

public Map<String,String> getAttributes()
Return the control's attributes Map.

Returns:
the control's attributes Map.

hasAttributes

public boolean hasAttributes()
Return true if the control has attributes or false otherwise.

Returns:
true if the control has attributes on false otherwise

hasAttribute

public boolean hasAttribute(String name)
Returns true if specified attribute is defined, false otherwise.

Parameters:
name - the specified attribute to check
Returns:
true if name is a defined attribute

getContext

public Context getContext()
Description copied from interface: Control
Return the Page request Context of the Control.

Specified by:
getContext in interface Control
Returns:
the Page request Context
See Also:
Control.getContext()

getName

public String getName()
Description copied from interface: Control
Return the name of the Control. Each control name must be unique in the containing Page model or the containing Form.

Specified by:
getName in interface Control
Returns:
the name of the control
See Also:
Control.getName()

setName

public void setName(String name)
Description copied from interface: Control
Set the name of the Control. Each control name must be unique in the containing Page model or the parent container.

Please note: changing the name of a Control after it has been added to its parent container is undefined. Thus it is best not to change the name of a Control once its been set.

Specified by:
setName in interface Control
Parameters:
name - of the control
Throws:
IllegalArgumentException - if the name is null
See Also:
Control.setName(String)

getId

public String getId()
Return the "id" attribute value if defined, or the control name otherwise.

Specified by:
getId in interface Control
Returns:
HTML element identifier attribute "id" value
See Also:
Control.getId()

setId

public void setId(String id)
Set the HTML id attribute for the control with the given value.

Parameters:
id - the element HTML id attribute value to set

getMessage

public String getMessage(String name)
Return the localized message for the given key or null if not found. The resource message returned will use the Locale obtained from the Context.

This method will attempt to lookup the localized message in the parent's messages, which resolves to the Page's resource bundle.

If the message was not found, this method will attempt to look up the value in the /click-control.properties message properties file, through the method getMessages().

If still not found, this method will return null.

Parameters:
name - the name of the message resource
Returns:
the named localized message for the control, or null if not found

getMessage

public String getMessage(String name,
                         Object... args)
Return the formatted message for the given resource name and message format arguments or null if no message was found. The resource message returned will use the Locale obtained from the Context.

getMessage(java.lang.String) is invoked to retrieve the message for the specified name.

Parameters:
name - resource name of the message
args - the message arguments to format
Returns:
the named localized message for the control or null if no message was found

getMessages

public Map<String,String> getMessages()
Return a Map of localized messages for the control. The messages returned will use the Locale obtained from the Context.

Specified by:
getMessages in interface Control
Returns:
a Map of localized messages for the control
Throws:
IllegalStateException - if the context for the control has not be set

getParent

public Object getParent()
Description copied from interface: Control
Return the parent of the Control.

Specified by:
getParent in interface Control
Returns:
the Control's parent
See Also:
Control.getParent()

setParent

public void setParent(Object parent)
Description copied from interface: Control
Set the parent of the Control.

Specified by:
setParent in interface Control
Parameters:
parent - the parent of the Control
Throws:
IllegalArgumentException - if the given parent instance is referencing this object: if (parent == this)
See Also:
Control.setParent(Object)

onProcess

public boolean onProcess()
Description copied from interface: Control
The on process event handler. Each control will be processed when the Page is requested.

ClickServlet will process all Page controls in the order they were added to the Page.

Container implementations should recursively invoke the onProcess method on each of their child controls ensuring that all controls receive this event. However when a control onProcess method return false, no other controls onProcess method should be invoked.

When a control is processed it should return true if the Page should continue event processing, or false if no other controls should be processed and the Page.onGet() or Page.onPost() methods should not be invoked.

Please note: a common problem when overriding onProcess in subclasses is forgetting to call super.onProcess(). Consider carefully whether you should call super.onProcess() or not, especially for Containers which by default call onProcess on all their child controls as well.

Specified by:
onProcess in interface Control
Returns:
true to continue Page event processing or false otherwise
See Also:
Control.onProcess()

setListener

public void setListener(Object listener,
                        String method)
Set the controls event listener.

The method signature of the listener is:

An example event listener method would be:

 public boolean onClick() {
     System.out.println("onClick called");
     return true;
 } 

Specified by:
setListener in interface Control
Parameters:
listener - the listener object with the named method to invoke
method - the name of the method to invoke

onInit

public void onInit()
This method does nothing. Subclasses may override this method to perform initialization.

Specified by:
onInit in interface Control
See Also:
Control.onInit()

onDestroy

public void onDestroy()
This method does nothing. Subclasses may override this method to perform clean up any resources.

Specified by:
onDestroy in interface Control
See Also:
Control.onDestroy()

onDeploy

public void onDeploy(ServletContext servletContext)
This method does nothing. Subclasses may override this method to deploy static web resources.

Specified by:
onDeploy in interface Control
Parameters:
servletContext - the servlet context
See Also:
Control.onDeploy(ServletContext)

onRender

public void onRender()
This method does nothing. Subclasses may override this method to perform pre rendering logic.

Specified by:
onRender in interface Control
See Also:
Control.onRender()

getHtmlImports

public final String getHtmlImports()
Deprecated. use the new getHeadElements() instead

Returns:
the HTML includes statements for the control stylesheet and JavaScript files

getHeadElements

public List<Element> getHeadElements()
Description copied from interface: Control
Return the list of HEAD elements to be included in the page. Example HEAD elements include JsImport, JsScript, CssImport and CssStyle.

Controls can contribute their own list of HEAD elements by implementing this method.

The recommended approach when implementing this method is to use lazy loading to ensure the HEAD elements are only added once and when needed. For example:

 public MyControl extends AbstractControl {

     public List getHeadElements() {
         // Use lazy loading to ensure the JS is only added the
         // first time this method is called.
         if (headElements == null) {
             // Get the head elements from the super implementation
             headElements = super.getHeadElements();

             // Include the control's external JavaScript resource
             JsImport jsImport = new JsImport("/mycorp/mycontrol/mycontrol.js");
             headElements.add(jsImport);

             // Include the control's external Css resource
             CssImport cssImport = new CssImport("/mycorp/mycontrol/mycontrol.css");
             headElements.add(cssImport);
         }
         return headElements;
     }
 } 
Alternatively one can add the HEAD elements in the Control's constructor:
 public MyControl extends AbstractControl {

     public MyControl() {

         JsImport jsImport = new JsImport("/mycorp/mycontrol/mycontrol.js");
         getHeadElements().add(jsImport);

         CssImport cssImport = new CssImport("/mycorp/mycontrol/mycontrol.css");
         getHeadHeaders().add(cssImport);
     }
 } 
One can also add HEAD elements from event handler methods such as Control.onInit(), Control.onProcess(), Control.onRender() etc.

The order in which JS and CSS files are included will be preserved in the page.

Note: this method must never return null. If no HEAD elements are available this method must return an empty List.

Also note: a common problem when overriding getHeadElements in subclasses is forgetting to call super.getHeadElements. Consider carefully whether you should call super.getHeadElements or not.

Specified by:
getHeadElements in interface Control
Returns:
the list of HEAD elements to be included in the page
See Also:
Control.getHeadElements()

getPage

public Page getPage()
Return the parent page of this control, or null if not defined.

Returns:
the parent page of this control, or null if not defined

getStyle

public String getStyle(String name)
Return the control CSS style for the given name.

Parameters:
name - the CSS style name
Returns:
the CSS style for the given name

setStyle

public void setStyle(String name,
                     String value)
Set the control CSS style name and value pair.

For example given the ActionLink:

 ActionLink addLink = new ActionLink("addLink", "Add");
 addLink.setStyle("color", "red");
 addLink.setStyle("border", "1px solid black"); 
Will render the HTML as:
 <a href=".." style="color:red;border:1px solid black;">Add</a>
 
To remove an existing style, set the value to null.

Parameters:
name - the CSS style name
value - the CSS style value

hasStyles

public boolean hasStyles()
Deprecated. use hasAttribute(String) instead

Return true if CSS styles are defined.

Returns:
true if CSS styles are defined

getStyles

public Map<String,String> getStyles()
Deprecated. use getAttribute(String) instead

Return the Map of control CSS styles.

Returns:
the Map of control CSS styles

addStyleClass

public void addStyleClass(String value)
Add the CSS class attribute. Null values will be ignored.

For example given the ActionLink:

 ActionLink addLink = new ActionLink("addLink", "Add");
 addLink.addStyleClass("red"); 
Will render the HTML as:
 <a href=".." class="red">Add</a> 

Parameters:
value - the class attribute to add

removeStyleClass

public void removeStyleClass(String value)
Removes the CSS class attribute.

Parameters:
value - the CSS class attribute

render

public void render(HtmlStringBuffer buffer)
Render the control's output to the specified buffer.

If getTag() returns null, this method will return an empty string.

Specified by:
render in interface Control
Parameters:
buffer - the specified buffer to render the control's output to
See Also:
Control.render(org.apache.click.util.HtmlStringBuffer)

toString

public String toString()
Returns the HTML representation of this control.

This method delegates the rendering to the method render(org.apache.click.util.HtmlStringBuffer). The size of buffer is determined by getControlSizeEst().

Overrides:
toString in class Object
Returns:
the HTML representation of this control
See Also:
Object.toString()

dispatchActionEvent

protected void dispatchActionEvent()
Dispatch an action event to the ActionEventDispatcher.

See Also:
ActionEventDispatcher.dispatchActionEvent(org.apache.click.Control, org.apache.click.ActionListener), ActionEventDispatcher.dispatchAjaxBehaviors(org.apache.click.Control)

appendAttributes

protected void appendAttributes(HtmlStringBuffer buffer)
Append all the controls attributes to the specified buffer.

Parameters:
buffer - the specified buffer to append all the attributes

renderTagBegin

protected void renderTagBegin(String tagName,
                              HtmlStringBuffer buffer)
Render the tag and common attributes including id, class and style. The name attribute is not rendered by this control. It is up to subclasses whether to render the name attribute or not. Generally only Field controls render the name attribute.

Please note: the tag will not be closed by this method. This enables callers of this method to append extra attributes as needed.

For example the following example:

 Field field = new TextField("mytext");
 HtmlStringBuffer buffer = new HtmlStringBuffer();
 field.renderTagBegin("input", buffer); 
will render:
 <input name="mytext" id="mytext" 
Note that the tag is not closed, so subclasses can render extra attributes.

Parameters:
tagName - the name of the tag to render
buffer - the buffer to append the output to

renderTagEnd

protected void renderTagEnd(String tagName,
                            HtmlStringBuffer buffer)
Closes the specified tag.

Parameters:
tagName - the name of the tag to close
buffer - the buffer to append the output to

getControlSizeEst

protected int getControlSizeEst()
Return the estimated rendered control size in characters.

Returns:
the estimated rendered control size in characters