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
21package org.jivesoftware.smackx.packet;
22
23import org.jivesoftware.smack.packet.IQ;
24import org.jivesoftware.smack.provider.IQProvider;
25import org.xmlpull.v1.XmlPullParser;
26
27import java.util.ArrayList;
28import java.util.Collections;
29import java.util.Iterator;
30import java.util.List;
31
32/**
33 * Represents a request to get some or all the offline messages of a user. This class can also
34 * be used for deleting some or all the offline messages of a user.
35 *
36 * @author Gaston Dombiak
37 */
38public class OfflineMessageRequest extends IQ {
39
40    private List<Item> items = new ArrayList<Item>();
41    private boolean purge = false;
42    private boolean fetch = false;
43
44    /**
45     * Returns an Iterator for item childs that holds information about offline messages to
46     * view or delete.
47     *
48     * @return an Iterator for item childs that holds information about offline messages to
49     *         view or delete.
50     */
51    public Iterator<Item> getItems() {
52        synchronized (items) {
53            return Collections.unmodifiableList(new ArrayList<Item>(items)).iterator();
54        }
55    }
56
57    /**
58     * Adds an item child that holds information about offline messages to view or delete.
59     *
60     * @param item the item child that holds information about offline messages to view or delete.
61     */
62    public void addItem(Item item) {
63        synchronized (items) {
64            items.add(item);
65        }
66    }
67
68    /**
69     * Returns true if all the offline messages of the user should be deleted.
70     *
71     * @return true if all the offline messages of the user should be deleted.
72     */
73    public boolean isPurge() {
74        return purge;
75    }
76
77    /**
78     * Sets if all the offline messages of the user should be deleted.
79     *
80     * @param purge true if all the offline messages of the user should be deleted.
81     */
82    public void setPurge(boolean purge) {
83        this.purge = purge;
84    }
85
86    /**
87     * Returns true if all the offline messages of the user should be retrieved.
88     *
89     * @return true if all the offline messages of the user should be retrieved.
90     */
91    public boolean isFetch() {
92        return fetch;
93    }
94
95    /**
96     * Sets if all the offline messages of the user should be retrieved.
97     *
98     * @param fetch true if all the offline messages of the user should be retrieved.
99     */
100    public void setFetch(boolean fetch) {
101        this.fetch = fetch;
102    }
103
104    public String getChildElementXML() {
105        StringBuilder buf = new StringBuilder();
106        buf.append("<offline xmlns=\"http://jabber.org/protocol/offline\">");
107        synchronized (items) {
108            for (int i = 0; i < items.size(); i++) {
109                Item item = items.get(i);
110                buf.append(item.toXML());
111            }
112        }
113        if (purge) {
114            buf.append("<purge/>");
115        }
116        if (fetch) {
117            buf.append("<fetch/>");
118        }
119        // Add packet extensions, if any are defined.
120        buf.append(getExtensionsXML());
121        buf.append("</offline>");
122        return buf.toString();
123    }
124
125    /**
126     * Item child that holds information about offline messages to view or delete.
127     *
128     * @author Gaston Dombiak
129     */
130    public static class Item {
131        private String action;
132        private String jid;
133        private String node;
134
135        /**
136         * Creates a new item child.
137         *
138         * @param node the actor's affiliation to the room
139         */
140        public Item(String node) {
141            this.node = node;
142        }
143
144        public String getNode() {
145            return node;
146        }
147
148        /**
149         * Returns "view" or "remove" that indicate if the server should return the specified
150         * offline message or delete it.
151         *
152         * @return "view" or "remove" that indicate if the server should return the specified
153         *         offline message or delete it.
154         */
155        public String getAction() {
156            return action;
157        }
158
159        /**
160         * Sets if the server should return the specified offline message or delete it. Possible
161         * values are "view" or "remove".
162         *
163         * @param action if the server should return the specified offline message or delete it.
164         */
165        public void setAction(String action) {
166            this.action = action;
167        }
168
169        public String getJid() {
170            return jid;
171        }
172
173        public void setJid(String jid) {
174            this.jid = jid;
175        }
176
177        public String toXML() {
178            StringBuilder buf = new StringBuilder();
179            buf.append("<item");
180            if (getAction() != null) {
181                buf.append(" action=\"").append(getAction()).append("\"");
182            }
183            if (getJid() != null) {
184                buf.append(" jid=\"").append(getJid()).append("\"");
185            }
186            if (getNode() != null) {
187                buf.append(" node=\"").append(getNode()).append("\"");
188            }
189            buf.append("/>");
190            return buf.toString();
191        }
192    }
193
194    public static class Provider implements IQProvider {
195
196        public IQ parseIQ(XmlPullParser parser) throws Exception {
197            OfflineMessageRequest request = new OfflineMessageRequest();
198            boolean done = false;
199            while (!done) {
200                int eventType = parser.next();
201                if (eventType == XmlPullParser.START_TAG) {
202                    if (parser.getName().equals("item")) {
203                        request.addItem(parseItem(parser));
204                    }
205                    else if (parser.getName().equals("purge")) {
206                        request.setPurge(true);
207                    }
208                    else if (parser.getName().equals("fetch")) {
209                        request.setFetch(true);
210                    }
211                } else if (eventType == XmlPullParser.END_TAG) {
212                    if (parser.getName().equals("offline")) {
213                        done = true;
214                    }
215                }
216            }
217
218            return request;
219        }
220
221        private Item parseItem(XmlPullParser parser) throws Exception {
222            boolean done = false;
223            Item item = new Item(parser.getAttributeValue("", "node"));
224            item.setAction(parser.getAttributeValue("", "action"));
225            item.setJid(parser.getAttributeValue("", "jid"));
226            while (!done) {
227                int eventType = parser.next();
228                if (eventType == XmlPullParser.END_TAG) {
229                    if (parser.getName().equals("item")) {
230                        done = true;
231                    }
232                }
233            }
234            return item;
235        }
236    }
237}
238