Source Code Cross Referenced for Form.java in  » Content-Management-System » apache-lenya-2.0 » org » apache » cocoon » forms » formmodel » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Content Management System » apache lenya 2.0 » org.apache.cocoon.forms.formmodel 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Licensed to the Apache Software Foundation (ASF) under one or more
003:         * contributor license agreements.  See the NOTICE file distributed with
004:         * this work for additional information regarding copyright ownership.
005:         * The ASF licenses this file to You under the Apache License, Version 2.0
006:         * (the "License"); you may not use this file except in compliance with
007:         * the License.  You may obtain a copy of the License at
008:         *
009:         *      http://www.apache.org/licenses/LICENSE-2.0
010:         *
011:         * Unless required by applicable law or agreed to in writing, software
012:         * distributed under the License is distributed on an "AS IS" BASIS,
013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014:         * See the License for the specific language governing permissions and
015:         * limitations under the License.
016:         */
017:        package org.apache.cocoon.forms.formmodel;
018:
019:        import java.util.HashSet;
020:        import java.util.Locale;
021:        import java.util.Set;
022:
023:        import org.apache.cocoon.forms.FormContext;
024:        import org.apache.cocoon.forms.event.FormHandler;
025:        import org.apache.cocoon.forms.event.ProcessingPhase;
026:        import org.apache.cocoon.forms.event.ProcessingPhaseEvent;
027:        import org.apache.cocoon.forms.event.ProcessingPhaseListener;
028:        import org.apache.cocoon.forms.event.WidgetEvent;
029:        import org.apache.cocoon.forms.event.WidgetEventMulticaster;
030:        import org.apache.cocoon.forms.validation.ValidationError;
031:        import org.apache.cocoon.forms.validation.ValidationErrorAware;
032:        import org.apache.commons.collections.list.CursorableLinkedList;
033:        import org.apache.commons.lang.BooleanUtils;
034:        import org.apache.commons.lang.StringUtils;
035:
036:        /**
037:         * A widget that serves as a container for other widgets, the top-level widget in
038:         * a form description file.
039:         *
040:         * @version $Id: Form.java 475908 2006-11-16 20:15:45Z vgritsenko $
041:         */
042:        public class Form extends AbstractContainerWidget implements 
043:                ValidationErrorAware {
044:
045:            /** Form parameter containing the submit widget's id */
046:            public static final String SUBMIT_ID_PARAMETER = "forms_submit_id";
047:
048:            private static final String FORM_EL = "form";
049:
050:            private final FormDefinition definition;
051:
052:            /**
053:             * If non-null, indicates that form processing should terminate at the end of the current phase.
054:             * If true, interaction with the form is finished. It doesn't imply that the form is valid though.
055:             * If false, interaction isn't finished and the form should be redisplayed (processing was triggered
056:             * by e.g. and action or a field with event listeners).
057:             */
058:            private Boolean endProcessing;
059:            private Locale locale = Locale.getDefault();
060:            private FormHandler formHandler;
061:            private Widget submitWidget;
062:            private boolean isValid;
063:            private ProcessingPhaseListener listener;
064:
065:            //In the "readFromRequest" phase, events are buffered to ensure that all widgets had the chance
066:            //to read their value before events get fired.
067:            private boolean bufferEvents;
068:            private CursorableLinkedList events;
069:
070:            /** Widgets that need to be updated in the client when in AJAX mode */
071:            private Set updatedWidgets;
072:
073:            /** Widgets that have at least one descendant that has to be updated */
074:            private Set childUpdatedWidgets;
075:
076:            /** Optional id which overrides the value from the form definition */
077:            private String id;
078:
079:            public Form(FormDefinition definition) {
080:                super (definition);
081:                this .definition = definition;
082:                this .listener = definition.getProcessingPhaseListener();
083:            }
084:
085:            /**
086:             * Initialize the form by recursively initializing all its children. Any events occuring within the
087:             * initialization phase are buffered and fired after initialization is complete, so that any action
088:             * from a widget on another one occurs after that other widget has been given the opportunity to
089:             * initialize itself.
090:             */
091:            public void initialize() {
092:                try {
093:                    // Start buffering events
094:                    this .bufferEvents = true;
095:                    super .initialize();
096:                    // Fire events, still buffering them: this ensures they will be handled in the same
097:                    // order as they were added.
098:                    fireEvents();
099:                } finally {
100:                    // Stop buffering events
101:                    this .bufferEvents = false;
102:                }
103:            }
104:
105:            public WidgetDefinition getDefinition() {
106:                return this .definition;
107:            }
108:
109:            /**
110:             * Events produced by child widgets should not be fired immediately, but queued in order to ensure
111:             * an overall consistency of the widget tree before being handled.
112:             *
113:             * @param event the event to queue
114:             */
115:            public void addWidgetEvent(WidgetEvent event) {
116:
117:                if (this .bufferEvents) {
118:                    if (this .events == null) {
119:                        this .events = new CursorableLinkedList();
120:                    }
121:
122:                    // FIXME: limit the number of events to detect recursive event loops ?
123:                    this .events.add(event);
124:                } else {
125:                    // Send it right now
126:                    event.getSourceWidget().broadcastEvent(event);
127:                }
128:            }
129:
130:            /**
131:             * Mark a widget as being updated. When it Ajax mode, only updated widgets will be redisplayed
132:             *
133:             * @param widget the updated widget
134:             * @return <code>true</code> if this widget was added to the list (i.e. wasn't alredy marked for update)
135:             */
136:            public boolean addWidgetUpdate(Widget widget) {
137:                if (this .updatedWidgets != null) {
138:                    if (this .updatedWidgets.add(widget
139:                            .getRequestParameterName())) {
140:                        // Wasn't already there: register parents
141:                        Widget parent = widget.getParent();
142:                        while (parent != this  && parent != null) {
143:                            if (this .childUpdatedWidgets.add(parent
144:                                    .getRequestParameterName())) {
145:                                parent = parent.getParent();
146:                            } else {
147:                                // Parent already there, and therefore its own parents.
148:                                break;
149:                            }
150:                        }
151:                        return true;
152:                    }
153:                }
154:                return false;
155:            }
156:
157:            public Set getUpdatedWidgetIds() {
158:                return this .updatedWidgets;
159:            }
160:
161:            public Set getChildUpdatedWidgetIds() {
162:                return this .childUpdatedWidgets;
163:            }
164:
165:            /**
166:             * Fire the events that have been queued.
167:             * Note that event handling can fire new events.
168:             */
169:            private void fireEvents() {
170:                if (this .events != null) {
171:                    try {
172:                        CursorableLinkedList.Cursor cursor = this .events
173:                                .cursor();
174:                        while (cursor.hasNext()) {
175:                            WidgetEvent event = (WidgetEvent) cursor.next();
176:                            event.getSourceWidget().broadcastEvent(event);
177:                            if (formHandler != null) {
178:                                formHandler.handleEvent(event);
179:                            }
180:                        }
181:                        cursor.close();
182:                    } finally {
183:                        this .events.clear();
184:                    }
185:                }
186:            }
187:
188:            /**
189:             * Inform the form that the values will be loaded.
190:             */
191:            public void informStartLoadingModel() {
192:                // nothing to do here
193:                // TODO - we could remove this method?
194:            }
195:
196:            /**
197:             * Inform the form that the values are loaded.
198:             */
199:            public void informEndLoadingModel() {
200:                // Notify the end of the load phase
201:                if (this .listener != null) {
202:                    this .listener.phaseEnded(new ProcessingPhaseEvent(this ,
203:                            ProcessingPhase.LOAD_MODEL));
204:                }
205:            }
206:
207:            /**
208:             * Inform the form that the values will be saved.
209:             */
210:            public void informStartSavingModel() {
211:                // nothing to do here
212:                // TODO - we could remove this method?
213:            }
214:
215:            /**
216:             * Inform the form that the values are saved.
217:             */
218:            public void informEndSavingModel() {
219:                // Notify the end of the save phase
220:                if (this .listener != null) {
221:                    this .listener.phaseEnded(new ProcessingPhaseEvent(this ,
222:                            ProcessingPhase.SAVE_MODEL));
223:                }
224:            }
225:
226:            /**
227:             * Get the locale to be used to process this form.
228:             *
229:             * @return the form's locale.
230:             */
231:            public Locale getLocale() {
232:                return this .locale;
233:            }
234:
235:            /**
236:             * Get the widget that triggered the current processing. Note that it can be any widget, and
237:             * not necessarily an action or a submit.
238:             *
239:             * @return the widget that submitted this form.
240:             */
241:            public Widget getSubmitWidget() {
242:                return this .submitWidget;
243:            }
244:
245:            /**
246:             * Set the widget that triggered the current form processing.
247:             *
248:             * @param widget the widget
249:             */
250:            public void setSubmitWidget(Widget widget) {
251:                if (this .submitWidget == widget) {
252:                    return;
253:                }
254:
255:                if (this .submitWidget != null) {
256:                    throw new IllegalStateException(
257:                            "Submit widget already set to " + this .submitWidget
258:                                    + ". Cannot set also " + widget);
259:                }
260:
261:                // Check that the submit widget is active
262:                if (widget.getCombinedState() != WidgetState.ACTIVE) {
263:                    throw new IllegalStateException("Widget " + widget
264:                            + " that submitted the form is not active.");
265:                }
266:
267:                // If the submit widget is not an action (e.g. a field with an event listener),
268:                // we end form processing after the current phase and redisplay the form.
269:                // Actions (including submits) will call endProcessing() themselves and it's their
270:                // responsibility to indicate how form processing should continue.
271:                if (!(widget instanceof  Action)) {
272:                    endProcessing(true);
273:                }
274:                this .submitWidget = widget;
275:            }
276:
277:            public boolean hasFormHandler() {
278:                return (this .formHandler != null);
279:            }
280:
281:            public void setFormHandler(FormHandler formHandler) {
282:                this .formHandler = formHandler;
283:            }
284:
285:            public void addProcessingPhaseListener(
286:                    ProcessingPhaseListener listener) {
287:                this .listener = WidgetEventMulticaster.add(this .listener,
288:                        listener);
289:            }
290:
291:            public void removeProcessingPhaseListener(
292:                    ProcessingPhaseListener listener) {
293:                this .listener = WidgetEventMulticaster.remove(this .listener,
294:                        listener);
295:            }
296:
297:            /**
298:             * Processes a form submit. If the form is finished, i.e. the form should not be redisplayed to the user,
299:             * then this method returns true, otherwise it returns false. To know if the form was sucessfully
300:             * validated, use the {@link #isValid()} method.
301:             * <p>
302:             * Form processing consists in multiple steps:
303:             * <ul>
304:             *  <li>all widgets read their value from the request (i.e.
305:             *      {@link #readFromRequest(FormContext)} is called recursively on
306:             *       the whole widget tree)
307:             *  <li>if there is an action event, call the FormHandler
308:             *  <li>perform validation.
309:             * </ul>
310:             * This processing can be interrupted by the widgets (or their event listeners) by calling
311:             * {@link #endProcessing(boolean)}.
312:             * <p>
313:             * Note that this method is synchronized as a Form is not thread-safe. This should not be a
314:             * bottleneck as such concurrent requests can only happen for a single user.
315:             */
316:            public synchronized boolean process(FormContext formContext) {
317:                // Is this an AJAX request?
318:                if (formContext.getRequest().getParameter("cocoon-ajax") != null) {
319:                    this .updatedWidgets = new HashSet();
320:                    this .childUpdatedWidgets = new HashSet();
321:                }
322:
323:                // Fire the binding phase events
324:                fireEvents();
325:
326:                // setup processing
327:                this .submitWidget = null;
328:                this .locale = formContext.getLocale();
329:                this .endProcessing = null;
330:                this .isValid = false;
331:
332:                // Notify the end of the current phase
333:                if (this .listener != null) {
334:                    this .listener.phaseEnded(new ProcessingPhaseEvent(this ,
335:                            ProcessingPhase.PROCESSING_INITIALIZE));
336:                }
337:
338:                try {
339:                    // Start buffering events
340:                    this .bufferEvents = true;
341:                    this .submitWidget = null;
342:
343:                    doReadFromRequest(formContext);
344:
345:                    // Find the submit widget, if not an action
346:                    // This has to occur after reading from the request, to handle stateless forms
347:                    // where the submit widget is recreated when the request is read (e.g. a row-action).
348:
349:                    // Note that we don't check this if the submit widget was already set, as it can cause problems
350:                    // if the user triggers submit with an input (which sets 'forms_submit_id'), then clicks back
351:                    // and submits using a regular submit button.
352:                    if (getSubmitWidget() == null) {
353:                        String submitId = formContext.getRequest()
354:                                .getParameter(SUBMIT_ID_PARAMETER);
355:                        if (!StringUtils.isEmpty(submitId)) {
356:                            // if the form has an ID, it is used as part of the submitId too and must be removed
357:                            if (!StringUtils.isEmpty(this .getId())) {
358:                                submitId = submitId.substring(submitId
359:                                        .indexOf('.') + 1);
360:                            }
361:                            Widget submit = this .lookupWidget(submitId.replace(
362:                                    '.', '/'));
363:                            if (submit == null) {
364:                                throw new IllegalArgumentException(
365:                                        "Invalid submit id (no such widget): "
366:                                                + submitId);
367:                            }
368:                            setSubmitWidget(submit);
369:                        }
370:                    }
371:
372:                    // Fire events, still buffering them: this ensures they will be handled in the same
373:                    // order as they were added.
374:                    fireEvents();
375:
376:                } finally {
377:                    // No need for buffering in the following phases
378:                    this .bufferEvents = false;
379:                }
380:
381:                // Notify the end of the current phase
382:                if (this .listener != null) {
383:                    this .listener.phaseEnded(new ProcessingPhaseEvent(this ,
384:                            ProcessingPhase.READ_FROM_REQUEST));
385:                }
386:
387:                if (this .endProcessing != null) {
388:                    return this .endProcessing.booleanValue();
389:                }
390:
391:                return validate();
392:            }
393:
394:            /**
395:             * End the current form processing after the current phase.
396:             *
397:             * @param redisplayForm indicates if the form should be redisplayed to the user.
398:             */
399:            public void endProcessing(boolean redisplayForm) {
400:                // Set the indicator that terminates the form processing.
401:                // If redisplayForm is true, interaction is not finished and process() must
402:                // return false, hence the negation below.
403:                this .endProcessing = BooleanUtils
404:                        .toBooleanObject(!redisplayForm);
405:            }
406:
407:            /**
408:             * Was form validation successful ?
409:             *
410:             * @return <code>true</code> if the form was successfully validated.
411:             */
412:            public boolean isValid() {
413:                return this .isValid;
414:            }
415:
416:            public void readFromRequest(FormContext formContext) {
417:                throw new UnsupportedOperationException(
418:                        "Please use Form.process()");
419:            }
420:
421:            private void doReadFromRequest(FormContext formContext) {
422:                // let all individual widgets read their value from the request object
423:                super .readFromRequest(formContext);
424:            }
425:
426:            /**
427:             * Set a validation error on this field. This allows the form to be externally marked as invalid by
428:             * application logic.
429:             *
430:             * @return the validation error
431:             */
432:            public ValidationError getValidationError() {
433:                return this .validationError;
434:            }
435:
436:            /**
437:             * set a validation error
438:             */
439:            public void setValidationError(ValidationError error) {
440:                this .validationError = error;
441:            }
442:
443:            /**
444:             * Performs validation phase of form processing.
445:             */
446:            public boolean validate() {
447:                // Validate the form
448:                this .isValid = super .validate();
449:
450:                // FIXME: Is this check needed, before invoking the listener?
451:                if (this .endProcessing != null) {
452:                    this .wasValid = this .endProcessing.booleanValue();
453:                    return this .wasValid;
454:                }
455:
456:                // Notify the end of the current phase
457:                if (this .listener != null) {
458:                    this .listener.phaseEnded(new ProcessingPhaseEvent(this ,
459:                            ProcessingPhase.VALIDATE));
460:                }
461:
462:                if (this .endProcessing != null) {
463:                    // De-validate the form if one of the listeners asked to end the processing
464:                    // This allows for additional application-level validation.
465:                    this .isValid = false;
466:                    this .wasValid = this .endProcessing.booleanValue();
467:                    return this .wasValid;
468:                }
469:
470:                this .wasValid = this .isValid && this .validationError == null;
471:                return this .wasValid;
472:            }
473:
474:            public String getXMLElementName() {
475:                return FORM_EL;
476:            }
477:
478:            /**
479:             * @see org.apache.cocoon.forms.formmodel.AbstractWidget#getId()
480:             */
481:            public String getId() {
482:                if (this .id != null) {
483:                    return this .id;
484:                }
485:                return super .getId();
486:            }
487:
488:            /**
489:             * Set the optional id.
490:             * @param value A new id.
491:             */
492:            public void setId(String value) {
493:                this.id = value;
494:            }
495:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.