001    // Copyright 2005 The Apache Software Foundation
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    //     http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    
015    package org.apache.tapestry;
016    
017    import org.apache.hivemind.Location;
018    import org.apache.tapestry.form.FormEventType;
019    import org.apache.tapestry.form.IFormComponent;
020    import org.apache.tapestry.json.JSONObject;
021    
022    /**
023     * Common interface extended by {@link org.apache.tapestry.IForm} and
024     * {@link org.apache.tapestry.form.FormSupport}.
025     * 
026     * @author Howard M. Lewis Ship
027     * @since 4.0
028     */
029    public interface FormBehavior
030    {
031        /**
032         * Adds an additional event handler. The type determines when the handler will be invoked,
033         * {@link FormEventType#SUBMIT}is most typical.
034         * 
035         * @deprecated Wiring of form event handlers is now managed on the client side. This method may
036         *             be removed in a future release of Tapestry.
037         */
038        void addEventHandler(FormEventType type, String functionName);
039    
040        /**
041         * Adds a hidden field value to be stored in the form. This ensures that all of the <input
042         * type="hidden"> (or equivalent) are grouped together, which ensures that the output HTML is
043         * valid (ie. doesn't have <input> improperly nested with <tr>, etc.).
044         * <p>
045         * It is acceptible to add multiple hidden fields with the same name. They will be written in
046         * the order they are received.
047         */
048    
049        void addHiddenValue(String name, String value);
050    
051        /**
052         * Adds a hidden field value to be stored in the form. This ensures that all of the &lt;input
053         * type="hidden"&gt; (or equivalent) are grouped together, which ensures that the output HTML is
054         * valid (ie. doesn't have &lt;input&gt; improperly nested with &lt;tr&gt;, etc.).
055         * <p>
056         * It is acceptible to add multiple hidden fields with the same name. They will be written in
057         * the order they are received.
058         * 
059         * @since 3.0
060         */
061    
062        void addHiddenValue(String name, String id, String value);
063    
064        /**
065         * Constructs a unique identifier (within the Form). The identifier consists of the component's
066         * id, with an index number added to ensure uniqueness.
067         * <p>
068         * Simply invokes {@link #getElementId(IFormComponent, String)}with the component's id.
069         * <p>
070         * Note: yes, some confusion on naming here. This is the form element id, which should be (for
071         * Tapestry purposes) unique within the rendered form. The {@link IFormComponent#getClientId()}
072         * is different, and should be unique within the rendered page.
073         */
074    
075        String getElementId(IFormComponent component);
076    
077        /**
078         * Constructs a unique identifier from the base id. If possible, the id is used as-is.
079         * Otherwise, a unique identifier is appended to the id.
080         * <p>
081         * This method is provided simply so that some components (
082         * {@link org.apache.tapestry.form.ImageSubmit}) have more specific control over their names.
083         * <p>
084         * Invokes {@link IFormComponent#setName(String)}with the result, as well as returning it.
085         * 
086         * @throws StaleLinkException
087         *             if, when the form itself is rewinding, the element id allocated does not match
088         *             the expected id (as allocated when the form rendered). This indicates that the
089         *             state of the application has changed between the time the form renderred and the
090         *             time it was submitted.
091         */
092    
093        String getElementId(IFormComponent component, String baseId);
094    
095        /**
096         * Returns true if the form is rewinding (meaning, the form was the subject of the request
097         * cycle).
098         */
099    
100        boolean isRewinding();
101    
102        /**
103         * May be invoked by a component to force the encoding type of the form to a particular value.
104         * 
105         * @see org.apache.tapestry.form.Upload
106         * @throws ApplicationRuntimeException
107         *             if the current encoding type is not null and doesn't match the provided encoding
108         *             type
109         */
110    
111        void setEncodingType(String encodingType);
112    
113        /**
114         * Pre-renders the specified field, buffering the result for later use by
115         * {@link #wasPrerendered(IMarkupWriter, IComponent)}. Typically, it is a
116         * {@link org.apache.tapestry.valid.FieldLabel}&nbsp;component that pre-renders an associated
117         * field. This little dance is necessary to properly support field labels inside loops, and to
118         * handle the portlet action/render request cycle.
119         * 
120         * @param writer
121         *            the markup writer (from which a nested markup writer is obtained)
122         * @param field
123         *            the field to pre-render. The field is responsible for invoking
124         *            {@link #wasPrerendered(IMarkupWriter, IComponent)}.
125         * @param location
126         *            an optional location (of the FieldLabel component) used when reporting errors.
127         */
128        void prerenderField(IMarkupWriter writer, IComponent field, Location location);
129    
130        /**
131         * Invoked by a form control component (a field) that may have been pre-rendered. If the field
132         * was pre-rendered, then the buffered output is printed into the writer and true is returned.
133         * Otherwise, false is returned.
134         * 
135         * @return true if the field was pre-rendered and should do nothing during its render phase,
136         *         false if the field should continue as normal.
137         */
138        boolean wasPrerendered(IMarkupWriter writer, IComponent field);
139        
140        /**
141         * Adds a deferred runnable, an object to be executed either before the &lt;/form&gt; tag is
142         * rendered (when rendering), or before the form's listener is invoked (when rewinding).
143         * Runnables are executed in the order in which they are added.
144         * 
145         * @param runnable
146         *            the object to execute (which may not be null)
147         */
148    
149        void addDeferredRunnable(Runnable runnable);
150    
151        /**
152         * Registers a field for automatic focus. The goal is for the first field that is in error to
153         * get focus; failing that, the first required field; failing that, any field.
154         * 
155         * @param field
156         *            the field requesting focus
157         * @param priority
158         *            a priority level used to determine whether the registered field becomes the focus
159         *            field. Constants for this purpose are defined in {@link ValidationConstants}.
160         * @since 4.0
161         */
162    
163        void registerForFocus(IFormComponent field, int priority);
164    
165        /**
166         * The javascript object profile being built by this context to validate/translate
167         * form values.
168         * @return {@link JSONObject} profile.
169         */
170        JSONObject getProfile();
171        
172        /**
173         * Sets a flag denoting whether or not an {@link IFormComponent} field has been
174         * updated according to the logic defined in 
175         * {@link org.apache.tapestry.services.ResponseBuilder#updateComponent(String)}.
176         * 
177         * <p>
178         * Currently this flag is used during ajax/json responses so that cooperating 
179         * {@link ResponseBuilder}s can be worked with to ensure form state is properly
180         * updated on the client. Specifically, that the hidden form input fields and 
181         * any associated validation profiles are updated.
182         * </p>
183         * 
184         * @param value 
185         *          The value to set.
186         */
187        void setFormFieldUpdating(boolean value);
188        
189        /**
190         * Checks to see if a form field has been updated. 
191         * 
192         * @see #setFormFieldUpdating(boolean)
193         * @return
194         */
195        boolean isFormFieldUpdating();
196    }