KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tapestry > form > Form


1 // Copyright 2004, 2005 The Apache Software Foundation
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14

15 package org.apache.tapestry.form;
16
17 import org.apache.hivemind.ApplicationRuntimeException;
18 import org.apache.hivemind.Location;
19 import org.apache.tapestry.AbstractComponent;
20 import org.apache.tapestry.IActionListener;
21 import org.apache.tapestry.IComponent;
22 import org.apache.tapestry.IDirect;
23 import org.apache.tapestry.IForm;
24 import org.apache.tapestry.IMarkupWriter;
25 import org.apache.tapestry.IRender;
26 import org.apache.tapestry.IRequestCycle;
27 import org.apache.tapestry.RenderRewoundException;
28 import org.apache.tapestry.Tapestry;
29 import org.apache.tapestry.TapestryUtils;
30 import org.apache.tapestry.engine.ActionServiceParameter;
31 import org.apache.tapestry.engine.DirectServiceParameter;
32 import org.apache.tapestry.engine.IEngineService;
33 import org.apache.tapestry.engine.ILink;
34 import org.apache.tapestry.listener.ListenerInvoker;
35 import org.apache.tapestry.valid.IValidationDelegate;
36 import org.apache.tapestry.web.WebResponse;
37
38 /**
39  * Component which contains form element components. Forms use the action or direct services to
40  * handle the form submission. A Form will wrap other components and static HTML, including form
41  * components such as {@link TextArea},{@link TextField},{@link Checkbox}, etc. [ <a
42  * HREF="../../../../../ComponentReference/Form.html">Component Reference </a>]
43  * <p>
44  * When a form is submitted, it continues through the rewind cycle until <em>after</em> all of its
45  * wrapped elements have renderred. As the form component render (in the rewind cycle), they will be
46  * updating properties of the containing page and notifying thier listeners. Again: each form
47  * component is responsible not only for rendering HTML (to present the form), but for handling it's
48  * share of the form submission.
49  * <p>
50  * Only after all that is done will the Form notify its listener.
51  * <p>
52  * Starting in release 1.0.2, a Form can use either the direct service or the action service. The
53  * default is the direct service, even though in earlier releases, only the action service was
54  * available.
55  * <p>
56  * Release 4.0 adds two new listener, {@link #getCancel()} and {@link #getRefresh()} and
57  * corresponding client-side behavior to force a form to refresh (update, bypassing input field
58  * validation) or cancel (update immediately).
59  *
60  * @author Howard Lewis Ship, David Solis
61  */

