BookmarkManager.java

  1package eu.siacs.conversations.xmpp.manager;
  2
  3import android.util.Log;
  4import androidx.annotation.NonNull;
  5import com.google.common.collect.ImmutableMap;
  6import com.google.common.util.concurrent.FutureCallback;
  7import com.google.common.util.concurrent.Futures;
  8import com.google.common.util.concurrent.ListenableFuture;
  9import com.google.common.util.concurrent.MoreExecutors;
 10import eu.siacs.conversations.Config;
 11import eu.siacs.conversations.entities.Bookmark;
 12import eu.siacs.conversations.services.XmppConnectionService;
 13import eu.siacs.conversations.xml.Namespace;
 14import eu.siacs.conversations.xmpp.Jid;
 15import eu.siacs.conversations.xmpp.XmppConnection;
 16import im.conversations.android.xmpp.NodeConfiguration;
 17import im.conversations.android.xmpp.model.bookmark2.Conference;
 18import im.conversations.android.xmpp.model.bookmark2.Nick;
 19import im.conversations.android.xmpp.model.bookmark2.Password;
 20import im.conversations.android.xmpp.model.pubsub.Items;
 21import im.conversations.android.xmpp.model.pubsub.event.Retract;
 22import java.util.Collection;
 23import java.util.Collections;
 24import java.util.Map;
 25
 26public class BookmarkManager extends AbstractBookmarkManager {
 27
 28    public BookmarkManager(final XmppConnectionService service, XmppConnection connection) {
 29        super(service, connection);
 30    }
 31
 32    public void fetch() {
 33        final var future = getManager(PepManager.class).fetchItems(Conference.class);
 34        Futures.addCallback(
 35                future,
 36                new FutureCallback<>() {
 37                    @Override
 38                    public void onSuccess(final Map<String, Conference> bookmarks) {
 39                        final var builder = new ImmutableMap.Builder<Jid, Bookmark>();
 40                        for (final var entry : bookmarks.entrySet()) {
 41                            final Bookmark bookmark =
 42                                    Bookmark.parseFromItem(
 43                                            entry.getKey(), entry.getValue(), getAccount());
 44                            if (bookmark == null) {
 45                                continue;
 46                            }
 47                            builder.put(bookmark.getJid(), bookmark);
 48                        }
 49                        processBookmarksInitial(builder.buildKeepingLast(), true);
 50                    }
 51
 52                    @Override
 53                    public void onFailure(@NonNull final Throwable throwable) {
 54                        Log.d(Config.LOGTAG, "Could not fetch bookmarks", throwable);
 55                    }
 56                },
 57                MoreExecutors.directExecutor());
 58    }
 59
 60    public void handleItems(final Items items) {
 61        this.handleItems(items.getItemMap(Conference.class));
 62        this.handleRetractions(items.getRetractions());
 63    }
 64
 65    private void handleRetractions(final Collection<Retract> retractions) {
 66        final var account = getAccount();
 67        for (final var retract : retractions) {
 68            final Jid id = Jid.Invalid.getNullForInvalid(retract.getAttributeAsJid("id"));
 69            if (id != null) {
 70                account.removeBookmark(id);
 71                Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": deleted bookmark for " + id);
 72                processDeletedBookmark(id);
 73                service.updateConversationUi();
 74            }
 75        }
 76    }
 77
 78    private void handleItems(final Map<String, Conference> items) {
 79        final var account = getAccount();
 80        for (final var item : items.entrySet()) {
 81            // TODO parseFromItem can be included in this Manager
 82            final Bookmark bookmark =
 83                    Bookmark.parseFromItem(item.getKey(), item.getValue(), account);
 84            if (bookmark == null) {
 85                continue;
 86            }
 87            account.putBookmark(bookmark);
 88            service.processModifiedBookmark(bookmark);
 89            service.updateConversationUi();
 90        }
 91    }
 92
 93    public ListenableFuture<Void> publish(final Bookmark bookmark) {
 94        final var address = bookmark.getJid();
 95        final var name = bookmark.getBookmarkName();
 96        final var nick = bookmark.getNick();
 97        final String password = bookmark.getPassword();
 98        final var itemId = address.toString();
 99        final var conference = new Conference();
100        conference.setAutoJoin(bookmark.autojoin());
101        if (nick != null) {
102            conference.addExtension(new Nick()).setContent(nick);
103        }
104        if (name != null) {
105            conference.setConferenceName(name);
106        }
107        if (password != null) {
108            conference.addExtension(new Password()).setContent(password);
109        }
110        conference.addExtension(bookmark.getExtensions());
111        return Futures.transform(
112                getManager(PepManager.class)
113                        .publish(conference, itemId, NodeConfiguration.WHITELIST_MAX_ITEMS),
114                result -> null,
115                MoreExecutors.directExecutor());
116    }
117
118    public ListenableFuture<Void> retract(final Jid address) {
119        final var itemId = address.toString();
120        return Futures.transform(
121                getManager(PepManager.class).retract(itemId, Namespace.BOOKMARKS2),
122                result -> null,
123                MoreExecutors.directExecutor());
124    }
125
126    private void deleteAllItems() {
127        final var account = getAccount();
128        final var previous = account.getBookmarkedJids();
129        account.setBookmarks(Collections.emptyMap());
130        processDeletedBookmarks(previous);
131    }
132
133    public void handleDelete() {
134        Log.d(Config.LOGTAG, getAccount().getJid().asBareJid() + ": deleted bookmarks node");
135        this.deleteAllItems();
136    }
137
138    public void handlePurge() {
139        Log.d(Config.LOGTAG, getAccount().getJid().asBareJid() + ": purged bookmarks");
140        this.deleteAllItems();
141    }
142
143    public boolean hasFeature() {
144        final var pep = getManager(PepManager.class);
145        final var disco = getManager(DiscoManager.class);
146        return pep.hasPublishOptions()
147                && pep.hasConfigNodeMax()
148                && disco.hasAccountFeature(Namespace.BOOKMARKS2_COMPAT);
149    }
150}