View Javadoc

1   // WARNING: This file was automatically generated. Do not edit it directly,
2   //          or you will lose your changes.
3   
4   /*
5    * Licensed to the Apache Software Foundation (ASF) under one
6    * or more contributor license agreements.  See the NOTICE file
7    * distributed with this work for additional information
8    * regarding copyright ownership.  The ASF licenses this file
9    * to you under the Apache License, Version 2.0 (the
10   * "License"); you may not use this file except in compliance
11   * with the License.  You may obtain a copy of the License at
12   *
13   *   http://www.apache.org/licenses/LICENSE-2.0
14   *
15   * Unless required by applicable law or agreed to in writing,
16   * software distributed under the License is distributed on an
17   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18   * KIND, either express or implied.  See the License for the
19   * specific language governing permissions and limitations
20   * under the License.
21  */
22  package org.apache.myfaces.trinidad.component;
23  
24  import javax.faces.FacesException;
25  import javax.faces.component.ContextCallback;
26  import javax.faces.component.NamingContainer;
27  import javax.faces.context.FacesContext;
28  import javax.faces.event.FacesEvent;
29  import javax.faces.event.PhaseId;
30  import org.apache.myfaces.trinidad.bean.FacesBean;
31  import org.apache.myfaces.trinidad.bean.PropertyKey;
32  import org.apache.myfaces.trinidad.util.ComponentUtils;
33  
34  /**
35   *
36   * UIXSubform is the base abstraction for an independently submittable
37   * region of a page.  The contents of a subform will only be validated
38   * (or otherwise processed) if a component inside of the subform is
39   * responsible for submitting the page.  This allows for comparatively
40   * fine-grained control of which components will be validated and pushed
41   * into the model without the compromises of using entirely separate form
42   * elements.  UIXSubform is a <html:code>NamingContainer</html:code> and
43   * therefore IDs can be reused between subforms.
44   * 
45   * <section name="Behavior of subforms">
46   * <html:p>
47   * A <html:code>UIXSubform</html:code> is considered &quot;submitted&quot; if an
48   * event is queued by one of its children or facets for a phase later
49   * than &quot;Apply Request Values&quot; (that is, for later than
50   * <html:code>decode()</html:code>).  The most common example is a
51   * (non-immediate) &quot;command&quot; component (like an &lt;h:commandButton&gt;
52   * or &lt;tr:commandButton&gt;).
53   * </html:p>
54   * <html:p>
55   * A <html:code>UIXSubform</html:code> will always allow the
56   * &quot;Apply Request Values&quot; phase to execute for its children,
57   * even when not &quot;submitted&quot;, but when not &quot;submitted&quot;, the
58   * &quot;Process Validations&quot; and &quot;Update Model Values&quot; phases will
59   * be skipped.  This differs from an ordinary form component,
60   * which, when not submitted, does not (and cannot) run
61   * &quot;Apply Request Values&quot; either.
62   * </html:p>
63   * </section>
64   * <section name="UIXSubform and &quot;default&quot;">
65   * <html:p>
66   * In some scenarios, there may be buttons (or other components
67   * that submit the page) outside of the main content of a page.  If
68   * this main content is in a UIXSubform, it could not be fully
69   * processed whenever those buttons are clicked, since those
70   * buttons aren't inside of the UIXSubform.  To support this
71   * scenario, Apache Trinidad supports a &quot;default&quot; property on
72   * UIXSubform.  A &quot;default&quot; subform behaves like any other
73   * subform in most respects, but if <html:em>no</html:em> subforms
74   * are &quot;submitted&quot; - if no subform has an appropriate event
75   * come from its children - then all &quot;default&quot; subforms act
76   * as if they are &quot;submitted&quot;.
77   * </html:p>
78   * </section>
79   *
80   * <h4>Events:</h4>
81   * <table border="1" width="100%" cellpadding="3" summary="">
82   * <tr bgcolor="#CCCCFF" class="TableHeadingColor">
83   * <th align="left">Type</th>
84   * <th align="left">Phases</th>
85   * <th align="left">Description</th>
86   * </tr>
87   * <tr class="TableRowColor">
88   * <td valign="top"><code>org.apache.myfaces.trinidad.event.AttributeChangeEvent</code></td>
89   * <td valign="top" nowrap>Invoke<br>Application<br>Apply<br>Request<br>Values</td>
90   * <td valign="top">Event delivered to describe an attribute change.  Attribute change events are not delivered for any programmatic change to a property.  They are only delivered when a renderer changes a property without the application's specific request.  An example of an attribute change event might include the width of a column that supported client-side resizing.</td>
91   * </tr>
92   * </table>
93   */
94  public class UIXSubform extends UIXComponentBase
95                          implements NamingContainer
96  {
97    static public final FacesBean.Type TYPE = new FacesBean.Type(
98      UIXComponentBase.TYPE);
99    static public final PropertyKey DEFAULT_KEY =
100     TYPE.registerKey("default", Boolean.class, Boolean.FALSE, PropertyKey.CAP_NOT_BOUND);
101 
102   static public final String COMPONENT_FAMILY =
103     "org.apache.myfaces.trinidad.Subform";
104   static public final String COMPONENT_TYPE =
105     "org.apache.myfaces.trinidad.Subform";
106 
107   /**
108    * Construct an instance of the UIXSubform.
109    */
110   public UIXSubform()
111   {
112     super("org.apache.myfaces.trinidad.Subform");
113   }
114   
115   @Override
116   public void queueEvent(FacesEvent event)
117   {
118     // If the event is being queued for anything *after* APPLY_REQUEST_VALUES,
119     // then this subform is active.
120     if (PhaseId.APPLY_REQUEST_VALUES.compareTo(event.getPhaseId()) < 0)
121     {
122       _storeSomethingSubmitted(FacesContext.getCurrentInstance());
123       setSubmitted(true);
124     }
125 
126     super.queueEvent(event);
127   }
128 
129   @Override
130   public void processDecodes(FacesContext context)
131   {
132     setSubmitted(false);
133     super.processDecodes(context);
134   }
135 
136   @Override
137   public void processValidators(FacesContext context)
138   {
139     boolean submitted = isSubmitted();
140 
141     if (!submitted && isDefault() && !_isSomethingSubmitted(context))
142     {
143     submitted = true;
144       setSubmitted(true);
145     }
146 
147     if (submitted)
148       super.processValidators(context);
149   }
150 
151   @Override
152   public void processUpdates(FacesContext context)
153   {
154     if (isSubmitted())
155       super.processUpdates(context);
156   }
157 
158 
159 
160 
161   @Override
162   public boolean invokeOnComponent(FacesContext context,
163                                    String clientId,
164                                    ContextCallback callback)
165     throws FacesException
166   {
167     // optimize case where clientId isn't in NamingContainer
168     return invokeOnNamingContainerComponent(context, clientId, callback);
169   }
170 
171   @SuppressWarnings("unchecked")
172   static private void _storeSomethingSubmitted(FacesContext context)
173   {
174     context.getExternalContext().getRequestMap().put(_SOMETHING_SUBMITTED,
175                                                      Boolean.TRUE);
176   }
177 
178   static private boolean _isSomethingSubmitted(FacesContext context)
179   {
180     return Boolean.TRUE.equals(context.getExternalContext().
181                                getRequestMap().get(_SOMETHING_SUBMITTED));
182   }
183 
184   /**
185    * Sets whether the subform was submitted on this request
186    *
187    * @param submitted  the new submitted value
188    */
189   final public void setSubmitted(boolean submitted)
190   {
191     String clientId = getClientId();
192     FacesContext.getCurrentInstance().getExternalContext().getRequestMap().put(
193                                                      _SUBMITTED_PREFIX + clientId,
194                                                      submitted ? Boolean.TRUE : Boolean.FALSE);
195   }
196 
197   /**
198    * Gets whether the subform was submitted on this request
199    *
200    * @return  the new submitted value
201    */
202   final public boolean isSubmitted()
203   {
204     String clientId = getClientId();
205     Object submitted = FacesContext.getCurrentInstance().getExternalContext().getRequestMap().get(
206                                                                      _SUBMITTED_PREFIX + clientId);
207     return ComponentUtils.resolveBoolean(submitted, false);
208   }
209 
210 
211   static private final String _SOMETHING_SUBMITTED =
212     "org.apache.myfaces.trinidad.component.UIXSubformSubmitted";
213   static private final String _SUBMITTED_PREFIX =
214     "org.apache.myfaces.trinidad.component.UIXSubform.";
215 
216  /**
217   * @deprecated submitted is request scope, and therefore will not be saved on the faces bean as a property
218   */
219   @Deprecated
220   static public final PropertyKey SUBMITTED_KEY =
221     TYPE.registerKey("submitted", Boolean.class, Boolean.FALSE, PropertyKey.CAP_NOT_BOUND | PropertyKey.CAP_TRANSIENT);
222 
223   /**
224    * Gets whether the subform should assume it
225    * has been submitted.  When set to "true", "submitted" will be
226    * considered true if no other subform has been submitted.
227    *
228    * @return  the new default value
229    */
230   final public boolean isDefault()
231   {
232     return ComponentUtils.resolveBoolean(getProperty(DEFAULT_KEY), false);
233   }
234 
235   /**
236    * Sets whether the subform should assume it
237    * has been submitted.  When set to "true", "submitted" will be
238    * considered true if no other subform has been submitted.
239    * 
240    * @param defaultParam  the new default value
241    */
242   final public void setDefault(boolean defaultParam)
243   {
244     setProperty(DEFAULT_KEY, defaultParam ? Boolean.TRUE : Boolean.FALSE);
245   }
246 
247   @Override
248   public String getFamily()
249   {
250     return COMPONENT_FAMILY;
251   }
252 
253   @Override
254   protected FacesBean.Type getBeanType()
255   {
256     return TYPE;
257   }
258 
259   /**
260    * Construct an instance of the UIXSubform.
261    */
262   protected UIXSubform(
263     String rendererType
264     )
265   {
266     super(rendererType);
267   }
268 
269   static
270   {
271     TYPE.lockAndRegister("org.apache.myfaces.trinidad.Subform","org.apache.myfaces.trinidad.Subform");
272   }
273 }