Jetspeed Proposal: Customizer Parameter Presentation Styles
Version: $Revision: 1.1 $
Proposed by: Mark Orciuch, Next Generation Solutions, Ltd. (mark_orciuch@ngsltd.com)
Status: Revised Proposal
Date: August 14, 2002

Overview
========

The purpose of this proposal is to introduce customizer parameter presentation styles. Currently, the default customizer displays all "visible" parameters using HTML input tag (or check box if parameter type is "boolean"). This approach works in most of the cases but there are situtations where individual portlet parameters need to be displayed using a custom presentation style. For example, DatabaseBrowserTest has a sql query parameter which is best presented using a text area rather than input. To achieve this effect a new customizer has been created. There may have been another reason to create a new customizer : to be able to notify the portlet that its configuration has changed??? But that is a topic for another conversation.

What I'm proposing is to provide the spec for creating custom presentation "widgets" for portlet parametes. This feature would be optional and if not used, the customizer would fallback to the old presentation method. Also, the ability to create custom portlet customizer would still be there.

Alternatives
============

Per Dave Taylor's suggestion, I reviewed some alternative solutions to this feature:

1. Java Server Faces (http://www.jcp.org/jsr/detail/127.jsp) - this jsr is in very early stage and is jsp oriented.
2. Turbine Intake - not lightweight enough + another turbine dependency?

I'm not against these approaches and I'm open to other solutions as well.

Approach
========

My proposed approach is to utilize Turbine module pattern in deploying the parameter presentation styles. I would add another module type "parameters" and configure an AssemblerBrokerService factory for creating these. Using this approach one could create custom parameter modules and place them on the module search path. 

Another advantage of this is the ease of overriding default "widgets". For example, Jetspeed might provide a default "date list box widget". To override its functionality, one could create their own version an place it in location at the beginning of the module search path.

Implementation
==============

1. The following new classes would be added:

org.apache.jetspeed.modules.parameters.ParameterPresentationStyle - an abstract class, all "widgets" would extend this class

org.apache.jetspeed.modules.parameters.ParameterPresentationStyleFactory - custom "widget" factory

org.apache.jetspeed.modules.parameters.ParameterLoader - class to load and execute "widgets"

2. The following classes/templates would be changed:

org.apache.jetspeed.util.template.JetspeedTool - add method to enable using "widgets" in Velocity templates:

    public static String getPortletParameter(RunData data, Portlet portlet, String parmName)

This method would lookup the style for parameter specified and render it. This would be achieved using the ParameterLoader.eval() method. 

customizer-portlet.vm - modify to render parameter using a custom widget if parameter type is "style"

3. The following line would be added in TurbineResources.properties:

services.AssemblerBrokerService.parameter=org.apache.jetspeed.modules.parameters.ParameterPresentationStyleFactory

The class names could be improved - I'm open to suggestions.

Example
=======

In this exanmple, we would configure "sql" parameter in DatabaseBrowserTest to use TextArea "widget" under the default customizer. Here's a registry definition:

    <portlet-entry name="DatabaseBrowserTest" hidden="false" type="ref"
        parent="DatabaseBrowserPortlet" application="false">
        <meta-info>
            <title>DatabaseBrowserTest</title>
            <description>Simple Test Database Browser Portlet Example</description>
        </meta-info>
        <classname>org.apache.jetspeed.portal.portlets.browser.DatabaseBrowserPortlet</classname>
        <parameter name="template" value="database-browser-portlet"
            hidden="false" cachedOnName="true" cachedOnValue="true"/>
        <parameter name="action"
            value="portlets.browser.DatabaseBrowserAction"
            hidden="false" cachedOnName="true" cachedOnValue="true"/>
        <parameter name="sql" value="select * from coffees"
            hidden="false" cachedOnName="true" cachedOnValue="true" TYPE="style"/>
        <parameter name="sql.style" value="TextArea" hidden="true"
            cachedOnName="true" cachedOnValue="true"/>
        <parameter name="sql.style.rows" value="10" hidden="true"
            cachedOnName="true" cachedOnValue="true"/>
        <parameter name="sql.style.cols" value="80" hidden="true"
            cachedOnName="true" cachedOnValue="true"/>
        <parameter name="windowSize" value="5" hidden="false"
            cachedOnName="true" cachedOnValue="true"/>
        <media-type ref="html"/>
        <url cachedOnURL="true"/>
        <category group="Jetspeed">database</category>
    </portlet-entry>

In the above fragment, there are three hidden parameters:
1. sql.style - identifies the style for this parameter as TextArea
2. sql.style.rows - each style may have additional parameters, in this case, text area with 10 rows and 80 columns
3. sql.style.cols - same above

Also, note that sql parameter is designated with type="style". this is the trigger to display it using a "widget".
And here's an implementation of TextArea class:

public class TextArea extends ParameterPresentationStyle {

    public static final String ROWS = "rows";
    public static final String COLS = "cols";

    /**
     * Returns presentation control
     */
    public String getContent(RunData data, String name, String value, Map parms) {

        String rows = (String)this.getParm(this.ROWS, "3");
        String cols = (String)this.getParm(this.COLS, "80");

        org.apache.ecs.html.TextArea tx = new org.apache.ecs.html.TextArea(name, rows, cols).addElement(value);

        return tx.toString();

    }

}

The above is a very simple example. Of course, there could be much more complex components with mutltiple HTML tags and JavaScript attached.

Also, please note that the usage of these "widgets" is not limited just the customizer. One could include those in Velocity and JSP templates. I can see variety of reusable components: SecurityIdListBox and SkinListBox being the closest examples. Both of them are used in Customize Pane and Customize Portlet.