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