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 */
017
018package org.jivesoftware.smackx.offline.packet;
019
020import org.jivesoftware.smack.packet.IQ;
021import org.jivesoftware.smack.provider.IQProvider;
022import org.xmlpull.v1.XmlPullParser;
023
024import java.util.ArrayList;
025import java.util.Collections;
026import java.util.List;
027
028/**
029 * Represents a request to get some or all the offline messages of a user. This class can also
030 * be used for deleting some or all the offline messages of a user.
031 *
032 * @author Gaston Dombiak
033 */
034public class OfflineMessageRequest extends IQ {
035
036    private List<Item> items = new ArrayList<Item>();
037    private boolean purge = false;
038    private boolean fetch = false;
039
040    /**
041     * Returns a List of item childs that holds information about offline messages to
042     * view or delete.
043     *
044     * @return a List of item childs that holds information about offline messages to
045     *         view or delete.
046     */
047    public List<Item> getItems() {
048        synchronized (items) {
049            return Collections.unmodifiableList(new ArrayList<Item>(items));
050        }
051    }
052
053    /**
054     * Adds an item child that holds information about offline messages to view or delete.
055     *
056     * @param item the item child that holds information about offline messages to view or delete.
057     */
058    public void addItem(Item item) {
059        synchronized (items) {
060            items.add(item);
061        }
062    }
063
064    /**
065     * Returns true if all the offline messages of the user should be deleted.
066     *
067     * @return true if all the offline messages of the user should be deleted.
068     */
069    public boolean isPurge() {
070        return purge;
071    }
072
073    /**
074     * Sets if all the offline messages of the user should be deleted.
075     *
076     * @param purge true if all the offline messages of the user should be deleted.
077     */
078    public void setPurge(boolean purge) {
079        this.purge = purge;
080    }
081
082    /**
083     * Returns true if all the offline messages of the user should be retrieved.
084     *
085     * @return true if all the offline messages of the user should be retrieved.
086     */
087    public boolean isFetch() {
088        return fetch;
089    }
090
091    /**
092     * Sets if all the offline messages of the user should be retrieved.
093     *
094     * @param fetch true if all the offline messages of the user should be retrieved.
095     */
096    public void setFetch(boolean fetch) {
097        this.fetch = fetch;
098    }
099
100    public String getChildElementXML() {
101        StringBuilder buf = new StringBuilder();
102        buf.append("<offline xmlns=\"http://jabber.org/protocol/offline\">");
103        synchronized (items) {
104            for (int i = 0; i < items.size(); i++) {
105                Item item = items.get(i);
106                buf.append(item.toXML());
107            }
108        }
109        if (purge) {
110            buf.append("<purge/>");
111        }
112        if (fetch) {
113            buf.append("<fetch/>");
114        }
115        // Add packet extensions, if any are defined.
116        buf.append(getExtensionsXML());
117        buf.append("</offline>");
118        return buf.toString();
119    }
120
121    /**
122     * Item child that holds information about offline messages to view or delete.
123     *
124     * @author Gaston Dombiak
125     */
126    public static class Item {
127        private String action;
128        private String jid;
129        private String node;
130
131        /**
132         * Creates a new item child.
133         *
134         * @param node the actor's affiliation to the room
135         */
136        public Item(String node) {
137            this.node = node;
138        }
139
140        public String getNode() {
141            return node;
142        }
143
144        /**
145         * Returns "view" or "remove" that indicate if the server should return the specified
146         * offline message or delete it.
147         *
148         * @return "view" or "remove" that indicate if the server should return the specified
149         *         offline message or delete it.
150         */
151        public String getAction() {
152            return action;
153        }
154
155        /**
156         * Sets if the server should return the specified offline message or delete it. Possible
157         * values are "view" or "remove".
158         *
159         * @param action if the server should return the specified offline message or delete it.
160         */
161        public void setAction(String action) {
162            this.action = action;
163        }
164
165        public String getJid() {
166            return jid;
167        }
168
169        public void setJid(String jid) {
170            this.jid = jid;
171        }
172
173        public String toXML() {
174            StringBuilder buf = new StringBuilder();
175            buf.append("<item");
176            if (getAction() != null) {
177                buf.append(" action=\"").append(getAction()).append("\"");
178            }
179            if (getJid() != null) {
180                buf.append(" jid=\"").append(getJid()).append("\"");
181            }
182            if (getNode() != null) {
183                buf.append(" node=\"").append(getNode()).append("\"");
184            }
185            buf.append("/>");
186            return buf.toString();
187        }
188    }
189
190    public static class Provider implements IQProvider {
191
192        public IQ parseIQ(XmlPullParser parser) throws Exception {
193            OfflineMessageRequest request = new OfflineMessageRequest();
194            boolean done = false;
195            while (!done) {
196                int eventType = parser.next();
197                if (eventType == XmlPullParser.START_TAG) {
198                    if (parser.getName().equals("item")) {
199                        request.addItem(parseItem(parser));
200                    }
201                    else if (parser.getName().equals("purge")) {
202                        request.setPurge(true);
203                    }
204                    else if (parser.getName().equals("fetch")) {
205                        request.setFetch(true);
206                    }
207                } else if (eventType == XmlPullParser.END_TAG) {
208                    if (parser.getName().equals("offline")) {
209                        done = true;
210                    }
211                }
212            }
213
214            return request;
215        }
216
217        private Item parseItem(XmlPullParser parser) throws Exception {
218            boolean done = false;
219            Item item = new Item(parser.getAttributeValue("", "node"));
220            item.setAction(parser.getAttributeValue("", "action"));
221            item.setJid(parser.getAttributeValue("", "jid"));
222            while (!done) {
223                int eventType = parser.next();
224                if (eventType == XmlPullParser.END_TAG) {
225                    if (parser.getName().equals("item")) {
226                        done = true;
227                    }
228                }
229            }
230            return item;
231        }
232    }
233}