Source Code Cross Referenced for Form.java in  » J2EE » wicket » wicket » markup » html » form » 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 » J2EE » wicket » wicket.markup.html.form 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $Id: Form.java 516860 2007-03-11 06:12:05Z ehillenius $
0003:         * $Revision: 516860 $ $Date: 2007-03-11 07:12:05 +0100 (Sun, 11 Mar 2007) $
0004:         * 
0005:         * ==============================================================================
0006:         * Licensed under the Apache License, Version 2.0 (the "License"); you may not
0007:         * use this file except in compliance with the License. You may obtain a copy of
0008:         * the License at
0009:         * 
0010:         * http://www.apache.org/licenses/LICENSE-2.0
0011:         * 
0012:         * Unless required by applicable law or agreed to in writing, software
0013:         * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
0014:         * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
0015:         * License for the specific language governing permissions and limitations under
0016:         * the License.
0017:         */
0018:        package wicket.markup.html.form;
0019:
0020:        import java.util.HashMap;
0021:        import java.util.Iterator;
0022:        import java.util.Locale;
0023:        import java.util.Map;
0024:        import java.util.StringTokenizer;
0025:
0026:        import org.apache.commons.logging.Log;
0027:        import org.apache.commons.logging.LogFactory;
0028:
0029:        import wicket.Component;
0030:        import wicket.IRequestTarget;
0031:        import wicket.MarkupContainer;
0032:        import wicket.Page;
0033:        import wicket.Request;
0034:        import wicket.RequestCycle;
0035:        import wicket.WicketRuntimeException;
0036:        import wicket.markup.ComponentTag;
0037:        import wicket.markup.MarkupStream;
0038:        import wicket.markup.html.WebMarkupContainer;
0039:        import wicket.markup.html.border.Border;
0040:        import wicket.markup.html.form.persistence.CookieValuePersister;
0041:        import wicket.markup.html.form.persistence.IValuePersister;
0042:        import wicket.markup.html.form.validation.IFormValidator;
0043:        import wicket.model.IModel;
0044:        import wicket.model.Model;
0045:        import wicket.protocol.http.WebRequest;
0046:        import wicket.protocol.http.WebRequestCycle;
0047:        import wicket.protocol.http.request.WebClientInfo;
0048:        import wicket.request.IRequestCycleProcessor;
0049:        import wicket.request.RequestParameters;
0050:        import wicket.request.target.component.listener.ListenerInterfaceRequestTarget;
0051:        import wicket.util.lang.Bytes;
0052:        import wicket.util.string.AppendingStringBuffer;
0053:        import wicket.util.string.Strings;
0054:        import wicket.util.string.interpolator.MapVariableInterpolator;
0055:        import wicket.util.upload.FileUploadException;
0056:        import wicket.util.upload.FileUploadBase.SizeLimitExceededException;
0057:
0058:        /**
0059:         * Base class for forms. To implement a form, subclass this class, add
0060:         * FormComponents (such as CheckBoxes, ListChoices or TextFields) to the form.
0061:         * You can nest multiple buttons if you want to vary submit behavior. However,
0062:         * it is not necessary to use Wicket's button class, just putting e.g. <input
0063:         * type="submit" value="go"> suffices.
0064:         * <p>
0065:         * By default, the processing of a form works like this:
0066:         * <li> The submitting button is looked up. A submitting button is a button that
0067:         * is nested in this form (is a child component) and that was clicked by the
0068:         * user. If a submitting button was found, and it has the defaultFormProcessing
0069:         * field set to false (default is true), it's onSubmit method will be called
0070:         * right away, thus no validition is done, and things like updating form
0071:         * component models that would normally be done are skipped. In that respect,
0072:         * nesting a button with the defaultFormProcessing field set to false has the
0073:         * same effect as nesting a normal link. If you want you can call validate() to
0074:         * execute form validation, hasError() to find out whether validate() resulted
0075:         * in validation errors, and updateFormComponentModels() to update the models of
0076:         * nested form components. </li>
0077:         * <li> When no submitting button with defaultFormProcessing set to false was
0078:         * found, this form is processed (method process()). Now, two possible paths
0079:         * exist:
0080:         * <ul>
0081:         * <li> Form validation failed. All nested form components will be marked
0082:         * invalid, and onError() is called to allow clients to provide custom error
0083:         * handling code. </li>
0084:         * <li> Form validation succeeded. The nested components will be asked to update
0085:         * their models and persist their data is applicable. After that, method
0086:         * delegateSubmit with optionally the submitting button is called. The default
0087:         * when there is a submitting button is to first call onSubmit on that button,
0088:         * and after that call onSubmit on this form. Clients may override
0089:         * delegateSubmit if they want different behavior. </li>
0090:         * </ul>
0091:         * </li>
0092:         * </li>
0093:         * </p>
0094:         * 
0095:         * Form for handling (file) uploads with multipart requests is supported by
0096:         * callign setMultiPart(true) ( although wicket will try to automatically detect
0097:         * this for you ). Use this with
0098:         * {@link wicket.markup.html.form.upload.FileUploadField} components. You can
0099:         * attach mutliple FileUploadField components for muliple file uploads.
0100:         * <p>
0101:         * In case of an upload error two resource keys are available to specify error
0102:         * messages: uploadTooLarge and uploadFailed
0103:         * 
0104:         * ie in [page].properties
0105:         * 
0106:         * [form-id].uploadTooLarge=You have uploaded a file that is over the allowed
0107:         * limit of 2Mb
0108:         * 
0109:         * <p>
0110:         * If you want to have multiple buttons which submit the same form, simply put
0111:         * two or more button components somewhere in the hierarchy of components that
0112:         * are children of the form.
0113:         * </p>
0114:         * <p>
0115:         * To get form components to persist their values for users via cookies, simply
0116:         * call setPersistent(true) on the form component.
0117:         * </p>
0118:         * 
0119:         * @author Jonathan Locke
0120:         * @author Juergen Donnerstag
0121:         * @author Eelco Hillenius
0122:         * @author Cameron Braid
0123:         * @author Johan Compagner
0124:         * @author Igor Vaynberg (ivaynberg)
0125:         */
0126:        public class Form extends WebMarkupContainer implements 
0127:                IFormSubmitListener {
0128:            /**
0129:             * Visitor used for validation
0130:             * 
0131:             * @author Igor Vaynberg (ivaynberg)
0132:             */
0133:            private static abstract class ValidationVisitor implements 
0134:                    FormComponent.IVisitor {
0135:
0136:                /**
0137:                 * @see wicket.markup.html.form.FormComponent.IVisitor#formComponent(wicket.markup.html.form.FormComponent)
0138:                 */
0139:                public void formComponent(FormComponent formComponent) {
0140:                    if (formComponent.isVisibleInHierarchy()
0141:                            && formComponent.isValid()
0142:                            && formComponent.isEnabled()
0143:                            && formComponent.isEnableAllowed()) {
0144:                        validate(formComponent);
0145:                    }
0146:                }
0147:
0148:                /**
0149:                 * Callback that should be used to validate form component
0150:                 * 
0151:                 * @param formComponent
0152:                 */
0153:                public abstract void validate(FormComponent formComponent);
0154:
0155:            }
0156:
0157:            private static final String UPLOAD_TOO_LARGE_RESOURCE_KEY = "uploadTooLarge";
0158:
0159:            private static final String UPLOAD_FAILED_RESOURCE_KEY = "uploadFailed";
0160:
0161:            /** Flag that indicates this form has been submitted during this request */
0162:            private static final short FLAG_SUBMITTED = FLAG_RESERVED1;
0163:
0164:            private static final long serialVersionUID = 1L;
0165:
0166:            /** Log. */
0167:            private static final Log log = LogFactory.getLog(Form.class);
0168:
0169:            /** Maximum size of an upload in bytes */
0170:            private Bytes maxSize = Bytes.MAX;
0171:
0172:            /** True if the form has enctype of multipart/form-data */
0173:            private boolean multiPart = false;
0174:
0175:            private String javascriptId;
0176:
0177:            /** multi-validators assigned to this form */
0178:            private Object formValidators = null;
0179:
0180:            /**
0181:             * Any default button. If set, a hidden submit button will be rendered right
0182:             * after the form tag, so that when users press enter in a textfield, this
0183:             * button's action will be selected. If no default button is set, nothing
0184:             * additional is rendered.
0185:             * <p>
0186:             * WARNING: note that this is a best effort only. Unfortunately having a
0187:             * 'default' button in a form is ill defined in the standards, and of course
0188:             * IE has it's own way of doing things.
0189:             * </p>
0190:             */
0191:            private Button defaultButton;
0192:
0193:            /**
0194:             * Constructs a form with no validation.
0195:             * 
0196:             * @param id
0197:             *            See Component
0198:             */
0199:            public Form(final String id) {
0200:                super (id);
0201:            }
0202:
0203:            /**
0204:             * @param id
0205:             *            See Component
0206:             * @param model
0207:             *            See Component
0208:             * @see wicket.Component#Component(String, IModel)
0209:             */
0210:            public Form(final String id, IModel model) {
0211:                super (id, model);
0212:            }
0213:
0214:            /**
0215:             * Gets the default button. If set (not null), a hidden submit button will
0216:             * be rendered right after the form tag, so that when users press enter in a
0217:             * textfield, this button's action will be selected. If no default button is
0218:             * set (it is null), nothing additional is rendered.
0219:             * <p>
0220:             * WARNING: note that this is a best effort only. Unfortunately having a
0221:             * 'default' button in a form is ill defined in the standards, and of course
0222:             * IE has it's own way of doing things.
0223:             * </p>
0224:             * 
0225:             * @return The button to set as the default button, or null when you want to
0226:             *         'unset' any previously set default button
0227:             */
0228:            public final Button getDefaultButton() {
0229:                return defaultButton;
0230:            }
0231:
0232:            /**
0233:             * @return the maxSize of uploaded files
0234:             */
0235:            public Bytes getMaxSize() {
0236:                return this .maxSize;
0237:            }
0238:
0239:            /**
0240:             * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT CALL IT.
0241:             * <p>
0242:             * Retrieves FormComponent values related to the page using the persister
0243:             * and assign the values to the FormComponent. Thus initializing them.
0244:             */
0245:            public final void loadPersistentFormComponentValues() {
0246:                visitFormComponents(new FormComponent.IVisitor() {
0247:                    public void formComponent(final FormComponent formComponent) {
0248:                        // Component must implement persister interface and
0249:                        // persistence for that component must be enabled.
0250:                        // Else ignore the persisted value. It'll be deleted
0251:                        // once the user submits the Form containing that FormComponent.
0252:                        // Note: if that is true, values may remain persisted longer
0253:                        // than really necessary
0254:                        if (formComponent.isVisibleInHierarchy()
0255:                                && formComponent.isPersistent()) {
0256:                            // The persister
0257:                            final IValuePersister persister = getValuePersister();
0258:
0259:                            // Retrieve persisted value
0260:                            persister.load(formComponent);
0261:                        }
0262:                    }
0263:                });
0264:            }
0265:
0266:            /**
0267:             * THIS METHOD IS NOT PART OF THE WICKET API. DO NOT ATTEMPT TO OVERRIDE OR
0268:             * CALL IT.
0269:             * 
0270:             * Handles form submissions.
0271:             * 
0272:             * @see Form#validate()
0273:             */
0274:            public final void onFormSubmitted() {
0275:                setFlag(FLAG_SUBMITTED, true);
0276:
0277:                if (handleMultiPart()) {
0278:                    // Tells FormComponents that a new user input has come
0279:                    inputChanged();
0280:
0281:                    String url = getRequest().getParameter(getHiddenFieldId());
0282:                    if (!Strings.isEmpty(url)) {
0283:                        dispatchEvent(getPage(), url);
0284:                    } else {
0285:                        // First, see if the processing was triggered by a Wicket button
0286:                        final Button submittingButton = findSubmittingButton();
0287:
0288:                        // When processing was triggered by a Wicket button and that
0289:                        // button indicates it wants to be called immediately
0290:                        // (without processing), call Button.onSubmit() right away.
0291:                        if (submittingButton != null
0292:                                && !submittingButton.getDefaultFormProcessing()) {
0293:                            submittingButton.onSubmit();
0294:                        } else {
0295:                            // process the form for this request
0296:                            if (process()) {
0297:                                // let clients handle further processing
0298:                                delegateSubmit(submittingButton);
0299:                            }
0300:                        }
0301:                    }
0302:                }
0303:                // If multi part did fail check if an error is registered and call
0304:                // onError
0305:                else if (hasError()) {
0306:                    onError();
0307:                }
0308:            }
0309:
0310:            /**
0311:             * Checks if this form has been submitted during the current request
0312:             * 
0313:             * @return true if the form has been submitted during this request, false
0314:             *         otherwise
0315:             */
0316:            public final boolean isSubmitted() {
0317:                return getFlag(FLAG_SUBMITTED);
0318:            }
0319:
0320:            /**
0321:             * @see wicket.Component#internalOnDetach()
0322:             */
0323:            protected void internalOnDetach() {
0324:                super .internalOnDetach();
0325:                setFlag(FLAG_SUBMITTED, false);
0326:            }
0327:
0328:            /**
0329:             * Removes already persisted data for all FormComponent childs and disable
0330:             * persistence for the same components.
0331:             * 
0332:             * @see Page#removePersistedFormData(Class, boolean)
0333:             * 
0334:             * @param disablePersistence
0335:             *            if true, disable persistence for all FormComponents on that
0336:             *            page. If false, it will remain unchanged.
0337:             */
0338:            public void removePersistentFormComponentValues(
0339:                    final boolean disablePersistence) {
0340:                // The persistence manager responsible to persist and retrieve
0341:                // FormComponent data
0342:                final IValuePersister persister = getValuePersister();
0343:
0344:                // Search for FormComponents like TextField etc.
0345:                visitFormComponents(new FormComponent.IVisitor() {
0346:                    public void formComponent(final FormComponent formComponent) {
0347:                        if (formComponent.isVisibleInHierarchy()) {
0348:                            // remove the FormComponent's persisted data
0349:                            persister.clear(formComponent);
0350:
0351:                            // Disable persistence if requested. Leave unchanged
0352:                            // otherwise.
0353:                            if (formComponent.isPersistent()
0354:                                    && disablePersistence) {
0355:                                formComponent.setPersistent(false);
0356:                            }
0357:                        }
0358:                    }
0359:                });
0360:            }
0361:
0362:            /**
0363:             * Sets the default button. If set (not null), a hidden submit button will
0364:             * be rendered right after the form tag, so that when users press enter in a
0365:             * textfield, this button's action will be selected. If no default button is
0366:             * set (so unset by calling this method with null), nothing additional is
0367:             * rendered.
0368:             * <p>
0369:             * WARNING: note that this is a best effort only. Unfortunately having a
0370:             * 'default' button in a form is ill defined in the standards, and of course
0371:             * IE has it's own way of doing things.
0372:             * </p>
0373:             * 
0374:             * @param button
0375:             *            The button to set as the default button, or null when you want
0376:             *            to 'unset' any previously set default button
0377:             */
0378:            public final void setDefaultButton(Button button) {
0379:                this .defaultButton = button;
0380:            }
0381:
0382:            /**
0383:             * @param maxSize
0384:             *            The maxSize for uploaded files
0385:             */
0386:            public void setMaxSize(final Bytes maxSize) {
0387:                this .maxSize = maxSize;
0388:            }
0389:
0390:            /**
0391:             * Set to true to use enctype='multipart/form-data', and to process file
0392:             * uplloads by default multiPart = false
0393:             * 
0394:             * @param multiPart
0395:             *            whether this form should behave as a multipart form
0396:             */
0397:            public void setMultiPart(boolean multiPart) {
0398:                this .multiPart = multiPart;
0399:            }
0400:
0401:            /**
0402:             * @see wicket.Component#setVersioned(boolean)
0403:             */
0404:            public final Component setVersioned(final boolean isVersioned) {
0405:                super .setVersioned(isVersioned);
0406:
0407:                // Search for FormComponents like TextField etc.
0408:                visitFormComponents(new FormComponent.IVisitor() {
0409:                    public void formComponent(final FormComponent formComponent) {
0410:                        formComponent.setVersioned(isVersioned);
0411:                    }
0412:                });
0413:                return this ;
0414:            }
0415:
0416:            /**
0417:             * Method made final because we want to ensure users call setVersioned.
0418:             * 
0419:             * @see wicket.Component#isVersioned()
0420:             */
0421:            public boolean isVersioned() {
0422:                return super .isVersioned();
0423:            }
0424:
0425:            /**
0426:             * Convenient and typesafe way to visit all the form components on a form
0427:             * 
0428:             * @param visitor
0429:             *            The visitor interface to call
0430:             */
0431:            public final void visitFormComponents(
0432:                    final FormComponent.IVisitor visitor) {
0433:                visitChildren(FormComponent.class, new IVisitor() {
0434:                    public Object component(final Component component) {
0435:                        visitor.formComponent((FormComponent) component);
0436:                        return CONTINUE_TRAVERSAL;
0437:                    }
0438:                });
0439:
0440:                /**
0441:                 * TODO Post 1.2 General: Maybe we should re-think how Borders are
0442:                 * implemented, because there are just too many exceptions in the code
0443:                 * base because of borders. This time it is to solve the problem tested
0444:                 * in BoxBorderTestPage_3 where the Form is defined in the box border
0445:                 * and the FormComponents are in the "body". Thus, the formComponents
0446:                 * are not childs of the form. They are rather childs of the border, as
0447:                 * the Form itself.
0448:                 */
0449:                if (getParent() instanceof  Border) {
0450:                    MarkupContainer border = getParent();
0451:                    Iterator iter = border.iterator();
0452:                    while (iter.hasNext()) {
0453:                        Component child = (Component) iter.next();
0454:                        if (child instanceof  FormComponent) {
0455:                            visitor.formComponent((FormComponent) child);
0456:                        }
0457:                    }
0458:                }
0459:            }
0460:
0461:            /**
0462:             * If a default button was set on this form, this method will be called to
0463:             * render an extra field with an invisible style so that pressing enter in
0464:             * one of the textfields will do a form submit using this button. This
0465:             * method is overridable as what we do is best effort only, and may not what
0466:             * you want in specific situations. So if you have specific usability
0467:             * concerns, or want to follow another strategy, you may override this
0468:             * method.
0469:             * 
0470:             * @param markupStream
0471:             *            The markup stream
0472:             * @param openTag
0473:             *            The open tag for the body
0474:             */
0475:            protected void appendDefaultButtonField(
0476:                    final MarkupStream markupStream, final ComponentTag openTag) {
0477:                String nameAndId = getHiddenFieldId();
0478:                AppendingStringBuffer buffer = new AppendingStringBuffer();
0479:                // get the value, first seeing whether the value attribute is set
0480:                // by a model
0481:                String value = defaultButton.getModelObjectAsString();
0482:                if (value == null || "".equals(value)) {
0483:                    // nope it isn't; try to read from the attributes
0484:                    // note that we're only trying lower case here
0485:                    value = defaultButton.getMarkupAttributes().getString(
0486:                            "value");
0487:                }
0488:
0489:                // append the button
0490:                String userAgent = ((WebClientInfo) getSession()
0491:                        .getClientInfo()).getUserAgent();
0492:                buffer.append("<input type=\"submit\" value=\"").append(value)
0493:                        .append("\" name=\"").append(
0494:                                defaultButton.getInputName()).append("\"");
0495:                if (userAgent != null && userAgent.indexOf("MSIE") != -1) {
0496:                    buffer
0497:                            .append("style=\"width: 0px; height: 0px; position: absolute;\"");
0498:                } else {
0499:                    buffer.append(" style=\"display: none\"");
0500:                }
0501:                buffer.append(" />");
0502:                getResponse().write(buffer);
0503:            }
0504:
0505:            /**
0506:             * Template method to allow clients to do any processing (like recording the
0507:             * current model so that, in case onSubmit does further validation, the
0508:             * model can be rolled back) before the actual updating of form component
0509:             * models is done.
0510:             */
0511:            protected void beforeUpdateFormComponentModels() {
0512:            }
0513:
0514:            /**
0515:             * Called (by the default implementation of 'process') when all fields
0516:             * validated, the form was updated and it's data was allowed to be
0517:             * persisted. It is meant for delegating further processing to clients.
0518:             * <p>
0519:             * This implementation first finds out whether the form processing was
0520:             * triggered by a nested button of this form. If that is the case, that
0521:             * button's onSubmit is called first.
0522:             * </p>
0523:             * <p>
0524:             * Regardless of whether a submitting button was found, the form's onSubmit
0525:             * method is called next.
0526:             * </p>
0527:             * 
0528:             * @param submittingButton
0529:             *            the button that triggered this form processing, or null if the
0530:             *            processing was triggered by something else (like a non-Wicket
0531:             *            submit button or a javascript execution)
0532:             */
0533:            protected void delegateSubmit(Button submittingButton) {
0534:                // when the given button is not null, it means that it was the
0535:                // submitting button
0536:                if (submittingButton != null) {
0537:                    submittingButton.onSubmit();
0538:                }
0539:
0540:                // Model was successfully updated with valid data
0541:                onSubmit();
0542:            }
0543:
0544:            /**
0545:             * Gets the button which submitted this form.
0546:             * 
0547:             * @return The button which submitted this form or null if the processing
0548:             *         was not trigger by a registered button component
0549:             */
0550:            public final Button findSubmittingButton() {
0551:                Button button = (Button) visitChildren(Button.class,
0552:                        new IVisitor() {
0553:                            public Object component(final Component component) {
0554:                                // Get button
0555:                                final Button button = (Button) component;
0556:
0557:                                // Check for button-name or button-name.x request string
0558:                                if (getRequest().getParameter(
0559:                                        button.getInputName()) != null
0560:                                        || getRequest().getParameter(
0561:                                                button.getInputName() + ".x") != null) {
0562:                                    if (!button.isVisible()) {
0563:                                        throw new WicketRuntimeException(
0564:                                                "Submit Button "
0565:                                                        + button.getInputName()
0566:                                                        + " (path="
0567:                                                        + button
0568:                                                                .getPageRelativePath()
0569:                                                        + ") is not visible");
0570:                                    }
0571:                                    return button;
0572:                                }
0573:                                return CONTINUE_TRAVERSAL;
0574:                            }
0575:                        });
0576:
0577:                if (button == null) {
0578:                    button = (Button) getPage().visitChildren(SubmitLink.class,
0579:                            new IVisitor() {
0580:                                public Object component(
0581:                                        final Component component) {
0582:                                    // Get button
0583:                                    final SubmitLink button = (SubmitLink) component;
0584:
0585:                                    // Check for button-name or button-name.x request string
0586:                                    if (button.getForm() == Form.this 
0587:                                            && (getRequest().getParameter(
0588:                                                    button.getInputName()) != null || getRequest()
0589:                                                    .getParameter(
0590:                                                            button
0591:                                                                    .getInputName()
0592:                                                                    + ".x") != null)) {
0593:                                        if (!button.isVisible()) {
0594:                                            throw new WicketRuntimeException(
0595:                                                    "Submit Button is not visible");
0596:                                        }
0597:                                        return button;
0598:                                    }
0599:                                    return CONTINUE_TRAVERSAL;
0600:                                }
0601:                            });
0602:                }
0603:                return button;
0604:            }
0605:
0606:            /**
0607:             * Gets the form component persistence manager; it is lazy loaded.
0608:             * 
0609:             * @return The form component value persister
0610:             */
0611:            protected IValuePersister getValuePersister() {
0612:                return new CookieValuePersister();
0613:            }
0614:
0615:            /**
0616:             * Gets whether the current form has any error registered.
0617:             * 
0618:             * @return True if this form has at least one error.
0619:             */
0620:            public final boolean hasError() {
0621:                // if this form itself has an error message
0622:                if (hasErrorMessage()) {
0623:                    return true;
0624:                }
0625:
0626:                // the form doesn't have any errors, now check any nested form
0627:                // components
0628:                return anyFormComponentError();
0629:            }
0630:
0631:            /**
0632:             * @see wicket.Component#internalOnModelChanged()
0633:             */
0634:            protected void internalOnModelChanged() {
0635:                // Visit all the form components and validate each
0636:                visitFormComponents(new FormComponent.IVisitor() {
0637:                    public void formComponent(final FormComponent formComponent) {
0638:                        // If form component is using form model
0639:                        if (formComponent.sameRootModel(Form.this )) {
0640:                            formComponent.modelChanged();
0641:                        }
0642:                    }
0643:                });
0644:            }
0645:
0646:            /**
0647:             * Mark each form component on this form invalid.
0648:             */
0649:            protected final void markFormComponentsInvalid() {
0650:                // call invalidate methods of all nested form components
0651:                visitFormComponents(new FormComponent.IVisitor() {
0652:                    public void formComponent(final FormComponent formComponent) {
0653:                        if (formComponent.isVisibleInHierarchy()) {
0654:                            formComponent.invalid();
0655:                        }
0656:                    }
0657:                });
0658:            }
0659:
0660:            /**
0661:             * Mark each form component on this form valid.
0662:             */
0663:            protected final void markFormComponentsValid() {
0664:                // call invalidate methods of all nested form components
0665:                visitFormComponents(new FormComponent.IVisitor() {
0666:                    public void formComponent(final FormComponent formComponent) {
0667:                        if (formComponent.isVisibleInHierarchy()) {
0668:                            formComponent.valid();
0669:                        }
0670:                    }
0671:                });
0672:            }
0673:
0674:            /**
0675:             * Returns the HiddenFieldId which will be used as the name and id property
0676:             * of the hiddenfield that is generated for event dispatches.
0677:             * 
0678:             * @return The name and id of the hidden field.
0679:             */
0680:            protected final String getHiddenFieldId() {
0681:                return getJavascriptId() + ":hf:0";
0682:            }
0683:
0684:            /**
0685:             * Returns the javascript/css id of this form that will be used to generated
0686:             * the id="xxx" attribute. it will be generated if not set already in the
0687:             * onComponentTag. Where it will be tried to load from the markup first
0688:             * before it is generated.
0689:             * 
0690:             * @return The javascript/css id of this form.
0691:             */
0692:            protected final String getJavascriptId() {
0693:                if (Strings.isEmpty(javascriptId)) {
0694:                    javascriptId = getMarkupId();
0695:                }
0696:                return javascriptId;
0697:            }
0698:
0699:            /**
0700:             * Append an additional hidden input tag to support anchor tags that can
0701:             * submit a form.
0702:             * 
0703:             * @param markupStream
0704:             *            The markup stream
0705:             * @param openTag
0706:             *            The open tag for the body
0707:             */
0708:            protected void onComponentTagBody(final MarkupStream markupStream,
0709:                    final ComponentTag openTag) {
0710:                // get the hidden field id
0711:                String nameAndId = getHiddenFieldId();
0712:
0713:                // render the hidden field
0714:                AppendingStringBuffer buffer = new AppendingStringBuffer(
0715:                        "<div style=\"display:none\"><input type=\"hidden\" name=\"")
0716:                        .append(nameAndId).append("\" id=\"").append(nameAndId)
0717:                        .append("\" /></div>");
0718:                getResponse().write(buffer);
0719:
0720:                // if a default button was set, handle the rendering of that
0721:                if (defaultButton != null
0722:                        && defaultButton.isVisibleInHierarchy()
0723:                        && defaultButton.isEnabled()) {
0724:                    appendDefaultButtonField(markupStream, openTag);
0725:                }
0726:
0727:                // do the rest of the processing
0728:                super .onComponentTagBody(markupStream, openTag);
0729:            }
0730:
0731:            /**
0732:             * @see wicket.Component#onComponentTag(ComponentTag)
0733:             */
0734:            protected void onComponentTag(final ComponentTag tag) {
0735:                checkComponentTag(tag, "form");
0736:                super .onComponentTag(tag);
0737:
0738:                // If the javascriptid is already generated then use that on even it was
0739:                // before the first render. Bbecause there could be a component which
0740:                // already uses it to submit the forum. This should be fixed when we
0741:                // pre parse the markup so that we know the id is at front.
0742:                if (!Strings.isEmpty(javascriptId)) {
0743:                    tag.put("id", javascriptId);
0744:                } else {
0745:                    javascriptId = (String) tag.getAttributes().get("id");
0746:                    if (Strings.isEmpty(javascriptId)) {
0747:                        javascriptId = getJavascriptId();
0748:                        tag.put("id", javascriptId);
0749:                    }
0750:                }
0751:                tag.put("method", "post");
0752:                tag.put("action", Strings.replaceAll(
0753:                        urlFor(IFormSubmitListener.INTERFACE), "&", "&amp;"));
0754:                if (multiPart) {
0755:                    tag.put("enctype", "multipart/form-data");
0756:                } else {
0757:                    // sanity check
0758:                    String enctype = (String) tag.getAttributes()
0759:                            .get("enctype");
0760:                    if ("multipart/form-data".equalsIgnoreCase(enctype)) {
0761:                        // though not set explicitly in Java, this is a multipart form
0762:                        setMultiPart(true);
0763:                    }
0764:                }
0765:            }
0766:
0767:            /**
0768:             * Method to override if you want to do something special when an error
0769:             * occurs (other than simply displaying validation errors).
0770:             */
0771:            protected void onError() {
0772:            }
0773:
0774:            /**
0775:             * @see wicket.Component#onRender(MarkupStream)
0776:             */
0777:            protected void onRender(final MarkupStream markupStream) {
0778:                // Force multi-part on if any child form component is multi-part
0779:                visitFormComponents(new FormComponent.IVisitor() {
0780:                    public void formComponent(FormComponent formComponent) {
0781:                        if (formComponent.isVisible()
0782:                                && formComponent.isMultiPart()) {
0783:                            setMultiPart(true);
0784:                        }
0785:                    }
0786:                });
0787:
0788:                super .onRender(markupStream);
0789:            }
0790:
0791:            /**
0792:             * Implemented by subclasses to deal with form submits.
0793:             */
0794:            protected void onSubmit() {
0795:            }
0796:
0797:            /**
0798:             * Process the form. Though you can override this method to provide your
0799:             * whole own algorithm, it is not recommended to do so.
0800:             * <p>
0801:             * See the class documentation for further details on the form processing
0802:             * </p>
0803:             * 
0804:             * @return False if the form had an error
0805:             */
0806:            public boolean process() {
0807:                // run validation
0808:                validate();
0809:
0810:                // If a validation error occurred
0811:                if (hasError()) {
0812:                    // mark all children as invalid
0813:                    markFormComponentsInvalid();
0814:
0815:                    // let subclass handle error
0816:                    onError();
0817:
0818:                    // Form has an error
0819:                    return false;
0820:                } else {
0821:                    // mark all childeren as valid
0822:                    markFormComponentsValid();
0823:
0824:                    // before updating, call the interception method for clients
0825:                    beforeUpdateFormComponentModels();
0826:
0827:                    // Update model using form data
0828:                    updateFormComponentModels();
0829:
0830:                    // Persist FormComponents if requested
0831:                    persistFormComponentData();
0832:
0833:                    // Form has no error
0834:                    return true;
0835:                }
0836:            }
0837:
0838:            /**
0839:             * Update the model of all form components using the fields that were sent
0840:             * with the current request.
0841:             * 
0842:             * @see wicket.markup.html.form.FormComponent#updateModel()
0843:             */
0844:            protected final void updateFormComponentModels() {
0845:                visitFormComponents(new FormComponent.IVisitor() {
0846:                    public void formComponent(final FormComponent formComponent) {
0847:                        // Only update the component when it is visible and valid
0848:                        if (formComponent.isVisibleInHierarchy()
0849:                                && formComponent.isEnabled()
0850:                                && formComponent.isValid()
0851:                                && formComponent.isEnableAllowed()) {
0852:                            // Potentially update the model
0853:                            formComponent.updateModel();
0854:                        }
0855:                    }
0856:                });
0857:            }
0858:
0859:            /**
0860:             * Clears the input from the form's nested children of type
0861:             * {@link FormComponent}. This method is typically called when a form needs
0862:             * to be reset.
0863:             */
0864:            public final void clearInput() {
0865:                // Visit all the (visible) form components and clear the input on each.
0866:                visitFormComponents(new FormComponent.IVisitor() {
0867:                    public void formComponent(final FormComponent formComponent) {
0868:                        if (formComponent.isVisibleInHierarchy()) {
0869:                            // Clear input from form component
0870:                            formComponent.clearInput();
0871:                        }
0872:                    }
0873:                });
0874:            }
0875:
0876:            /**
0877:             * Validates the form. This method is typically called before updating any
0878:             * models.
0879:             */
0880:            protected void validate() {
0881:                validateRequired();
0882:
0883:                validateConversion();
0884:
0885:                validateValidators();
0886:
0887:                validateFormValidators();
0888:            }
0889:
0890:            /**
0891:             * Triggers input required attribute validation on all form components
0892:             */
0893:            private void validateRequired() {
0894:                visitFormComponents(new ValidationVisitor() {
0895:                    public void validate(final FormComponent formComponent) {
0896:                        formComponent.validateRequired();
0897:                    }
0898:                });
0899:            }
0900:
0901:            /**
0902:             * Triggers type conversion on form components
0903:             */
0904:            private void validateConversion() {
0905:                visitFormComponents(new ValidationVisitor() {
0906:                    public void validate(final FormComponent formComponent) {
0907:                        formComponent.convert();
0908:                    }
0909:                });
0910:            }
0911:
0912:            /**
0913:             * Triggers all IValidator validators added to the form components
0914:             */
0915:            private void validateValidators() {
0916:                visitFormComponents(new ValidationVisitor() {
0917:                    public void validate(final FormComponent formComponent) {
0918:                        formComponent.validateValidators();
0919:                    }
0920:                });
0921:            }
0922:
0923:            /**
0924:             * Triggers any added {@link IFormValidator}s.
0925:             */
0926:            private void validateFormValidators() {
0927:                final int count = formValidators_size();
0928:                for (int i = 0; i < count; i++) {
0929:                    validateFormValidator(formValidators_get(i));
0930:                }
0931:            }
0932:
0933:            /**
0934:             * Validates form with the given form validator
0935:             * 
0936:             * @param validator
0937:             */
0938:            protected final void validateFormValidator(
0939:                    final IFormValidator validator) {
0940:                if (validator == null) {
0941:                    throw new IllegalArgumentException(
0942:                            "Argument [[validator]] cannot be null");
0943:                }
0944:
0945:                final FormComponent[] dependents = validator
0946:                        .getDependentFormComponents();
0947:
0948:                boolean validate = true;
0949:
0950:                if (dependents != null) {
0951:                    for (int j = 0; j < dependents.length; j++) {
0952:                        final FormComponent dependent = dependents[j];
0953:                        if (!dependent.isValid()) {
0954:                            validate = false;
0955:                            break;
0956:                        }
0957:                    }
0958:                }
0959:
0960:                if (validate) {
0961:                    validator.validate(this );
0962:                }
0963:            }
0964:
0965:            /**
0966:             * Find out whether there is any registered error for a form component.
0967:             * 
0968:             * @return whether there is any registered error for a form component
0969:             */
0970:            private boolean anyFormComponentError() {
0971:                final Object value = visitChildren(new IVisitor() {
0972:                    public Object component(final Component component) {
0973:                        if (component.hasErrorMessage()) {
0974:                            return STOP_TRAVERSAL;
0975:                        }
0976:
0977:                        // Traverse all children
0978:                        return CONTINUE_TRAVERSAL;
0979:                    }
0980:                });
0981:
0982:                return value == IVisitor.STOP_TRAVERSAL ? true : false;
0983:            }
0984:
0985:            /**
0986:             * @return False if form is multipart and upload failed
0987:             */
0988:            private final boolean handleMultiPart() {
0989:                if (multiPart) {
0990:                    // Change the request to a multipart web request so parameters are
0991:                    // parsed out correctly
0992:                    try {
0993:                        final WebRequest multipartWebRequest = ((WebRequest) getRequest())
0994:                                .newMultipartWebRequest(this .maxSize);
0995:                        getRequestCycle().setRequest(multipartWebRequest);
0996:                    } catch (WicketRuntimeException wre) {
0997:                        if (wre.getCause() == null
0998:                                || !(wre.getCause() instanceof  FileUploadException)) {
0999:                            throw wre;
1000:                        }
1001:
1002:                        FileUploadException e = (FileUploadException) wre
1003:                                .getCause();
1004:                        // Create model with exception and maximum size values
1005:                        final Map model = new HashMap();
1006:                        model.put("exception", e);
1007:                        model.put("maxSize", maxSize);
1008:
1009:                        if (e instanceof  SizeLimitExceededException) {
1010:                            // Resource key should be <form-id>.uploadTooLarge to
1011:                            // override default message
1012:                            final String defaultValue = "Upload must be less than "
1013:                                    + maxSize;
1014:                            String msg = getString(getId() + "."
1015:                                    + UPLOAD_TOO_LARGE_RESOURCE_KEY, Model
1016:                                    .valueOf(model), defaultValue);
1017:                            error(msg);
1018:
1019:                            if (log.isDebugEnabled()) {
1020:                                log.error(msg, e);
1021:                            } else {
1022:                                log.error(msg);
1023:                            }
1024:                        } else {
1025:                            // Resource key should be <form-id>.uploadFailed to override
1026:                            // default message
1027:                            final String defaultValue = "Upload failed: "
1028:                                    + e.getLocalizedMessage();
1029:                            String msg = getString(getId() + "."
1030:                                    + UPLOAD_FAILED_RESOURCE_KEY, Model
1031:                                    .valueOf(model), defaultValue);
1032:                            error(msg);
1033:
1034:                            log.error(msg, e);
1035:                        }
1036:
1037:                        // don't process the form if there is a FileUploadException
1038:                        return false;
1039:                    }
1040:                }
1041:                return true;
1042:            }
1043:
1044:            /**
1045:             * Persist (e.g. Cookie) FormComponent data to be reloaded and re-assigned
1046:             * to the FormComponent automatically when the page is visited by the user
1047:             * next time.
1048:             * 
1049:             * @see wicket.markup.html.form.FormComponent#updateModel()
1050:             */
1051:            private void persistFormComponentData() {
1052:                // Cannot add cookies to request cycle unless it accepts them
1053:                // We could conceivably be HTML over some other protocol!
1054:                if (getRequestCycle() instanceof  WebRequestCycle) {
1055:                    // The persistence manager responsible to persist and retrieve
1056:                    // FormComponent data
1057:                    final IValuePersister persister = getValuePersister();
1058:
1059:                    // Search for FormComponent children. Ignore all other
1060:                    visitFormComponents(new FormComponent.IVisitor() {
1061:                        public void formComponent(
1062:                                final FormComponent formComponent) {
1063:                            if (formComponent.isVisibleInHierarchy()) {
1064:                                // If peristence is switched on for that FormComponent
1065:                                // ...
1066:                                if (formComponent.isPersistent()) {
1067:                                    // Save component's data (e.g. in a cookie)
1068:                                    persister.save(formComponent);
1069:                                } else {
1070:                                    // Remove component's data (e.g. cookie)
1071:                                    persister.clear(formComponent);
1072:                                }
1073:                            }
1074:                        }
1075:                    });
1076:                }
1077:            }
1078:
1079:            /**
1080:             * Method for dispatching/calling a interface on a page from the given url.
1081:             * Used by {@link wicket.markup.html.form.Form#onFormSubmitted()} for
1082:             * dispatching events
1083:             * 
1084:             * @param page
1085:             *            The page where the event should be called on.
1086:             * @param url
1087:             *            The url which describes the component path and the interface
1088:             *            to be called.
1089:             */
1090:            private void dispatchEvent(final Page page, final String url) {
1091:                RequestCycle rc = RequestCycle.get();
1092:                IRequestCycleProcessor processor = rc.getProcessor();
1093:                final RequestParameters requestParameters = processor
1094:                        .getRequestCodingStrategy().decode(
1095:                                new FormDispatchRequest(rc.getRequest(), url));
1096:                IRequestTarget rt = processor.resolve(rc, requestParameters);
1097:                if (rt instanceof  ListenerInterfaceRequestTarget) {
1098:                    ListenerInterfaceRequestTarget interfaceTarget = ((ListenerInterfaceRequestTarget) rt);
1099:                    interfaceTarget.getRequestListenerInterface().invoke(page,
1100:                            interfaceTarget.getTarget());
1101:                } else {
1102:                    throw new WicketRuntimeException(
1103:                            "Attempt to access unknown request listener interface "
1104:                                    + requestParameters.getInterfaceName());
1105:                }
1106:            }
1107:
1108:            /**
1109:             * Visits the form's children FormComponents and inform them that a new user
1110:             * input is available in the Request
1111:             */
1112:            private void inputChanged() {
1113:                visitFormComponents(new FormComponent.IVisitor() {
1114:                    public void formComponent(final FormComponent formComponent) {
1115:                        if (formComponent.isVisibleInHierarchy()) {
1116:                            formComponent.inputChanged();
1117:                        }
1118:                    }
1119:                });
1120:            }
1121:
1122:            /**
1123:             * This generates a piece of javascript code that sets the url in the
1124:             * special hidden field and submits the form.
1125:             * 
1126:             * Warning: This code should only be called in the rendering phase for form
1127:             * components inside the form because it uses the css/javascript id of the
1128:             * form which can be stored in the markup.
1129:             * 
1130:             * @param url
1131:             *            The interface url that has to be stored in the hidden field
1132:             *            and submitted
1133:             * @return The javascript code that submits the form.
1134:             */
1135:            public final CharSequence getJsForInterfaceUrl(CharSequence url) {
1136:                return new AppendingStringBuffer("document.getElementById('")
1137:                        .append(getHiddenFieldId()).append("').value='")
1138:                        .append(url).append("';document.getElementById('")
1139:                        .append(getJavascriptId()).append("').submit();");
1140:            }
1141:
1142:            /**
1143:             * 
1144:             */
1145:            class FormDispatchRequest extends Request {
1146:                private final Request realRequest;
1147:
1148:                private final String url;
1149:
1150:                private final Map params = new HashMap(4);
1151:
1152:                /**
1153:                 * Construct.
1154:                 * 
1155:                 * @param realRequest
1156:                 * @param url
1157:                 */
1158:                public FormDispatchRequest(final Request realRequest,
1159:                        final String url) {
1160:                    this .realRequest = realRequest;
1161:                    this .url = realRequest.decodeURL(url);
1162:
1163:                    String queryPart = this .url
1164:                            .substring(this .url.indexOf("?") + 1);
1165:                    StringTokenizer paramsSt = new StringTokenizer(queryPart,
1166:                            "&");
1167:                    while (paramsSt.hasMoreTokens()) {
1168:                        String param = paramsSt.nextToken();
1169:                        int equalsSign = param.indexOf("=");
1170:                        if (equalsSign >= 0) {
1171:                            String paramName = param.substring(0, equalsSign);
1172:                            String value = param.substring(equalsSign + 1);
1173:                            params.put(paramName, value);
1174:                        } else {
1175:                            params.put(param, "");
1176:                        }
1177:                    }
1178:                }
1179:
1180:                /**
1181:                 * @see wicket.Request#getLocale()
1182:                 */
1183:                public Locale getLocale() {
1184:                    return realRequest.getLocale();
1185:                }
1186:
1187:                /**
1188:                 * @see wicket.Request#getParameter(java.lang.String)
1189:                 */
1190:                public String getParameter(String key) {
1191:                    return (String) params.get(key);
1192:                }
1193:
1194:                /**
1195:                 * @see wicket.Request#getParameterMap()
1196:                 */
1197:                public Map getParameterMap() {
1198:                    return params;
1199:                }
1200:
1201:                /**
1202:                 * @see wicket.Request#getParameters(java.lang.String)
1203:                 */
1204:                public String[] getParameters(String key) {
1205:                    String param = (String) params.get(key);
1206:                    if (param != null) {
1207:                        return new String[] { param };
1208:                    }
1209:                    return new String[0];
1210:                }
1211:
1212:                /**
1213:                 * @see wicket.Request#getPath()
1214:                 */
1215:                public String getPath() {
1216:                    return realRequest.getPath();
1217:                }
1218:
1219:                /**
1220:                 * @see wicket.Request#getRelativeURL()
1221:                 */
1222:                public String getRelativeURL() {
1223:                    int tmp = url.indexOf("/", 1);
1224:                    if (tmp != -1) {
1225:                        return url.substring(tmp);
1226:                    }
1227:                    return url;
1228:                }
1229:
1230:                /**
1231:                 * @see wicket.Request#getURL()
1232:                 */
1233:                public String getURL() {
1234:                    return url;
1235:                }
1236:            }
1237:
1238:            /**
1239:             * Returns the prefix used when building validator keys. This allows a form
1240:             * to use a separate "set" of keys. For example if prefix "short" is
1241:             * returned, validator key short.RequiredValidator will be tried instead of
1242:             * RequiredValidator key.
1243:             * <p>
1244:             * This can be useful when different designs are used for a form. In a form
1245:             * where error messages are displayed next to their respective form
1246:             * components as opposed to at the top of the form, the ${label} attribute
1247:             * is of little use and only causes redundant information to appear in the
1248:             * message. Forms like these can return the "short" (or any other string)
1249:             * validator prefix and declare key: short.RequiredValidator=required to
1250:             * override the longer message which is usually declared like this:
1251:             * RequiredValidator=${label} is a required field
1252:             * <p>
1253:             * Returned prefix will be used for all form components. The prefix can also
1254:             * be overridden on form component level by overriding
1255:             * {@link FormComponent#getValidatorKeyPrefix()}
1256:             * 
1257:             * @return prefix prepended to validator keys
1258:             */
1259:            public String getValidatorKeyPrefix() {
1260:                return null;
1261:            }
1262:
1263:            /**
1264:             * Adds a form validator to the form.
1265:             * 
1266:             * @see IFormValidator
1267:             * @param validator
1268:             *            validator
1269:             */
1270:            public void add(IFormValidator validator) {
1271:                if (validator == null) {
1272:                    throw new IllegalArgumentException(
1273:                            "validator argument cannot be null");
1274:                }
1275:                formValidators_add(validator);
1276:            }
1277:
1278:            /**
1279:             * @param validator
1280:             *            The form validator to add to the formValidators Object (which
1281:             *            may be an array of IFormValidators or a single instance, for
1282:             *            efficiency)
1283:             */
1284:            private void formValidators_add(final IFormValidator validator) {
1285:                if (this .formValidators == null) {
1286:                    this .formValidators = validator;
1287:                } else {
1288:                    // Get current list size
1289:                    final int size = formValidators_size();
1290:
1291:                    // Create array that holds size + 1 elements
1292:                    final IFormValidator[] validators = new IFormValidator[size + 1];
1293:
1294:                    // Loop through existing validators copying them
1295:                    for (int i = 0; i < size; i++) {
1296:                        validators[i] = formValidators_get(i);
1297:                    }
1298:
1299:                    // Add new validator to the end
1300:                    validators[size] = validator;
1301:
1302:                    // Save new validator list
1303:                    this .formValidators = validators;
1304:                }
1305:            }
1306:
1307:            /**
1308:             * Gets form validator from formValidators Object (which may be an array of
1309:             * IFormValidators or a single instance, for efficiency) at the given index
1310:             * 
1311:             * @param index
1312:             *            The index of the validator to get
1313:             * @return The form validator
1314:             */
1315:            private IFormValidator formValidators_get(int index) {
1316:                if (this .formValidators == null) {
1317:                    throw new IndexOutOfBoundsException();
1318:                }
1319:                if (this .formValidators instanceof  IFormValidator[]) {
1320:                    return ((IFormValidator[]) formValidators)[index];
1321:                }
1322:                return (IFormValidator) formValidators;
1323:            }
1324:
1325:            /**
1326:             * @return The number of form validators in the formValidators Object (which
1327:             *         may be an array of IFormValidators or a single instance, for
1328:             *         efficiency)
1329:             */
1330:            private int formValidators_size() {
1331:                if (this .formValidators == null) {
1332:                    return 0;
1333:                }
1334:                if (this .formValidators instanceof  IFormValidator[]) {
1335:                    return ((IFormValidator[]) formValidators).length;
1336:                }
1337:                return 1;
1338:            }
1339:
1340:            /**
1341:             * /** Registers an error feedback message for this component
1342:             * 
1343:             * @param error
1344:             *            error message
1345:             * @param args
1346:             *            argument replacement map for ${key} variables
1347:             */
1348:            public final void error(String error, Map args) {
1349:                error(new MapVariableInterpolator(error, args).toString());
1350:            }
1351:
1352:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.