Component Generator Framework

Document created by resplin Employee on Jun 6, 2015
Version 1Show Document
  • View in full screen mode

Obsolete Pages{{Obsolete}}

The official documentation is at: http://docs.alfresco.com



Web Client Customization


Introduction


1.3 introduced the Component Generator Framework, allowing custom controls to be provided in an extensible way.


Overview


The component generator framework consists of a managed bean which implements the IComponentGenerator interface. The bean can then be used to dynamically generate a JSF component. Being a managed bean the default component generators can be overridden with custom implementations and new generators can be added very easily.


IComponentGenerator interface


The definition of the IComponentGenerator interface is shown below:



public interface IComponentGenerator
{
   UIComponent generate(FacesContext context, String id);
   UIComponent generateAndAdd(FacesContext context, UIPropertySheet propertySheet,
         PropertySheetItem item);
}

The generate() method creates a plain vanilla JSF component it represents. For example, the TextField Generator will generate a UIInput component and set it's id to the one given. If an id is not supplied a unique id is generated (using the standard JSF algorithm).

The generateAndAdd() method however generates a component to represent the given property or association and incorporate it into the given property sheet component. The data dictionary definition of the property or association is used to determine what type of UI control to create. For example, if the item is a mandatory, multi-valued text property the TextFieldGenerator would generate a required field icon and a UIInput component wrapped in a UIMultiValueEditor component.

The latter method is obviously used solely by the PropertySheet component.


Retrieving a component generator


A component generator must first be defined as a managed bean. The definition of the TextFieldGenerator is shown below:



<managed-bean>
   <description>
      Bean that generates a text field component
   </description>
   <managed-bean-name>TextFieldGenerator</managed-bean-name>
   <managed-bean-class>org.alfresco.web.bean.generator.TextFieldGenerator</managed-bean-class>
   <managed-bean-scope>request</managed-bean-scope>
</managed-bean>

To retrieve an instance of the TextFieldGenerator use the static helper method on the FacesHelper class.



FacesHelper.getComponentGenerator(context, 'TextFieldGenerator');

If a request is made for a component generator that can not be found warnings will be output to the appserver console and an instance of a TextFieldGenerator returned. If the system fails to find a TextFieldGenerator a RuntimeException is thrown.


Implementing a component generator


There is a BaseComponentGenerator class that implements the IComponentGenerator interface and provides a default implementation of generateAndAdd().

Each component generator implementation has to implement the generate() in order to produce the default state component.

The generateAndAdd() method is structured in such a way to allow sub classes to easily pick and choose which areas they need to customise.

The default implementation of generateAndAdd() is shown below:



public UIComponent generateAndAdd(FacesContext context, UIPropertySheet propertySheet,
         PropertySheetItem item)
   {
      UIComponent component = null;
     
      if (item instanceof UIProperty)
      {
         // get the property definition
         PropertyDefinition propertyDef = getPropertyDefinition(context,
               propertySheet.getNode(), item.getName());

         // create the component and add it to the property sheet
         component = createComponent(context, propertySheet, item);
        
         // setup the component for multi value editing if necessary
         component = setupMultiValuePropertyIfNecessary(context, propertySheet,
               item, propertyDef, component);
        
         // setup common aspects of the property i.e. value binding
         setupProperty(context, propertySheet, item, propertyDef, component);
        
         // add the component now, it needs to be added before the validations
         // are setup as we need access to the component id, which in turn needs
         // to have a parent to get the correct id
         item.getChildren().add(component);
        
         // setup the component for mandatory validation if necessary
         setupMandatoryPropertyIfNecessary(context, propertySheet, item,
               propertyDef, component);
        
         // setup any constraints the property has
         setupConstraints(context, propertySheet, item, propertyDef, component);
        
         // setup any converter the property needs
         setupConverter(context, propertySheet, item, propertyDef, component);
      }
      else
      {
         // get the association definition
         AssociationDefinition assocationDef = this.getAssociationDefinition(context,
               propertySheet.getNode(), item.getName());
        
         // create the component and add it to the property sheet
         component = createComponent(context, propertySheet, item);
        
         // setup common aspects of the association i.e. value binding
         setupAssociation(context, propertySheet, item, assocationDef, component);
        
         // add the component now, it needs to be added before the validations
         // are setup as we need access to the component id, which needs have a
         // parent to get the correct id
         item.getChildren().add(component);
        
         // setup the component for mandatory validation if necessary
         setupMandatoryAssociationIfNecessary(context, propertySheet, item,
               assocationDef, component);
        
         // setup any converter the association needs
         setupConverter(context, propertySheet, item, assocationDef, component);
      }
     
      return component;
   }

The component generator framework also handles any constraints defined in the model so any custom component generators must support the various scenarios it could be places in. Take a look at the org.alfresco.web.bean.generator package for all the supplied component generators.


Goals


The goal is to use this framework across the web client where ever components are being dynamically generated. This allows one of the default generators to be customised and effect the whole client.

Currently, only the property sheet uses component generators, this will spread to the advanced search as well in a future release.

Attachments

    Outcomes