KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > riotfamily > forms > Form


1 /* ***** BEGIN LICENSE BLOCK *****
2  * Version: MPL 1.1
3  * The contents of this file are subject to the Mozilla Public License Version
4  * 1.1 (the "License"); you may not use this file except in compliance with
5  * the License. You may obtain a copy of the License at
6  * http://www.mozilla.org/MPL/
7  *
8  * Software distributed under the License is distributed on an "AS IS" basis,
9  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
10  * for the specific language governing rights and limitations under the
11  * License.
12  *
13  * The Original Code is Riot.
14  *
15  * The Initial Developer of the Original Code is
16  * Neteye GmbH.
17  * Portions created by the Initial Developer are Copyright (C) 2006
18  * the Initial Developer. All Rights Reserved.
19  *
20  * Contributor(s):
21  * Felix Gnass [fgnass at neteye dot de]
22  *
23  * ***** END LICENSE BLOCK ***** */

24 package org.riotfamily.forms;
25
26 import java.io.PrintWriter JavaDoc;
27 import java.util.ArrayList JavaDoc;
28 import java.util.Collection JavaDoc;
29 import java.util.HashMap JavaDoc;
30 import java.util.HashSet JavaDoc;
31 import java.util.Iterator JavaDoc;
32 import java.util.List JavaDoc;
33 import java.util.Map JavaDoc;
34 import java.util.Set JavaDoc;
35
36 import javax.servlet.http.HttpServletRequest JavaDoc;
37
38 import org.apache.commons.logging.Log;
39 import org.apache.commons.logging.LogFactory;
40 import org.riotfamily.common.markup.DocumentWriter;
41 import org.riotfamily.common.markup.Html;
42 import org.riotfamily.common.markup.TagWriter;
43 import org.riotfamily.forms.request.FormRequest;
44 import org.riotfamily.forms.request.HttpFormRequest;
45 import org.riotfamily.forms.resource.FormResource;
46 import org.riotfamily.forms.resource.LoadingCodeGenerator;
47 import org.riotfamily.forms.resource.ResourceElement;
48 import org.riotfamily.forms.resource.StylesheetResource;
49 import org.riotfamily.forms.support.MapOrBeanWrapper;
50 import org.springframework.util.Assert;
51 import org.springframework.validation.Validator;
52
53
54 /**
55  * Serverside representation of a HTML form.
56  */

