KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jivesoftware > smackx > Form


1 /**
2  * $RCSfile$
3  * $Revision: 2407 $
4  * $Date: 2004-11-02 20:37:00 -0300 (Tue, 02 Nov 2004) $
5  *
6  * Copyright 2003-2004 Jive Software.
7  *
8  * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */

20
21 package org.jivesoftware.smackx;
22
23 import java.util.*;
24
25 import org.jivesoftware.smack.packet.*;
26 import org.jivesoftware.smackx.packet.DataForm;
27
28 /**
29  * Represents a Form for gathering data. The form could be of the following types:
30  * <ul>
31  * <li>form -> Indicates a form to fill out.</li>
32  * <li>submit -> The form is filled out, and this is the data that is being returned from
33  * the form.</li>
34  * <li>cancel -> The form was cancelled. Tell the asker that piece of information.</li>
35  * <li>result -> Data results being returned from a search, or some other query.</li>
36  * </ul>
37  *
38  * Depending of the form's type different operations are available. For example, it's only possible
39  * to set answers if the form is of type "submit".
40  *
41  * @author Gaston Dombiak
42  */

43 public class Form {
44     
45     public static final String JavaDoc TYPE_FORM = "form";
46     public static final String JavaDoc TYPE_SUBMIT = "submit";
47     public static final String JavaDoc TYPE_CANCEL = "cancel";
48     public static final String JavaDoc TYPE_RESULT = "result";
49     
50     private DataForm dataForm;
51     
52     /**
53      * Returns a new ReportedData if the packet is used for gathering data and includes an
54      * extension that matches the elementName and namespace "x","jabber:x:data".
55      *
56      * @param packet the packet used for gathering data.
57      */

58     public static Form getFormFrom(Packet packet) {
59         // Check if the packet includes the DataForm extension
60
PacketExtension packetExtension = packet.getExtension("x","jabber:x:data");
61         if (packetExtension != null) {
62             // Check if the existing DataForm is not a result of a search
63
DataForm dataForm = (DataForm) packetExtension;
64             if (dataForm.getReportedData() == null)
65                 return new Form(dataForm);
66         }
67         // Otherwise return null
68
return null;
69     }
70
71     /**
72      * Creates a new Form that will wrap an existing DataForm. The wrapped DataForm must be
73      * used for gathering data.
74      *
75      * @param dataForm the data form used for gathering data.
76      */

77     private Form(DataForm dataForm) {
78         this.dataForm = dataForm;
79     }
80     
81     /**
82      * Creates a new Form of a given type from scratch.<p>
83      *
84      * Possible form types are:
85      * <ul>
86      * <li>form -> Indicates a form to fill out.</li>
87      * <li>submit -> The form is filled out, and this is the data that is being returned from
88      * the form.</li>
89      * <li>cancel -> The form was cancelled. Tell the asker that piece of information.</li>
90      * <li>result -> Data results being returned from a search, or some other query.</li>
91      * </ul>
92      *
93      * @param type the form's type (e.g. form, submit,cancel,result).
94      */

95     public Form(String JavaDoc type) {
96         this.dataForm = new DataForm(type);
97     }
98     
99     /**
100      * Adds a new field to complete as part of the form.
101      *
102      * @param field the field to complete.
103      */

104     public void addField(FormField field) {
105         dataForm.addField(field);
106     }
107     
108     /**
109      * Sets a new String value to a given form's field. The field whose variable matches the
110      * requested variable will be completed with the specified value. If no field could be found
111      * for the specified variable then an exception will be raised.<p>
112      *
113      * If the value to set to the field is not a basic type (e.g. String, boolean, int, etc.) you
114      * can use this message where the String value is the String representation of the object.
115      *
116      * @param variable the variable name that was completed.
117      * @param value the String value that was answered.
118      * @throws IllegalStateException if the form is not of type "submit".
119      * @throws IllegalArgumentException if the form does not include the specified variable.
120      * @throws IllegalArgumentException if the answer type does not correspond with the field type.
121      */

122     public void setAnswer(String JavaDoc variable, String JavaDoc value) {
123         FormField field = getField(variable);
124         if (field == null) {
125             throw new IllegalArgumentException JavaDoc("Field not found for the specified variable name.");
126         }
127         if (!FormField.TYPE_TEXT_MULTI.equals(field.getType())
128             && !FormField.TYPE_TEXT_PRIVATE.equals(field.getType())
129             && !FormField.TYPE_TEXT_SINGLE.equals(field.getType())
130             && !FormField.TYPE_JID_SINGLE.equals(field.getType())
131             && !FormField.TYPE_HIDDEN.equals(field.getType())) {
132             throw new IllegalArgumentException JavaDoc("This field is not of type String.");
133         }
134         setAnswer(field, value);
135     }
136
137     /**
138      * Sets a new int value to a given form's field. The field whose variable matches the
139      * requested variable will be completed with the specified value. If no field could be found
140      * for the specified variable then an exception will be raised.
141      *
142      * @param variable the variable name that was completed.
143      * @param value the int value that was answered.
144      * @throws IllegalStateException if the form is not of type "submit".
145      * @throws IllegalArgumentException if the form does not include the specified variable.
146      * @throws IllegalArgumentException if the answer type does not correspond with the field type.
147      */

148     public void setAnswer(String JavaDoc variable, int value) {
149         FormField field = getField(variable);
150         if (field == null) {
151             throw new IllegalArgumentException JavaDoc("Field not found for the specified variable name.");
152         }
153         if (!FormField.TYPE_TEXT_MULTI.equals(field.getType())
154             && !FormField.TYPE_TEXT_PRIVATE.equals(field.getType())
155             && !FormField.TYPE_TEXT_SINGLE.equals(field.getType())) {
156             throw new IllegalArgumentException JavaDoc("This field is not of type int.");
157         }
158         setAnswer(field, new Integer JavaDoc(value));
159     }
160
161     /**
162      * Sets a new long value to a given form's field. The field whose variable matches the
163      * requested variable will be completed with the specified value. If no field could be found
164      * for the specified variable then an exception will be raised.
165      *
166      * @param variable the variable name that was completed.
167      * @param value the long value that was answered.
168      * @throws IllegalStateException if the form is not of type "submit".
169      * @throws IllegalArgumentException if the form does not include the specified variable.
170      * @throws IllegalArgumentException if the answer type does not correspond with the field type.
171      */

172     public void setAnswer(String JavaDoc variable, long value) {
173         FormField field = getField(variable);
174         if (field == null) {
175             throw new IllegalArgumentException JavaDoc("Field not found for the specified variable name.");
176         }
177         if (!FormField.TYPE_TEXT_MULTI.equals(field.getType())
178             && !FormField.TYPE_TEXT_PRIVATE.equals(field.getType())
179             && !FormField.TYPE_TEXT_SINGLE.equals(field.getType())) {
180             throw new IllegalArgumentException JavaDoc("This field is not of type long.");
181         }
182         setAnswer(field, new Long JavaDoc(value));
183     }
184
185     /**
186      * Sets a new float value to a given form's field. The field whose variable matches the
187      * requested variable will be completed with the specified value. If no field could be found
188      * for the specified variable then an exception will be raised.
189      *
190      * @param variable the variable name that was completed.
191      * @param value the float value that was answered.
192      * @throws IllegalStateException if the form is not of type "submit".
193      * @throws IllegalArgumentException if the form does not include the specified variable.
194      * @throws IllegalArgumentException if the answer type does not correspond with the field type.
195      */

196     public void setAnswer(String JavaDoc variable, float value) {
197         FormField field = getField(variable);
198         if (field == null) {
199             throw new IllegalArgumentException JavaDoc("Field not found for the specified variable name.");
200         }
201         if (!FormField.TYPE_TEXT_MULTI.equals(field.getType())
202             && !FormField.TYPE_TEXT_PRIVATE.equals(field.getType())
203             && !FormField.TYPE_TEXT_SINGLE.equals(field.getType())) {
204             throw new IllegalArgumentException JavaDoc("This field is not of type float.");
205         }
206         setAnswer(field, new Float JavaDoc(value));
207     }
208
209     /**
210      * Sets a new double value to a given form's field. The field whose variable matches the
211      * requested variable will be completed with the specified value. If no field could be found
212      * for the specified variable then an exception will be raised.
213      *
214      * @param variable the variable name that was completed.
215      * @param value the double value that was answered.
216      * @throws IllegalStateException if the form is not of type "submit".
217      * @throws IllegalArgumentException if the form does not include the specified variable.
218      * @throws IllegalArgumentException if the answer type does not correspond with the field type.
219      */

220     public void setAnswer(String JavaDoc variable, double value) {
221         FormField field = getField(variable);
222         if (field == null) {
223             throw new IllegalArgumentException JavaDoc("Field not found for the specified variable name.");
224         }
225         if (!FormField.TYPE_TEXT_MULTI.equals(field.getType())
226             && !FormField.TYPE_TEXT_PRIVATE.equals(field.getType())
227             && !FormField.TYPE_TEXT_SINGLE.equals(field.getType())) {
228             throw new IllegalArgumentException JavaDoc("This field is not of type double.");
229         }
230         setAnswer(field, new Double JavaDoc(value));
231     }
232
233     /**
234      * Sets a new boolean value to a given form's field. The field whose variable matches the
235      * requested variable will be completed with the specified value. If no field could be found
236      * for the specified variable then an exception will be raised.
237      *
238      * @param variable the variable name that was completed.
239      * @param value the boolean value that was answered.
240      * @throws IllegalStateException if the form is not of type "submit".
241      * @throws IllegalArgumentException if the form does not include the specified variable.
242      * @throws IllegalArgumentException if the answer type does not correspond with the field type.
243      */

244     public void setAnswer(String JavaDoc variable, boolean value) {
245         FormField field = getField(variable);
246         if (field == null) {
247             throw new IllegalArgumentException JavaDoc("Field not found for the specified variable name.");
248         }
249         if (!FormField.TYPE_BOOLEAN.equals(field.getType())) {
250             throw new IllegalArgumentException JavaDoc("This field is not of type boolean.");
251         }
252         setAnswer(field, (value ? "1" : "0"));
253     }
254
255     /**
256      * Sets a new Object value to a given form's field. In fact, the object representation
257      * (i.e. #toString) will be the actual value of the field.<p>
258      *
259      * If the value to set to the field is not a basic type (e.g. String, boolean, int, etc.) you
260      * will need to use {@link #setAnswer(String, String))} where the String value is the
261      * String representation of the object.<p>
262      *
263      * Before setting the new value to the field we will check if the form is of type submit. If
264      * the form isn't of type submit means that it's not possible to complete the form and an
265      * exception will be thrown.
266      *
267      * @param field the form field that was completed.
268      * @param value the Object value that was answered. The object representation will be the
269      * actual value.
270      * @throws IllegalStateException if the form is not of type "submit".
271      */

272     private void setAnswer(FormField field, Object JavaDoc value) {
273         if (!isSubmitType()) {
274             throw new IllegalStateException JavaDoc("Cannot set an answer if the form is not of type " +
275             "\"submit\"");
276         }
277         field.resetValues();
278         field.addValue(value.toString());
279     }
280
281     /**
282      * Sets a new values to a given form's field. The field whose variable matches the requested
283      * variable will be completed with the specified values. If no field could be found for
284      * the specified variable then an exception will be raised.<p>
285      *
286      * The Objects contained in the List could be of any type. The String representation of them
287      * (i.e. #toString) will be actually used when sending the answer to the server.
288      *
289      * @param variable the variable that was completed.
290      * @param values the values that were answered.
291      * @throws IllegalStateException if the form is not of type "submit".
292      * @throws IllegalArgumentException if the form does not include the specified variable.
293      */

294     public void setAnswer(String JavaDoc variable, List values) {
295         if (!isSubmitType()) {
296             throw new IllegalStateException JavaDoc("Cannot set an answer if the form is not of type " +
297             "\"submit\"");
298         }
299         FormField field = getField(variable);
300         if (field != null) {
301             // Check that the field can accept a collection of values
302
if (!FormField.TYPE_JID_MULTI.equals(field.getType())
303                 && !FormField.TYPE_LIST_MULTI.equals(field.getType())
304                 && !FormField.TYPE_LIST_SINGLE.equals(field.getType())
305                 && !FormField.TYPE_HIDDEN.equals(field.getType())) {
306                 throw new IllegalArgumentException JavaDoc("This field only accept list of values.");
307             }
308             // Clear the old values
309
field.resetValues();
310             // Set the new values. The string representation of each value will be actually used.
311
field.addValues(values);
312         }
313         else {
314             throw new IllegalArgumentException JavaDoc("Couldn't find a field for the specified variable.");
315         }
316     }
317
318     /**
319      * Sets the default value as the value of a given form's field. The field whose variable matches
320      * the requested variable will be completed with its default value. If no field could be found
321      * for the specified variable then an exception will be raised.
322      *
323      * @param variable the variable to complete with its default value.
324      * @throws IllegalStateException if the form is not of type "submit".
325      * @throws IllegalArgumentException if the form does not include the specified variable.
326      */

327     public void setDefaultAnswer(String JavaDoc variable) {
328         if (!isSubmitType()) {
329             throw new IllegalStateException JavaDoc("Cannot set an answer if the form is not of type " +
330             "\"submit\"");
331         }
332         FormField field = getField(variable);
333         if (field != null) {
334             // Clear the old values
335
field.resetValues();
336             // Set the default value
337
for (Iterator it = field.getValues(); it.hasNext();) {
338                 field.addValue((String JavaDoc) it.next());
339             }
340         }
341         else {
342             throw new IllegalArgumentException JavaDoc("Couldn't find a field for the specified variable.");
343         }
344     }
345
346     /**
347      * Returns an Iterator for the fields that are part of the form.
348      *
349      * @return an Iterator for the fields that are part of the form.
350      */

351     public Iterator getFields() {
352         return dataForm.getFields();
353     }
354
355     /**
356      * Returns the field of the form whose variable matches the specified variable.
357      * The fields of type FIXED will never be returned since they do not specify a
358      * variable.
359      *
360      * @param variable the variable to look for in the form fields.
361      * @return the field of the form whose variable matches the specified variable.
362      */

363     public FormField getField(String JavaDoc variable) {
364         if (variable == null || variable.equals("")) {
365             throw new IllegalArgumentException JavaDoc("Variable must not be null or blank.");
366         }
367         // Look for the field whose variable matches the requested variable
368
FormField field;
369         for (Iterator it=getFields();it.hasNext();) {
370             field = (FormField)it.next();
371             if (variable.equals(field.getVariable())) {
372                 return field;
373             }
374         }
375         return null;
376     }
377
378     /**
379      * Returns the instructions that explain how to fill out the form and what the form is about.
380      *
381      * @return instructions that explain how to fill out the form.
382      */

383     public String JavaDoc getInstructions() {
384         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
385         // Join the list of instructions together separated by newlines
386
for (Iterator it = dataForm.getInstructions(); it.hasNext();) {
387             sb.append((String JavaDoc) it.next());
388             // If this is not the last instruction then append a newline
389
if (it.hasNext()) {
390                 sb.append("\n");
391             }
392         }
393         return sb.toString();
394     }
395
396
397     /**
398      * Returns the description of the data. It is similar to the title on a web page or an X
399      * window. You can put a <title/> on either a form to fill out, or a set of data results.
400      *
401      * @return description of the data.
402      */

403     public String JavaDoc getTitle() {
404         return dataForm.getTitle();
405     }
406
407
408     /**
409      * Returns the meaning of the data within the context. The data could be part of a form
410      * to fill out, a form submission or data results.<p>
411      *
412      * Possible form types are:
413      * <ul>
414      * <li>form -> Indicates a form to fill out.</li>
415      * <li>submit -> The form is filled out, and this is the data that is being returned from
416      * the form.</li>
417      * <li>cancel -> The form was cancelled. Tell the asker that piece of information.</li>
418      * <li>result -> Data results being returned from a search, or some other query.</li>
419      * </ul>
420      *
421      * @return the form's type.
422      */

423     public String JavaDoc getType() {
424         return dataForm.getType();
425     }
426     
427
428     /**
429      * Sets instructions that explain how to fill out the form and what the form is about.
430      *
431      * @param instructions instructions that explain how to fill out the form.
432      */

433     public void setInstructions(String JavaDoc instructions) {
434         // Split the instructions into multiple instructions for each existent newline
435
ArrayList instructionsList = new ArrayList();
436         StringTokenizer st = new StringTokenizer(instructions, "\n");
437         while (st.hasMoreTokens()) {
438             instructionsList.add(st.nextToken());
439         }
440         // Set the new list of instructions
441
dataForm.setInstructions(instructionsList);
442         
443     }
444
445
446     /**
447      * Sets the description of the data. It is similar to the title on a web page or an X window.
448      * You can put a <title/> on either a form to fill out, or a set of data results.
449      *
450      * @param title description of the data.
451      */

452     public void setTitle(String JavaDoc title) {
453         dataForm.setTitle(title);
454     }
455     
456     /**
457      * Returns a DataForm that serves to send this Form to the server. If the form is of type
458      * submit, it may contain fields with no value. These fields will be removed since they only
459      * exist to assist the user while editing/completing the form in a UI.
460      *
461      * @return the wrapped DataForm.
462      */

463     public DataForm getDataFormToSend() {
464         if (isSubmitType()) {
465             // Create a new DataForm that contains only the answered fields
466
DataForm dataFormToSend = new DataForm(getType());
467             for(Iterator it=getFields();it.hasNext();) {
468                 FormField field = (FormField)it.next();
469                 if (field.getValues().hasNext()) {
470                     dataFormToSend.addField(field);
471                 }
472             }
473             return dataFormToSend;
474         }
475         return dataForm;
476     }
477     
478     /**
479      * Returns true if the form is a form to fill out.
480      *
481      * @return if the form is a form to fill out.
482      */

483     private boolean isFormType() {
484         return TYPE_FORM.equals(dataForm.getType());
485     }
486     
487     /**
488      * Returns true if the form is a form to submit.
489      *
490      * @return if the form is a form to submit.
491      */

492     private boolean isSubmitType() {
493         return TYPE_SUBMIT.equals(dataForm.getType());
494     }
495
496     /**
497      * Returns a new Form to submit the completed values. The new Form will include all the fields
498      * of the original form except for the fields of type FIXED. Only the HIDDEN fields will
499      * include the same value of the original form. The other fields of the new form MUST be
500      * completed. If a field remains with no answer when sending the completed form, then it won't
501      * be included as part of the completed form.<p>
502      *
503      * The reason why the fields with variables are included in the new form is to provide a model
504      * for binding with any UI. This means that the UIs will use the original form (of type
505      * "form") to learn how to render the form, but the UIs will bind the fields to the form of
506      * type submit.
507      *
508      * @return a Form to submit the completed values.
509      */

510     public Form createAnswerForm() {
511         if (!isFormType()) {
512             throw new IllegalStateException JavaDoc("Only forms of type \"form\" could be answered");
513         }
514         // Create a new Form
515
Form form = new Form(TYPE_SUBMIT);
516         for (Iterator fields=getFields(); fields.hasNext();) {
517             FormField field = (FormField)fields.next();
518             // Add to the new form any type of field that includes a variable.
519
// Note: The fields of type FIXED are the only ones that don't specify a variable
520
if (field.getVariable() != null) {
521                 FormField newField = new FormField(field.getVariable());
522                 newField.setType(field.getType());
523                 form.addField(newField);
524                 // Set the answer ONLY to the hidden fields
525
if (FormField.TYPE_HIDDEN.equals(field.getType())) {
526                     // Since a hidden field could have many values we need to collect them
527
// in a list
528
List values = new ArrayList();
529                     for (Iterator it=field.getValues();it.hasNext();) {
530                         values.add((String JavaDoc)it.next());
531                     }
532                     form.setAnswer(field.getVariable(), values);
533                 }
534             }
535         }
536         return form;
537     }
538
539 }
540
Popular Tags