Class MarkupContainer

java.lang.Object
org.apache.wicket.Component
org.apache.wicket.MarkupContainer
All Implemented Interfaces:
Serializable, Iterable<Component>, IEventSink, IEventSource, IFeedbackContributor, IConverterLocator, IMetadataContext<Serializable,Component>, IHeaderContributor, IRequestableComponent, IHierarchical<Component>, IClusterable
Direct Known Subclasses:
AbstractOutputTransformerContainer, Page, WebMarkupContainer

public abstract class MarkupContainer extends Component implements Iterable<Component>
A MarkupContainer holds a map of child components.
  • Children - Children can be added by calling the add(Component...) method, and they can be looked up using a colon separated path. For example, if a container called "a" held a nested container "b" which held a nested component "c", then a.get("b:c") would return the Component with id "c". The number of children in a MarkupContainer can be determined by calling size(), and the whole hierarchy of children held by a MarkupContainer can be traversed by calling visitChildren(), passing in an implementation of IVisitor.
  • Markup Rendering - A MarkupContainer also holds/references associated markup which is used to render the container. As the markup stream for a container is rendered, component references in the markup are resolved by using the container to look up Components in the container's component map by id. Each component referenced by the markup stream is given an opportunity to render itself using the markup stream.

Components may alter their referring tag, replace the tag's body or insert markup after the tag. But components cannot remove tags from the markup stream. This is an important guarantee because graphic designers may be setting attributes on component tags that affect visual presentation.

The type of markup held in a given container subclass can be determined by calling getMarkupType(). Markup is accessed via a MarkupStream object which allows a component to traverse ComponentTag and RawMarkup MarkupElements while rendering a response. Markup in the stream may be HTML or some other kind of markup, such as VXML, as determined by the specific container subclass.

A markup stream may be directly associated with a container via setMarkupStream. However, a container which does not have a markup stream (its getMarkupStream() returns null) may inherit a markup stream from a container above it in the component hierarchy. The Component.findMarkupStream() method will locate the first container at or above this container which has a markup stream.

All Page containers set a markup stream before rendering by calling the method getAssociatedMarkupStream(boolean) to load the markup associated with the page. Since Page is at the top of the container hierarchy, it is guaranteed that Component.findMarkupStream() will always return a valid markup stream.

