1 /*
2 * $Id: UIForm.java,v 1.52.4.2 2008/02/22 01:46:40 rlubke Exp $
3 */
4
5 /*
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
7 *
8 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
9 *
10 * The contents of this file are subject to the terms of either the GNU
11 * General Public License Version 2 only ("GPL") or the Common Development
12 * and Distribution License("CDDL") (collectively, the "License"). You
13 * may not use this file except in compliance with the License. You can obtain
14 * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
15 * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
16 * language governing permissions and limitations under the License.
17 *
18 * When distributing the software, include this License Header Notice in each
19 * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
20 * Sun designates this particular file as subject to the "Classpath" exception
21 * as provided by Sun in the GPL Version 2 section of the License file that
22 * accompanied this code. If applicable, add the following below the License
23 * Header, with the fields enclosed by brackets [] replaced by your own
24 * identifying information: "Portions Copyrighted [year]
25 * [name of copyright owner]"
26 *
27 * Contributor(s):
28 *
29 * If you wish your version of this file to be governed by only the CDDL or
30 * only the GPL Version 2, indicate your decision by adding "[Contributor]
31 * elects to include this software in this distribution under the [CDDL or GPL
32 * Version 2] license." If you don't indicate a single choice of license, a
33 * recipient has the option to distribute your version of this file under
34 * either the CDDL, the GPL Version 2 or to extend the choice of license to
35 * its licensees as provided above. However, if you add GPL Version 2 code
36 * and therefore, elected the GPL Version 2 license, then the option applies
37 * only if the new code is made subject to such option by the copyright
38 * holder.
39 */
40
41 package javax.faces.component;
42
43
44 import java.util.Iterator;
45 import javax.el.ELException;
46 import javax.el.ValueExpression;
47 import javax.faces.FacesException;
48 import javax.faces.context.FacesContext;
49
50
51 /**
52 * <p><strong>UIForm</strong> is a {@link UIComponent} that represents an
53 * input form to be presented to the user, and whose child components represent
54 * (among other things) the input fields to be included when the form is
55 * submitted.</p>
56 *
57 * <p>By default, the <code>rendererType</code> property must be set to
58 * "<code>javax.faces.Form</code>". This value can be changed by calling the
59 * <code>setRendererType()</code> method.</p>
60 */
61
62 public class UIForm extends UIComponentBase implements NamingContainer {
63
64
65 // ------------------------------------------------------ Manifest Constants
66
67
68 /**
69 * <p>The standard component type for this component.</p>
70 */
71 public static final String COMPONENT_TYPE = "javax.faces.Form";
72
73
74 /**
75 * <p>The standard component family for this component.</p>
76 */
77 public static final String COMPONENT_FAMILY = "javax.faces.Form";
78
79
80 // ------------------------------------------------------------ Constructors
81
82
83 /**
84 * <p>Create a new {@link UIForm} instance with default property
85 * values.</p>
86 */
87 public UIForm() {
88
89 super();
90 setRendererType("javax.faces.Form");
91
92 }
93
94
95 // ------------------------------------------------------ Instance Variables
96
97
98 // -------------------------------------------------------------- Properties
99
100
101 public String getFamily() {
102
103 return (COMPONENT_FAMILY);
104
105 }
106
107
108 /**
109 * <p>The form submitted flag for this {@link UIForm}.</p>
110 */
111 private boolean submitted = false;
112
113
114 /**
115 * <p>Returns the current value of the <code>submitted</code>
116 * property. The default value is <code>false</code>. See {@link
117 * #setSubmitted} for details.</p>
118 *
119 */
120 public boolean isSubmitted() {
121
122 return (this.submitted);
123
124 }
125
126
127 /**
128 * <p>If <strong>this</strong> <code>UIForm</code> instance (as
129 * opposed to other forms in the page) is experiencing a submit
130 * during this request processing lifecycle, this method must be
131 * called, with <code>true</code> as the argument, during the {@link
132 * UIComponent#decode} for this <code>UIForm</code> instance. If
133 * <strong>this</strong> <code>UIForm</code> instance is
134 * <strong>not</strong> experiencing a submit, this method must be
135 * called, with <code>false</code> as the argument, during the
136 * {@link UIComponent#decode} for this <code>UIForm</code>
137 * instance.</p>
138 *
139 * <p>The value of a <code>UIForm</code>'s submitted property must
140 * not be saved as part of its state.</p>
141 */
142 public void setSubmitted(boolean submitted) {
143
144 this.submitted = submitted;
145
146 }
147
148 /**
149 * <p>The prependId flag.</p>
150 */
151 private Boolean prependId;
152
153
154 public boolean isPrependId() {
155
156 if (this.prependId != null) {
157 return (this.prependId);
158 }
159 ValueExpression ve = getValueExpression("prependId");
160 if (ve != null) {
161 try {
162 return (Boolean.TRUE.equals(ve.getValue(getFacesContext().getELContext())));
163 }
164 catch (ELException e) {
165 throw new FacesException(e);
166 }
167 } else {
168 return (true);
169 }
170
171 }
172
173
174 public void setPrependId(boolean prependId) {
175
176 this.prependId = prependId;
177
178 }
179
180 // ----------------------------------------------------- UIComponent Methods
181
182
183 /**
184 * <p>Override {@link UIComponent#processDecodes} to ensure that the
185 * form is decoded <strong>before</strong> its children. This is
186 * necessary to allow the <code>submitted</code> property to be
187 * correctly set.</p>
188 *
189 * @throws NullPointerException {@inheritDoc}
190 */
191 public void processDecodes(FacesContext context) {
192
193 if (context == null) {
194 throw new NullPointerException();
195 }
196
197 // Process this component itself
198 decode(context);
199
200 // if we're not the submitted form, don't process children.
201 if (!isSubmitted()) {
202 return;
203 }
204
205 // Process all facets and children of this component
206 Iterator kids = getFacetsAndChildren();
207 while (kids.hasNext()) {
208 UIComponent kid = (UIComponent) kids.next();
209 kid.processDecodes(context);
210 }
211
212 }
213
214
215 /**
216 * <p>Override {@link UIComponent#processValidators} to ensure that
217 * the children of this <code>UIForm</code> instance are only
218 * processed if {@link #isSubmitted} returns <code>true</code>.</p>
219 *
220 * @throws NullPointerException {@inheritDoc}
221 */
222 public void processValidators(FacesContext context) {
223
224 if (context == null) {
225 throw new NullPointerException();
226 }
227 if (!isSubmitted()) {
228 return;
229 }
230
231 // Process all the facets and children of this component
232 Iterator kids = getFacetsAndChildren();
233 while (kids.hasNext()) {
234 UIComponent kid = (UIComponent) kids.next();
235 kid.processValidators(context);
236 }
237
238 }
239
240
241 /**
242 * <p>Override {@link UIComponent#processUpdates} to ensure that the
243 * children of this <code>UIForm</code> instance are only processed
244 * if {@link #isSubmitted} returns <code>true</code>.</p>
245 *
246 * @throws NullPointerException {@inheritDoc}
247 */
248 public void processUpdates(FacesContext context) {
249
250 if (context == null) {
251 throw new NullPointerException();
252 }
253 if (!isSubmitted()) {
254 return;
255 }
256
257 // Process all facets and children of this component
258 Iterator kids = getFacetsAndChildren();
259 while (kids.hasNext()) {
260 UIComponent kid = (UIComponent) kids.next();
261 kid.processUpdates(context);
262 }
263
264 }
265
266
267 /**
268 * <p>Override the {@link UIComponent#getContainerClientId} to allow
269 * users to disable this form from prepending its <code>clientId</code> to
270 * its descendent's <code>clientIds</code> depending on the value of
271 * this form's {@link #isPrependId} property.</p>
272 */
273 public String getContainerClientId(FacesContext context) {
274 if (this.isPrependId()) {
275 return super.getContainerClientId(context);
276 } else {
277 UIComponent parent = this.getParent();
278 while (parent != null) {
279 if (parent instanceof NamingContainer) {
280 return parent.getContainerClientId(context);
281 }
282 parent = parent.getParent();
283 }
284 }
285 return null;
286 }
287
288 private Object[] values;
289
290 @Override
291 public Object saveState(FacesContext context) {
292
293 if (values == null) {
294 values = new Object[2];
295 }
296 values[0] = super.saveState(context);
297 values[1] = prependId;
298
299 return values;
300
301 }
302
303 @Override
304 public void restoreState(FacesContext context, Object state) {
305
306 values = (Object[]) state;
307 super.restoreState(context, values[0]);
308 prependId = (Boolean) values[1];
309
310 }
311 }