3.1.1.1. UI Extension components

UIExtensionManager

This class is used to manage all extensions available in the system. The target is to create the ability to add a new extension dynamically without changing anything in the source code. UIExtensionManager is implemented by UIExtensionManagerImpl.


<component>
  <key>org.exoplatform.webui.ext.UIExtensionManager</key>
  <type>org.exoplatform.webui.ext.impl.UIExtensionManagerImpl</type>
</component>

UIExtensionPlugin

This class allows you to define new extensions in the configuration file dynamically (for example: configuration.xml). As you want UIExtensionManager to manage every extension, you have to plug UIExtensionPlugin into it:


<external-component-plugins>
    <target-component>org.exoplatform.webui.ext.UIExtensionManager</target-component>
    <component-plugin>
      <name>add.action</name>
      <set-method>registerUIExtensionPlugin</set-method>
      <type>org.exoplatform.webui.ext.UIExtensionPlugin</type>
        ...
    </component-plugin>
</external-component-plugins>

Definition of UI Extensions

Each UI Extension is defined as an object param:


...
<object-param>
    <name>EditPage</name>
    <object type="org.exoplatform.webui.ext.UIExtension">
        <field name="type"><string>org.exoplatform.wiki.UIPageToolBar</string></field>
        <field name="rank"><int>300</int></field>
        <field name="name"><string>EditPage</string></field>
        <field name="component"><string>org.exoplatform.wiki.webui.control.action.EditPageActionComponent</string></field>
    </object>
 </object-param>
...

In which:

UI Extension Definition class

This class is used to define filters, actions and templates of each UI Extension:

@ComponentConfig(

  events =
{(listeners = EditPageActionComponent.EditPageActionListener.class);})
  public class EditPageActionComponent extends UIComponent {
  private static final List<UIExtensionFilter> FILTERS = Arrays.asList(new UIExtensionFilter[] { new IsViewModeFilter() });
  @UIExtensionFilters
   public List<UIExtensionFilter> getFilters() {
    return FILTERS;
}
  public static class EditPageActionListener extends UIPageToolBarActionListener<EditPageActionComponent> {
    @Override
    protected void processEvent(Event<EditPageActionComponent> event) throws Exception {
     ...
      super.processEvent(event);
    }
  }
...

Parent UI Component

This is what your UI Extension will be added to (in this example, the parent UI Componet is UIPageToolBar). All extensions of this component are got by UIExtensionManager.

UIExtensionManager manager = getApplicationComponent(UIExtensionManager.class);


List<UIExtension> extensions = manager.getUIExtensions(EXTENSION_TYPE);
 public List<ActionComponent> getActions() throws Exception {
    ....
    List<UIExtension> extensions = manager.getUIExtensions(EXTENSION_TYPE);
    if (extensions != null) {
      for (UIExtension extension : extensions) {
        UIComponent component = manager.addUIExtension(extension, context, this);
// Child UI Component has been made by UI Extension
// It's available to use now
        ...
      }
    }
    return activeActions;
  }

Internal filter

Each UI Extension has a list of filters depending on variety of purposes. It indicates which UI Extension is accepted and which is denied. You are free to create your own filter extended from UIExtensionAbstractFilter. Internal filters are part of the business logic of your component. For example, if your component is only dedicated to articles, you will add an internal filter to your component that will check the type of the current document.

public class IsViewModeFilter extends UIExtensionAbstractFilter {

   public IsViewModeFilter(String messageKey) {
    super(messageKey, UIExtensionFilterType.MANDATORY);
  }
  @Override
  public boolean accept(Map<String, Object> context) throws Exception {
    UIWikiPortlet wikiPortlet = (UIWikiPortlet) context.get(UIWikiPortlet.class.getName());
    return(wikiPortlet.getWikiMode() == WikiMode.VIEW||wikiPortlet.getWikiMode() == WikiMode.VIEWREVISION);
  }
  @Override
  public void onDeny(Map<String, Object> context) throws Exception {
    // TODO Auto-generated method stub
  }

Your filter will define which type of filter it belongs to (in UIExtensionFilterType). There are 4 types:

TypesDescription
MANDATORY Checks if the action related to the extension can be launched and if the component related to the extension can be added to the WebUI tree. This filter is required to launch the action and add the component related to the extension to the WebUI tree. If it succeeds, you need to check the other filters. If it fails, you need to stop.
REQUISITE Checks if the action related to the extension can be launched. This filter is required to launch the action to the WebUI tree. If it succeeds, you need to check the other filters. If it fails, you need to stop.
REQUIRED Checks if the action related to the extension can be launched and can be used for adding warnings. This filter is required to launch the action. If it succeeds or fails, you need to check the other filters.
OPTIONAL Checks if the action related to the extension can be launched and can be used for the auditing purpose. This filter is not required to launch the action. If it succeeds or fails, you need to check the other filters.

There are 2 conditions for filtering: Accept and onDeny.

You have known how and where the filter is put in a UI Component, but when it is gonna fire?

It falls into 2 situations: when you get it and when it is action fire. Thus, you should ensure that your UI Extension is always trapped by its filter.

External filter

External filters are mainly used to add new filters that are not related to the business logic to your component. A good example is the UserACLFilter which allows you to filter by access permissions.

For example, to make the EditPage action only be used by manager:/platform/administrators, do as follows:

public class UserACLFilter implements UIExtensionFilter {

  /**
   * The list of all access permissions allowed
   */
  protected List<String> permissions;
  /**
   * {@inheritDoc}
   */
  public boolean accept(Map<String, Object> context) throws Exception {
    if (permissions == null || permissions.isEmpty()) {
      return true;
    }
    ExoContainer container = ExoContainerContext.getCurrentContainer();
    UserACL userACL = (UserACL) container.getComponentInstance(UserACL.class);
    for (int i = 0, length = permissions.size(); i < length; i++) {
      String permission = permissions.get(i);
      if (userACL.hasPermission(permission)) {
        return true;
      }
    }
    return false;
  }
  /**
   * {@inheritDoc}
   */
  public UIExtensionFilterType getType() {
    return UIExtensionFilterType.MANDATORY;
  }
  /**
   * {@inheritDoc}
   */
  public void onDeny(Map<String, Object> context) throws Exception {}
}

<object-param>
  <name>EditPage</name>
  <object type="org.exoplatform.webui.ext.UIExtension">
    <field name="type"> <string>org.exoplatform.wiki.UIPageToolBar</string> </field>
 <field name="rank"><int>300</int></field>
    <field name="name"> <string>EditPage</string> </field>
    <field name="component"><string>org.exoplatform.wiki.webui.control.action.EditPageActionComponent</string> </field>
    <!-- The external filters -->
    <field name="extendedFilters">
      <collection type="java.util.ArrayList">
        <value>
          <object type="org.exoplatform.webui.ext.filter.impl.UserACLFilter">
            <field name="permissions">
              <collection type="java.util.ArrayList">
                <value>
                  <string>manager:/platform/administrators</string>
                </value>
              </collection>
            </field>
          </object>
        </value>
      </collection>
    </field>
  </object>
</object-param>
Copyright ©. All rights reserved. eXo Platform SAS
blog comments powered byDisqus