Author:
Jonathan Locke
See Also:
  • Constructor Details

  • Method Details

    • add

      public MarkupContainer add(Component... children)
      Adds the child component(s) to this container.
      Parameters:
      children - The child(ren) to add.
      Returns:
      This
      Throws:
      IllegalArgumentException - Thrown if a child with the same id is replaced by the add operation.
    • addOrReplace

      public MarkupContainer addOrReplace(Component... children)
      Replaces a child component of this container with another or just adds it in case no child with the same id existed yet.
      Parameters:
      children - The child(ren) to be added or replaced
      Returns:
      this markup container
    • autoAdd

      public final boolean autoAdd(Component component, MarkupStream markupStream)
      This method allows a component to be added by an auto-resolver such as AutoLinkResolver. While the component is being added, the component's FLAG_AUTO boolean is set. The isAuto() method of Component returns true if a component or any of its parents has this bit set. When a component is added via autoAdd(), the logic in Page that normally (a) checks for modifications during the rendering process, and (b) versions components, is bypassed if Component.isAuto() returns true.

      The result of all this is that components added with autoAdd() are free from versioning and can add their own children without the usual exception that would normally be thrown when the component hierarchy is modified during rendering.

      Parameters:
      component - The component to add
      markupStream - Null, if the parent container is able to provide the markup. Else the markup stream to be used to render the component.
      Returns:
      True, if component has been added
    • contains

      public boolean contains(Component component, boolean recurse)
      Parameters:
      component - The component to check
      recurse - True if all descendents should be considered
      Returns:
      True if the component is contained in this container
    • get

      public final Component get(String path)
      Get a child component by looking it up with the given path.

      A component path consists of component ids separated by colons, e.g. "b:c" identifies a component "c" inside container "b" inside this container.

      Specified by:
      get in interface IRequestableComponent
      Overrides:
      get in class Component
      Parameters:
      path - path to component
      Returns:
      The component at the path
    • getAssociatedMarkupStream

      public MarkupStream getAssociatedMarkupStream(boolean throwException)
      Gets a fresh markup stream that contains the (immutable) markup resource for this class.
      Parameters:
      throwException - If true, throw an exception, if markup could not be found
      Returns:
      A stream of MarkupElement elements
    • getAssociatedMarkup

      Gets a fresh markup stream that contains the (immutable) markup resource for this class.
      Returns:
      A stream of MarkupElement elements. Null if not found.
    • getMarkup

      Get the markup of the child.
      Parameters:
      child - The child component. If null, the container's markup will be returned. See Border, Panel or Enclosure where getMarkup(null) != getMarkup().
      Returns:
      The child's markup
      See Also:
    • getMarkupType

      Get the type of associated markup for this component. The markup type for a component is independent of whether or not the component actually has an associated markup resource file (which is determined at runtime).
      Returns:
      The type of associated markup for this component (for example, "html", "wml" or "vxml"). If there is no markup type for a component, null may be returned, but this means that no markup can be loaded for the class. Null is also returned if the component, or any of its parents, has not been added to a Page.
    • internalAdd

      public void internalAdd(Component child)
      THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT USE IT. Adds a child component to this container.
      Parameters:
      child - The child
      Throws:
      IllegalArgumentException - Thrown if a child with the same id is replaced by the add operation.
    • iterator

      Gives an iterator that allow you to iterate through the children of this markup container in the order the children were added. The iterator supports additions and removals from the list of children during iteration.
      Specified by:
      iterator in interface Iterable<Component>
      Returns:
      Iterator that iterates through children in the order they were added
    • iterator

      public final Iterator<Component> iterator(Comparator<Component> comparator)
      Creates an iterator that iterates over children in the order specified by comparator. This works on a copy of the children list.
      Parameters:
      comparator - The comparator
      Returns:
      Iterator that iterates over children in the order specified by comparator
    • remove

      public MarkupContainer remove(Component component)
      Removes a component from the children identified by the component.getId()
      Parameters:
      component - Component to remove from this container
      Returns:
      this for chaining
    • remove

      Removes the given component
      Parameters:
      id - The id of the component to remove
      Returns:
      this for chaining
    • removeAll

      Removes all children from this container.

      Note: implementation does not call remove(Component) for each component.

      Returns:
      this for method chaining
    • renderAssociatedMarkup

      public final void renderAssociatedMarkup(String openTagName)
      Renders the entire associated markup for a container such as a Border or Panel. Any leading or trailing raw markup in the associated markup is skipped.
      Parameters:
      openTagName - the tag to render the associated markup for
    • replace

      Replaces a child component of this container with another
      Parameters:
      child - The child
      Returns:
      This
      Throws:
      IllegalArgumentException - Thrown if there was no child with the same id.
    • setDefaultModel

      Description copied from class: Component
      Sets the given model.

      WARNING: DO NOT OVERRIDE THIS METHOD UNLESS YOU HAVE A VERY GOOD REASON FOR IT. OVERRIDING THIS MIGHT OPEN UP SECURITY LEAKS AND BREAK BACK-BUTTON SUPPORT.

      Overrides:
      setDefaultModel in class Component
      Parameters:
      model - The model
      Returns:
      This
    • size

      public int size()
      Get the number of children in this container.
      Returns:
      Number of children in this container
    • toString

      public String toString()
      Description copied from class: Component
      Gets the string representation of this component.
      Overrides:
      toString in class Component
      Returns:
      The path to this component
    • toString

      public String toString(boolean detailed)
      Overrides:
      toString in class Component
      Parameters:
      detailed - True if a detailed string is desired
      Returns:
      String representation of this container
    • visitChildren

      public final <S extends Component, R> R visitChildren(Class<?> clazz, IVisitor<S,R> visitor)
      Traverses all child components of the given class in this container, calling the visitor's visit method at each one. Make sure that if you give a type S that the clazz parameter will only resolve to those types. Else a class cast exception will occur.
      Type Parameters:
      S - The type that goes into the Visitor.component() method.
      R -
      Parameters:
      clazz - The class of child to visit
      visitor - The visitor to call back to
      Returns:
      The return value from a visitor which halted the traversal, or null if the entire traversal occurred
    • visitChildren

      public final <R> R visitChildren(IVisitor<Component,R> visitor)
      Traverses all child components in this container, calling the visitor's visit method at each one.
      Type Parameters:
      R -
      Parameters:
      visitor - The visitor to call back to
      Returns:
      The return value from a visitor which halted the traversal, or null if the entire traversal occurred
    • internalInitialize

      public final void internalInitialize()
      THIS METHOD IS NOT PART OF THE PUBLIC API, DO NOT CALL IT Overrides Component.internalInitialize() to call Component.fireInitialize() for itself and for all its children.
      Overrides:
      internalInitialize in class Component
      See Also:
      • Component.fireInitialize()
    • renderNext

      protected boolean renderNext(MarkupStream markupStream)
      THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT USE OR OVERWRITE IT. Renders the next element of markup in the given markup stream.
      Parameters:
      markupStream - The markup stream
      Returns:
      true, if element was rendered as RawMarkup
    • onComponentTagBody

      public void onComponentTagBody(MarkupStream markupStream, ComponentTag openTag)
      Handle the container's body. If your override of this method does not advance the markup stream to the close tag for the openTag, a runtime exception will be thrown by the framework.
      Overrides:
      onComponentTagBody in class Component
      Parameters:
      markupStream - The markup stream
      openTag - The open tag for the body
    • onRender

      protected void onRender()
      Description copied from class: Component
      Implementation that renders this component.
      Specified by:
      onRender in class Component
    • renderAll

      protected final void renderAll(MarkupStream markupStream, ComponentTag openTag)
      Loop through the markup in this container
      Parameters:
      markupStream -
      openTag -
    • onDetach

      protected void onDetach()
      Description copied from class: Component
      Called to allow a component to detach resources after use. Overrides of this method MUST call the super implementation, the most logical place to do this is the last line of the override method.
      Overrides:
      onDetach in class Component
    • queue

      public MarkupContainer queue(Component... components)
      Queues one or more components to be dequeued later. The advantage of this method over the add(Component...) method is that the component does not have to be added to its direct parent, only to a parent upstream; it will be dequeued into the correct parent using the hierarchy defined in the markup. This allows the component hierarchy to be maintained only in markup instead of in markup and in java code; affording designers and developers more freedom when moving components in markup.
      Parameters:
      components - the components to queue
      Returns:
      this for method chaining
    • dequeue

      public void dequeue()
      See Also:
    • onInitialize

      protected void onInitialize()
      Description copied from class: Component
      This method is meant to be used as an alternative to initialize components. Usually the component's constructor is used for this task, but sometimes a component cannot be initialized in isolation, it may need to access its parent component or its markup in order to fully initialize. This method is invoked once per component's lifecycle when a path exists from this component to the Page thus providing the component with an atomic callback when the component's environment is built out.

      Overrides must call super#Component.onInitialize(). Usually this should be the first thing an override does, much like a constructor.

      Parent containers are guaranteed to be initialized before their children

      It is safe to use Component.getPage() in this method

      NOTE:The timing of this call is not precise, the contract is that it is called sometime before Component.onBeforeRender().

      Overrides:
      onInitialize in class Component
    • dequeuePreamble

      protected void dequeuePreamble(DequeueContext dequeue)
      Run preliminary operations before running dequeue(DequeueContext). More in detail it throws an exception if the container is already dequeuing, and it also takes care of setting flag RFLAG_CONTAINER_DEQUEING to true before running dequeue(DequeueContext) and setting it back to false after dequeuing is completed.
      Parameters:
      dequeue - the dequeue context to use
    • dequeue

      public void dequeue(DequeueContext dequeue)
      Dequeues components. The default implementation iterates direct children of this container found in its markup and tries to find matching components in queues filled by a call to queue(Component...). It then delegates the dequeueing to these children. Certain components that implement custom markup behaviors (such as repeaters and borders) override this method to bring dequeueing in line with their custom markup handling.
      Parameters:
      dequeue - the dequeue context to use
    • findChildComponent

      Search the child component for the given tag.
      Parameters:
      tag - the component tag
      Returns:
      the child component for the given tag or null if no child can not be found.
    • newDequeueContext

      See Also:
    • getRegionMarkup

      See Also:
    • canDequeueTag

      Checks if this container can dequeue a child represented by the specified tag. This method should be overridden when containers can dequeue components represented by non-standard tags. For example, borders override this method and dequeue their body container when processing the body tag. By default all ComponentTags are supported as well as WicketTags that return a non-null value from ComponentTag.getAutoComponentFactory() method.
      Parameters:
      tag -
    • findComponentToDequeue

      Queries this container to find a child that can be dequeued that matches the specified tag. The default implementation will check if there is a component in the queue that has the same id as a tag, but sometimes custom tags can be dequeued and in those situations this method should be overridden.
      Parameters:
      tag -
      Returns:
    • addDequeuedComponent

      protected void addDequeuedComponent(Component component, ComponentTag tag)
      Adds a dequeued component to this container. This method should rarely be overridden because the common case of simply forwarding the component to add(Component...) method should cover most cases. Components that implement a custom hierarchy, such as borders, may wish to override it to support edge-case non-standard behavior.
      Parameters:
      component -
      tag -
    • stream

      public Stream<Component> stream()
      Returns a sequential Stream with the direct children of this markup container as its source. This stream doesn't traverse the component tree.
      Returns:
      a sequential Stream over the direct children of this markup container
      Since:
      8.0
    • streamChildren

      Returns a sequential Stream with the all children of this markup container as its source. This stream does traverse the component tree.
      Returns:
      a sequential Stream over the all children of this markup container
      Since:
      8.0