Home | History | Annotate | Download | only in packet
      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 
     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 }
    313