001/**
002 *
003 * Copyright 2003-2007 Jive Software.
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.jivesoftware.smackx.disco.packet;
018
019import org.jivesoftware.smack.packet.IQ;
020import org.jivesoftware.smack.util.XmlStringBuilder;
021
022import java.util.Collection;
023import java.util.Collections;
024import java.util.LinkedList;
025import java.util.List;
026
027/**
028 * A DiscoverItems IQ packet, which is used by XMPP clients to request and receive items 
029 * associated with XMPP entities.<p>
030 * 
031 * The items could also be queried in order to discover if they contain items inside. Some items 
032 * may be addressable by its JID and others may require to be addressed by a JID and a node name.
033 *
034 * @author Gaston Dombiak
035 */
036public class DiscoverItems extends IQ {
037
038    public static final String NAMESPACE = "http://jabber.org/protocol/disco#items";
039
040    private final List<Item> items = new LinkedList<Item>();
041    private String node;
042
043    /**
044     * Adds a new item to the discovered information.
045     * 
046     * @param item the discovered entity's item
047     */
048    public void addItem(Item item) {
049        items.add(item);
050    }
051
052    /**
053     * Adds a collection of items to the discovered information. Does nothing if itemsToAdd is null
054     *
055     * @param itemsToAdd
056     */
057    public void addItems(Collection<Item> itemsToAdd) {
058        if (itemsToAdd == null) return;
059        for (Item i : itemsToAdd) {
060            addItem(i);
061        }
062    }
063
064
065    /**
066     * Returns the discovered items of the queried XMPP entity. 
067     *
068     * @return an unmodifiable list of the discovered entity's items
069     */
070    public List<DiscoverItems.Item> getItems() {
071        return Collections.unmodifiableList(items);
072    }
073
074    /**
075     * Returns the node attribute that supplements the 'jid' attribute. A node is merely 
076     * something that is associated with a JID and for which the JID can provide information.<p> 
077     * 
078     * Node attributes SHOULD be used only when trying to provide or query information which 
079     * is not directly addressable.
080     *
081     * @return the node attribute that supplements the 'jid' attribute
082     */
083    public String getNode() {
084        return node;
085    }
086
087    /**
088     * Sets the node attribute that supplements the 'jid' attribute. A node is merely 
089     * something that is associated with a JID and for which the JID can provide information.<p> 
090     * 
091     * Node attributes SHOULD be used only when trying to provide or query information which 
092     * is not directly addressable.
093     * 
094     * @param node the node attribute that supplements the 'jid' attribute
095     */
096    public void setNode(String node) {
097        this.node = node;
098    }
099
100    public XmlStringBuilder getChildElementXML() {
101        XmlStringBuilder xml = new XmlStringBuilder();
102        xml.halfOpenElement("query");
103        xml.xmlnsAttribute(NAMESPACE);
104        xml.optAttribute("node", getNode());
105        xml.rightAngelBracket();
106
107        for (Item item : items) {
108            xml.append(item.toXML());
109        }
110
111        xml.closeElement("query");
112        return xml;
113    }
114
115    /**
116     * An item is associated with an XMPP Entity, usually thought of a children of the parent 
117     * entity and normally are addressable as a JID.<p> 
118     * 
119     * An item associated with an entity may not be addressable as a JID. In order to handle 
120     * such items, Service Discovery uses an optional 'node' attribute that supplements the 
121     * 'jid' attribute.
122     */
123    public static class Item {
124
125        /**
126         * Request to create or update the item.
127         */
128        public static final String UPDATE_ACTION = "update";
129
130        /**
131         * Request to remove the item.
132         */
133        public static final String REMOVE_ACTION = "remove";
134
135        private String entityID;
136        private String name;
137        private String node;
138        private String action;
139
140        /**
141         * Create a new Item associated with a given entity.
142         * 
143         * @param entityID the id of the entity that contains the item
144         */
145        public Item(String entityID) {
146            this.entityID = entityID;
147        }
148
149        /**
150         * Returns the entity's ID.
151         *
152         * @return the entity's ID.
153         */
154        public String getEntityID() {
155            return entityID;
156        }
157
158        /**
159         * Returns the entity's name.
160         *
161         * @return the entity's name.
162         */
163        public String getName() {
164            return name;
165        }
166
167        /**
168         * Sets the entity's name.
169         *
170         * @param name the entity's name.
171         */
172        public void setName(String name) {
173            this.name = name;
174        }
175
176        /**
177         * Returns the node attribute that supplements the 'jid' attribute. A node is merely 
178         * something that is associated with a JID and for which the JID can provide information.<p> 
179         * 
180         * Node attributes SHOULD be used only when trying to provide or query information which 
181         * is not directly addressable.
182         *
183         * @return the node attribute that supplements the 'jid' attribute
184         */
185        public String getNode() {
186            return node;
187        }
188
189        /**
190         * Sets the node attribute that supplements the 'jid' attribute. A node is merely 
191         * something that is associated with a JID and for which the JID can provide information.<p> 
192         * 
193         * Node attributes SHOULD be used only when trying to provide or query information which 
194         * is not directly addressable.
195         * 
196         * @param node the node attribute that supplements the 'jid' attribute
197         */
198        public void setNode(String node) {
199            this.node = node;
200        }
201
202        /**
203         * Returns the action that specifies the action being taken for this item. Possible action 
204         * values are: "update" and "remove". Update should either create a new entry if the node 
205         * and jid combination does not already exist, or simply update an existing entry. If 
206         * "remove" is used as the action, the item should be removed from persistent storage.
207         *  
208         * @return the action being taken for this item
209         */
210        public String getAction() {
211            return action;
212        }
213
214        /**
215         * Sets the action that specifies the action being taken for this item. Possible action 
216         * values are: "update" and "remove". Update should either create a new entry if the node 
217         * and jid combination does not already exist, or simply update an existing entry. If 
218         * "remove" is used as the action, the item should be removed from persistent storage.
219         * 
220         * @param action the action being taken for this item
221         */
222        public void setAction(String action) {
223            this.action = action;
224        }
225
226        public XmlStringBuilder toXML() {
227            XmlStringBuilder xml = new XmlStringBuilder();
228            xml.halfOpenElement("item");
229            xml.attribute("jid", entityID);
230            xml.optAttribute("name", name);
231            xml.optAttribute("node", node);
232            xml.optAttribute("action", action);
233            xml.closeEmptyElement();
234            return xml;
235        }
236    }
237}