View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.trinidad.component;
20  
21  import java.util.Collections;
22  import java.util.Set;
23  
24  /**
25   * ProcessingContext passed to FlattenedComponents and ComponentProcessors representing the
26   * current component iteration context.
27   * @see ComponentProcessor
28   * @see UIXComponent#processFlattenedChildren(FacesContext, ComponentProcessor, UIComponent, Object)
29   * @see UIXComponent#processFlattenedChildren(FacesContext, ComponentProcessor, Iterable, Object)
30   * @see UIXComponent#processFlattenedChildren(FacesContext, ComponentProcessingContext, ComponentProcessor, UIComponent, Object)
31   * @see UIXComponent#processFlattenedChildren(FacesContext, ComponentProcessingContext, ComponentProcessor, Iterable, Object)
32   * @see FlattenedComponent
33   */
34  public final class ComponentProcessingContext
35  {
36    ComponentProcessingContext()
37    {      
38    }
39  
40    /**
41     * Hints to the the FlattenedComponents regarding what the flattened iteration is being used for,
42     * The FlattenedComponent may use this information to change its flattening behavior.
43     * For example, a FlattenedComponent may generate output during a <code>PROCESS_FOR_ENCODING</code>
44     * iteration, but not during a normal iteration.
45     */
46    public enum ProcessingHint
47    {
48      /**
49       * Indicates that the iteration is occurring in order to encode iterated components.  This
50       * hint may only be used during the RenderResponse phase and only once per an iterated
51       * component.  Due to these guarantees, the FlattenedComponent is allowed to generate
52       * content during the iteration, an exception to the normal rule that iterations must
53       * be idempotent in case the same component is iterated multiple times.
54       */
55      PROCESS_FOR_ENCODING
56    }
57    
58    /**
59     * Returns the current starting group depth of the ProcessingContext.  The starting depth is only
60     * non-zero for the first rendered child inside a group or nested groups.  If two grouping
61     * components, such as UIXGroup, are nested immediately inside of each other, the first processed
62     * component in the second UIXGroup will see 2 for the start depth.  The second would see 0.
63     * @see #getGroupDepth
64     */
65    public int getStartDepth()
66    {
67      return _startDepth;
68    }
69    
70    /**
71     * Returns the current group depth of the ProcessingContext.  The group depth is equal to the
72     * nesting depth of grouping components, such as UIXGroup that the current iteratior has
73     * entered.  In contrast to <code>getStartDepth()</code>, all siblings at a particular nesting
74     * level see the same group depth.
75     * @see #getStartDepth
76     */
77    public int getGroupDepth()
78    {
79      return _groupDepth;
80    }
81  
82    /**
83     * <p>Returns hints that influence the behavior of the component processing</p>
84     *
85     * @return a non-empty, unmodifiable collection of ProcessingHints
86     */
87    public Set<ProcessingHint> getHints()
88    {
89      return _hints;
90    }
91  
92    /**
93     * Increment the grouping and startGroup states.
94     * <p>
95     * If pushGroup is called, the seubsequent code should be
96     * wrapped in a <code>try{}finally{ComponentProcessingContext.popGroup()} block to guarantee
97     * that the group is popped correctly in case an exception is thrown.
98     * @see #popGroup
99     */
100   void pushGroup()
101   {
102     _startDepth++;
103     _groupDepth++;
104   }
105   
106   /**
107    * Decrement the grouping and startGroup states.
108    * <p>
109    * If pushGroup is called, the seubsequent code should be
110    * wrapped in a <code>try{}finally{ComponentProcessingContext.popGroup()} block to guarantee
111    * that the group is popped correctly in case an exception is thrown.
112    * @see #pushGroup
113    */
114   void popGroup()
115   {
116     _groupDepth--;
117     
118     if (_startDepth > 0)
119       _startDepth--;
120   }
121   
122   /**
123    * Called by the object performing the iteration over Component instances to 
124    * reset the start depth after the ChildProcessor is called on the first component at the
125    * new depth.  When iterating, the iterator should place the call to <code>resetStartDepth</code>
126    * in a <code>finally</code> block to guarantee that the reset happens correctly in case
127    * an exception is thrown.
128    */
129   void resetStartDepth()
130   {
131     _startDepth = 0;
132   }
133   
134   /**
135    * Handshake from the UIXComponent
136    */
137   void __setIsRendering()
138   {
139     _hints = Collections.singleton(ProcessingHint.PROCESS_FOR_ENCODING);
140   }
141 
142   private int _startDepth;
143   private int _groupDepth;
144   private Set<ProcessingHint> _hints = Collections.emptySet();
145 }