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.bookmarks;
018
019import org.jivesoftware.smack.util.XmlStringBuilder;
020import org.jivesoftware.smackx.iqprivate.packet.PrivateData;
021import org.jivesoftware.smackx.iqprivate.provider.PrivateDataProvider;
022import org.xmlpull.v1.XmlPullParser;
023import org.xmlpull.v1.XmlPullParserException;
024
025import java.io.IOException;
026import java.util.ArrayList;
027import java.util.List;
028
029/**
030 * Bookmarks is used for storing and retrieving URLS and Conference rooms.
031 * Bookmark Storage (XEP-0048) defined a protocol for the storage of bookmarks to conference rooms and other entities
032 * in a Jabber user's account.
033 * See the following code sample for saving Bookmarks:
034 * <p/>
035 * <pre>
036 * XMPPConnection con = new XMPPTCPConnection("jabber.org");
037 * con.login("john", "doe");
038 * Bookmarks bookmarks = new Bookmarks();
039 * <p/>
040 * // Bookmark a URL
041 * BookmarkedURL url = new BookmarkedURL();
042 * url.setName("Google");
043 * url.setURL("http://www.jivesoftware.com");
044 * bookmarks.addURL(url);
045 * // Bookmark a Conference room.
046 * BookmarkedConference conference = new BookmarkedConference();
047 * conference.setName("My Favorite Room");
048 * conference.setAutoJoin("true");
049 * conference.setJID("dev@conference.jivesoftware.com");
050 * bookmarks.addConference(conference);
051 * // Save Bookmarks using PrivateDataManager.
052 * PrivateDataManager manager = new PrivateDataManager(con);
053 * manager.setPrivateData(bookmarks);
054 * <p/>
055 * <p/>
056 * LastActivity activity = LastActivity.getLastActivity(con, "xray@jabber.org");
057 * </pre>
058 *
059 * @author Derek DeMoro
060 */
061public class Bookmarks implements PrivateData {
062
063    public static final String NAMESPACE = "storage:bookmarks";
064    public static final String ELEMENT = "storage";
065
066    private List<BookmarkedURL> bookmarkedURLS;
067    private List<BookmarkedConference> bookmarkedConferences;
068
069    /**
070     * Required Empty Constructor to use Bookmarks.
071     */
072    public Bookmarks() {
073        bookmarkedURLS = new ArrayList<BookmarkedURL>();
074        bookmarkedConferences = new ArrayList<BookmarkedConference>();
075    }
076
077    /**
078     * Adds a BookmarkedURL.
079     *
080     * @param bookmarkedURL the bookmarked bookmarkedURL.
081     */
082    public void addBookmarkedURL(BookmarkedURL bookmarkedURL) {
083        bookmarkedURLS.add(bookmarkedURL);
084    }
085
086    /**
087     * Removes a bookmarked bookmarkedURL.
088     *
089     * @param bookmarkedURL the bookmarked bookmarkedURL to remove.
090     */
091    public void removeBookmarkedURL(BookmarkedURL bookmarkedURL) {
092        bookmarkedURLS.remove(bookmarkedURL);
093    }
094
095    /**
096     * Removes all BookmarkedURLs from user's bookmarks.
097     */
098    public void clearBookmarkedURLS() {
099        bookmarkedURLS.clear();
100    }
101
102    /**
103     * Add a BookmarkedConference to bookmarks.
104     *
105     * @param bookmarkedConference the conference to remove.
106     */
107    public void addBookmarkedConference(BookmarkedConference bookmarkedConference) {
108        bookmarkedConferences.add(bookmarkedConference);
109    }
110
111    /**
112     * Removes a BookmarkedConference.
113     *
114     * @param bookmarkedConference the BookmarkedConference to remove.
115     */
116    public void removeBookmarkedConference(BookmarkedConference bookmarkedConference) {
117        bookmarkedConferences.remove(bookmarkedConference);
118    }
119
120    /**
121     * Removes all BookmarkedConferences from Bookmarks.
122     */
123    public void clearBookmarkedConferences() {
124        bookmarkedConferences.clear();
125    }
126
127    /**
128     * Returns a Collection of all Bookmarked URLs for this user.
129     *
130     * @return a collection of all Bookmarked URLs.
131     */
132    public List<BookmarkedURL> getBookmarkedURLS() {
133        return bookmarkedURLS;
134    }
135
136    /**
137     * Returns a Collection of all Bookmarked Conference for this user.
138     *
139     * @return a collection of all Bookmarked Conferences.
140     */
141    public List<BookmarkedConference> getBookmarkedConferences() {
142        return bookmarkedConferences;
143    }
144
145
146    /**
147     * Returns the root element name.
148     *
149     * @return the element name.
150     */
151    public String getElementName() {
152        return ELEMENT;
153    }
154
155    /**
156     * Returns the root element XML namespace.
157     *
158     * @return the namespace.
159     */
160    public String getNamespace() {
161        return NAMESPACE;
162    }
163
164    /**
165     * Returns the XML representation of the PrivateData.
166     *
167     * @return the private data as XML.
168     */
169    @Override
170    public XmlStringBuilder toXML() {
171        XmlStringBuilder buf = new XmlStringBuilder();
172        buf.halfOpenElement(ELEMENT).xmlnsAttribute(NAMESPACE).rightAngelBracket();
173
174        for (BookmarkedURL urlStorage : getBookmarkedURLS()) {
175            if(urlStorage.isShared()) {
176                continue;
177            }
178            buf.halfOpenElement("url").attribute("name", urlStorage.getName()).attribute("url", urlStorage.getURL());
179            buf.condAttribute(urlStorage.isRss(), "rss", "true");
180            buf.closeEmptyElement();
181        }
182
183        // Add Conference additions
184        for (BookmarkedConference conference : getBookmarkedConferences()) {
185            if(conference.isShared()) {
186                continue;
187            }
188            buf.halfOpenElement("conference");
189            buf.attribute("name", conference.getName());
190            buf.attribute("autojoin", Boolean.toString(conference.isAutoJoin()));
191            buf.attribute("jid", conference.getJid());
192            buf.rightAngelBracket();
193
194            buf.optElement("nick", conference.getNickname());
195            buf.optElement("password", conference.getPassword());
196
197            buf.closeElement("conference");
198        }
199
200        buf.closeElement(ELEMENT);
201        return buf;
202    }
203
204    /**
205     * The IQ Provider for BookmarkStorage.
206     *
207     * @author Derek DeMoro
208     */
209    public static class Provider implements PrivateDataProvider {
210
211        /**
212         * Empty Constructor for PrivateDataProvider.
213         */
214        public Provider() {
215            super();
216        }
217
218        public PrivateData parsePrivateData(XmlPullParser parser) throws Exception {
219            Bookmarks storage = new Bookmarks();
220
221            boolean done = false;
222            while (!done) {
223                int eventType = parser.next();
224                if (eventType == XmlPullParser.START_TAG && "url".equals(parser.getName())) {
225                    final BookmarkedURL urlStorage = getURLStorage(parser);
226                    if (urlStorage != null) {
227                        storage.addBookmarkedURL(urlStorage);
228                    }
229                }
230                else if (eventType == XmlPullParser.START_TAG &&
231                        "conference".equals(parser.getName()))
232                {
233                    final BookmarkedConference conference = getConferenceStorage(parser);
234                    storage.addBookmarkedConference(conference);
235                }
236                else if (eventType == XmlPullParser.END_TAG && "storage".equals(parser.getName()))
237                {
238                    done = true;
239                }
240            }
241
242
243            return storage;
244        }
245    }
246
247    private static BookmarkedURL getURLStorage(XmlPullParser parser) throws IOException, XmlPullParserException {
248        String name = parser.getAttributeValue("", "name");
249        String url = parser.getAttributeValue("", "url");
250        String rssString = parser.getAttributeValue("", "rss");
251        boolean rss = rssString != null && "true".equals(rssString);
252
253        BookmarkedURL urlStore = new BookmarkedURL(url, name, rss);
254        boolean done = false;
255        while (!done) {
256            int eventType = parser.next();
257            if(eventType == XmlPullParser.START_TAG
258                        && "shared_bookmark".equals(parser.getName())) {
259                    urlStore.setShared(true);
260            }
261            else if (eventType == XmlPullParser.END_TAG && "url".equals(parser.getName())) {
262                done = true;
263            }
264        }
265        return urlStore;
266    }
267
268    private static BookmarkedConference getConferenceStorage(XmlPullParser parser) throws Exception {
269        String name = parser.getAttributeValue("", "name");
270        String autojoin = parser.getAttributeValue("", "autojoin");
271        String jid = parser.getAttributeValue("", "jid");
272
273        BookmarkedConference conf = new BookmarkedConference(jid);
274        conf.setName(name);
275        conf.setAutoJoin(Boolean.valueOf(autojoin).booleanValue());
276
277        // Check for nickname
278        boolean done = false;
279        while (!done) {
280            int eventType = parser.next();
281            if (eventType == XmlPullParser.START_TAG && "nick".equals(parser.getName())) {
282                conf.setNickname(parser.nextText());
283            }
284            else if (eventType == XmlPullParser.START_TAG && "password".equals(parser.getName())) {
285                conf.setPassword(parser.nextText());
286            }
287            else if(eventType == XmlPullParser.START_TAG
288                        && "shared_bookmark".equals(parser.getName())) {
289                    conf.setShared(true);
290            }
291            else if (eventType == XmlPullParser.END_TAG && "conference".equals(parser.getName())) {
292                done = true;
293            }
294        }
295
296
297        return conf;
298    }
299}