• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * $RCSfile$
3  * $Revision$
4  * $Date$
5  *
6  * Copyright 2003-2007 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 org.jivesoftware.smack.util.StringUtils;
24 
25 import java.util.ArrayList;
26 import java.util.Collections;
27 import java.util.Iterator;
28 import java.util.List;
29 
30 /**
31  * Represents a field of a form. The field could be used to represent a question to complete,
32  * a completed question or a data returned from a search. The exact interpretation of the field
33  * depends on the context where the field is used.
34  *
35  * @author Gaston Dombiak
36  */
37 public class FormField {
38 
39     public static final String TYPE_BOOLEAN = "boolean";
40     public static final String TYPE_FIXED = "fixed";
41     public static final String TYPE_HIDDEN = "hidden";
42     public static final String TYPE_JID_MULTI = "jid-multi";
43     public static final String TYPE_JID_SINGLE = "jid-single";
44     public static final String TYPE_LIST_MULTI = "list-multi";
45     public static final String TYPE_LIST_SINGLE = "list-single";
46     public static final String TYPE_TEXT_MULTI = "text-multi";
47     public static final String TYPE_TEXT_PRIVATE = "text-private";
48     public static final String TYPE_TEXT_SINGLE = "text-single";
49 
50     private String description;
51     private boolean required = false;
52     private String label;
53     private String variable;
54     private String type;
55     private final List<Option> options = new ArrayList<Option>();
56     private final List<String> values = new ArrayList<String>();
57 
58     /**
59      * Creates a new FormField with the variable name that uniquely identifies the field
60      * in the context of the form.
61      *
62      * @param variable the variable name of the question.
63      */
FormField(String variable)64     public FormField(String variable) {
65         this.variable = variable;
66     }
67 
68     /**
69      * Creates a new FormField of type FIXED. The fields of type FIXED do not define a variable
70      * name.
71      */
FormField()72     public FormField() {
73         this.type = FormField.TYPE_FIXED;
74     }
75 
76     /**
77      * Returns a description that provides extra clarification about the question. This information
78      * could be presented to the user either in tool-tip, help button, or as a section of text
79      * before the question.<p>
80      * <p/>
81      * If the question is of type FIXED then the description should remain empty.
82      *
83      * @return description that provides extra clarification about the question.
84      */
getDescription()85     public String getDescription() {
86         return description;
87     }
88 
89     /**
90      * Returns the label of the question which should give enough information to the user to
91      * fill out the form.
92      *
93      * @return label of the question.
94      */
getLabel()95     public String getLabel() {
96         return label;
97     }
98 
99     /**
100      * Returns an Iterator for the available options that the user has in order to answer
101      * the question.
102      *
103      * @return Iterator for the available options.
104      */
getOptions()105     public Iterator<Option> getOptions() {
106         synchronized (options) {
107             return Collections.unmodifiableList(new ArrayList<Option>(options)).iterator();
108         }
109     }
110 
111     /**
112      * Returns true if the question must be answered in order to complete the questionnaire.
113      *
114      * @return true if the question must be answered in order to complete the questionnaire.
115      */
isRequired()116     public boolean isRequired() {
117         return required;
118     }
119 
120     /**
121      * Returns an indicative of the format for the data to answer. Valid formats are:
122      * <p/>
123      * <ul>
124      * <li>text-single -> single line or word of text
125      * <li>text-private -> instead of showing the user what they typed, you show ***** to
126      * protect it
127      * <li>text-multi -> multiple lines of text entry
128      * <li>list-single -> given a list of choices, pick one
129      * <li>list-multi -> given a list of choices, pick one or more
130      * <li>boolean -> 0 or 1, true or false, yes or no. Default value is 0
131      * <li>fixed -> fixed for putting in text to show sections, or just advertise your web
132      * site in the middle of the form
133      * <li>hidden -> is not given to the user at all, but returned with the questionnaire
134      * <li>jid-single -> Jabber ID - choosing a JID from your roster, and entering one based
135      * on the rules for a JID.
136      * <li>jid-multi -> multiple entries for JIDs
137      * </ul>
138      *
139      * @return format for the data to answer.
140      */
getType()141     public String getType() {
142         return type;
143     }
144 
145     /**
146      * Returns an Iterator for the default values of the question if the question is part
147      * of a form to fill out. Otherwise, returns an Iterator for the answered values of
148      * the question.
149      *
150      * @return an Iterator for the default values or answered values of the question.
151      */
getValues()152     public Iterator<String> getValues() {
153         synchronized (values) {
154             return Collections.unmodifiableList(new ArrayList<String>(values)).iterator();
155         }
156     }
157 
158     /**
159      * Returns the variable name that the question is filling out.
160      *
161      * @return the variable name of the question.
162      */
getVariable()163     public String getVariable() {
164         return variable;
165     }
166 
167     /**
168      * Sets a description that provides extra clarification about the question. This information
169      * could be presented to the user either in tool-tip, help button, or as a section of text
170      * before the question.<p>
171      * <p/>
172      * If the question is of type FIXED then the description should remain empty.
173      *
174      * @param description provides extra clarification about the question.
175      */
setDescription(String description)176     public void setDescription(String description) {
177         this.description = description;
178     }
179 
180     /**
181      * Sets the label of the question which should give enough information to the user to
182      * fill out the form.
183      *
184      * @param label the label of the question.
185      */
setLabel(String label)186     public void setLabel(String label) {
187         this.label = label;
188     }
189 
190     /**
191      * Sets if the question must be answered in order to complete the questionnaire.
192      *
193      * @param required if the question must be answered in order to complete the questionnaire.
194      */
setRequired(boolean required)195     public void setRequired(boolean required) {
196         this.required = required;
197     }
198 
199     /**
200      * Sets an indicative of the format for the data to answer. Valid formats are:
201      * <p/>
202      * <ul>
203      * <li>text-single -> single line or word of text
204      * <li>text-private -> instead of showing the user what they typed, you show ***** to
205      * protect it
206      * <li>text-multi -> multiple lines of text entry
207      * <li>list-single -> given a list of choices, pick one
208      * <li>list-multi -> given a list of choices, pick one or more
209      * <li>boolean -> 0 or 1, true or false, yes or no. Default value is 0
210      * <li>fixed -> fixed for putting in text to show sections, or just advertise your web
211      * site in the middle of the form
212      * <li>hidden -> is not given to the user at all, but returned with the questionnaire
213      * <li>jid-single -> Jabber ID - choosing a JID from your roster, and entering one based
214      * on the rules for a JID.
215      * <li>jid-multi -> multiple entries for JIDs
216      * </ul>
217      *
218      * @param type an indicative of the format for the data to answer.
219      */
setType(String type)220     public void setType(String type) {
221         this.type = type;
222     }
223 
224     /**
225      * Adds a default value to the question if the question is part of a form to fill out.
226      * Otherwise, adds an answered value to the question.
227      *
228      * @param value a default value or an answered value of the question.
229      */
addValue(String value)230     public void addValue(String value) {
231         synchronized (values) {
232             values.add(value);
233         }
234     }
235 
236     /**
237      * Adds a default values to the question if the question is part of a form to fill out.
238      * Otherwise, adds an answered values to the question.
239      *
240      * @param newValues default values or an answered values of the question.
241      */
addValues(List<String> newValues)242     public void addValues(List<String> newValues) {
243         synchronized (values) {
244             values.addAll(newValues);
245         }
246     }
247 
248     /**
249      * Removes all the values of the field.
250      */
resetValues()251     protected void resetValues() {
252         synchronized (values) {
253             values.removeAll(new ArrayList<String>(values));
254         }
255     }
256 
257     /**
258      * Adss an available options to the question that the user has in order to answer
259      * the question.
260      *
261      * @param option a new available option for the question.
262      */
addOption(Option option)263     public void addOption(Option option) {
264         synchronized (options) {
265             options.add(option);
266         }
267     }
268 
toXML()269     public String toXML() {
270         StringBuilder buf = new StringBuilder();
271         buf.append("<field");
272         // Add attributes
273         if (getLabel() != null) {
274             buf.append(" label=\"").append(getLabel()).append("\"");
275         }
276         if (getVariable() != null) {
277             buf.append(" var=\"").append(getVariable()).append("\"");
278         }
279         if (getType() != null) {
280             buf.append(" type=\"").append(getType()).append("\"");
281         }
282         buf.append(">");
283         // Add elements
284         if (getDescription() != null) {
285             buf.append("<desc>").append(getDescription()).append("</desc>");
286         }
287         if (isRequired()) {
288             buf.append("<required/>");
289         }
290         // Loop through all the values and append them to the string buffer
291         for (Iterator<String> i = getValues(); i.hasNext();) {
292             buf.append("<value>").append(i.next()).append("</value>");
293         }
294         // Loop through all the values and append them to the string buffer
295         for (Iterator<Option> i = getOptions(); i.hasNext();) {
296             buf.append((i.next()).toXML());
297         }
298         buf.append("</field>");
299         return buf.toString();
300     }
301 
302     @Override
equals(Object obj)303     public boolean equals(Object obj) {
304         if (obj == null)
305             return false;
306         if (obj == this)
307             return true;
308         if (!(obj instanceof FormField))
309             return false;
310 
311         FormField other = (FormField) obj;
312 
313         return toXML().equals(other.toXML());
314     }
315 
316     @Override
hashCode()317     public int hashCode() {
318         return toXML().hashCode();
319     }
320 
321     /**
322      * Represents the available option of a given FormField.
323      *
324      * @author Gaston Dombiak
325      */
326     public static class Option {
327 
328         private String label;
329         private String value;
330 
Option(String value)331         public Option(String value) {
332             this.value = value;
333         }
334 
Option(String label, String value)335         public Option(String label, String value) {
336             this.label = label;
337             this.value = value;
338         }
339 
340         /**
341          * Returns the label that represents the option.
342          *
343          * @return the label that represents the option.
344          */
getLabel()345         public String getLabel() {
346             return label;
347         }
348 
349         /**
350          * Returns the value of the option.
351          *
352          * @return the value of the option.
353          */
getValue()354         public String getValue() {
355             return value;
356         }
357 
358         @Override
toString()359         public String toString() {
360             return getLabel();
361         }
362 
toXML()363         public String toXML() {
364             StringBuilder buf = new StringBuilder();
365             buf.append("<option");
366             // Add attribute
367             if (getLabel() != null) {
368                 buf.append(" label=\"").append(getLabel()).append("\"");
369             }
370             buf.append(">");
371             // Add element
372             buf.append("<value>").append(StringUtils.escapeForXML(getValue())).append("</value>");
373 
374             buf.append("</option>");
375             return buf.toString();
376         }
377 
378         @Override
equals(Object obj)379         public boolean equals(Object obj) {
380             if (obj == null)
381                 return false;
382             if (obj == this)
383                 return true;
384             if (obj.getClass() != getClass())
385                 return false;
386 
387             Option other = (Option) obj;
388 
389             if (!value.equals(other.value))
390                 return false;
391 
392             String thisLabel = label == null ? "" : label;
393             String otherLabel = other.label == null ? "" : other.label;
394 
395             if (!thisLabel.equals(otherLabel))
396                 return false;
397 
398             return true;
399         }
400 
401         @Override
hashCode()402         public int hashCode() {
403             int result = 1;
404             result = 37 * result + value.hashCode();
405             result = 37 * result + (label == null ? 0 : label.hashCode());
406             return result;
407         }
408     }
409 }
410