62
63 public abstract class Form extends AbstractComponent implements IForm, IDirect
64 {
65     private String JavaDoc _name;
66
67     private FormSupport _formSupport;
68
69     private class RenderInformalParameters implements IRender
70     {
71         public void render(IMarkupWriter writer, IRequestCycle cycle)
72         {
73             renderInformalParameters(writer, cycle);
74         }
75     }
76
77     private IRender _renderInformalParameters;
78
79     /**
80      * Returns the currently active {@link IForm}, or null if no form is active. This is a
81      * convienience method, the result will be null, or an instance of {@link IForm}, but not
82      * necessarily a <code>Form</code>.
83      *
84      * @deprecated Use {@link TapestryUtils#getForm(IRequestCycle, IComponent)}&nbsp;instead.
85      */

86
87     public static IForm get(IRequestCycle cycle)
88     {
89         return (IForm) cycle.getAttribute(ATTRIBUTE_NAME);
90     }
91
92     /**
93      * Indicates to any wrapped form components that they should respond to the form submission.
94      *
95      * @throws ApplicationRuntimeException
96      * if not rendering.
97      */

98
99     public boolean isRewinding()
100     {
101         if (!isRendering())
102             throw Tapestry.createRenderOnlyPropertyException(this, "rewinding");
103
104         return _formSupport.isRewinding();
105     }
106
107     /**
108      * Injected.
109      *
110      * @since 4.0
111      */

112
113     public abstract IEngineService getDirectService();
114
115     /**
116      * Injected.
117      *
118      * @since 4.0
119      */

120
121     public abstract IEngineService getActionService();
122
123     /**
124      * Returns true if this Form is configured to use the direct service.
125      * <p>
126      * This is derived from the direct parameter, and defaults to true if not bound.
127      *
128      * @since 1.0.2
129      */

130
131     public abstract boolean isDirect();
132
133     /**
134      * Returns true if the stateful parameter is bound to a true value. If stateful is not bound,
135      * also returns the default, true.
136      *
137      * @since 1.0.1
138      */

139
140     public boolean getRequiresSession()
141     {
142         return isStateful();
143     }
144
145     /**
146      * Constructs a unique identifier (within the Form). The identifier consists of the component's
147      * id, with an index number added to ensure uniqueness.
148      * <p>
149      * Simply invokes
150      * {@link #getElementId(org.apache.tapestry.form.IFormComponent, java.lang.String)}with the
151      * component's id.
152      *
153      * @since 1.0.2
154      */

155
156     public String JavaDoc getElementId(IFormComponent component)
157     {
158         return _formSupport.getElementId(component, component.getId());
159     }
160
161     /**
162      * Constructs a unique identifier from the base id. If possible, the id is used as-is.
163      * Otherwise, a unique identifier is appended to the id.
164      * <p>
165      * This method is provided simply so that some components ({@link ImageSubmit}) have more
166      * specific control over their names.
167      *
168      * @since 1.0.3
169      */

170
171     public String JavaDoc getElementId(IFormComponent component, String JavaDoc baseId)
172     {
173         return _formSupport.getElementId(component, baseId);
174     }
175
176     /**
177      * Returns the name generated for the form. This is used to faciliate components that write
178      * JavaScript and need to access the form or its contents.
179      * <p>
180      * This value is generated when the form renders, and is not cleared. If the Form is inside a
181      * {@link org.apache.tapestry.components.Foreach}, this will be the most recently generated
182      * name for the Form.
183      * <p>
184      * This property is exposed so that sophisticated applications can write JavaScript handlers for
185      * the form and components within the form.
186      *
187      * @see AbstractFormComponent#getName()
188      */

189
190     public String JavaDoc getName()
191     {
192         return _name;
193     }
194
195     /** @since 3.0 * */
196
197     protected void prepareForRender(IRequestCycle cycle)
198     {
199         super.prepareForRender(cycle);
200
201         TapestryUtils.storeForm(cycle, this);
202     }
203
204     protected void cleanupAfterRender(IRequestCycle cycle)
205     {
206         _formSupport = null;
207
208         TapestryUtils.removeForm(cycle);
209
210         IValidationDelegate delegate = getDelegate();
211
212         if (delegate != null)
213             delegate.setFormComponent(null);
214
215         super.cleanupAfterRender(cycle);
216     }
217
218     protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle)
219     {
220         String JavaDoc actionId = cycle.getNextActionId();
221
222         _formSupport = newFormSupport(writer, cycle);
223
224         if (isRewinding())
225         {
226             String JavaDoc submitType = _formSupport.rewind();
227
228             IActionListener listener = findListener(submitType);
229
230             getListenerInvoker().invokeListener(listener, this, cycle);
231
232             // Abort the rewind render.
233

234             throw new RenderRewoundException(this);
235         }
236
237         // Note: not safe to invoke getNamespace() in Portlet world
238
// except during a RenderRequest.
239

240         String JavaDoc baseName = isDirect() ? constructFormNameForDirectService(cycle)
241                 : constructFormNameForActionService(actionId);
242
243         _name = baseName + getResponse().getNamespace();
244
245         if (_renderInformalParameters == null)
246             _renderInformalParameters = new RenderInformalParameters();
247
248         ILink link = getLink(cycle, actionId);
249
250         _formSupport.render(getMethod(), _renderInformalParameters, link);
251     }
252
253     IActionListener findListener(String JavaDoc mode)
254     {
255         IActionListener result = null;
256
257         if (mode.equals(FormConstants.SUBMIT_CANCEL))
258             result = getCancel();
259         else if (mode.equals(FormConstants.SUBMIT_REFRESH))
260             result = getRefresh();
261
262         // If not cancel or refresh, or the corresponding listener
263
// is itself null, then use the default listener
264
// (which may be null as well!).
265

266         if (result == null)
267             result = getListener();
268
269         return result;
270     }
271
272     /**
273      * Construct a form name for use with the action service. This implementation returns "Form"
274      * appended with the actionId.
275      *
276      * @since 4.0
277      */

