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