Package org.zkoss.zk.ui.util

## Class Composition

- java.lang.Object
- - org.zkoss.zk.ui.util.Composition

- All Implemented Interfaces:
    `Initiator`, `InitiatorExt`

      public class Composition
      extends java.lang.Object
      implements Initiator, InitiatorExt

  Composition manager that compose the given components into a whole page per the "insert" components and "define" components annotations. The "define" components will attach itself on to the "insert" component with the same annotated joinId. That is, the "insert" component is the parent component of the "define" components with the same annotated joinId. Note that "insert" components can NOT have duplicate joinId in a page while "define" components can because you can have multiple child components but you cannot have multiple parent components. Also note that a "define" components must be a root component of the page.

  This Composition manager is useful when you need to do layout injection or you want to design a common page template across multiple pages.

  - You first design a template with "insert" components telling where the insert points are. Each insert component has to be given a distinguish joinId in a page(e.g. <window self="@{insert(content)}"/> here the "content" is the joinId).
  - Then in the real page, you have root "define" components telling which "define" components are to be attach onto the "insert" component with the same joinId (e.g. <label self="@{define(content)}"; here the "content" is the joinId).
  - This Composition class is designed as a page `Initiator` and a `InitiatorExt`, so you have to specify in the real page as following to use it.

         <?init class="org.zkoss.zk.ui.util.Composition" [arg0="TEMPLATE1"[, arg1="TEMPLATE2"]...]?>
         ...

    Where the arg0 ~ argx you can give zul template uri. This implementation use Excecutions.createComponents() to create them and then do the real composition in the `InitiatorExt.doAfterCompose(Page, Component[])`.
  - If more than one "define" components have the same joinId, they are attached onto the "insert" component in the sequence of the definition.
  - If a "define" component cannot find the corresponding "insert" component, it will be simply detached from the page.
  - Also you can prepare a parent component and pass it in via Execution.getCurrent().setAttribute(Composition.PARENT, parent) then this implementation will attach finally composed root components as the children of the provided parent.
  - If you did not provide the parent component, the finally composed root components are attached directly to the current page.
  Since:
    3.5.2
  Author:
    henrichen

- - ### Field Summary

    Fields
    Modifier and Type | Field | Description
    --- | --- | ---
    `static java.lang.String` | `PARENT` |

  - ### Constructor Summary

    Constructors
    Constructor | Description
    --- | ---
    `Composition()` |

  - ### Method Summary

    All Methods Instance Methods Concrete Methods
    Modifier and Type | Method | Description
    --- | --- | ---
    `void` | `doAfterCompose​(Page page, Component[] comps)` | Called after all components are created (a.k.a., composed), and before any event is processed.
    `boolean` | `doCatch​(java.lang.Throwable ex)` | Called when an exception occurs during the evaluation of the page.
    `void` | `doFinally()` | Do the cleanup after the page has been evaluated.
    `void` | `doInit​(Page page, java.util.Map<java.lang.String,​java.lang.Object> args)` | Does the initializes before the page is evaluated.

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Field Detail

    - #### PARENT

          public static final java.lang.String PARENT

      See Also:
        Constant Field Values

  - ### Constructor Detail

    - #### Composition

          public Composition()

  - ### Method Detail

    - #### doCatch

          public boolean doCatch​(java.lang.Throwable ex)
                          throws java.lang.Exception

      Description copied from interface: `InitiatorExt`
      Called when an exception occurs during the evaluation of the page.

      If you don't want to handle the exception, simply returns false. `boolean doCatch(Throwable ex) {return false;}`

      An exception thrown in this method is simply logged. It has no effect on the execution. If you want to ignore the exception, just return true.

      Notice: this method won't be called if the exception occurs in `Initiator.doInit(org.zkoss.zk.ui.Page, java.util.Map<java.lang.String, java.lang.Object>)`.

      Specified by:
        `doCatch` in interface `InitiatorExt`
      Parameters:
        `ex` - the exception being thrown
      Returns:
        whether to ignore the exception. If false is returned, the exception will be re-thrown. Note: once an initiator's doCatch returns true, the exception will be ignored and it means doCatch of the following initiators won't be called. Prior to ZK 3.0.0, void is returned and it means always re-thrown
      Throws:
        `java.lang.Exception`

    - #### doFinally

          public void doFinally()
                         throws java.lang.Exception

      Description copied from interface: `InitiatorExt`
      Do the cleanup after the page has been evaluated. It won't be called if `Initiator.doInit(org.zkoss.zk.ui.Page, java.util.Map<java.lang.String, java.lang.Object>)` throws an exception. However,it is always called no matter whether `InitiatorExt.doCatch(java.lang.Throwable)` is called.

      An exception thrown in this method is simply logged. It has no effect on the execution.

      Specified by:
        `doFinally` in interface `InitiatorExt`
      Throws:
        `java.lang.Exception`

    - #### doInit

          public void doInit​(Page page,
                             java.util.Map<java.lang.String,​java.lang.Object> args)
                      throws java.lang.Exception

      Description copied from interface: `Initiator`
      Does the initializes before the page is evaluated.

      Note: when it is called, `Page.getDesktop()`, `Page.getId()` and `Page.getTitle()` all return null, since the page is not initialized yet. To get the current desktop, you have to use `Execution.getDesktop()` (from `Executions.getCurrent()`) instead. On the other hand, you can set the page's ID, title or style in this method (to override the declarations in the page definition) by `Page.setId(java.lang.String)`, `Page.setTitle(java.lang.String)` and `Page.setStyle(java.lang.String)`. In additions, `Page.getRequestPath()` and `Page.getAttribute(java.lang.String, int)` are all available.

      Specified by:
        `doInit` in interface `Initiator`
      Parameters:
        `page` - the page being evaluated
        `args` - a map of arguments. Prior to 3.6.2, it is an array. To upgrade, use args.get("arg0") instead of args[0], args.get("arg1") instead of args[1] and so on. Of course, it is better to have a more meaningful name for each argument. If no argument is specified, args is an empty map (never null).
      Throws:
        `java.lang.Exception`

    - #### doAfterCompose

          public void doAfterCompose​(Page page,
                                     Component[] comps)
                              throws java.lang.Exception

      Description copied from interface: `InitiatorExt`
      Called after all components are created (a.k.a., composed), and before any event is processed.

      It won't be called if an un-caught exception occurs when creating components.

      Specified by:
        `doAfterCompose` in interface `InitiatorExt`
      Parameters:
        `page` - the page that new components are attached to. It is the same as `Initiator.doInit(org.zkoss.zk.ui.Page, java.util.Map<java.lang.String, java.lang.Object>)`'s page argument.
        `comps` - the root components being created (never null, but the length might be zero). Note: It is not necessary the same as `Page.getRoots()`, since this method might be called thru `Executions.createComponents(java.lang.String, org.zkoss.zk.ui.Component, java.util.Map<?, ?>)`.
      Throws:
        `java.lang.Exception`