Portlet Customization and Parameter Styles

The next portlet example illustrates editing your portlet parameters using the default Portlet Customizer. The first portlet titled "Tutorial Stock Portfolio" in this tutorial uses the default customizer. The second portlet titled "Tutorial Stock Portfolio with parameter styles" illustrates how to enhance the parameter edit fields in the default Portlet Customizer.

To see these examples working, you will need to login as the turbine/turbine user. First let's look again at the first portlet that doesn't have any parameter styles so that we can see the customizer before and after.

The Default Portlet Customizer

You can customize a portlet by clicking a portlet?s customize action button. With the default deployment, portlets cannot be customized for the anonymous user. Since the anonymous user PSML resource is shared, this is probably a good idea. But for that odd case where you need anonymous customization of portlets, it is possible. Modify the JetspeedSecurity.properties file:


services.JetspeedSecurity.actions.anon.disable=false

For now just logon as turbine/turbine. Click on the customize action button for the first portlet titled "Tutorial Stock Portfolio". You will see the Default Portlet Customizer. This customizer will display all of the non-hidden portlet-entry parameters:

The Title and Skin parameters are always customizable. Remember from Tutorial 6, all parameters that are edited are not stored back to the registry. The edited parameters are stored to the PSML resource for the current logged on user. Thus if we change the title of this portlet, it will only change for the user "turbine" and only for this one particular instance of this portlet on this page. Likewise for all other parameters. If you are logged on as a user with the admin role, you can also change the security constraint for this portlet instance. Only when logged on as a user with the admin role, a third drop-down list of security constraints is displayed. See Tutorial 4 for details.

The third parameter shown above, "Symbols", is a parameter that we defined for this portlet. It is the list of stock symbols for the portlet instance.


<parameter name="symbols" value="MSFT,IBM,ORCL,SUNW" type=""
            hidden="false" cachedOnName="true" cachedOnValue="true">
    <meta-info>
        <title>Symbols</title>
        <description>List of comma-separated stock symbols</description>
    </meta-info>
</parameter>

The read-only meta-info parameters title and description are listed in the portlet customizer from the registry entry above. The value of the parameter obviously comes from the value attribute. Now let's see how we can enhance parameter customization using Parameter Styles.

The Default Portlet Customizer with Parameter Styles

Parameter styles are custom widgets which allow you to present portlet parameter using something other than the default input text box control. These widgets can be as simple as text area control or as complex as a pop up calendar control.

The second portlet titled "Tutorial Stock Portfolio with parameter styles" illustrates how to enhance the parameter edit fields in the default Portlet Customizer. Its action class is TutorialStockQuoteAction2. This portlet also retrieves stock quotes from a web service, just like the first example. The only difference is that we will show you how to use Parameter Styles to make your portlet's customization more dynamic.

Logon as turbine/turbine. Click on the customize action button for the second portlet titled "Tutorial Stock Portfolio with parameter styles". You will see the Default Portlet Customizer with two custom widgets:

The "Symbols" parameter has a TextArea parameter style, and a new parameter "Columns" has a CheckBoxGroup style. The columns parameter lets us customize which columns are displayed in view mode. If you don't want to see all stock quote columns, just uncheck the column.

Looking at the registry entry, we have created several parameter styles. First there is the Symbols widget, it has a TextArea style:


<parameter name="symbols" value="MSFT,IBM,ORCL,SUNW" type="style"
            hidden="false" cachedOnName="true" cachedOnValue="true">
    <meta-info>
         <title>Symbols</title>
         <description>List of comma-separated stock symbols</description>
    </meta-info>
</parameter>

<parameter name="symbols.style" value="TextArea" hidden="true"
           cachedOnName="true" cachedOnValue="true"/>

The default value for all portlet instances is provided in the value attribute of the symbols parameter. Again, when a user customizes this portlet, its values are not stored back to the registry but to the PSML resource for the particular portlet instance. The meta-info title and description are displayed by the customizer. The symbols parameter is linked to the symbols.style by name, and the parameter style TextArea is selected there.

The next parameter is the columns parameter, which allows you to choose which columns will be displayed in the portlet?s view mode.


<parameter name="columns" value="Symbols,Price,Change,Volume" type="style"
           hidden="false" cachedOnName="true" cachedOnValue="true">
    <meta-info>
        <title>Columns</title>
        <description>Columns to display</description>
    </meta-info>
</parameter>

<parameter name="columns.style.items" value="Symbol,Price,Change,Volume"
           hidden="true" cachedOnName="true" cachedOnValue="true"/>
<parameter name="columns.style.layout" value="$eastwest" hidden="true"
           cachedOnName="true" cachedOnValue="true"/>
<parameter name="columns.style" value="CheckBoxGroup" hidden="true"  
           cachedOnName="true" cachedOnValue="true"/>

The column headers strings are defined in the value attribute for the parameter style. The style is set to be a CheckBoxGroup. The layout of the check boxes is controlled by the layout style, which automatically aligns the check boxes vertically or horizontally using the keywords: $eastwest or $northsouth. The names of the check box items are defined in the columns.style.items parameter.

The action class is responsible for displaying the content in view mode. The action class for our portlet only handles normal (view mode) processing. It let?s the base class handle default processing for maximize and customize modes.


protected void buildNormalContext(VelocityPortlet portlet,
                                       Context context,
                                       RunData rundata)
    {
        try
        {
            // Get reference to stock quote web service
            StockQuoteService service = (StockQuoteService)
                   TurbineServices.getInstance().
                   getService(StockQuoteService.SERVICE_NAME);
 
            // Retrieve portlet parameters
            String symbols = PortletConfigState.getParameter(portlet,
                                rundata, SYMBOLS, "IBM,MSFT,ORCL,SUNW");
            String columns = PortletConfigState.getParameter(portlet,   
                                     rundata, COLUMNS,                                                          
                           StringUtils.arrayToString(ALL_COLUMNS, ","));
            String[] selectedColumnsArray =
                        StringUtils.stringToArray(columns, ",");
 
            // Request stock quote(s) from the stock quote web service
            String[] symbolArray = StringUtils.stringToArray(symbols,",");
            StockQuote[] quotes = service.fullQuotes(symbolArray);
 
            // Place appropriate objects in Velocity context
            context.put(QUOTES, quotes);
            context.put(SELECTED_COLUMNS, selectedColumnsArray);
            context.put(COLUMNS, columns);

Three objects are put into the Velocity context: $quotes, $columns, and $selected-columns. These objects are then used to generate the content of the portlet in view and maximize modes. Two changes are made in the second example. First only the selected headers from the customizer are displayed:


          #foreach ($column in $selected-columns)
          #headerCell ($column)
          #end

Secondly, only the selected column-values are displayed:


#foreach ($quote in $quotes)
<tr>
#if ($columns.indexOf("Symbol") >= 0) #entryCell ($quote.Symbol) #end
#if ($columns.indexOf("Price") >= 0) #entryCell ($quote.Price) #end
#if ($columns.indexOf("Change") >= 0) #entryCell ($quote.Change) #end
#if ($columns.indexOf("Volume") >= 0) #entryCell ($quote.Volume) #end
</tr>
#end