Source Code Cross Referenced for FormControl.java in  » HTML-Parser » jericho-html » au » id » jericho » lib » html » 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 » HTML Parser » jericho html » au.id.jericho.lib.html 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        // Jericho HTML Parser - Java based library for analysing and manipulating HTML
0002:        // Version 2.5
0003:        // Copyright (C) 2007 Martin Jericho
0004:        // http://jerichohtml.sourceforge.net/
0005:        //
0006:        // This library is free software; you can redistribute it and/or
0007:        // modify it under the terms of either one of the following licences:
0008:        //
0009:        // 1. The Eclipse Public License (EPL) version 1.0,
0010:        // included in this distribution in the file licence-epl-1.0.html
0011:        // or available at http://www.eclipse.org/legal/epl-v10.html
0012:        //
0013:        // 2. The GNU Lesser General Public License (LGPL) version 2.1 or later,
0014:        // included in this distribution in the file licence-lgpl-2.1.txt
0015:        // or available at http://www.gnu.org/licenses/lgpl.txt
0016:        //
0017:        // This library is distributed on an "AS IS" basis,
0018:        // WITHOUT WARRANTY OF ANY KIND, either express or implied.
0019:        // See the individual licence texts for more details.
0020:
0021:        package au.id.jericho.lib.html;
0022:
0023:        import java.util.*;
0024:
0025:        /**
0026:         * Represents an HTML form <a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#form-controls">control</a>.
0027:         * <p>
0028:         * A <code>FormControl</code> consists of a single {@linkplain #getElement() element}
0029:         * that matches one of the {@linkplain FormControlType form control types}.
0030:         * <p>
0031:         * The term <i><a name="OutputElement">output element</a></i> is used to describe the element that is
0032:         * {@linkplain OutputSegment#writeTo(Writer) output} if this form control is {@linkplain OutputDocument#replace(FormControl) replaced}
0033:         * in an {@link OutputDocument}.
0034:         * <p>
0035:         * A <i><a name="PredefinedValueControl">predefined value control</a></i> is a form control for which
0036:         * {@link #getFormControlType()}.{@link FormControlType#hasPredefinedValue() hasPredefinedValue()}
0037:         * returns <code>true</code>.  It has a {@linkplain #getFormControlType() control type} of
0038:         * {@link FormControlType#CHECKBOX CHECKBOX}, {@link FormControlType#RADIO RADIO}, {@link FormControlType#BUTTON BUTTON},
0039:         * {@link FormControlType#SUBMIT SUBMIT}, {@link FormControlType#IMAGE IMAGE}, {@link FormControlType#SELECT_SINGLE SELECT_SINGLE}
0040:         * or {@link FormControlType#SELECT_MULTIPLE SELECT_MULTIPLE}.
0041:         * <p>
0042:         * A <i><a name="UserValueControl">user value control</a></i> is a form control for which
0043:         * {@link #getFormControlType()}.{@link FormControlType#hasPredefinedValue() hasPredefinedValue()}
0044:         * returns <code>false</code>.  It has a {@linkplain #getFormControlType() control type} of
0045:         * {@link FormControlType#FILE FILE}, {@link FormControlType#HIDDEN HIDDEN}, {@link FormControlType#PASSWORD PASSWORD},
0046:         * {@link FormControlType#TEXT TEXT} or {@link FormControlType#TEXTAREA TEXTAREA}.
0047:         * <p>
0048:         * The functionality of most significance to users of this class relates to the
0049:         * <i><a name="DisplayCharacteristics">display characteristics</a></i> of the <a href="#OutputElement">output element</a>,
0050:         * manipulated using the {@link #setDisabled(boolean)} and {@link #setOutputStyle(FormControlOutputStyle)} methods.
0051:         * <p>
0052:         * As a general rule, the operations dealing with the control's <a href="#SubmissionValue">submission values</a>
0053:         * are better performed on a {@link FormFields} or {@link FormField} object, which provide a more
0054:         * intuitive interface by grouping form controls of the same {@linkplain #getName() name} together.
0055:         * The higher abstraction level of these classes means they can automatically ensure that the
0056:         * <a href="#SubmissionValue">submission values</a> of their constituent controls are consistent with each other,
0057:         * for example by ensuring that only one {@link FormControlType#RADIO RADIO} control with a given name is
0058:         * {@link #isChecked() checked} at a time.
0059:         * <p>
0060:         * A {@link FormFields} object can be directly {@linkplain FormFields#FormFields(Collection) constructed} from
0061:         * a collection of <code>FormControl</code> objects.
0062:         * <p>
0063:         * <code>FormControl</code> instances are obtained using the {@link Element#getFormControl()} method or are created automatically
0064:         * with the creation of a {@link FormFields} object via the {@link Segment#findFormFields()} method.
0065:         *
0066:         * @see FormControlType
0067:         * @see FormFields
0068:         * @see FormField
0069:         */
0070:        public abstract class FormControl extends Segment {
0071:            FormControlType formControlType;
0072:            String name;
0073:            ElementContainer elementContainer;
0074:            FormControlOutputStyle outputStyle = FormControlOutputStyle.NORMAL;
0075:
0076:            private static final String CHECKBOX_NULL_DEFAULT_VALUE = "on";
0077:            private static Comparator COMPARATOR = new PositionComparator();
0078:
0079:            static FormControl construct(final Element element) {
0080:                final String tagName = element.getStartTag().getName();
0081:                if (tagName == Tag.INPUT) {
0082:                    final String typeAttributeValue = element.getAttributes()
0083:                            .getRawValue(Attribute.TYPE);
0084:                    if (typeAttributeValue == null)
0085:                        return new InputFormControl(element,
0086:                                FormControlType.TEXT);
0087:                    FormControlType formControlType = FormControlType
0088:                            .getFromInputElementType(typeAttributeValue
0089:                                    .toLowerCase());
0090:                    if (formControlType == null) {
0091:                        if (element.source.logger.isInfoEnabled())
0092:                            element.source.logger
0093:                                    .info(element.source
0094:                                            .getRowColumnVector(element.begin)
0095:                                            .appendTo(new StringBuffer(200))
0096:                                            .append(
0097:                                                    ": INPUT control with unrecognised type \"")
0098:                                            .append(typeAttributeValue)
0099:                                            .append(
0100:                                                    "\" assumed to be type \"text\"")
0101:                                            .toString());
0102:                        formControlType = FormControlType.TEXT;
0103:                    }
0104:                    if (formControlType == FormControlType.TEXT)
0105:                        return new InputFormControl(element, formControlType);
0106:                    if (formControlType == FormControlType.CHECKBOX
0107:                            || formControlType == FormControlType.RADIO)
0108:                        return new RadioCheckboxFormControl(element,
0109:                                formControlType);
0110:                    if (formControlType == FormControlType.SUBMIT)
0111:                        return new SubmitFormControl(element, formControlType);
0112:                    if (formControlType == FormControlType.IMAGE)
0113:                        return new ImageSubmitFormControl(element);
0114:                    if (formControlType == FormControlType.NON_FORM_CONTROL)
0115:                        return null;
0116:                    // formControlType is HIDDEN || PASSWORD || FILE
0117:                    return new InputFormControl(element, formControlType);
0118:                } else if (tagName == Tag.SELECT) {
0119:                    return new SelectFormControl(element);
0120:                } else if (tagName == Tag.TEXTAREA) {
0121:                    return new TextAreaFormControl(element);
0122:                } else if (tagName == Tag.BUTTON) {
0123:                    return "submit".equalsIgnoreCase(element.getAttributes()
0124:                            .getRawValue(Attribute.TYPE)) ? new SubmitFormControl(
0125:                            element, FormControlType.BUTTON)
0126:                            : null;
0127:                } else {
0128:                    return null;
0129:                }
0130:            }
0131:
0132:            private FormControl(final Element element,
0133:                    final FormControlType formControlType,
0134:                    final boolean loadPredefinedValue) {
0135:                super (element.source, element.begin, element.end);
0136:                elementContainer = new ElementContainer(element,
0137:                        loadPredefinedValue);
0138:                this .formControlType = formControlType;
0139:                name = element.getAttributes().getValue(Attribute.NAME);
0140:                verifyName();
0141:            }
0142:
0143:            /**
0144:             * Returns the {@linkplain FormControlType type} of this form control.
0145:             * @return the {@linkplain FormControlType type} of this form control.
0146:             */
0147:            public final FormControlType getFormControlType() {
0148:                return formControlType;
0149:            }
0150:
0151:            /**
0152:             * Returns the <a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#control-name">name</a> of the control.
0153:             * <p>
0154:             * The name comes from the value of the <code>name</code> {@linkplain Attribute attribute} of the
0155:             * {@linkplain #getElement() form control's element}, not the {@linkplain Element#getName() name of the element} itself.
0156:             * <p>
0157:             * Since a {@link FormField} is simply a group of controls with the same name, the terms <i>control name</i> and
0158:             * <i>field name</i> are for the most part synonymous, with only a possible difference in case differentiating them.
0159:             * <p>
0160:             * In contrast to the {@link FormField#getName()} method, this method always returns the name using the original case
0161:             * from the source document, regardless of the current setting of the
0162:             * {@link Config#CurrentCompatibilityMode}<code>.</code>{@link Config.CompatibilityMode#isFormFieldNameCaseInsensitive() FormFieldNameCaseInsensitive} property.
0163:             *
0164:             * @return the <a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#control-name">name</a> of the control.
0165:             */
0166:            public final String getName() {
0167:                return name;
0168:            }
0169:
0170:            /**
0171:             * Returns the {@linkplain Element element} representing this form control in the source document.
0172:             * <p>
0173:             * The {@linkplain Element#getAttributes() attributes} of this source element should correspond with the
0174:             * <a href="#OutputAttributes">output attributes</a> if the
0175:             * <a href="#DisplayCharacteristics">display characteristics</a> or <a href="FormField.html#SubmissionValue">submission values</a>
0176:             * have not been modified.
0177:             *
0178:             * @return the {@linkplain Element element} representing this form control in the source document.
0179:             */
0180:            public final Element getElement() {
0181:                return elementContainer.element;
0182:            }
0183:
0184:            /**
0185:             * Returns an iterator over the {@link Tag#OPTION OPTION} {@linkplain Element elements} contained within this control, in order of appearance.
0186:             * <p>
0187:             * This method is only relevant to form controls with a {@linkplain #getFormControlType() type} of 
0188:             * {@link FormControlType#SELECT_SINGLE SELECT_SINGLE} or {@link FormControlType#SELECT_MULTIPLE SELECT_MULTIPLE}.
0189:             *
0190:             * @return an iterator over the {@link Tag#OPTION OPTION} {@linkplain Element elements} contained within this control, in order of appearance.
0191:             * @throws UnsupportedOperationException if the {@linkplain #getFormControlType() type} of this control is not {@link FormControlType#SELECT_SINGLE SELECT_SINGLE} or {@link FormControlType#SELECT_MULTIPLE SELECT_MULTIPLE}.
0192:             */
0193:            public Iterator getOptionElementIterator() {
0194:                // overridden in SelectFormControl
0195:                throw new UnsupportedOperationException(
0196:                        "Only SELECT controls contain OPTION elements");
0197:            }
0198:
0199:            /**
0200:             * Returns the current {@linkplain FormControlOutputStyle output style} of this form control.
0201:             * <p>
0202:             * This property affects how this form control is displayed if it has been {@linkplain OutputDocument#replace(FormControl) replaced}
0203:             * in an {@link OutputDocument}.
0204:             * See the documentation of the {@link FormControlOutputStyle} class for information on the available output styles.
0205:             * <p>
0206:             * The default output style for every form control is {@link FormControlOutputStyle#NORMAL}.
0207:             *
0208:             * @return the current {@linkplain FormControlOutputStyle output style} of this form control.
0209:             * @see #setOutputStyle(FormControlOutputStyle)
0210:             */
0211:            public FormControlOutputStyle getOutputStyle() {
0212:                return outputStyle;
0213:            }
0214:
0215:            /**
0216:             * Sets the {@linkplain FormControlOutputStyle output style} of this form control.
0217:             * <p>
0218:             * See the {@link #getOutputStyle()} method for a full description of this property.
0219:             *
0220:             * @param outputStyle  the new {@linkplain FormControlOutputStyle output style} of this form control.
0221:             */
0222:            public void setOutputStyle(final FormControlOutputStyle outputStyle) {
0223:                this .outputStyle = outputStyle;
0224:            }
0225:
0226:            /**
0227:             * Returns a map of the names and values of this form control's <a href="#OutputAttributes">output attributes</a>.
0228:             * <p>
0229:             * The term <i><a name="OutputAttributes">output attributes</a></i> is used in this library to refer to the
0230:             * <a target="_blank" href="http://www.w3.org/TR/html401/intro/sgmltut.html#h-3.2.2">attributes</a> of a form control's
0231:             * <a href="#OutputElement">output element</a>.
0232:             * <p>
0233:             * The map keys are the <code>String</code> attribute names, which should all be in lower case.
0234:             * The map values are the corresponding <code>CharSequence</code> attribute values, with a <code>null</code> value given
0235:             * to an attribute that {@linkplain Attribute#hasValue() has no value}.
0236:             * <p>
0237:             * Direct manipulation of the returned map affects the attributes of this form control's <a href="#OutputElement">output element</a>.
0238:             * It is the responsibility of the user to ensure that all entries added to the map use the correct key and value types,
0239:             * and that all keys (attribute names) are in lower case.
0240:             * <p>
0241:             * It is recommended that the <a href="#SubmissionValueModificationMethods">submission value modification methods</a>
0242:             * are used to modify attributes that affect the <a href="#SubmissionValue">submission value</a> of the control
0243:             * rather than manipulating the attributes map directly.
0244:             * <p>
0245:             * An iteration over the map entries will return the attributes in the same order as they appeared in the source document, or
0246:             * at the end if the attribute was not present in the source document.
0247:             * <p>
0248:             * The returned attributes only correspond with those of the {@linkplain #getElement() source element} if the control's
0249:             * <a href="#DisplayCharacteristics">display characteristics</a> and <a href="#SubmissionValue">submission values</a>
0250:             * have not been modified.
0251:             *
0252:             * @return a map of the names and values of this form control's <a href="#OutputAttributes">output attributes</a>.
0253:             */
0254:            public final Map getAttributesMap() {
0255:                return elementContainer.getAttributesMap();
0256:            }
0257:
0258:            /**
0259:             * Indicates whether this form control is <a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#adef-disabled">disabled</a>.
0260:             * <p>
0261:             * The form control is disabled if the attribute 
0262:             * "<code><a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#adef-disabled">disabled</a></code>" 
0263:             * is present in its <a href="#OutputElement">output element</a>.
0264:             * <p>
0265:             * The return value is is logically equivalent to {@link #getAttributesMap()}<code>.containsKey("disabled")</code>,
0266:             * but using this property may be more efficient in some circumstances.
0267:             *
0268:             * @return <code>true</code> if this form control is <a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#adef-disabled">disabled</a>, otherwise <code>false</code>.
0269:             */
0270:            public final boolean isDisabled() {
0271:                return elementContainer.getBooleanAttribute(Attribute.DISABLED);
0272:            }
0273:
0274:            /**
0275:             * Sets whether this form control is <a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#adef-disabled">disabled</a>.
0276:             * <p>
0277:             * If the argument supplied to this method is <code>true</code> and the <code>disabled</code> attribute is not already present
0278:             * in the output element, the full
0279:             * <a target="_blank" href="http://www.w3.org/TR/xhtml1/">XHTML</a> compatible attribute <code>disabled="disabled"</code> is added.  
0280:             * If the attribute is already present, it is left unchanged.
0281:             * <p>
0282:             * If the argument supplied to this method is <code>false</code>, the attribute is removed from the output element.
0283:             * <p>
0284:             * See the {@link #isDisabled()} method for more information.
0285:             *
0286:             * @param disabled  the new value of this property.
0287:             */
0288:            public final void setDisabled(final boolean disabled) {
0289:                elementContainer.setBooleanAttribute(Attribute.DISABLED,
0290:                        disabled);
0291:            }
0292:
0293:            /**
0294:             * Indicates whether this form control is <a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#adef-checked">checked</a>.
0295:             * <p>
0296:             * The term <i>checked</i> is used to describe a checkbox or radio button control that is selected, which is the case if the attribute
0297:             * "<code><a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#adef-checked">checked</a></code>" 
0298:             * is present in its <a href="#OutputElement">output element</a>.
0299:             * <p>
0300:             * This property is only relevant to form controls with a {@linkplain #getFormControlType() type} of 
0301:             * {@link FormControlType#CHECKBOX} or {@link FormControlType#RADIO}, and throws an <code>UnsupportedOperationException</code>
0302:             * for other control types.
0303:             * <p>
0304:             * Use one of the <a href="#SubmissionValueModificationMethods">submission value modification methods</a> to change the value
0305:             * of this property.
0306:             * <p>
0307:             * If this control is a checkbox, you can set it to checked by calling
0308:             * {@link #setValue(CharSequence) setValue}<code>(</code>{@link #getName()}<code>)</code>, and set it to unchecked by calling
0309:             * {@link #clearValues()}.
0310:             * <p>
0311:             * If this control is a radio button, you should use the {@link FormField#setValue(CharSequence)} method or one of the other
0312:             * higher level <a href="#SubmissionValueModificationMethods">submission value modification methods</a>
0313:             * to set the control to checked, as calling {@link #setValue(CharSequence)} method on this object
0314:             * in the same way as for a checkbox does not automatically uncheck all other radio buttons with the same name.
0315:             * Even calling {@link #clearValues()} on this object to ensure that this radio button is unchecked is not recommended, as
0316:             * it can lead to a situation where all the radio buttons with this name are unchecked.
0317:             * The <a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#radio">HTML 4.01 specification of radio buttons</a>
0318:             * recommends against this situation because it is not defined how user agents should handle it, and behaviour differs amongst browsers.
0319:             * <p>
0320:             * The return value is logically equivalent to {@link #getAttributesMap()}<code>.containsKey("checked")</code>,
0321:             * but using this property may be more efficient in some circumstances.
0322:             *
0323:             * @return <code>true</code> if this form control is <a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#adef-checked">checked</a>, otherwise <code>false</code>.
0324:             * @throws UnsupportedOperationException if the {@linkplain #getFormControlType() type} of this control is not {@link FormControlType#CHECKBOX} or {@link FormControlType#RADIO}.
0325:             */
0326:            public boolean isChecked() {
0327:                throw new UnsupportedOperationException(
0328:                        "This property is only relevant for CHECKBOX and RADIO controls");
0329:            }
0330:
0331:            /**
0332:             * Returns the <a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#initial-value">initial value</a> of this control if it has a {@linkplain FormControlType#hasPredefinedValue() predefined value}.
0333:             * <p>
0334:             * Only <a href="#PredefinedValueControl">predefined value controls</a> can return a non-<code>null</code> result.
0335:             * All other control types return <code>null</code>.
0336:             * <p>
0337:             * {@link FormControlType#CHECKBOX CHECKBOX} and {@link FormControlType#RADIO RADIO} controls have a guaranteed
0338:             * predefined value determined by the value of its compulsory
0339:             * <code><a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#adef-value-INPUT">value</a></code>
0340:             * attribute.  If the attribute is not present in the source document, this library assigns the control a default
0341:             * predefined value of "<code>on</code>", consistent with popular browsers.
0342:             * <p>
0343:             * {@link FormControlType#SUBMIT SUBMIT}, {@link FormControlType#BUTTON BUTTON} and {@link FormControlType#IMAGE IMAGE}
0344:             * controls have an optional predefined value determined by the value of its
0345:             * <code><a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#adef-value-INPUT">value</a></code>
0346:             * attribute.  This value is
0347:             * <a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#successful-controls">successful</a>
0348:             * only in the control used to submit the form.
0349:             * <p>
0350:             * {@link FormControlType#SELECT_SINGLE} and {@link FormControlType#SELECT_MULTIPLE} controls are special cases
0351:             * because they usually contain multiple
0352:             * <code><a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#edef-OPTION">OPTION</a></code>
0353:             * elements, each with its own predefined value.
0354:             * In this case the {@link #getPredefinedValues()} method should be used instead, which returns a collection of all the
0355:             * control's predefined values.  Attempting to call this method on a <code>SELECT</code> control results in
0356:             * a <code>java.lang.UnsupportedOperationException</code>.
0357:             * <p>
0358:             * The predefined value of a control is not affected by changes to the
0359:             * <a href="#SubmissionValue">submission value</a> of the control.
0360:             *
0361:             * @return the <a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#initial-value">initial value</a> of this control if it has a {@linkplain FormControlType#hasPredefinedValue() predefined value}, or <code>null</code> if none.
0362:             */
0363:            public String getPredefinedValue() {
0364:                return elementContainer.predefinedValue;
0365:            }
0366:
0367:            /**
0368:             * Returns a collection of all {@linkplain #getPredefinedValue() predefined values} in this control.
0369:             * <p>
0370:             * All objects in the returned collection are of type <code>String</code>, with no <code>null</code> entries.
0371:             * <p>
0372:             * This method is most useful for
0373:             * <code><a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#edef-SELECT">SELECT</a></code>
0374:             * controls since they typically contain multiple predefined values.
0375:             * In other controls it returns a collection with zero or one item based on the output of the
0376:             * {@link #getPredefinedValue()} method, so for efficiency it is recommended to use the
0377:             * {@link #getPredefinedValue()} method instead.
0378:             * <p>
0379:             * The multiple predefined values of a
0380:             * <code><a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#edef-SELECT">SELECT</a></code>
0381:             * control are defined by the
0382:             * <code><a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#edef-OPTION">OPTION</a></code>
0383:             * elements within it.
0384:             * Each <code>OPTION</code> element has an
0385:             * <a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#initial-value">initial value</a>
0386:             * determined by the value of its
0387:             * <code><a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#adef-value-OPTION">value</a></code>
0388:             * attribute, or if this attribute is not present, by its
0389:             * {@linkplain CharacterReference#decode(CharSequence) decoded} {@linkplain Element#getContent() content}
0390:             * text with {@linkplain CharacterReference#decodeCollapseWhiteSpace(CharSequence) collapsed white space}.
0391:             * <p>
0392:             * The predefined values of a control are not affected by changes to the
0393:             * <a href="#SubmissionValue">submission values</a> of the control.
0394:             *
0395:             * @return a collection of all {@linkplain #getPredefinedValue() predefined values} in this control, guaranteed not <code>null</code>.
0396:             * @see FormField#getPredefinedValues()
0397:             */
0398:            public Collection getPredefinedValues() {
0399:                return getPredefinedValue() != null ? Collections
0400:                        .singleton(getPredefinedValue())
0401:                        : Collections.EMPTY_SET;
0402:            }
0403:
0404:            /**
0405:             * Returns a collection of the control's <a href="#SubmissionValue">submission values</a>.
0406:             * <p>
0407:             * All objects in the returned collection are of type <code>CharSequence</code>, with no <code>null</code> entries.
0408:             * <p>
0409:             * The term <i><a name="SubmissionValue">submission value</a></i> is used in this library to refer to the value the control 
0410:             * would contribute to the
0411:             * <a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#form-data-set">form data set</a>
0412:             * of a <a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#submit-format">submitted</a>
0413:             * form, assuming no modification of the control's
0414:             * <a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#current-value">current value</a> by the
0415:             * <a target="_blank" href="http://www.w3.org/TR/html401/conform.html#didx-user_agent">user agent</a> or by end user interaction.
0416:             * <p>
0417:             * For <a href="#UserValueControl">user value controls</a>, the submission value corresponds to the
0418:             * control's <a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#initial-value">initial value</a>.
0419:             * <p>
0420:             * The definition of the submission value for each <a href="#PredefinedValueControl">predefined value control</a> type is as follows:
0421:             * <p>
0422:             * {@link FormControlType#CHECKBOX CHECKBOX} and {@link FormControlType#RADIO RADIO} controls
0423:             * have a submission value specified by its {@linkplain #getPredefinedValue() predefined value}
0424:             * if it is {@link #isChecked() checked}, otherwise it has no submission value.
0425:             * <p>
0426:             * {@link FormControlType#SELECT_SINGLE SELECT_SINGLE} and {@link FormControlType#SELECT_MULTIPLE SELECT_MULTIPLE} controls
0427:             * have submission values specified by the
0428:             * <a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#adef-value-OPTION">values</a> of the control's
0429:             * <a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#adef-selected">selected</a>
0430:             * <code>OPTION</code> elements.
0431:             * <p>
0432:             * Only a {@link FormControlType#SELECT_MULTIPLE SELECT_MULTIPLE} control can have more than one submission value,
0433:             * all other {@linkplain FormControlType control types} return a collection containing either one value or no values.
0434:             * A {@link FormControlType#SELECT_SINGLE SELECT_SINGLE} control only returns multiple submission values
0435:             * if it illegally contains multiple selected options in the source document.
0436:             * <p>
0437:             * {@link FormControlType#SUBMIT SUBMIT}, {@link FormControlType#BUTTON BUTTON}, and {@link FormControlType#IMAGE IMAGE}
0438:             * controls are only ever
0439:             * <a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#successful-controls">successful</a>
0440:             * when they are activated by the user to
0441:             * <a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#submit-format">submit</a> the form.
0442:             * Because the submission value is intended to be a static representation of a control's data without
0443:             * interaction by the user, this library never associates submission values with
0444:             * {@linkplain FormControlType#isSubmit() submit} buttons, so this method always returns an empty collection for these
0445:             * control types.
0446:             * <p>
0447:             * The <a href="#SubmissionValue">submission value(s)</a> of a control can be modified for subsequent output in
0448:             * an {@link OutputDocument} using the various 
0449:             * <i><a name="SubmissionValueModificationMethods">submission value modification methods</a></i>, namely:<br />
0450:             * {@link FormField#setValue(CharSequence)}<br />
0451:             * {@link FormField#addValue(CharSequence)}<br />
0452:             * {@link FormField#setValues(Collection)}<br />
0453:             * {@link FormField#clearValues()}<br />
0454:             * {@link FormFields#setValue(String fieldName, CharSequence value)}<br />
0455:             * {@link FormFields#addValue(String fieldName, CharSequence value)}<br />
0456:             * {@link FormFields#setDataSet(Map)}<br />
0457:             * {@link FormFields#clearValues()}<br />
0458:             * {@link #setValue(CharSequence) FormControl.setValue(CharSequence)}<br />
0459:             * {@link #addValue(CharSequence) FormControl.addValue(CharSequence)}<br />
0460:             * {@link #clearValues() FormControl.clearValues()}<br />
0461:             * <p>
0462:             * The values returned by this method reflect any changes made using the submission value modification methods,
0463:             * in contrast to methods found in the {@link Attributes} and {@link Attribute} classes, which always reflect the source document.
0464:             *
0465:             * @return a collection of the control's <i>submission values</i>, guaranteed not <code>null</code>.
0466:             * @see #getPredefinedValues()
0467:             */
0468:            public Collection getValues() {
0469:                final HashSet values = new HashSet();
0470:                addValuesTo(values);
0471:                return values;
0472:            }
0473:
0474:            /**
0475:             * Clears the control's existing <a href="#SubmissionValue">submission values</a>.
0476:             * <p>
0477:             * This is equivalent to {@link #setValue(CharSequence) setValue(null)}.
0478:             * <p>
0479:             * NOTE: The {@link FormFields} and {@link FormField} classes provide a more appropriate abstraction level for the modification of form control submission values.
0480:             *
0481:             * @see FormFields#clearValues()
0482:             * @see FormField#clearValues()
0483:             */
0484:            public final void clearValues() {
0485:                setValue(null);
0486:            }
0487:
0488:            /**
0489:             * Sets the control's <a href="#SubmissionValue">submission value</a> *.
0490:             * <p>
0491:             * * NOTE: The {@link FormFields} and {@link FormField} classes provide a more appropriate abstraction level for the modification of form control submission values.
0492:             * Consider using the {@link FormFields#setValue(String fieldName, CharSequence value)} method instead.
0493:             * <p>
0494:             * The specified value replaces any existing <a href="#SubmissionValue">submission values</a> of the control.
0495:             * <p>
0496:             * The return value indicates whether the control has "accepted" the value.
0497:             * For <a href="#UserValueControl">user value controls</a>, the return value is always <code>true</code>.
0498:             * <p>
0499:             * For <a href="#PredefinedValueControl">predefined value controls</a>,
0500:             * calling this method does not affect the control's
0501:             * {@linkplain #getPredefinedValues() predefined values}, but instead determines whether the control (or its options) become
0502:             * <code><a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#adef-checked">checked</a></code> or
0503:             * <code><a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#adef-selected">selected</a></code>
0504:             * as detailed below:
0505:             * <p>
0506:             * {@link FormControlType#CHECKBOX CHECKBOX} and {@link FormControlType#RADIO RADIO} controls become {@link #isChecked() checked}
0507:             * and the method returns <code>true</code> if the specified value matches the control's predefined value (case sensitive),
0508:             * otherwise the control becomes unchecked and the method returns <code>false</code>.
0509:             * Note that any other controls with the same {@linkplain #getName() name} are not unchecked if this control becomes checked,
0510:             * possibly resulting in an invalid state where multiple <code>RADIO</code> controls are checked at the same time.
0511:             * The {@link FormField#setValue(CharSequence)} method avoids such problems and its use is recommended over this method.
0512:             * <p>
0513:             * {@link FormControlType#SELECT_SINGLE SELECT_SINGLE} and {@link FormControlType#SELECT_MULTIPLE SELECT_MULTIPLE}
0514:             * controls receive the specified value by selecting the option with the matching value and deselecting all others.
0515:             * If none of the options match, all are deselected.
0516:             * The return value of this method indicates whether one of the options matched.
0517:             * <p>
0518:             * {@link FormControlType#SUBMIT SUBMIT}, {@link FormControlType#BUTTON BUTTON}, and {@link FormControlType#IMAGE IMAGE}
0519:             * controls never have a <a href="#SubmissionValue">submission value</a>, so calling this method has no effect and
0520:             * always returns <code>false</code>.
0521:             *
0522:             * @param value  the new <a href="#SubmissionValue">submission value</a> of this control, or <code>null</code> to clear the control of all submission values.
0523:             * @return <code>true</code> if the control accepts the value, otherwise <code>false</code>.
0524:             * @see FormFields#setValue(String fieldName, CharSequence value)
0525:             */
0526:            public abstract boolean setValue(CharSequence value);
0527:
0528:            /**
0529:             * Adds the specified value to this control's <a href="#SubmissionValue">submission values</a> *.
0530:             * <p>
0531:             * * NOTE: The {@link FormFields} and {@link FormField} classes provide a more appropriate abstraction level for the modification of form control submission values.
0532:             * Consider using the {@link FormFields#addValue(String fieldName, CharSequence value)} method instead.
0533:             * <p>
0534:             * This is almost equivalent to {@link #setValue(CharSequence)}, with only the following differences:
0535:             * <p>
0536:             * {@link FormControlType#CHECKBOX CHECKBOX} controls retain their existing <a href="#SubmissionValue">submission value</a>
0537:             * instead of becoming unchecked if the specified value does not match the control's {@linkplain #getPredefinedValue() predefined value}.
0538:             * <p>
0539:             * {@link FormControlType#SELECT_MULTIPLE SELECT_MULTIPLE} controls retain their existing
0540:             * <a href="#SubmissionValue">submission values</a>, meaning that the control's
0541:             * <code><a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#edef-OPTION">OPTION</a></code>
0542:             * elements whose {@linkplain #getPredefinedValues() predefined values} do not match the specified value are not deselected.
0543:             * This is the only type of control that can have multiple submission values within the one control.
0544:             *
0545:             * @param value  the value to add to this control's <a href="#SubmissionValue">submission values</a>, must not be <code>null</code>.
0546:             * @return <code>true</code> if the control accepts the value, otherwise <code>false</code>.
0547:             * @see FormFields#addValue(String fieldName, CharSequence value)
0548:             */
0549:            public boolean addValue(final CharSequence value) {
0550:                return setValue(value);
0551:            }
0552:
0553:            abstract void addValuesTo(Collection collection); // should not add null values, values must be of type CharSequence
0554:
0555:            abstract void addToFormFields(FormFields formFields);
0556:
0557:            abstract void replaceInOutputDocument(OutputDocument outputDocument);
0558:
0559:            public String getDebugInfo() {
0560:                final StringBuffer sb = new StringBuffer();
0561:                sb.append(formControlType).append(" name=\"").append(name)
0562:                        .append('"');
0563:                if (elementContainer.predefinedValue != null)
0564:                    sb.append(" PredefinedValue=\"").append(
0565:                            elementContainer.predefinedValue).append('"');
0566:                sb.append(" - ").append(getElement().getDebugInfo());
0567:                return sb.toString();
0568:            }
0569:
0570:            static final class InputFormControl extends FormControl {
0571:                // TEXT, HIDDEN, PASSORD or FILE
0572:                public InputFormControl(final Element element,
0573:                        final FormControlType formControlType) {
0574:                    super (element, formControlType, false);
0575:                }
0576:
0577:                public boolean setValue(final CharSequence value) {
0578:                    elementContainer.setAttributeValue(Attribute.VALUE, value);
0579:                    return true;
0580:                }
0581:
0582:                void addValuesTo(final Collection collection) {
0583:                    addValueTo(collection, elementContainer
0584:                            .getAttributeValue(Attribute.VALUE));
0585:                }
0586:
0587:                void addToFormFields(final FormFields formFields) {
0588:                    formFields.add(this );
0589:                }
0590:
0591:                void replaceInOutputDocument(final OutputDocument outputDocument) {
0592:                    if (outputStyle == FormControlOutputStyle.REMOVE) {
0593:                        outputDocument.remove(getElement());
0594:                    } else if (outputStyle == FormControlOutputStyle.DISPLAY_VALUE) {
0595:                        String output = null;
0596:                        if (formControlType != FormControlType.HIDDEN) {
0597:                            CharSequence value = elementContainer
0598:                                    .getAttributeValue(Attribute.VALUE);
0599:                            if (formControlType == FormControlType.PASSWORD
0600:                                    && value != null)
0601:                                value = getString(
0602:                                        FormControlOutputStyle.ConfigDisplayValue.PasswordChar,
0603:                                        value.length());
0604:                            output = getDisplayValueHTML(value, false);
0605:                        }
0606:                        outputDocument.replace(getElement(), output);
0607:                    } else {
0608:                        replaceAttributesInOutputDocumentIfModified(outputDocument);
0609:                    }
0610:                }
0611:            }
0612:
0613:            static final class TextAreaFormControl extends FormControl {
0614:                // TEXTAREA
0615:                public CharSequence value = UNCHANGED;
0616:                private static final String UNCHANGED = new String();
0617:
0618:                public TextAreaFormControl(final Element element) {
0619:                    super (element, FormControlType.TEXTAREA, false);
0620:                }
0621:
0622:                public boolean setValue(final CharSequence value) {
0623:                    this .value = value;
0624:                    return true;
0625:                }
0626:
0627:                void addValuesTo(final Collection collection) {
0628:                    addValueTo(collection, getValue());
0629:                }
0630:
0631:                void addToFormFields(final FormFields formFields) {
0632:                    formFields.add(this );
0633:                }
0634:
0635:                void replaceInOutputDocument(final OutputDocument outputDocument) {
0636:                    if (outputStyle == FormControlOutputStyle.REMOVE) {
0637:                        outputDocument.remove(getElement());
0638:                    } else if (outputStyle == FormControlOutputStyle.DISPLAY_VALUE) {
0639:                        outputDocument.replace(getElement(),
0640:                                getDisplayValueHTML(getValue(), true));
0641:                    } else {
0642:                        replaceAttributesInOutputDocumentIfModified(outputDocument);
0643:                        if (value != UNCHANGED)
0644:                            outputDocument.replace(getElement().getContent(),
0645:                                    CharacterReference.encode(value));
0646:                    }
0647:                }
0648:
0649:                private CharSequence getValue() {
0650:                    return (value == UNCHANGED) ? CharacterReference
0651:                            .decode(getElement().getContent()) : value;
0652:                }
0653:            }
0654:
0655:            static final class RadioCheckboxFormControl extends FormControl {
0656:                // RADIO or CHECKBOX
0657:                public RadioCheckboxFormControl(final Element element,
0658:                        final FormControlType formControlType) {
0659:                    super (element, formControlType, true);
0660:                    if (elementContainer.predefinedValue == null) {
0661:                        elementContainer.predefinedValue = CHECKBOX_NULL_DEFAULT_VALUE;
0662:                        if (element.source.logger.isInfoEnabled())
0663:                            element.source.logger
0664:                                    .info(element.source
0665:                                            .getRowColumnVector(element.begin)
0666:                                            .appendTo(new StringBuffer(200))
0667:                                            .append(
0668:                                                    ": compulsory \"value\" attribute of ")
0669:                                            .append(formControlType)
0670:                                            .append(" control \"")
0671:                                            .append(name)
0672:                                            .append(
0673:                                                    "\" is missing, assuming the value \"")
0674:                                            .append(CHECKBOX_NULL_DEFAULT_VALUE)
0675:                                            .append('"').toString());
0676:                    }
0677:                }
0678:
0679:                public boolean setValue(final CharSequence value) {
0680:                    return elementContainer.setSelected(value,
0681:                            Attribute.CHECKED, false);
0682:                }
0683:
0684:                public boolean addValue(final CharSequence value) {
0685:                    return elementContainer.setSelected(value,
0686:                            Attribute.CHECKED,
0687:                            formControlType == FormControlType.CHECKBOX);
0688:                }
0689:
0690:                void addValuesTo(final Collection collection) {
0691:                    if (isChecked())
0692:                        addValueTo(collection, getPredefinedValue());
0693:                }
0694:
0695:                public boolean isChecked() {
0696:                    return elementContainer
0697:                            .getBooleanAttribute(Attribute.CHECKED);
0698:                }
0699:
0700:                void addToFormFields(final FormFields formFields) {
0701:                    formFields.add(this );
0702:                }
0703:
0704:                void replaceInOutputDocument(final OutputDocument outputDocument) {
0705:                    if (outputStyle == FormControlOutputStyle.REMOVE) {
0706:                        outputDocument.remove(getElement());
0707:                    } else {
0708:                        if (outputStyle == FormControlOutputStyle.DISPLAY_VALUE) {
0709:                            final String html = isChecked() ? FormControlOutputStyle.ConfigDisplayValue.CheckedHTML
0710:                                    : FormControlOutputStyle.ConfigDisplayValue.UncheckedHTML;
0711:                            if (html != null) {
0712:                                outputDocument.replace(getElement(), html);
0713:                                return;
0714:                            }
0715:                            setDisabled(true);
0716:                        }
0717:                        replaceAttributesInOutputDocumentIfModified(outputDocument);
0718:                    }
0719:                }
0720:            }
0721:
0722:            static class SubmitFormControl extends FormControl {
0723:                // BUTTON, SUBMIT or (in subclass) IMAGE
0724:                public SubmitFormControl(final Element element,
0725:                        final FormControlType formControlType) {
0726:                    super (element, formControlType, true);
0727:                }
0728:
0729:                public boolean setValue(final CharSequence value) {
0730:                    return false;
0731:                }
0732:
0733:                void addValuesTo(final Collection collection) {
0734:                }
0735:
0736:                void addToFormFields(final FormFields formFields) {
0737:                    if (getPredefinedValue() != null)
0738:                        formFields.add(this );
0739:                }
0740:
0741:                void replaceInOutputDocument(final OutputDocument outputDocument) {
0742:                    if (outputStyle == FormControlOutputStyle.REMOVE) {
0743:                        outputDocument.remove(getElement());
0744:                    } else {
0745:                        if (outputStyle == FormControlOutputStyle.DISPLAY_VALUE)
0746:                            setDisabled(true);
0747:                        replaceAttributesInOutputDocumentIfModified(outputDocument);
0748:                    }
0749:                }
0750:            }
0751:
0752:            static final class ImageSubmitFormControl extends SubmitFormControl {
0753:                // IMAGE
0754:                public ImageSubmitFormControl(final Element element) {
0755:                    super (element, FormControlType.IMAGE);
0756:                }
0757:
0758:                void addToFormFields(final FormFields formFields) {
0759:                    super .addToFormFields(formFields);
0760:                    formFields.addName(this , name + ".x");
0761:                    formFields.addName(this , name + ".y");
0762:                }
0763:            }
0764:
0765:            static final class SelectFormControl extends FormControl {
0766:                // SELECT_MULTIPLE or SELECT_SINGLE
0767:                public ElementContainer[] optionElementContainers;
0768:
0769:                public SelectFormControl(final Element element) {
0770:                    super (
0771:                            element,
0772:                            element.getAttributes().get(Attribute.MULTIPLE) != null ? FormControlType.SELECT_MULTIPLE
0773:                                    : FormControlType.SELECT_SINGLE, false);
0774:                    final List optionElements = element
0775:                            .findAllElements(Tag.OPTION);
0776:                    optionElementContainers = new ElementContainer[optionElements
0777:                            .size()];
0778:                    int x = 0;
0779:                    for (final Iterator i = optionElements.iterator(); i
0780:                            .hasNext();) {
0781:                        final ElementContainer optionElementContainer = new ElementContainer(
0782:                                (Element) i.next(), true);
0783:                        if (optionElementContainer.predefinedValue == null)
0784:                            // use the content of the element if it has no value attribute
0785:                            optionElementContainer.predefinedValue = CharacterReference
0786:                                    .decodeCollapseWhiteSpace(optionElementContainer.element
0787:                                            .getContent());
0788:                        optionElementContainers[x++] = optionElementContainer;
0789:                    }
0790:                }
0791:
0792:                public String getPredefinedValue() {
0793:                    throw new UnsupportedOperationException(
0794:                            "Use getPredefinedValues() method instead on SELECT controls");
0795:                }
0796:
0797:                public Collection getPredefinedValues() {
0798:                    final ArrayList arrayList = new ArrayList(
0799:                            optionElementContainers.length);
0800:                    for (int i = 0; i < optionElementContainers.length; i++)
0801:                        arrayList
0802:                                .add(optionElementContainers[i].predefinedValue);
0803:                    return arrayList;
0804:                }
0805:
0806:                public Iterator getOptionElementIterator() {
0807:                    return new OptionElementIterator();
0808:                }
0809:
0810:                public boolean setValue(final CharSequence value) {
0811:                    return addValue(value, false);
0812:                }
0813:
0814:                public boolean addValue(final CharSequence value) {
0815:                    return addValue(value,
0816:                            formControlType == FormControlType.SELECT_MULTIPLE);
0817:                }
0818:
0819:                private boolean addValue(final CharSequence value,
0820:                        final boolean allowMultipleValues) {
0821:                    boolean valueFound = false;
0822:                    for (int i = 0; i < optionElementContainers.length; i++) {
0823:                        if (optionElementContainers[i].setSelected(value,
0824:                                Attribute.SELECTED, allowMultipleValues))
0825:                            valueFound = true;
0826:                    }
0827:                    return valueFound;
0828:                }
0829:
0830:                void addValuesTo(final Collection collection) {
0831:                    for (int i = 0; i < optionElementContainers.length; i++) {
0832:                        if (optionElementContainers[i]
0833:                                .getBooleanAttribute(Attribute.SELECTED))
0834:                            addValueTo(collection,
0835:                                    optionElementContainers[i].predefinedValue);
0836:                    }
0837:                }
0838:
0839:                void addToFormFields(final FormFields formFields) {
0840:                    for (int i = 0; i < optionElementContainers.length; i++)
0841:                        formFields.add(this ,
0842:                                optionElementContainers[i].predefinedValue);
0843:                }
0844:
0845:                void replaceInOutputDocument(final OutputDocument outputDocument) {
0846:                    if (outputStyle == FormControlOutputStyle.REMOVE) {
0847:                        outputDocument.remove(getElement());
0848:                    } else if (outputStyle == FormControlOutputStyle.DISPLAY_VALUE) {
0849:                        final StringBuffer sb = new StringBuffer(100);
0850:                        for (int i = 0; i < optionElementContainers.length; i++) {
0851:                            if (optionElementContainers[i]
0852:                                    .getBooleanAttribute(Attribute.SELECTED)) {
0853:                                appendCollapseWhiteSpace(sb,
0854:                                        optionElementContainers[i].element
0855:                                                .getContent());
0856:                                sb
0857:                                        .append(FormControlOutputStyle.ConfigDisplayValue.MultipleValueSeparator);
0858:                            }
0859:                        }
0860:                        if (sb.length() > 0)
0861:                            sb
0862:                                    .setLength(sb.length()
0863:                                            - FormControlOutputStyle.ConfigDisplayValue.MultipleValueSeparator
0864:                                                    .length()); // remove last separator
0865:                        outputDocument.replace(getElement(),
0866:                                getDisplayValueHTML(sb, false));
0867:                    } else {
0868:                        replaceAttributesInOutputDocumentIfModified(outputDocument);
0869:                        for (int i = 0; i < optionElementContainers.length; i++) {
0870:                            optionElementContainers[i]
0871:                                    .replaceAttributesInOutputDocumentIfModified(outputDocument);
0872:                        }
0873:                    }
0874:                }
0875:
0876:                private final class OptionElementIterator implements  Iterator {
0877:                    private int i = 0;
0878:
0879:                    public boolean hasNext() {
0880:                        return i < optionElementContainers.length;
0881:                    }
0882:
0883:                    public Object next() {
0884:                        if (!hasNext())
0885:                            throw new NoSuchElementException();
0886:                        return optionElementContainers[i++].element;
0887:                    }
0888:
0889:                    public void remove() {
0890:                        throw new UnsupportedOperationException();
0891:                    }
0892:                }
0893:            }
0894:
0895:            final String getDisplayValueHTML(final CharSequence text,
0896:                    final boolean whiteSpaceFormatting) {
0897:                final StringBuffer sb = new StringBuffer((text == null ? 0
0898:                        : text.length() * 2) + 50);
0899:                sb.append('<').append(
0900:                        FormControlOutputStyle.ConfigDisplayValue.ElementName);
0901:                for (final Iterator i = FormControlOutputStyle.ConfigDisplayValue.AttributeNames
0902:                        .iterator(); i.hasNext();) {
0903:                    final String attributeName = i.next().toString();
0904:                    final CharSequence attributeValue = elementContainer
0905:                            .getAttributeValue(attributeName);
0906:                    if (attributeValue == null)
0907:                        continue;
0908:                    Attribute.appendHTML(sb, attributeName, attributeValue);
0909:                }
0910:                sb.append('>');
0911:                if (text == null || text.length() == 0)
0912:                    sb
0913:                            .append(FormControlOutputStyle.ConfigDisplayValue.EmptyHTML);
0914:                else
0915:                    CharacterReference.appendEncode(sb, text,
0916:                            whiteSpaceFormatting);
0917:                sb.append(EndTagType.START_DELIMITER_PREFIX).append(
0918:                        FormControlOutputStyle.ConfigDisplayValue.ElementName)
0919:                        .append('>');
0920:                return sb.toString();
0921:            }
0922:
0923:            final void replaceAttributesInOutputDocumentIfModified(
0924:                    final OutputDocument outputDocument) {
0925:                elementContainer
0926:                        .replaceAttributesInOutputDocumentIfModified(outputDocument);
0927:            }
0928:
0929:            static List findAll(final Segment segment) {
0930:                final ArrayList list = new ArrayList();
0931:                findAll(segment, list, Tag.INPUT);
0932:                findAll(segment, list, Tag.TEXTAREA);
0933:                findAll(segment, list, Tag.SELECT);
0934:                findAll(segment, list, Tag.BUTTON);
0935:                Collections.sort(list, COMPARATOR);
0936:                return list;
0937:            }
0938:
0939:            private static void findAll(final Segment segment,
0940:                    final ArrayList list, final String tagName) {
0941:                for (final Iterator i = segment.findAllElements(tagName)
0942:                        .iterator(); i.hasNext();) {
0943:                    final FormControl formControl = ((Element) i.next())
0944:                            .getFormControl();
0945:                    if (formControl != null)
0946:                        list.add(formControl);
0947:                }
0948:            }
0949:
0950:            private static CharSequence getString(final char ch,
0951:                    final int length) {
0952:                if (length == 0)
0953:                    return "";
0954:                final StringBuffer sb = new StringBuffer(length);
0955:                for (int i = 0; i < length; i++)
0956:                    sb.append(ch);
0957:                return sb.toString();
0958:            }
0959:
0960:            private void verifyName() {
0961:                if (formControlType.isSubmit())
0962:                    return;
0963:                String missingOrBlank;
0964:                if (name == null) {
0965:                    missingOrBlank = "missing";
0966:                } else {
0967:                    if (name.length() != 0)
0968:                        return;
0969:                    missingOrBlank = "blank";
0970:                }
0971:                final Source source = getElement().source;
0972:                if (source.logger.isInfoEnabled())
0973:                    source.logger.info(getElement().source.getRowColumnVector(
0974:                            getElement().begin).appendTo(new StringBuffer(200))
0975:                            .append(": compulsory \"name\" attribute of ")
0976:                            .append(formControlType).append(" control is ")
0977:                            .append(missingOrBlank).toString());
0978:            }
0979:
0980:            private static final void addValueTo(final Collection collection,
0981:                    final CharSequence value) {
0982:                collection.add(value != null ? value : "");
0983:            }
0984:
0985:            private static final class PositionComparator implements  Comparator {
0986:                public int compare(final Object o1, final Object o2) {
0987:                    int formControl1Begin = ((FormControl) o1).getElement()
0988:                            .getBegin();
0989:                    int formControl2Begin = ((FormControl) o2).getElement()
0990:                            .getBegin();
0991:                    if (formControl1Begin < formControl2Begin)
0992:                        return -1;
0993:                    if (formControl1Begin > formControl2Begin)
0994:                        return 1;
0995:                    return 0;
0996:                }
0997:            }
0998:
0999:            //////////////////////////////////////////////////////////////////////////////////////
1000:
1001:            static final class ElementContainer {
1002:                // Contains the information common to both a FormControl and to each OPTION element
1003:                // within a SELECT FormControl
1004:                public final Element element;
1005:                public Map attributesMap = null;
1006:                public String predefinedValue; // never null for option, checkbox or radio elements
1007:
1008:                public ElementContainer(final Element element,
1009:                        final boolean loadPredefinedValue) {
1010:                    this .element = element;
1011:                    predefinedValue = loadPredefinedValue ? element
1012:                            .getAttributes().getValue(Attribute.VALUE) : null;
1013:                }
1014:
1015:                public Map getAttributesMap() {
1016:                    if (attributesMap == null)
1017:                        attributesMap = element.getAttributes().getMap(true);
1018:                    return attributesMap;
1019:                }
1020:
1021:                public boolean setSelected(final CharSequence value,
1022:                        final String selectedOrChecked,
1023:                        final boolean allowMultipleValues) {
1024:                    if (value != null
1025:                            && predefinedValue.equals(value.toString())) {
1026:                        setBooleanAttribute(selectedOrChecked, true);
1027:                        return true;
1028:                    }
1029:                    if (!allowMultipleValues)
1030:                        setBooleanAttribute(selectedOrChecked, false);
1031:                    return false;
1032:                }
1033:
1034:                public CharSequence getAttributeValue(final String attributeName) {
1035:                    if (attributesMap != null)
1036:                        return (CharSequence) attributesMap.get(attributeName);
1037:                    else
1038:                        return element.getAttributes().getValue(attributeName);
1039:                }
1040:
1041:                public void setAttributeValue(final String attributeName,
1042:                        final CharSequence value) {
1043:                    // null value indicates attribute should be removed.
1044:                    if (value == null) {
1045:                        setBooleanAttribute(attributeName, false);
1046:                        return;
1047:                    }
1048:                    if (attributesMap != null) {
1049:                        attributesMap.put(attributeName, value);
1050:                        return;
1051:                    }
1052:                    final String valueString = value.toString();
1053:                    final CharSequence existingValue = getAttributeValue(attributeName);
1054:                    if (existingValue != null
1055:                            && existingValue.toString().equals(valueString))
1056:                        return;
1057:                    getAttributesMap().put(attributeName, valueString);
1058:                }
1059:
1060:                public boolean getBooleanAttribute(final String attributeName) {
1061:                    if (attributesMap != null)
1062:                        return attributesMap.containsKey(attributeName);
1063:                    else
1064:                        return element.getAttributes().get(attributeName) != null;
1065:                }
1066:
1067:                public void setBooleanAttribute(final String attributeName,
1068:                        final boolean value) {
1069:                    final boolean oldValue = getBooleanAttribute(attributeName);
1070:                    if (value == oldValue)
1071:                        return;
1072:                    if (value)
1073:                        getAttributesMap().put(attributeName, attributeName); // xhtml compatible attribute
1074:                    else
1075:                        getAttributesMap().remove(attributeName);
1076:                }
1077:
1078:                public void replaceAttributesInOutputDocumentIfModified(
1079:                        final OutputDocument outputDocument) {
1080:                    if (attributesMap != null)
1081:                        outputDocument.replace(element.getAttributes(),
1082:                                attributesMap);
1083:                }
1084:            }
1085:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.