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 }