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 ELEMENT = QUERY_ELEMENT;
039    public static final String NAMESPACE = "http://jabber.org/protocol/disco#items";
040
041    private final List<Item> items = new LinkedList<Item>();
042    private String node;
043
044    public DiscoverItems() {
045        super(ELEMENT, NAMESPACE);
046    }
047
048    /**
049     * Adds a new item to the discovered information.
050     * 
051     * @param item the discovered entity's item
052     */
053    public void addItem(Item item) {
054        items.add(item);
055    }
056
057    /**
058     * Adds a collection of items to the discovered information. Does nothing if itemsToAdd is null
059     *
060     * @param itemsToAdd
061     */
062    public void addItems(Collection<Item> itemsToAdd) {
063        if (itemsToAdd == null) return;
064        for (Item i : itemsToAdd) {
065            addItem(i);
066        }
067    }
068
069
070    /**
071     * Returns the discovered items of the queried XMPP entity. 
072     *
073     * @return an unmodifiable list of the discovered entity's items
074     */
075    public List<DiscoverItems.Item> getItems() {
076        return Collections.unmodifiableList(items);
077    }
078
079    /**
080     * Returns the node attribute that supplements the 'jid' attribute. A node is merely 
081     * something that is associated with a JID and for which the JID can provide information.<p> 
082     * 
083     * Node attributes SHOULD be used only when trying to provide or query information which 
084     * is not directly addressable.
085     *
086     * @return the node attribute that supplements the 'jid' attribute
087     */
088    public String getNode() {
089        return node;
090    }
091
092    /**
093     * Sets the node attribute that supplements the 'jid' attribute. A node is merely 
094     * something that is associated with a JID and for which the JID can provide information.<p> 
095     * 
096     * Node attributes SHOULD be used only when trying to provide or query information which 
097     * is not directly addressable.
098     * 
099     * @param node the node attribute that supplements the 'jid' attribute
100     */
101    public void setNode(String node) {
102        this.node = node;
103    }
104
105    @Override
106    protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
107        xml.optAttribute("node", getNode());
108        xml.rightAngleBracket();
109
110        for (Item item : items) {
111            xml.append(item.toXML());
112        }
113
114        return xml;
115    }
116
117    /**
118     * An item is associated with an XMPP Entity, usually thought of a children of the parent 
119     * entity and normally are addressable as a JID.<p> 
120     * 
121     * An item associated with an entity may not be addressable as a JID. In order to handle 
122     * such items, Service Discovery uses an optional 'node' attribute that supplements the 
123     * 'jid' attribute.
124     */
125    public static class Item {
126
127        /**
128         * Request to create or update the item.
129         */
130        public static final String UPDATE_ACTION = "update";
131
132        /**
133         * Request to remove the item.
134         */
135        public static final String REMOVE_ACTION = "remove";
136
137        private String entityID;
138        private String name;
139        private String node;
140        private String action;
141
142        /**
143         * Create a new Item associated with a given entity.
144         * 
145         * @param entityID the id of the entity that contains the item
146         */
147        public Item(String entityID) {
148            this.entityID = entityID;
149        }
150
151        /**
152         * Returns the entity's ID.
153         *
154         * @return the entity's ID.
155         */
156        public String getEntityID() {
157            return entityID;
158        }
159
160        /**
161         * Returns the entity's name.
162         *
163         * @return the entity's name.
164         */
165        public String getName() {
166            return name;
167        }
168
169        /**
170         * Sets the entity's name.
171         *
172         * @param name the entity's name.
173         */
174        public void setName(String name) {
175            this.name = name;
176        }
177
178        /**
179         * Returns the node attribute that supplements the 'jid' attribute. A node is merely 
180         * something that is associated with a JID and for which the JID can provide information.<p> 
181         * 
182         * Node attributes SHOULD be used only when trying to provide or query information which 
183         * is not directly addressable.
184         *
185         * @return the node attribute that supplements the 'jid' attribute
186         */
187        public String getNode() {
188            return node;
189        }
190
191        /**
192         * Sets the node attribute that supplements the 'jid' attribute. A node is merely 
193         * something that is associated with a JID and for which the JID can provide information.<p> 
194         * 
195         * Node attributes SHOULD be used only when trying to provide or query information which 
196         * is not directly addressable.
197         * 
198         * @param node the node attribute that supplements the 'jid' attribute
199         */
200        public void setNode(String node) {
201            this.node = node;
202        }
203
204        /**
205         * Returns the action that specifies the action being taken for this item. Possible action 
206         * values are: "update" and "remove". Update should either create a new entry if the node 
207         * and jid combination does not already exist, or simply update an existing entry. If 
208         * "remove" is used as the action, the item should be removed from persistent storage.
209         *  
210         * @return the action being taken for this item
211         */
212        public String getAction() {
213            return action;
214        }
215
216        /**
217         * Sets the action that specifies the action being taken for this item. Possible action 
218         * values are: "update" and "remove". Update should either create a new entry if the node 
219         * and jid combination does not already exist, or simply update an existing entry. If 
220         * "remove" is used as the action, the item should be removed from persistent storage.
221         * 
222         * @param action the action being taken for this item
223         */
224        public void setAction(String action) {
225            this.action = action;
226        }
227
228        public XmlStringBuilder toXML() {
229            XmlStringBuilder xml = new XmlStringBuilder();
230            xml.halfOpenElement("item");
231            xml.attribute("jid", entityID);
232            xml.optAttribute("name", name);
233            xml.optAttribute("node", node);
234            xml.optAttribute("action", action);
235            xml.closeEmptyElement();
236            return xml;
237        }
238    }
239}