You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@myfaces.apache.org by Blake Sullivan <bl...@oracle.com> on 2009/06/12 23:50:04 UTC

[TRINIDAD][API] JIRA_1504 Allow FlattenedComponent to render content

Currently components implementing the FlattenedComponent interface 
cannot render any content when flattening their children because while 
rendering can only occur once per component per request, flattening may 
occur multiple times during rendering since Renderers often make one or 
more passes over their children to collect information before making the 
rendering pass.  Unfortunately, there is currently no way for 
FlattenedComponents to distinguish the cases where flattening is 
occurring for the purposes of simple in-context child iteration from the 
cases where encoding will occur.  The proposal is to add apis to allow 
the FlattenedComponents to distinguish between these two cases.

To org.apache.myfaces.trinidad.component.ComponentProcessingContext

Add:

  /**
   * Hints to the the FlattenedComponents regarding what the flattened 
iteration is being used for,
   * The FlattenedComponent may use this information to change its 
flattening behavior.
   * For example, a FlattenedComponent may generate output during a 
<code>PROCESS_FOR_ENCODING</code>
   * iteration, but not during a normal iteration.
   */
  public enum ProcessingHint
  {
    /**
     * Indicates that the iteration is occurring in order to encode 
iterated components.  This
     * hint may only be used during the RenderResponse phase and only 
once per an iterated
     * component.  Due to these guarantees, the FlattenedComponent is 
allowed to generate
     * content during the iteration, an exception to the normal rule 
that iterations must
     * be idempotent in case the same component is iterated multiple times.
     */
    PROCESS_FOR_ENCODING
  }

  /**
   * <p>Returns hints that influence the behavior of the component 
processing</p>
   *
   * @return a non-empty, unmodifiable collection of ProcessingHints
   */
  public Set<ProcessingHint> getHints()
  {
    return _hints;
  }

To org.apache.myfaces.trinidad.component.UIXComponent

Add:

  /**
   * Helper function called by Renderers to encode a flattened view of a 
group of
   * potentially FlattenedComponent instances rooted at a single child 
of the component,
   * invoking the <code>childProcessor</code> with its
   * <code>callbackContext</code> on each renderable instance.  This 
method must  be called
   * when the childProcessor is actually encoding and the childProcessor 
must not attempt
   * to encode the same component instances more than once per request.
   * <p>
   * If a Renderer needs to
   * collect information about its possibly flattened children before 
calling
   * <code>encodeFlattenedChild(FacesContext, ComponentProcessor, 
UIComponent, Object)</code>,
   * it should call <code>processFlattenedChildren(FacesContext, 
ComponentProcessor, UIComponent, Object)</code>
   * to collect the information.
   * <p>
   * If the child is a FlattenedComponent, the 
<code>childProcessor</code> will
   * be called  on each of that FlattenedComponent's children, recursing 
if those children are
   * themselves FlattenedComponents, otherwise, the 
<code>childProcessor</code> will be called on
   * the child itself.
   * <p>
   * FlattenedComponents that wish to check whether they are processed 
for the purpose of
   * encoding can check the ProcessingHints of the 
ComponentProcessingContext for the
   * presence of <code>PROCESS_FOR_ENCODING hint</code>.
   * <p>
   * If the Renderer accidentally passes in the component to be encoded 
instead of one
   * of its children, the result will almost certainly be an infinite 
recursion and stack overflow.
   * @return <code>true</code> If any children were processed
   * @see UIXComponent#processFlattenedChildren(FacesContext, 
ComponentProcessor, UIComponent, Object)
   * @see FlattenedComponent
   */
  public static <S> boolean encodeFlattenedChild(
    FacesContext context,
    ComponentProcessor<S> childProcessor,
    UIComponent child,
    S callbackContext) throws IOException

  /**
   * Helper function called by Renderers to encode a flattened view of 
their children,
   * invoking the <code>childProcessor</code> with its
   * <code>callbackContext</code> on each renderable instance.  This 
method must  be called
   * when the childProcessor is actually encoding and the childProcessor 
must not attempt
   * to encode the same component instances more than once per request.
   * <p>
   * If a Renderer needs to
   * collect information about its possibly flattened children before 
calling
   * <code>encodeFlattenedChild(FacesContext, ComponentProcessor, 
Iterable<UIComponent>, Object)</code>,
   * it should call
   * <code>processFlattenedChildren(FacesContext, ComponentProcessor, 
Iterable<UIComponent>, Object)</code>
   * to collect the information.
   * <p>
   * For each FlattenedComponent child, the <code>childProcessor</code> will
   * be called on each of that FlattenedComponent's children, recursing 
if those children are
   * themselves FlattenedComponents, otherwise, the 
<code>childProcessor</code> will be called on
   * the child itself.
   * <p>
   * FlattenedComponents that wish to check whether they are processed 
for the purpose of
   * encoding can check the ProcessingHints of the 
ComponentProcessingContext for the
   * presence of <code>PROCESS_FOR_ENCODING hint</code>.
   * @return <code>true</code> If any children were processed
   * @see UIXComponent#processFlattenedChildren(FacesContext, 
ComponentProcessor, Iterable, Object)
   * @see FlattenedComponent
   */
  public static <S> boolean encodeFlattenedChildren(
    FacesContext context,
    ComponentProcessor<S> childProcessor,
    Iterable<UIComponent> children,
    S callbackContext) throws IOException

When encoding their flattened children, the Renderers call one of the 
two encoding methods on UIXComponent.  If a FlattenedComponent wishes to 
check whether its children are being flattened for the purpose of 
encoding, it can check 
ComponentProcessingContext.getHints().contains(ProcessingHint.PROCESS_FOR_ENCODING)

-- Blake Sullivan