278
279     protected String JavaDoc constructFormNameForActionService(String JavaDoc actionId)
280     {
281         return "Form" + actionId;
282     }
283
284     /**
285      * Constructs a form name for use with the direct service. This implementation bases the form
286      * name on the form component's id (but ensures it is unique). Remember that Tapestry assigns an
287      * "ugly" id if an explicit component id is not provided.
288      *
289      * @since 4.0
290      */

291
292     private String JavaDoc constructFormNameForDirectService(IRequestCycle cycle)
293     {
294         return cycle.getUniqueId(getId());
295     }
296
297     /**
298      * Returns a new instance of {@link FormSupportImpl}.
299      */

300
301     protected FormSupport newFormSupport(IMarkupWriter writer, IRequestCycle cycle)
302     {
303         return new FormSupportImpl(writer, cycle, this);
304     }
305
306     /**
307      * Adds an additional event handler.
308      *
309      * @since 1.0.2
310      */

311
312     public void addEventHandler(FormEventType type, String JavaDoc functionName)
313     {
314         _formSupport.addEventHandler(type, functionName);
315     }
316
317     /**
318      * Simply invokes {@link #render(IMarkupWriter, IRequestCycle)}.
319      *
320      * @since 1.0.2
321      */

322
323     public void rewind(IMarkupWriter writer, IRequestCycle cycle)
324     {
325         render(writer, cycle);
326     }
327
328     /**
329      * Method invoked by the direct service.
330      *
331      * @since 1.0.2
332      */

333
334     public void trigger(IRequestCycle cycle)
335     {
336         cycle.rewindForm(this);
337     }
338
339     /**
340      * Builds the EngineServiceLink for the form, using either the direct or action service.
341      *
342      * @since 1.0.3
343      */

344
345     private ILink getLink(IRequestCycle cycle, String JavaDoc actionId)
346     {
347         if (isDirect())
348         {
349             Object JavaDoc parameter = new DirectServiceParameter(this);
350             return getDirectService().getLink(cycle, parameter);
351         }
352
353         // I'd love to pull out support for the action service entirely!
354

355         Object JavaDoc parameter = new ActionServiceParameter(this, actionId);
356
357         return getActionService().getLink(cycle, parameter);
358     }
359
360     /** Injected */
361
362     public abstract WebResponse getResponse();
363
364     /**
365      * delegate parameter, which has a default (starting in release 4.0).
366      */

367
368     public abstract IValidationDelegate getDelegate();
369
370     /** listener parameter, may be null */
371     public abstract IActionListener getListener();
372
373     /** cancel parameter, may be null */
374     public abstract IActionListener getCancel();
375
376     /** refresh parameter, may be null */
377     public abstract IActionListener getRefresh();
378
379     /** method parameter */
380     public abstract String JavaDoc getMethod();
381
382     /** stateful parameter */
383     public abstract boolean isStateful();
384
385     public void setEncodingType(String JavaDoc encodingType)
386     {
387         _formSupport.setEncodingType(encodingType);
388     }
389
390     /** @since 3.0 */
391
392     public void addHiddenValue(String JavaDoc name, String JavaDoc value)
393     {
394         _formSupport.addHiddenValue(name, value);
395     }
396
397     /** @since 3.0 */
398
399     public void addHiddenValue(String JavaDoc name, String JavaDoc id, String JavaDoc value)
400     {
401         _formSupport.addHiddenValue(name, id, value);
402     }
403
404     public void prerenderField(IMarkupWriter writer, IComponent field, Location location)
405     {
406         _formSupport.prerenderField(writer, field, location);
407     }
408
409     public boolean wasPrerendered(IMarkupWriter writer, IComponent field)
410     {
411         return _formSupport.wasPrerendered(writer, field);
412     }
413
414     /** @since 4.0 */
415
416     public void addDeferredRunnable(Runnable JavaDoc runnable)
417     {
418         _formSupport.addDeferredRunnable(runnable);
419     }
420
421     /**
422      * Injected
423      *
424      * @since 4.0
425      */

426
427     public abstract ListenerInvoker getListenerInvoker();
428 }
Popular Tags