57 public class Form implements BeanEditor {
58
59     private static final String JavaDoc DEFAULT_ID = "form";
60
61     private static final String JavaDoc FORM_ATTR = "form";
62
63     private static final String JavaDoc ELEMENT_CONTAINER_ATTR = "elements";
64
65     private Log log = LogFactory.getLog(Form.class);
66
67     private String JavaDoc id = DEFAULT_ID;
68
69     /** Elements keyed by their id */
70     private Map JavaDoc elementMap = new HashMap JavaDoc();
71
72     /** Counter to create unique ids */
73     private int idCount;
74
75     /** Set of used parameter names */
76     private Set JavaDoc paramNames = new HashSet JavaDoc();
77
78     /** EditorBinder to bind toplevel elements to properties */
79     private EditorBinder editorBinder;
80
81
82     /** Set containing resources required by the form itself (not it's elements) */
83     private List JavaDoc globalResources = new ArrayList JavaDoc();
84
85     private FormInitializer initializer;
86
87     private List JavaDoc containers = new ArrayList JavaDoc();
88
89     private Container elements;
90
91     private FormContext formContext;
92
93     private FormErrors errors;
94
95     private Validator validator;
96
97     private FormListener formListener;
98
99     private boolean rendering;
100
101     private boolean includeStylesheet;
102
103     private String JavaDoc template = TemplateUtils.getTemplatePath(this);
104
105     private Map JavaDoc renderModel = new HashMap JavaDoc();
106
107     private String JavaDoc hint;
108
109     public Form() {
110         setAttribute(FORM_ATTR, this);
111         elements = createContainer(ELEMENT_CONTAINER_ATTR);
112     }
113
114     public Form(Class JavaDoc type) {
115         this();
116         setBeanClass(type);
117     }
118
119     /**
120      * @since 6.4
121      */

122     public Form(Object JavaDoc object) {
123         this();
124         editorBinder = new EditorBinder(new MapOrBeanWrapper(object.getClass()));
125         editorBinder.setBackingObject(object);
126     }
127
128     public String JavaDoc getId() {
129         return this.id;
130     }
131
132     public void setId(String JavaDoc id) {
133         this.id = id;
134     }
135
136     public void setTemplate(String JavaDoc template) {
137         this.template = template;
138     }
139
140     public Collection JavaDoc getRegisteredElements() {
141         return elementMap.values();
142     }
143
144     public void setAttribute(String JavaDoc key, Object JavaDoc value) {
145         renderModel.put(key,value);
146     }
147
148     public Object JavaDoc getAttribute(String JavaDoc key) {
149         return renderModel.get(key);
150     }
151
152     public void setBeanClass(Class JavaDoc beanClass) {
153         Assert.notNull(beanClass, "The beanClass must not be null.");
154         editorBinder = new EditorBinder(new MapOrBeanWrapper(beanClass));
155     }
156
157     public void setValue(Object JavaDoc backingObject) {
158         if (backingObject != null) {
159             editorBinder.setBackingObject(backingObject);
160         }
161     }
162
163     public Object JavaDoc getValue() {
164         return editorBinder.getBackingObject();
165     }
166
167     public boolean isNew() {
168         return !editorBinder.isEditingExistingBean();
169     }
170
171     public EditorBinder getEditorBinder() {
172         return editorBinder;
173     }
174
175     public Editor getEditor(String JavaDoc property) {
176         return editorBinder.getEditor(property);
177     }
178
179     public void bind(Editor editor, String JavaDoc property) {
180         editorBinder.bind(editor, property);
181     }
182
183     public void addElement(Element element) {
184         elements.addElement(element);
185     }
186
187     public String JavaDoc getHint() {
188         if (hint == null) {
189             hint = MessageUtils.getHint(this, editorBinder.getBeanClass());
190         }
191         return hint;
192     }
193
194     /**
195      * Convinience method to add and bind an element within a single step.
196      */

197     public void addElement(Editor element, String JavaDoc property) {
198         addElement(element);
199         bind(element, property);
200     }
201
202     public Container createContainer(String JavaDoc name) {
203         Container container = new Container();
204         containers.add(container);
205         registerElement(container);
206         setAttribute(name, container);
207         return container;
208     }
209
210     public void addResource(FormResource resource) {
211         globalResources.add(resource);
212     }
213
214     protected List JavaDoc getResources() {
215         List JavaDoc resources = new ArrayList JavaDoc(globalResources);
216         Iterator JavaDoc it = getRegisteredElements().iterator();
217         while (it.hasNext()) {
218             Element element = (Element) it.next();
219             if (element instanceof ResourceElement) {
220                 ResourceElement re = (ResourceElement) element;
221                 FormResource res = re.getResource();
222                 if (res != null) {
223                     resources.add(res);
224                 }
225             }
226         }
227         return resources;
228     }
229
230     /**
231      * Creates and sets an id for the given element and puts it into the
232      * internal elementMap.
233      *
234      * @param element the element to register
235      */

236     public void registerElement(Element element) {
237         String JavaDoc id = createId();
238         element.setId(id);
239         element.setForm(this);
240         if (formContext != null) {
241             element.setFormContext(formContext);
242         }
243         elementMap.put(id, element);
244     }
245
246     public void unregisterElement(Element element) {
247         elementMap.remove(element.getId());
248     }
249
250     public String JavaDoc createId() {
251         return "e" + idCount++;
252     }
253
254     /**
255      * Returns the previously registered element with the given id.
256      */

257     public Element getElementById(String JavaDoc id) {
258         return (Element) elementMap.get(id);
259     }
260
261     /**
262      * Returns a String that can be used as parameter name for input elements.
263      * Subsequent calls will return different values to ensure uniqueness of
264      * parameter names within a form.
265      */

266     public String JavaDoc createUniqueParameterName() {
267         return createUniqueParameterName(null);
268     }
269
270     /**
271      * Like {@link #createUniqueParameterName()}this method returns a String
272      * that can be used as parameter name. Since most modern browsers keep track
273      * of previously entered values (with the same parameter name) a desired
274      * name can be passed to this method. Typically an element will use the name
275      * of the property it is bound to as name. As this name might already be
276      * taken by another element (especially when lists of nested forms are used)
277      * this method will append an integer value to the given name if necessary.
278      */

279     public String JavaDoc createUniqueParameterName(String JavaDoc desiredName) {
280         if (desiredName == null) {
281             desiredName = "p" + paramNames.size();
282         }
283         String JavaDoc name = desiredName;
284         if (name.equalsIgnoreCase("target")) {
285             // Otherwise changing the target of the form would not work
286
name = "_target";
287         }
288         //TODO Aussure uniqueness of syntetic names
289
if (paramNames.contains(name)) {
290             name = desiredName + paramNames.size();
291         }
292         paramNames.add(name);
293         return name;
294     }
295
296     public void render(PrintWriter JavaDoc writer) {
297         rendering = true;
298
299         formContext.setWriter(writer);
300         DocumentWriter doc = new DocumentWriter(writer);
301
302         doc.start(Html.SCRIPT);
303         doc.attribute(Html.SCRIPT_SRC, formContext.getContextPath()
304                 + formContext.getResourcePath() + "riot-js/resources.js");
305
306         doc.attribute(Html.SCRIPT_TYPE, "text/javascript");
307         doc.attribute(Html.SCRIPT_LANGUAGE, "JavaScript");
308         doc.end();
309
310         doc.start(Html.SCRIPT);
311         doc.attribute(Html.SCRIPT_SRC, formContext.getContextPath()
312                 + formContext.getResourcePath() + "form/hint.js");
313
314         doc.attribute(Html.SCRIPT_TYPE, "text/javascript");
315         doc.attribute(Html.SCRIPT_LANGUAGE, "JavaScript");
316         doc.end();
317
318         doc.start(Html.SCRIPT).body();
319         LoadingCodeGenerator.renderLoadingCode(getResources(), writer);
320         doc.end();
321
322         formContext.getTemplateRenderer().render(
323                 template, renderModel, writer);
324
325         rendering = false;
326     }
327
328     public boolean isRendering() {
329         return rendering;
330     }
331
332     public void elementRendered(Element element) {
333         log.debug("Element rendered: " + element.getId());
334         if (getFormListener() != null) {
335             getFormListener().elementRendered(element);
336         }
337         if (rendering && element instanceof DHTMLElement) {
338             DHTMLElement dhtml = (DHTMLElement) element;
339             PrintWriter JavaDoc writer = formContext.getWriter();
340             TagWriter script = new TagWriter(writer);
341             String JavaDoc initScript = dhtml.getInitScript();
342             if (initScript != null) {
343                 script.start(Html.SCRIPT);
344                 script.attribute(Html.SCRIPT_LANGUAGE, "JavaScript");
345                 script.attribute(Html.SCRIPT_TYPE, "text/javascript");
346                 script.body().print("//").cData().println();
347                 if (dhtml instanceof ResourceElement) {
348                     ResourceElement resEle = (ResourceElement) dhtml;
349                     FormResource res = resEle.getResource();
350                     if (res != null) {
351                         script.print("Resources.execWhenLoaded(['");
352                         script.print(res.getUrl());
353                         script.print("'], function() {");
354                         script.print(initScript);
355                         script.print("})");
356                     }
357                     else {
358                         script.print(initScript);
359                     }
360                 }
361                 else {
362                     script.print(initScript);
363                 }
364                 script.print("//").end();
365             }
366         }
367     }
368
369     public void setInitializer(FormInitializer initializer) {
370         this.initializer = initializer;
371     }
372
373     public void setValidator(Validator validator) {
374         this.validator = validator;
375     }
376
377     public void init() {
378         if (initializer != null) {
379             initializer.initForm(this);
380         }
381         editorBinder.initEditors();
382         if (includeStylesheet) {
383             addResource(new StylesheetResource("form/form.css"));
384         }
385     }
386
387     public void processRequest(HttpServletRequest JavaDoc request) {
388         processRequest(new HttpFormRequest(request));
389     }
390
391     public void processRequest(FormRequest request) {
392         errors = new FormErrors(this);
393         Iterator JavaDoc it = containers.iterator();
394         while (it.hasNext()) {
395             Container container = (Container) it.next();
396             container.processRequest(request);
397         }
398         if (validator != null) {
399             validator.validate(populateBackingObject(), errors);
400         }
401     }
402     
403     public void processExclusiveRequest(String JavaDoc elementId,
404             HttpServletRequest JavaDoc request) {
405         
406         processExclusiveRequest(elementId, new HttpFormRequest(request));
407     }
408     
409     public void processExclusiveRequest(String JavaDoc elementId, FormRequest request) {
410         errors = new FormErrors(this);
411         Element element = getElementById(elementId);
412         element.processRequest(request);
413     }
414
415     public void setFormListener(FormListener formListener) {
416         this.formListener = formListener;
417     }
418
419     public FormListener getFormListener() {
420         return formListener;
421     }
422
423     public void requestFocus(Element element) {
424         if (formListener != null) {
425             formListener.elementFocused(element);
426         }
427     }
428
429     public Object JavaDoc getBackingObject() {
430         return editorBinder.getBackingObject();
431     }
432
433     public Object JavaDoc populateBackingObject() {
434         return editorBinder.populateBackingObject();
435     }
436
437     public FormContext getFormContext() {
438         return this.formContext;
439     }
440
441     public void setFormContext(FormContext formContext) {
442         this.formContext = formContext;
443         this.errors = new FormErrors(this);
444         Iterator JavaDoc it = getRegisteredElements().iterator();
445         while (it.hasNext()) {
446             Element element = (Element) it.next();
447             element.setFormContext(formContext);
448         }
449     }
450
451     public FormErrors getErrors() {
452         return errors;
453     }
454
455     public boolean hasErrors() {
456         return errors.hasErrors();
457     }
458 }
Popular Tags