• 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.packet;
22 
23 import org.jivesoftware.smack.packet.PacketExtension;
24 import org.jivesoftware.smackx.Form;
25 import org.jivesoftware.smackx.FormField;
26 
27 import java.util.ArrayList;
28 import java.util.Collections;
29 import java.util.Iterator;
30 import java.util.List;
31 
32 /**
33  * Represents a form that could be use for gathering data as well as for reporting data
34  * returned from a search.
35  *
36  * @author Gaston Dombiak
37  */
38 public class DataForm implements PacketExtension {
39 
40     private String type;
41     private String title;
42     private List<String> instructions = new ArrayList<String>();
43     private ReportedData reportedData;
44     private final List<Item> items = new ArrayList<Item>();
45     private final List<FormField> fields = new ArrayList<FormField>();
46 
DataForm(String type)47     public DataForm(String type) {
48         this.type = type;
49     }
50 
51     /**
52      * Returns the meaning of the data within the context. The data could be part of a form
53      * to fill out, a form submission or data results.<p>
54      *
55      * Possible form types are:
56      * <ul>
57      *  <li>form -> This packet contains a form to fill out. Display it to the user (if your
58      * program can).</li>
59      *  <li>submit -> The form is filled out, and this is the data that is being returned from
60      * the form.</li>
61      *  <li>cancel -> The form was cancelled. Tell the asker that piece of information.</li>
62      *  <li>result -> Data results being returned from a search, or some other query.</li>
63      * </ul>
64      *
65      * @return the form's type.
66      */
getType()67     public String getType() {
68         return type;
69     }
70 
71     /**
72      * Returns the description of the data. It is similar to the title on a web page or an X
73      * window.  You can put a <title/> on either a form to fill out, or a set of data results.
74      *
75      * @return description of the data.
76      */
getTitle()77     public String getTitle() {
78         return title;
79     }
80 
81     /**
82      * Returns an Iterator for the list of instructions that explain how to fill out the form and
83      * what the form is about. The dataform could include multiple instructions since each
84      * instruction could not contain newlines characters. Join the instructions together in order
85      * to show them to the user.
86      *
87      * @return an Iterator for the list of instructions that explain how to fill out the form.
88      */
getInstructions()89     public Iterator<String> getInstructions() {
90         synchronized (instructions) {
91             return Collections.unmodifiableList(new ArrayList<String>(instructions)).iterator();
92         }
93     }
94 
95     /**
96      * Returns the fields that will be returned from a search.
97      *
98      * @return fields that will be returned from a search.
99      */
getReportedData()100     public ReportedData getReportedData() {
101         return reportedData;
102     }
103 
104     /**
105      * Returns an Iterator for the items returned from a search.
106      *
107      * @return an Iterator for the items returned from a search.
108      */
getItems()109     public Iterator<Item> getItems() {
110         synchronized (items) {
111             return Collections.unmodifiableList(new ArrayList<Item>(items)).iterator();
112         }
113     }
114 
115     /**
116      * Returns an Iterator for the fields that are part of the form.
117      *
118      * @return an Iterator for the fields that are part of the form.
119      */
getFields()120     public Iterator<FormField> getFields() {
121         synchronized (fields) {
122             return Collections.unmodifiableList(new ArrayList<FormField>(fields)).iterator();
123         }
124     }
125 
getElementName()126     public String getElementName() {
127         return Form.ELEMENT;
128     }
129 
getNamespace()130     public String getNamespace() {
131         return Form.NAMESPACE;
132     }
133 
134     /**
135      * Sets the description of the data. It is similar to the title on a web page or an X window.
136      * You can put a <title/> on either a form to fill out, or a set of data results.
137      *
138      * @param title description of the data.
139      */
setTitle(String title)140     public void setTitle(String title) {
141         this.title = title;
142     }
143 
144     /**
145      * Sets the list of instructions that explain how to fill out the form and what the form is
146      * about. The dataform could include multiple instructions since each instruction could not
147      * contain newlines characters.
148      *
149      * @param instructions list of instructions that explain how to fill out the form.
150      */
setInstructions(List<String> instructions)151     public void setInstructions(List<String> instructions) {
152         this.instructions = instructions;
153     }
154 
155     /**
156      * Sets the fields that will be returned from a search.
157      *
158      * @param reportedData the fields that will be returned from a search.
159      */
setReportedData(ReportedData reportedData)160     public void setReportedData(ReportedData reportedData) {
161         this.reportedData = reportedData;
162     }
163 
164     /**
165      * Adds a new field as part of the form.
166      *
167      * @param field the field to add to the form.
168      */
addField(FormField field)169     public void addField(FormField field) {
170         synchronized (fields) {
171             fields.add(field);
172         }
173     }
174 
175     /**
176      * Adds a new instruction to the list of instructions that explain how to fill out the form
177      * and what the form is about. The dataform could include multiple instructions since each
178      * instruction could not contain newlines characters.
179      *
180      * @param instruction the new instruction that explain how to fill out the form.
181      */
addInstruction(String instruction)182     public void addInstruction(String instruction) {
183         synchronized (instructions) {
184             instructions.add(instruction);
185         }
186     }
187 
188     /**
189      * Adds a new item returned from a search.
190      *
191      * @param item the item returned from a search.
192      */
addItem(Item item)193     public void addItem(Item item) {
194         synchronized (items) {
195             items.add(item);
196         }
197     }
198 
199     /**
200      * Returns true if this DataForm has at least one FORM_TYPE field which is
201      * hidden. This method is used for sanity checks.
202      *
203      * @return
204      */
hasHiddenFormTypeField()205     public boolean hasHiddenFormTypeField() {
206         boolean found = false;
207         for (FormField f : fields) {
208             if (f.getVariable().equals("FORM_TYPE") && f.getType() != null && f.getType().equals("hidden"))
209                 found = true;
210         }
211         return found;
212     }
213 
toXML()214     public String toXML() {
215         StringBuilder buf = new StringBuilder();
216         buf.append("<").append(getElementName()).append(" xmlns=\"").append(getNamespace()).append(
217             "\" type=\"" + getType() +"\">");
218         if (getTitle() != null) {
219             buf.append("<title>").append(getTitle()).append("</title>");
220         }
221         for (Iterator<String> it=getInstructions(); it.hasNext();) {
222             buf.append("<instructions>").append(it.next()).append("</instructions>");
223         }
224         // Append the list of fields returned from a search
225         if (getReportedData() != null) {
226             buf.append(getReportedData().toXML());
227         }
228         // Loop through all the items returned from a search and append them to the string buffer
229         for (Iterator<Item> i = getItems(); i.hasNext();) {
230             Item item = i.next();
231             buf.append(item.toXML());
232         }
233         // Loop through all the form fields and append them to the string buffer
234         for (Iterator<FormField> i = getFields(); i.hasNext();) {
235             FormField field = i.next();
236             buf.append(field.toXML());
237         }
238         buf.append("</").append(getElementName()).append(">");
239         return buf.toString();
240     }
241 
242     /**
243      *
244      * Represents the fields that will be returned from a search. This information is useful when
245      * you try to use the jabber:iq:search namespace to return dynamic form information.
246      *
247      * @author Gaston Dombiak
248      */
249     public static class ReportedData {
250         private List<FormField> fields = new ArrayList<FormField>();
251 
ReportedData(List<FormField> fields)252         public ReportedData(List<FormField> fields) {
253             this.fields = fields;
254         }
255 
256         /**
257          * Returns the fields returned from a search.
258          *
259          * @return the fields returned from a search.
260          */
getFields()261         public Iterator<FormField> getFields() {
262             return Collections.unmodifiableList(new ArrayList<FormField>(fields)).iterator();
263         }
264 
toXML()265         public String toXML() {
266             StringBuilder buf = new StringBuilder();
267             buf.append("<reported>");
268             // Loop through all the form items and append them to the string buffer
269             for (Iterator<FormField> i = getFields(); i.hasNext();) {
270                 FormField field = i.next();
271                 buf.append(field.toXML());
272             }
273             buf.append("</reported>");
274             return buf.toString();
275         }
276     }
277 
278     /**
279      *
280      * Represents items of reported data.
281      *
282      * @author Gaston Dombiak
283      */
284     public static class Item {
285         private List<FormField> fields = new ArrayList<FormField>();
286 
Item(List<FormField> fields)287         public Item(List<FormField> fields) {
288             this.fields = fields;
289         }
290 
291         /**
292          * Returns the fields that define the data that goes with the item.
293          *
294          * @return the fields that define the data that goes with the item.
295          */
getFields()296         public Iterator<FormField> getFields() {
297             return Collections.unmodifiableList(new ArrayList<FormField>(fields)).iterator();
298         }
299 
toXML()300         public String toXML() {
301             StringBuilder buf = new StringBuilder();
302             buf.append("<item>");
303             // Loop through all the form items and append them to the string buffer
304             for (Iterator<FormField> i = getFields(); i.hasNext();) {
305                 FormField field = i.next();
306                 buf.append(field.toXML());
307             }
308             buf.append("</item>");
309             return buf.toString();
310         }
311     }
312 }
313