1/**
2 * $Revision$
3 * $Date$
4 *
5 * Copyright 2003-2007 Jive Software.
6 *
7 * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *     http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19package org.jivesoftware.smackx.bookmark;
20
21import org.jivesoftware.smackx.packet.PrivateData;
22import org.jivesoftware.smackx.provider.PrivateDataProvider;
23import org.xmlpull.v1.XmlPullParser;
24import org.xmlpull.v1.XmlPullParserException;
25
26import java.io.IOException;
27import java.util.ArrayList;
28import java.util.Iterator;
29import java.util.List;
30
31/**
32 * Bookmarks is used for storing and retrieving URLS and Conference rooms.
33 * Bookmark Storage (JEP-0048) defined a protocol for the storage of bookmarks to conference rooms and other entities
34 * in a Jabber user's account.
35 * See the following code sample for saving Bookmarks:
36 * <p/>
37 * <pre>
38 * Connection con = new XMPPConnection("jabber.org");
39 * con.login("john", "doe");
40 * Bookmarks bookmarks = new Bookmarks();
41 * <p/>
42 * // Bookmark a URL
43 * BookmarkedURL url = new BookmarkedURL();
44 * url.setName("Google");
45 * url.setURL("http://www.jivesoftware.com");
46 * bookmarks.addURL(url);
47 * // Bookmark a Conference room.
48 * BookmarkedConference conference = new BookmarkedConference();
49 * conference.setName("My Favorite Room");
50 * conference.setAutoJoin("true");
51 * conference.setJID("dev@conference.jivesoftware.com");
52 * bookmarks.addConference(conference);
53 * // Save Bookmarks using PrivateDataManager.
54 * PrivateDataManager manager = new PrivateDataManager(con);
55 * manager.setPrivateData(bookmarks);
56 * <p/>
57 * <p/>
58 * LastActivity activity = LastActivity.getLastActivity(con, "xray@jabber.org");
59 * </pre>
60 *
61 * @author Derek DeMoro
62 */
63public class Bookmarks implements PrivateData {
64
65    private List<BookmarkedURL> bookmarkedURLS;
66    private List<BookmarkedConference> bookmarkedConferences;
67
68    /**
69     * Required Empty Constructor to use Bookmarks.
70     */
71    public Bookmarks() {
72        bookmarkedURLS = new ArrayList<BookmarkedURL>();
73        bookmarkedConferences = new ArrayList<BookmarkedConference>();
74    }
75
76    /**
77     * Adds a BookmarkedURL.
78     *
79     * @param bookmarkedURL the bookmarked bookmarkedURL.
80     */
81    public void addBookmarkedURL(BookmarkedURL bookmarkedURL) {
82        bookmarkedURLS.add(bookmarkedURL);
83    }
84
85    /**
86     * Removes a bookmarked bookmarkedURL.
87     *
88     * @param bookmarkedURL the bookmarked bookmarkedURL to remove.
89     */
90    public void removeBookmarkedURL(BookmarkedURL bookmarkedURL) {
91        bookmarkedURLS.remove(bookmarkedURL);
92    }
93
94    /**
95     * Removes all BookmarkedURLs from user's bookmarks.
96     */
97    public void clearBookmarkedURLS() {
98        bookmarkedURLS.clear();
99    }
100
101    /**
102     * Add a BookmarkedConference to bookmarks.
103     *
104     * @param bookmarkedConference the conference to remove.
105     */
106    public void addBookmarkedConference(BookmarkedConference bookmarkedConference) {
107        bookmarkedConferences.add(bookmarkedConference);
108    }
109
110    /**
111     * Removes a BookmarkedConference.
112     *
113     * @param bookmarkedConference the BookmarkedConference to remove.
114     */
115    public void removeBookmarkedConference(BookmarkedConference bookmarkedConference) {
116        bookmarkedConferences.remove(bookmarkedConference);
117    }
118
119    /**
120     * Removes all BookmarkedConferences from Bookmarks.
121     */
122    public void clearBookmarkedConferences() {
123        bookmarkedConferences.clear();
124    }
125
126    /**
127     * Returns a Collection of all Bookmarked URLs for this user.
128     *
129     * @return a collection of all Bookmarked URLs.
130     */
131    public List<BookmarkedURL> getBookmarkedURLS() {
132        return bookmarkedURLS;
133    }
134
135    /**
136     * Returns a Collection of all Bookmarked Conference for this user.
137     *
138     * @return a collection of all Bookmarked Conferences.
139     */
140    public List<BookmarkedConference> getBookmarkedConferences() {
141        return bookmarkedConferences;
142    }
143
144
145    /**
146     * Returns the root element name.
147     *
148     * @return the element name.
149     */
150    public String getElementName() {
151        return "storage";
152    }
153
154    /**
155     * Returns the root element XML namespace.
156     *
157     * @return the namespace.
158     */
159    public String getNamespace() {
160        return "storage:bookmarks";
161    }
162
163    /**
164     * Returns the XML reppresentation of the PrivateData.
165     *
166     * @return the private data as XML.
167     */
168    public String toXML() {
169        StringBuilder buf = new StringBuilder();
170        buf.append("<storage xmlns=\"storage:bookmarks\">");
171
172        final Iterator<BookmarkedURL> urls = getBookmarkedURLS().iterator();
173        while (urls.hasNext()) {
174            BookmarkedURL urlStorage = urls.next();
175            if(urlStorage.isShared()) {
176                continue;
177            }
178            buf.append("<url name=\"").append(urlStorage.getName()).
179                    append("\" url=\"").append(urlStorage.getURL()).append("\"");
180            if(urlStorage.isRss()) {
181                buf.append(" rss=\"").append(true).append("\"");
182            }
183            buf.append(" />");
184        }
185
186        // Add Conference additions
187        final Iterator<BookmarkedConference> conferences = getBookmarkedConferences().iterator();
188        while (conferences.hasNext()) {
189            BookmarkedConference conference = conferences.next();
190            if(conference.isShared()) {
191                continue;
192            }
193            buf.append("<conference ");
194            buf.append("name=\"").append(conference.getName()).append("\" ");
195            buf.append("autojoin=\"").append(conference.isAutoJoin()).append("\" ");
196            buf.append("jid=\"").append(conference.getJid()).append("\" ");
197            buf.append(">");
198
199            if (conference.getNickname() != null) {
200                buf.append("<nick>").append(conference.getNickname()).append("</nick>");
201            }
202
203
204            if (conference.getPassword() != null) {
205                buf.append("<password>").append(conference.getPassword()).append("</password>");
206            }
207            buf.append("</conference>");
208        }
209
210
211        buf.append("</storage>");
212        return buf.toString();
213    }
214
215    /**
216     * The IQ Provider for BookmarkStorage.
217     *
218     * @author Derek DeMoro
219     */
220    public static class Provider implements PrivateDataProvider {
221
222        /**
223         * Empty Constructor for PrivateDataProvider.
224         */
225        public Provider() {
226            super();
227        }
228
229        public PrivateData parsePrivateData(XmlPullParser parser) throws Exception {
230            Bookmarks storage = new Bookmarks();
231
232            boolean done = false;
233            while (!done) {
234                int eventType = parser.next();
235                if (eventType == XmlPullParser.START_TAG && "url".equals(parser.getName())) {
236                    final BookmarkedURL urlStorage = getURLStorage(parser);
237                    if (urlStorage != null) {
238                        storage.addBookmarkedURL(urlStorage);
239                    }
240                }
241                else if (eventType == XmlPullParser.START_TAG &&
242                        "conference".equals(parser.getName()))
243                {
244                    final BookmarkedConference conference = getConferenceStorage(parser);
245                    storage.addBookmarkedConference(conference);
246                }
247                else if (eventType == XmlPullParser.END_TAG && "storage".equals(parser.getName()))
248                {
249                    done = true;
250                }
251            }
252
253
254            return storage;
255        }
256    }
257
258    private static BookmarkedURL getURLStorage(XmlPullParser parser) throws IOException, XmlPullParserException {
259        String name = parser.getAttributeValue("", "name");
260        String url = parser.getAttributeValue("", "url");
261        String rssString = parser.getAttributeValue("", "rss");
262        boolean rss = rssString != null && "true".equals(rssString);
263
264        BookmarkedURL urlStore = new BookmarkedURL(url, name, rss);
265        boolean done = false;
266        while (!done) {
267            int eventType = parser.next();
268            if(eventType == XmlPullParser.START_TAG
269                        && "shared_bookmark".equals(parser.getName())) {
270                    urlStore.setShared(true);
271            }
272            else if (eventType == XmlPullParser.END_TAG && "url".equals(parser.getName())) {
273                done = true;
274            }
275        }
276        return urlStore;
277    }
278
279    private static BookmarkedConference getConferenceStorage(XmlPullParser parser) throws Exception {
280        String name = parser.getAttributeValue("", "name");
281        String autojoin = parser.getAttributeValue("", "autojoin");
282        String jid = parser.getAttributeValue("", "jid");
283
284        BookmarkedConference conf = new BookmarkedConference(jid);
285        conf.setName(name);
286        conf.setAutoJoin(Boolean.valueOf(autojoin).booleanValue());
287
288        // Check for nickname
289        boolean done = false;
290        while (!done) {
291            int eventType = parser.next();
292            if (eventType == XmlPullParser.START_TAG && "nick".equals(parser.getName())) {
293                conf.setNickname(parser.nextText());
294            }
295            else if (eventType == XmlPullParser.START_TAG && "password".equals(parser.getName())) {
296                conf.setPassword(parser.nextText());
297            }
298            else if(eventType == XmlPullParser.START_TAG
299                        && "shared_bookmark".equals(parser.getName())) {
300                    conf.setShared(true);
301            }
302            else if (eventType == XmlPullParser.END_TAG && "conference".equals(parser.getName())) {
303                done = true;
304            }
305        }
306
307
308        return conf;
309    }
310}
311