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