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