Source Code Cross Referenced for FormFields.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) 


001:        // Jericho HTML Parser - Java based library for analysing and manipulating HTML
002:        // Version 2.5
003:        // Copyright (C) 2007 Martin Jericho
004:        // http://jerichohtml.sourceforge.net/
005:        //
006:        // This library is free software; you can redistribute it and/or
007:        // modify it under the terms of either one of the following licences:
008:        //
009:        // 1. The Eclipse Public License (EPL) version 1.0,
010:        // included in this distribution in the file licence-epl-1.0.html
011:        // or available at http://www.eclipse.org/legal/epl-v10.html
012:        //
013:        // 2. The GNU Lesser General Public License (LGPL) version 2.1 or later,
014:        // included in this distribution in the file licence-lgpl-2.1.txt
015:        // or available at http://www.gnu.org/licenses/lgpl.txt
016:        //
017:        // This library is distributed on an "AS IS" basis,
018:        // WITHOUT WARRANTY OF ANY KIND, either express or implied.
019:        // See the individual licence texts for more details.
020:
021:        package au.id.jericho.lib.html;
022:
023:        import java.util.*;
024:
025:        /**
026:         * Represents a collection of {@link FormField} objects.
027:         * <p>
028:         * This class provides the main interface for the analysis and manipulation of {@linkplain FormControl form controls}.
029:         * A <code>FormFields</code> object is a collection of {@link FormField} objects, with each form field consisting of
030:         * a group of {@linkplain FormControl form controls} having the same {@linkplain FormControl#getName() name}.
031:         * <p>
032:         * The functionality provided by this class can be used to accomplish two main tasks:
033:         * <ol>
034:         *  <li style="margin-bottom: 1.5em">
035:         *   Modify the <a href="FormControl.html#SubmissionValue">submission values</a> of the constituent form controls
036:         *   for subsequent output in an {@link OutputDocument}.
037:         *   <p>
038:         *   The methods available for this purpose are:<br />
039:         *   {@link #getValues(String) Collection getValues(String fieldName)}<br />
040:         *   {@link #getDataSet() Map getDataSet()}<br />
041:         *   {@link #clearValues() void clearValues()}<br />
042:         *   {@link #setDataSet(Map) void setDataSet(Map)}<br />
043:         *   {@link #setValue(String,CharSequence) boolean setValue(String fieldName, CharSequence value)}<br />
044:         *   {@link #addValue(String,CharSequence) boolean addValue(String fieldName, CharSequence value)}<br />
045:         *   <p>
046:         *   Although the {@link FormField} and {@link FormControl} classes provide methods for directly modifying
047:         *   the submission values of individual form fields and controls, it is generally recommended to use the interface provided by this
048:         *   (the <code>FormFields</code>) class unless there is a specific requirement for the lower level functionality.
049:         *   <p>
050:         *   The <a href="FormControl.html#DisplayCharacteristics">display characteristics</a> of individual controls,
051:         *   such as whether the control is {@linkplain FormControl#setDisabled(boolean) disabled}, replaced with a simple
052:         *   {@linkplain FormControlOutputStyle#DISPLAY_VALUE value}, or {@linkplain FormControlOutputStyle#REMOVE removed} altogether,
053:         *   can only be set on the individual {@link FormControl} objects.
054:         *   See below for information about retrieving a specific <code>FormControl</code> object from the <code>FormFields</code> object.
055:         *  <li>
056:         *   Convert data from a <a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#form-data-set">form data set</a>
057:         *   (represented as a <a href="#FieldDataSet">field data set</a>) into a simple array format,
058:         *   suitable for storage in a tabular format such as a database table or <code>.CSV</code> file.
059:         *   <p>
060:         *   The methods available for this purpose are:<br />
061:         *   {@link #getColumnLabels() String[] getColumnLabels()}<br />
062:         *   {@link #getColumnValues(Map) String[] getColumnValues(Map)}<br />
063:         *   {@link #getColumnValues() String[] getColumnValues()}<br />
064:         *   <p>
065:         *   The {@link Util} class contains a method called {@link Util#outputCSVLine(Writer,String[]) outputCSVLine(Writer,String[])}
066:         *   which writes the <code>String[]</code> output of these methods to the specified <code>Writer</code> in <code>.CSV</code> format.
067:         *   <p>
068:         *   The implementation of these methods makes use of certain <a href="FormField.html#DataStructureProperties">properties</a>
069:         *   in the {@link FormField} class that describe the structure of the data in each field.
070:         *   These properties can be utilised directly in the event that a
071:         *   <a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#form-data-set">form data set</a> is to be converted
072:         *   from its <a href="FormFields.html#FieldDataSet">normal format</a> into some other type of data structure.
073:         * </ol>
074:         * <p>
075:         * To access a specific {@link FormControl} from a <code>FormFields</code> object, use:
076:         * <ul style="margin-top: 0px">
077:         *  <li><code>formFields.</code>{@link #get(String) get(fieldName)}<code>.</code>{@link FormField#getFormControl() getFormControl()}
078:         *   if the control is the only one with the specified {@linkplain FormControl#getName() name}, or
079:         *  <li><code>formFields.</code>{@link #get(String) get(fieldName)}<code>.</code>{@link FormField#getFormControl(String) getFormControl(predefinedValue)}
080:         *   to retrieve the control having the speficied {@linkplain FormControl#getPredefinedValue() predefined value}
081:         *   if it is part of a {@linkplain FormField field} containing multiple controls.
082:         * </ul>
083:         * <p>
084:         * The term <i><a name="FieldDataSet">field data set</a></i> is used in this library to refer to a data structure consisting of
085:         * a set of names (in lower case), each mapped to one or more values.
086:         * Generally, this is represented by a <code>java.util.Map</code> with the keys (names) being of type <code>String</code> and the
087:         * values represented by either an array or collection containing one or more items of type <code>CharSequence</code>.
088:         * A field data set can be used to represent the data in an HTML
089:         * <a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#form-data-set">form data set</a>.
090:         * <p>
091:         * <code>FormFields</code> instances are obtained using the {@link #FormFields(Collection formControls)} constructor
092:         * or by calling the {@link Segment#findFormFields()} method.
093:         * <p>
094:         * The case sensitivity of form field names is determined by the
095:         * {@link Config#CurrentCompatibilityMode}<code>.</code>{@link Config.CompatibilityMode#isFormFieldNameCaseInsensitive() FormFieldNameCaseInsensitive} property.
096:         * <p>
097:         * <b>Examples:</b>
098:         * <ol>
099:         *  <li>
100:         *   Write the data received from in the current <code>ServletRequest</code> to a <code>.CSV</code> file,
101:         *   and then display the form populated with this data:
102:         *   <p><pre>
103:         *    Source source=new Source(htmlTextOfOriginatingForm);
104:         *    FormFields formFields=source.findFormFields();
105:         *
106:         *    File csvOutputFile=new File("FormData.csv");
107:         *    boolean outputHeadings=!csvOutputFile.exists();
108:         *    Writer writer=new FileWriter(csvOutputFile,true);
109:         *    if (outputHeadings) Util.outputCSVLine(writer,formFields.getColumnLabels());
110:         *    Util.outputCSVLine(writer,formFields.getColumnValues(servletRequest.getParameterMap()));
111:         *    writer.close();
112:         *
113:         *    formFields.setDataSet(servletRequest.getParameterMap());
114:         *    OutputDocument outputDocument=new OutputDocument(source);
115:         *    outputDocument.replace(formFields);
116:         *    outputDocument.writeTo(servletResponse.getWriter());</pre>
117:         *   <p>See also the sample program FormFieldCSVOutput.<br /><br />
118:         *  <li>Replace the initial values of controls in the form named "MyForm" with new values:
119:         *   <p><pre>
120:         *    Source source=new Source(htmlText);
121:         *    Element myForm=null;
122:         *    List formElements=source.findAllElements(Tag.FORM);
123:         *    for (Iterator i=formElements.iterator(); i.hasNext();) {
124:         *      Element formElement=(Element)i.next();
125:         *      String formName=formElement.getAttributes().getValue("name");
126:         *      if ("MyForm".equals(formName)) {
127:         *        myForm=form;
128:         *        break;
129:         *      }
130:         *    }
131:         *    FormFields formFields=myForm.findFormFields();
132:         *    formFields.clearValues(); // clear any values that might be set in the source document
133:         *    formFields.addValue("Name","Humphrey Bear");
134:         *    formFields.addValue("MailingList","A");
135:         *    formFields.addValue("MailingList","B");
136:         *    formFields.addValue("FavouriteFare","honey");
137:         *    OutputDocument outputDocument=new OutputDocument(source);
138:         *    outputDocument.replace(formFields);
139:         *    String newHtmlText=outputDocument.toString();</pre>
140:         *   <p>See also the sample program FormFieldSetValues.<br /><br />
141:         *  <li>Change the display characteristics of individual controls:
142:         *   <p><pre>
143:         *    Source source=new Source(htmlText);
144:         *    FormFields formFields=source.findFormFields();
145:         *    // disable some controls:
146:         *    formFields.get("Password").getFormControl().setDisabled(true);
147:         *    FormField mailingListFormField=formFields.get("MailingList");
148:         *    mailingListFormField.setValue("C");
149:         *    mailingListFormField.getFormControl("C").setDisabled(true);
150:         *    mailingListFormField.getFormControl("D").setDisabled(true);
151:         *    // remove some controls:
152:         *    formFields.get("button1").getFormControl().setOutputStyle(FormControlOutputStyle.REMOVE);
153:         *    FormControl rhubarbFormControl=formFields.get("FavouriteFare").getFormControl("rhubarb");
154:         *    rhubarbFormControl.setOutputStyle(FormControlOutputStyle.REMOVE);
155:         *    // set some controls to display value:
156:         *    formFields.setValue("Address","The Lodge\nDeakin  ACT  2600\nAustralia");
157:         *    formFields.get("Address").getFormControl().setOutputStyle(FormControlOutputStyle.DISPLAY_VALUE);
158:         *    FormField favouriteSportsFormField=formFields.get("FavouriteSports");
159:         *    favouriteSportsFormField.setValue("BB");
160:         *    favouriteSportsFormField.addValue("AFL");
161:         *    favouriteSportsFormField.getFormControl().setOutputStyle(FormControlOutputStyle.DISPLAY_VALUE);
162:         *    OutputDocument outputDocument=new OutputDocument(source);
163:         *    outputDocument.replace(formFields); // adds all segments necessary to effect changes
164:         *    String newHtmlText=outputDocument.toString();</pre>
165:         *   <p>See also the sample program FormControlDisplayCharacteristics.<br /><br />
166:         * </ol>
167:         * @see FormField
168:         * @see FormControl
169:         */
170:        public final class FormFields extends AbstractCollection {
171:            private final LinkedHashMap map = new LinkedHashMap();
172:            private final ArrayList formControls = new ArrayList();
173:
174:            /**
175:             * Constructs a new <code>FormFields</code> object consisting of the specified {@linkplain FormControl form controls}.
176:             * @param formControls  a collection of {@link FormControl} objects.
177:             * @see Segment#findFormFields()
178:             */
179:            public FormFields(final Collection formControls) {
180:                // Passing "this" as a parameter inside a constructor used to cause some strange problems back in java 1.0,
181:                // but it seems to work here and there is no explicit mention in the Java language spec about any potential problems.
182:                // The alternative is an ugly static FormFields constructFrom(List formControls) method.
183:                for (final Iterator i = formControls.iterator(); i.hasNext();) {
184:                    final FormControl formControl = (FormControl) i.next();
185:                    if (formControl.getName() != null
186:                            && formControl.getName().length() != 0) {
187:                        formControl.addToFormFields(this );
188:                        this .formControls.add(formControl);
189:                    }
190:                }
191:            }
192:
193:            /**
194:             * Returns the number of <code>FormField</code> objects.
195:             * @return the number of <code>FormField</code> objects.
196:             */
197:            public int getCount() {
198:                return map.size();
199:            }
200:
201:            /**
202:             * Returns the number of <code>FormField</code> objects.
203:             * <p>
204:             * This is equivalent to {@link #getCount()},
205:             * and is necessary to for the implementation of the <code>java.util.Collection</code> interface.
206:             *
207:             * @return the number of <code>FormField</code> objects.
208:             */
209:            public int size() {
210:                return getCount();
211:            }
212:
213:            /**
214:             * Returns the <code>FormField</code> with the specified {@linkplain FormField#getName() name}.
215:             * <p>
216:             * The case sensitivity of the <code>fieldName</code> argument is determined by the
217:             * {@link Config#CurrentCompatibilityMode}<code>.</code>{@link Config.CompatibilityMode#isFormFieldNameCaseInsensitive() FormFieldNameCaseInsensitive} property.
218:             *
219:             * @param fieldName  the name of the <code>FormField</code> to get.
220:             * @return the <code>FormField</code> with the specified {@linkplain FormField#getName() name}, or <code>null</code> if no <code>FormField</code> with the specified name exists.
221:             */
222:            public FormField get(String fieldName) {
223:                if (Config.CurrentCompatibilityMode
224:                        .isFormFieldNameCaseInsensitive())
225:                    fieldName = fieldName.toLowerCase();
226:                return (FormField) map.get(fieldName);
227:            }
228:
229:            /**
230:             * Returns an iterator over the {@link FormField} objects in the collection.
231:             * <p>
232:             * The order in which the form fields are iterated corresponds to the order of appearance
233:             * of each form field's first {@link FormControl} in the source document.
234:             * <p>
235:             * If this <code>FormFields</code> object has been {@linkplain #merge(FormFields) merged} with another,
236:             * the ordering is no longer defined.
237:             *
238:             * @return an iterator over the {@link FormField} objects in the collection.
239:             */
240:            public Iterator iterator() {
241:                return map.values().iterator();
242:            }
243:
244:            /**
245:             * Returns a collection of the <a href="FormField.html#FieldSubmissionValue">field submission values</a> of all the specified constituent {@linkplain FormField form field} with the specified {@linkplain FormField#getName() name}.
246:             * <p>
247:             * All objects in the returned collection are of type <code>CharSequence</code>, with no <code>null</code> entries.
248:             * <p>
249:             * This is equivalent to {@link #get(String) get(fieldName)}<code>.</code>{@link FormField#getValues() getValues()},
250:             * assuming that a field with the specified name exists in this collection.
251:             *
252:             * @param fieldName  the {@linkplain FormField#getName() name} of the form field.
253:             * @return a collection of the <a href="FormField.html#FieldSubmissionValue">field submission values</a> of all the specified constituent {@linkplain FormField form field} with the specified {@linkplain FormField#getName() name}, or <code>null</code> if no form field with this name exists.
254:             * @see FormField#getValues()
255:             */
256:            public Collection getValues(final String fieldName) {
257:                final FormField formField = get(fieldName);
258:                return formField == null ? null : formField.getValues();
259:            }
260:
261:            /**
262:             * Returns the entire <a href="#FieldDataSet">field data set</a> represented by the {@linkplain FormField#getValues() values} of the constituent form fields.
263:             * <p>
264:             * The values in the map returned by this method are represented as a string array, giving the map a format consistent with the
265:             * <code><a target="_blank" href="http://java.sun.com/products/servlet/2.3/javadoc/javax/servlet/ServletRequest.html#getParameterMap()">javax.servlet.ServletRequest.getParameterMap()</a></code>
266:             * method.
267:             * <p>
268:             * Only the {@linkplain FormField#getName() names} of form fields with at least one {@linkplain FormField#getValues() value}
269:             * are included in the map, meaning every <code>String[]</code> is guaranteed to have at least one entry.
270:             *
271:             * @return the entire <a href="#FieldDataSet">field data set</a> represented by the {@linkplain FormField#getValues() values} of the constituent form fields.
272:             * @see #setDataSet(Map)
273:             */
274:            public Map getDataSet() {
275:                final HashMap map = new HashMap((int) (getCount() / 0.7));
276:                for (final Iterator i = iterator(); i.hasNext();) {
277:                    final FormField formField = (FormField) i.next();
278:                    final Collection values = formField.getValues();
279:                    if (values.isEmpty())
280:                        continue;
281:                    final String[] valuesArray = new String[values.size()];
282:                    final Iterator valuesIterator = values.iterator();
283:                    for (int x = 0; x < values.size(); x++)
284:                        valuesArray[x] = valuesIterator.next().toString();
285:                    map.put(formField.getName(), valuesArray);
286:                }
287:                return map;
288:            }
289:
290:            /**
291:             * Clears the <a href="FormControl.html#SubmissionValue">submission values</a> of all the constituent {@linkplain #getFormControls() form controls}.
292:             * @see FormControl#clearValues()
293:             */
294:            public void clearValues() {
295:                for (final Iterator i = formControls.iterator(); i.hasNext();)
296:                    ((FormControl) i.next()).clearValues();
297:            }
298:
299:            /**
300:             * Sets the <a href="FormControl.html#SubmissionValue">submission values</a> of all the constituent
301:             * {@linkplain FormControl form controls} to match the data in the specified <a href="#FieldDataSet">field data set</a>.
302:             * <p>
303:             * The map keys must be <code>String</code> {@linkplain FormField#getName() field names}, with each map value either an array or 
304:             * <code>Collection</code> of <code>CharSequence</code> objects containing the field's new 
305:             * {@linkplain FormField#setValues(Collection) values}.
306:             * <p>
307:             * The map returned by the
308:             * <code><a target="_blank" href="http://java.sun.com/products/servlet/2.3/javadoc/javax/servlet/ServletRequest.html#getParameterMap()">javax.servlet.ServletRequest.getParameterMap()</a></code>
309:             * method has a suitable format for use with this method.
310:             * <p>
311:             * All existing values are {@linkplain #clearValues() cleared} before the values from the field data set are added.
312:             * <p>
313:             * Any map entries with a <code>null</code> value are ignored.
314:             *
315:             * @param dataSet  the <a href="#FieldDataSet">field data set</a> containing the new {@linkplain FormField#setValues(Collection) values} of the constituent form fields.
316:             * @see #getDataSet()
317:             */
318:            public void setDataSet(final Map dataSet) {
319:                clearValues();
320:                if (map == null)
321:                    return;
322:                for (final Iterator i = dataSet.entrySet().iterator(); i
323:                        .hasNext();) {
324:                    final Map.Entry entry = (Map.Entry) i.next();
325:                    final String fieldName = entry.getKey().toString();
326:                    final FormField formField = get(fieldName);
327:                    if (formField != null) {
328:                        if (entry.getValue() instanceof  Collection)
329:                            formField.addValues((Collection) entry.getValue());
330:                        else
331:                            formField.addValues((CharSequence[]) entry
332:                                    .getValue());
333:                    }
334:                }
335:            }
336:
337:            /**
338:             * Sets the <a href="FormField.html#FieldSubmissionValues">field submission values</a> of the constituent
339:             * {@linkplain FormField form field} with the specified {@linkplain FormField#getName() name} to the single specified value.
340:             * <p>
341:             * This is equivalent to {@link #get(String) get(fieldName)}<code>.</code>{@link FormField#setValue(CharSequence) setValue(value)},
342:             * assuming that a field with the specified name exists in this collection.
343:             * <p>
344:             * The return value indicates whether the specified form field "accepted" the value.
345:             * A return value of <code>false</code> implies an error condition as either no field with the specified name exists, or
346:             * the specified value is not compatible with the specified field.
347:             *
348:             * @param fieldName  the {@linkplain FormField#getName() name} of the form field.
349:             * @param value  the new <a href="FormField.html#FieldSubmissionValues">field submission value</a> of the specified field, or <code>null</code> to {@linkplain FormField#clearValues() clear} the field of all submission values.
350:             * @return <code>true</code> if a field of the specified name exists in this collection and it accepts the specified value, otherwise <code>false</code>.
351:             */
352:            public boolean setValue(final String fieldName,
353:                    final CharSequence value) {
354:                final FormField formField = get(fieldName);
355:                return formField == null ? false : formField.setValue(value);
356:            }
357:
358:            /**
359:             * Adds the specified value to the <a href="FormField.html#FieldSubmissionValues">field submission values</a> of the constituent
360:             * {@linkplain FormField form field} with the specified {@linkplain FormField#getName() name}.
361:             * <p>
362:             * This is equivalent to {@link #get(String) get(fieldName)}<code>.</code>{@link FormField#addValue(CharSequence) addValue(value)},
363:             * assuming that a field with the specified name exists in this collection.
364:             * <p>
365:             * The return value indicates whether the specified form field "accepted" the value.
366:             * A return value of <code>false</code> implies an error condition as either no field with the specified name exists, or
367:             * the specified value is not compatible with the specified field.
368:             *
369:             * @param fieldName  the {@linkplain FormField#getName() name} of the form field.
370:             * @param value  the new <a href="FormField.html#FieldSubmissionValues">field submission value</a> to add to the specified field, must not be <code>null</code>.
371:             * @return <code>true</code> if a field of the specified name exists in this collection and it accepts the specified value, otherwise <code>false</code>.
372:             */
373:            public boolean addValue(final String fieldName,
374:                    final CharSequence value) {
375:                final FormField formField = get(fieldName);
376:                return formField == null ? false : formField.addValue(value);
377:            }
378:
379:            /**
380:             * Returns a string array containing the column labels corresponding to the values from the {@link #getColumnValues(Map)} method.
381:             * <p>
382:             * Instead of using the {@linkplain FormField#getName() name} of each constituent form field to construct the labels,
383:             * the {@linkplain FormControl#getName() name} of the first {@linkplain FormControl form control} from each form field is used.
384:             * This allows the labels to be constructed using the names with the original case from the source document rather than
385:             * unsing the all lower case names of the form fields.
386:             * <p>
387:             * See the documentation of the {@link #getColumnValues(Map)} method for more details.
388:             *
389:             * @return a string array containing the column labels corresponding to the values from the {@link #getColumnValues(Map)} method.
390:             * @see Util#outputCSVLine(Writer,String[])
391:             */
392:            public String[] getColumnLabels() {
393:                initColumns();
394:                final String[] columnLabels = new String[columns.length];
395:                for (int i = 0; i < columns.length; i++) {
396:                    final Column column = columns[i];
397:                    final String fieldName = column.formField
398:                            .getFirstFormControl().getName(); // use this instead of formControl.getName() so that the original case is used even if Config.CurrentCompatibilityMode.isFormFieldNameCaseInsensitive() is true.
399:                    columnLabels[i] = column.predefinedValue != null ? fieldName
400:                            + '.' + column.predefinedValue
401:                            : fieldName;
402:                }
403:                return columnLabels;
404:            }
405:
406:            /**
407:             * Converts the data values in the specified <a href="#FieldDataSet">field data set</a> into a simple string array,
408:             * suitable for storage in a tabular format such as a database table or <code>.CSV</code> file.
409:             * <p>
410:             * The conversion is performed in a way that allows the multiple values of certain fields to be stored in separate columns,
411:             * by analysing the possible <a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#form-data-set">form data sets</a>
412:             * that can be generated from the constituent {@linkplain #getFormControls() form controls}.
413:             * <p>
414:             * The column labels and values are determined as follows:
415:             * <p>
416:             * <ul class="HalfSeparated">
417:             *  <li>
418:             *   For each {@linkplain FormField form field} in this collection (taken in {@linkplain #iterator() iterator} order):
419:             *   <ul>
420:             *    <li>
421:             *     If the form field has no {@linkplain FormField#getPredefinedValues() predefined values},
422:             *     such as a single {@linkplain FormControlType#TEXT text control}, then:
423:             *     <ul>
424:             *      <li>
425:             *       Add a single column:
426:             *       <table class="CompactDL">
427:             *        <tr><td>{@linkplain #getColumnLabels() Label}:<td>the {@linkplain FormField#getName() name} of the form field in original case
428:             *        <tr><td>Value:<td>the single value mapped to this field in the specified <a href="#FieldDataSet">field data set</a>.
429:             *       </table>
430:             *       In the unlikely event that this field contains more than one value, all values are included in this one column and
431:             *       separated by the text defined in the {@link Config#ColumnMultipleValueSeparator} property.
432:             *     </ul>
433:             *    <li>
434:             *     Otherwise, if the form field does have {@linkplain FormField#getPredefinedValues() predefined values},
435:             *     but does not {@linkplain FormField#allowsMultipleValues() allow multiple values}, then:
436:             *     <ul>
437:             *      <li>
438:             *       If the form field has only one {@linkplain FormField#getPredefinedValues() predefined value},
439:             *       such as a single {@linkplain FormControlType#CHECKBOX checkbox}, then:
440:             *       <ul>
441:             *        <li>
442:             *         Add a single boolean column:
443:             *         <table class="CompactDL">
444:             *          <tr><td>{@linkplain #getColumnLabels() Label}:<td>the {@linkplain FormField#getName() name} of the form field in original case
445:             *          <tr><td>Value:<td>the currently configured string representation for <i>{@linkplain Config#ColumnValueTrue true}</i>
446:             *           if a value mapped to this field in the specified <a href="#FieldDataSet">field data set</a> matches the
447:             *           {@linkplain FormField#getPredefinedValues() predefined value}, otherwise <i>{@linkplain Config#ColumnValueFalse false}</i>
448:             *         </table>
449:             *       </ul>
450:             *      <li>
451:             *       Otherwise, if the form field has more than one {@linkplain FormField#getPredefinedValues() predefined value},
452:             *       such as a set of {@linkplain FormControlType#RADIO radio buttons}, then:
453:             *       <ul>
454:             *        <li>
455:             *         Add a single column:
456:             *         <table class="CompactDL">
457:             *          <tr><td>{@linkplain #getColumnLabels() Label}:<td>the {@linkplain FormField#getName() name} of the form field in original case
458:             *          <tr><td>Value:<td>the single value mapped to this field in the specified <a href="#FieldDataSet">field data set</a>,
459:             *           which in the case of a set of radio buttons should be the {@linkplain FormControl#getPredefinedValue() predefined value}
460:             *           of the {@linkplain FormControl#isChecked() checked} radio button.
461:             *         </table>
462:             *       </ul>
463:             *     </ul>
464:             *    <li>
465:             *     Otherwise, if the form field has {@linkplain FormField#getPredefinedValues() predefined values}
466:             *     and {@linkplain FormField#allowsMultipleValues() allows multiple values},
467:             *     such as a set of {@linkplain FormControlType#CHECKBOX checkboxes}, then:
468:             *     <ul>
469:             *      <li>
470:             *       For each {@linkplain FormField#getPredefinedValues() predefined value} in the form field:
471:             *       <ul>
472:             *        <li>
473:             *         Add a boolean column:
474:             *         <table class="CompactDL">
475:             *          <tr><td>{@linkplain #getColumnLabels() Label}:<td>"<code><i>FieldName</i>.<i>PredefinedValue</i></code>",
476:             *           where <code><i>FieldName</i></code> is the {@linkplain FormField#getName() name} of the form field in original case,
477:             *           and <code><i>PredefinedValue</i></code> is the {@linkplain FormField#getPredefinedValues() predefined value}.
478:             *          <tr><td>Value:<td>the currently configured string representation for <i>{@linkplain Config#ColumnValueTrue true}</i>
479:             *           if a value mapped to this field in the specified <a href="#FieldDataSet">field data set</a> matches the 
480:             *           {@linkplain FormField#getPredefinedValues() predefined value}, otherwise <i>{@linkplain Config#ColumnValueFalse false}</i>
481:             *         </table>
482:             *       </ul>
483:             *      <li>
484:             *       In addition, if the form field can also contain user values ({@link FormField#getUserValueCount()}<code>&gt;0</code>), then:
485:             *       <ul>
486:             *        <li>
487:             *         Add another column:
488:             *         <table class="CompactDL">
489:             *          <tr><td>{@linkplain #getColumnLabels() Label}:<td>the {@linkplain FormField#getName() name} of the form field in original case
490:             *          <tr><td>Value:<td>all values mapped to this field in the specified <a href="#FieldDataSet">field data set</a>
491:             *          that do not match any of the {@linkplain FormField#getPredefinedValues() predefined values},
492:             *          separated by the text defined in the {@link Config#ColumnMultipleValueSeparator} property.
493:             *         </table>
494:             *       </ul>
495:             *     </ul>
496:             *   </ul>
497:             * </ul>
498:             * <p>
499:             * The sample program FormFieldCSVOutput demonstrates the use of this method and its output.
500:             *
501:             * @param dataSet  a <a href="#FieldDataSet">field data set</a> containing the data to convert.
502:             * @return the data values in the specified <a href="#FieldDataSet">field data set</a> in the form of a simple string array.
503:             * @see Util#outputCSVLine(Writer,String[])
504:             * @see #getColumnLabels()
505:             * @see #getColumnValues()
506:             */
507:            public String[] getColumnValues(final Map dataSet) {
508:                initColumns();
509:                final String[] columnValues = new String[columns.length];
510:                if (Config.ColumnValueFalse != null) {
511:                    // initialise all boolean columns with false string
512:                    for (int i = 0; i < columns.length; i++)
513:                        if (columns[i].isBoolean)
514:                            columnValues[i] = Config.ColumnValueFalse;
515:                }
516:                for (final Iterator i = dataSet.entrySet().iterator(); i
517:                        .hasNext();) {
518:                    final Map.Entry entry = (Map.Entry) i.next();
519:                    final String fieldName = entry.getKey().toString();
520:                    final FormField formField = get(fieldName);
521:                    if (formField != null) {
522:                        final Collection values = (entry.getValue() instanceof  Collection) ? (Collection) entry
523:                                .getValue()
524:                                : Arrays.asList((CharSequence[]) entry
525:                                        .getValue());
526:                        final int columnIndex = formField.columnIndex;
527:                        for (final Iterator valueIterator = values.iterator(); valueIterator
528:                                .hasNext();) {
529:                            final String value = valueIterator.next()
530:                                    .toString();
531:                            for (int ci = columnIndex; ci < columns.length; ci++) {
532:                                final Column column = columns[ci];
533:                                if (column.formField != formField)
534:                                    break;
535:                                if (column.predefinedValue != null) {
536:                                    if (!column.predefinedValue.equals(value))
537:                                        continue;
538:                                    columnValues[ci] = Config.ColumnValueTrue;
539:                                } else {
540:                                    if (column.isBoolean) {
541:                                        if (value != null)
542:                                            columnValues[ci] = Config.ColumnValueTrue;
543:                                    } else if (columnValues[ci] == null) {
544:                                        columnValues[ci] = value;
545:                                    } else {
546:                                        columnValues[ci] = columnValues[ci]
547:                                                + Config.ColumnMultipleValueSeparator
548:                                                + value;
549:                                    }
550:                                }
551:                                break;
552:                            }
553:                        }
554:                    }
555:                }
556:                return columnValues;
557:            }
558:
559:            /**
560:             * Converts all the {@linkplain FormField#getValues() form submission values} of the constituent form fields into a simple string array,
561:             * suitable for storage in a tabular format such as a database table or <code>.CSV</code> file.
562:             * <p>
563:             * This is equivalent to {@link #getColumnValues(Map) getColumnValues}<code>(</code>{@link #getDataSet()}<code>)</code>.
564:             *
565:             * @return all the {@linkplain FormField#getValues() form submission values} of the constituent form fields in the form of a simple string array.
566:             */
567:            public String[] getColumnValues() {
568:                return getColumnValues(getDataSet());
569:            }
570:
571:            private void initColumns() {
572:                if (columns != null)
573:                    return;
574:                final ArrayList columnList = new ArrayList();
575:                for (final Iterator i = iterator(); i.hasNext();) {
576:                    final FormField formField = (FormField) i.next();
577:                    formField.columnIndex = columnList.size();
578:                    if (!formField.allowsMultipleValues()
579:                            || formField.getPredefinedValues().isEmpty()) {
580:                        columnList.add(new Column(formField, formField
581:                                .getPredefinedValues().size() == 1, null));
582:                    } else {
583:                        // add a column for every predefined value
584:                        for (final Iterator pvi = formField
585:                                .getPredefinedValues().iterator(); pvi
586:                                .hasNext();)
587:                            columnList.add(new Column(formField, true,
588:                                    (String) pvi.next()));
589:                        if (formField.getUserValueCount() > 0)
590:                            columnList.add(new Column(formField, false, null)); // add a column for user values, must come after predefined values for algorithm in getColumnValues to work
591:                    }
592:                }
593:                columns = (Column[]) columnList.toArray(new Column[columnList
594:                        .size()]);
595:            }
596:
597:            private Column[] columns = null;
598:
599:            private static class Column {
600:                public FormField formField;
601:                public boolean isBoolean;
602:                public String predefinedValue;
603:
604:                public Column(final FormField formField,
605:                        final boolean isBoolean, final String predefinedValue) {
606:                    this .formField = formField;
607:                    this .isBoolean = isBoolean;
608:                    this .predefinedValue = predefinedValue;
609:                }
610:            }
611:
612:            /**
613:             * Returns a list of all the {@linkplain FormField#getFormControls() constituent form controls} from all the {@linkplain FormField form fields} in this collection.
614:             * @return a list of all the {@linkplain FormField#getFormControls() constituent form controls} from all the {@linkplain FormField form fields} in this collection.
615:             */
616:            public List getFormControls() {
617:                return formControls;
618:            }
619:
620:            /**
621:             * Merges the specified <code>FormFields</code> into this <code>FormFields</code> collection.
622:             * This is useful if a full collection of possible form fields is required from multiple {@linkplain Source source} documents.
623:             * <p>
624:             * If both collections contain a <code>FormField</code> with the same {@linkplain FormField#getName() name},
625:             * the resulting <code>FormField</code> has the following properties:
626:             * <ul>
627:             * <li>{@link FormField#getUserValueCount() getUserValueCount()} : the maximum user value count from both form fields</li>
628:             * <li>{@link FormField#allowsMultipleValues() allowsMultipleValues()} : <code>true</code> if either form field allows multiple values</li>
629:             * <li>{@link FormField#getPredefinedValues() getPredefinedValues()} : the union of predefined values in both form fields</li>
630:             * <li>{@link FormField#getFormControls() getFormControls()} : the union of {@linkplain FormControl form controls} from both form fields</li>
631:             * </ul>
632:             * <p>
633:             * NOTE: Some underlying data structures may end up being shared between the two merged <code>FormFields</code> collections.
634:             */
635:            public void merge(final FormFields formFields) {
636:                for (final Iterator i = formFields.iterator(); i.hasNext();) {
637:                    final FormField formField = (FormField) i.next();
638:                    final String fieldName = formField.getName();
639:                    final FormField existingFormField = get(fieldName);
640:                    if (existingFormField == null)
641:                        add(formField);
642:                    else
643:                        existingFormField.merge(formField);
644:                }
645:            }
646:
647:            /**
648:             * Returns a string representation of this object useful for debugging purposes.
649:             * @return a string representation of this object useful for debugging purposes.
650:             */
651:            public String getDebugInfo() {
652:                final StringBuffer sb = new StringBuffer();
653:                for (final Iterator i = iterator(); i.hasNext();) {
654:                    sb.append(i.next());
655:                }
656:                return sb.toString();
657:            }
658:
659:            /**
660:             * Returns a string representation of this object useful for debugging purposes.
661:             * <p>
662:             * This is equivalent to {@link #getDebugInfo()}.
663:             *
664:             * @return a string representation of this object useful for debugging purposes.
665:             */
666:            public String toString() {
667:                return getDebugInfo();
668:            }
669:
670:            void add(final FormControl formControl) {
671:                add(formControl, formControl.getPredefinedValue());
672:            }
673:
674:            void add(final FormControl formControl, final String predefinedValue) {
675:                add(formControl, predefinedValue, formControl.name);
676:            }
677:
678:            void addName(final FormControl formControl, final String fieldName) {
679:                add(formControl, null, fieldName);
680:            }
681:
682:            void add(final FormControl formControl,
683:                    final String predefinedValue, String fieldName) {
684:                if (Config.CurrentCompatibilityMode
685:                        .isFormFieldNameCaseInsensitive())
686:                    fieldName = fieldName.toLowerCase();
687:                FormField formField = (FormField) map.get(fieldName);
688:                if (formField == null) {
689:                    formField = new FormField(fieldName);
690:                    add(formField);
691:                }
692:                formField.addFormControl(formControl, predefinedValue);
693:            }
694:
695:            void replaceInOutputDocument(final OutputDocument outputDocument) {
696:                for (final Iterator i = formControls.iterator(); i.hasNext();)
697:                    outputDocument.replace((FormControl) i.next());
698:            }
699:
700:            private void add(final FormField formField) {
701:                map.put(formField.getName(), formField);
702:            }
703:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.