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