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