LS10 Tagcloud JSF Component - Usage guide

Introduction

The architecture of the LS10 Tagcloud JSF Component is based on the idea of a separation between the model and the classes responsible for the presentation. The component is generally usable for any presentation technology, but only a renderer and a renderer-specific subclass for HTML have been implemented so far.

Tagcloud tag

The only required attribute for the Tagcloud tag is the reference to the model that should be showed. The value of this attribute needs to evaluate to an object implementing TagCloudModel.

So the following line would already be sufficient, if the given EL expression evaluates to an appropriate model.

<ls10:tagCloud model="#{tagCloudController.model}"/>

The model can be named with a titel through an respective attribute. Moreover a bunch of different attributes can be used to customize the presentation of the model, especially by the usage of CSS.

Tagcloud model

The model referenced by the tag attribute has to be an implementation of TagCloudModel.

The simplest way to build your own model is to extend the DefaultTagCloudModel. This abstract default implementation offers already most of the needed functionality, the only method that has to be written is update().

In the update() method you have to fill the model with the tags that should be visualized by the Tagcloud Component. The method is called during the construction of the model and should afterwards be called to synchronize the model with the underlying data.

The tags are represented as instances of TagCloudLink inside the model. There are two different kinds of TagCloudLinks:

  • TagCloudLinkInternal: internal TagCloudLinks allow you to associate JSF actions or actionListener with the representation of a tag
  • TagCloudLinkExternal: external TagCloudLinks allow you to to specify an URL that is associated with the representation of a tag

Moreover each TagCloudLink has a label as well as a particular TagCloudLinkImportance. This TagCloudLinkImportance defines the size in which the respective tag is visualized.

An example for a Tagcloud model would like the following:

public class ExampleTagCloudModel extends DefaultTagCloudModel {
        
public void update() {
                
        removeAllTags();
                
        TagManager tm = ServiceLocator.getTagManager();
                
        List<Tag> list = tm.listTags();
        
        int overallCount = tm.getTagDocumentCount();
        
        for (Tag tag: list) {
                TagCloudLinkInternal link = new TagCloudLinkInternal();
                
                link.setValue(tag.getName());
                
                // set the action of the link 
                link.setAction("#{manageTagController.selectTagByParam}");
        
                // determine the importance of the link
                if (overallCount > 0) {
                        int docCount = tm.getDocumentsForTag(tag).size();
                        
                        float ratio = ((float) docCount) / ((float) overallCount);
                        
                        if (ratio > 0.4) {
                                link.setWeight(TagCloudLinkImportance.HIGHLY_IMPORTANT);
                        } else if (ratio > 0.3) {
                                link.setWeight(TagCloudLinkImportance.MORE_IMPORTANT);
                        } else if (ratio > 0.2) {
                                link.setWeight(TagCloudLinkImportance.IMPORTANT);
                        } else if (ratio > 0.1) {
                                link.setWeight(TagCloudLinkImportance.LESS_IMPORTANT);
                        } else {
                                link.setWeight(TagCloudLinkImportance.NOT_IMPORTANT);
                        }                               
                } else {
                        link.setWeight(TagCloudLinkImportance.IMPORTANT);
                }
                
                addTag(link);
        }
}
}

In this implementation of update() TagCloudLinkInternals are createad based on a list of tags and weighted according to the count of their associations.

The most interesting part of this code example is probably the definition of the JSF action associated with each TagCloudLinkInternal:

link.setAction("#{manageTagController.selectTagByParam}");

It is the same action for each tag, but since a UIParameter with the name of the respectiv tag is associated with each tag representation, it is possible to extract the selection:

public String selectTagByParam() {              
        FacesContext context = FacesContext.getCurrentInstance(); 
        Map map = context.getExternalContext().getRequestParameterMap();
        String name = (String) map.get(HtmlTagCloudRenderer.SELECTED_TAG_PARAM_NAME);   
        
        return selectTagByName(name);
}

Tagcloud model with Seam

When using JBoss Seam, it is possible to use a simpler way for selecting tags without using UIParameter. Due to Seam's enhancements of the Expression Language it is allowed to add method parameters directly into the specification of the associated JSF action.

In the case of the Tagcloud Component you are able to specify an action that takes a String as an argument and therefore provide the name of the tag immediately:

link.setAction("#{manageTagController.selectTagByName(\"" + tag.getName() + "\")}");

The method called by this action looks as following:

public String selectTagByName(String name) {
        TagManager tm = ServiceLocator.getTagManager();
        Tag t = tm.findTagByName(name);
        selectTag(t);
        return "manageTags";
}