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