blob: 4d12892b51cd6052b3f480fe8ae1c6f2e28dac3c [file] [log] [blame]
Shuyi Chend7955ce2013-05-22 14:51:55 -07001/**
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
21package org.jivesoftware.smackx.packet;
22
23import org.jivesoftware.smack.packet.PacketExtension;
24import org.jivesoftware.smackx.Form;
25import org.jivesoftware.smackx.FormField;
26
27import java.util.ArrayList;
28import java.util.Collections;
29import java.util.Iterator;
30import 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 */
38public 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
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 */
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 */
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 */
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 */
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 */
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 */
120 public Iterator<FormField> getFields() {
121 synchronized (fields) {
122 return Collections.unmodifiableList(new ArrayList<FormField>(fields)).iterator();
123 }
124 }
125
126 public String getElementName() {
127 return Form.ELEMENT;
128 }
129
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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
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
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 */
261 public Iterator<FormField> getFields() {
262 return Collections.unmodifiableList(new ArrayList<FormField>(fields)).iterator();
263 }
264
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
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 */
296 public Iterator<FormField> getFields() {
297 return Collections.unmodifiableList(new ArrayList<FormField>(fields)).iterator();
298 }
299
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}