Bookmark.java

  1package eu.siacs.conversations.entities;
  2
  3import android.content.Context;
  4import androidx.annotation.NonNull;
  5import androidx.annotation.Nullable;
  6import com.google.common.base.Strings;
  7import com.google.common.collect.ImmutableList;
  8import eu.siacs.conversations.utils.StringUtils;
  9import eu.siacs.conversations.utils.UIHelper;
 10import eu.siacs.conversations.xml.Element;
 11import eu.siacs.conversations.xml.Namespace;
 12import eu.siacs.conversations.xmpp.Jid;
 13import im.conversations.android.xmpp.model.bookmark.Storage;
 14import im.conversations.android.xmpp.model.bookmark2.Conference;
 15import im.conversations.android.xmpp.model.pubsub.PubSub;
 16import java.lang.ref.WeakReference;
 17import java.util.Collections;
 18import java.util.HashMap;
 19import java.util.List;
 20import java.util.Locale;
 21import java.util.Map;
 22
 23public class Bookmark extends Element implements ListItem {
 24
 25    private final Account account;
 26    private WeakReference<Conversation> conversation;
 27    private Jid jid;
 28    protected Element extensions = new Element("extensions", Namespace.BOOKMARKS2);
 29
 30    public Bookmark(final Account account, final Jid jid) {
 31        super("conference");
 32        this.jid = jid;
 33        this.setAttribute("jid", jid);
 34        this.account = account;
 35    }
 36
 37    private Bookmark(Account account) {
 38        super("conference");
 39        this.account = account;
 40    }
 41
 42    public static Map<Jid, Bookmark> parseFromStorage(
 43            final Storage storage, final Account account) {
 44        if (storage == null) {
 45            return Collections.emptyMap();
 46        }
 47        final HashMap<Jid, Bookmark> bookmarks = new HashMap<>();
 48        for (final Element item : storage.getChildren()) {
 49            if (item.getName().equals("conference")) {
 50                final Bookmark bookmark = Bookmark.parse(item, account);
 51                if (bookmark != null) {
 52                    final Bookmark old = bookmarks.put(bookmark.jid, bookmark);
 53                    if (old != null
 54                            && old.getBookmarkName() != null
 55                            && bookmark.getBookmarkName() == null) {
 56                        bookmark.setBookmarkName(old.getBookmarkName());
 57                    }
 58                }
 59            }
 60        }
 61        return bookmarks;
 62    }
 63
 64    public static Map<Jid, Bookmark> parseFromPubSub(final PubSub pubSub, final Account account) {
 65        if (pubSub == null) {
 66            return Collections.emptyMap();
 67        }
 68        final var items = pubSub.getItems();
 69        if (items == null || !Namespace.BOOKMARKS2.equals(items.getNode())) {
 70            return Collections.emptyMap();
 71        }
 72        final Map<Jid, Bookmark> bookmarks = new HashMap<>();
 73        for (final var item : items.getItemMap(Conference.class).entrySet()) {
 74            final Bookmark bookmark =
 75                    Bookmark.parseFromItem(item.getKey(), item.getValue(), account);
 76            if (bookmark == null) {
 77                continue;
 78            }
 79            bookmarks.put(bookmark.jid, bookmark);
 80        }
 81        return bookmarks;
 82    }
 83
 84    public static Bookmark parse(Element element, Account account) {
 85        Bookmark bookmark = new Bookmark(account);
 86        bookmark.setAttributes(element.getAttributes());
 87        bookmark.setChildren(element.getChildren());
 88        bookmark.jid = Jid.Invalid.getNullForInvalid(bookmark.getAttributeAsJid("jid"));
 89        if (bookmark.jid == null) {
 90            return null;
 91        }
 92        return bookmark;
 93    }
 94
 95    public static Bookmark parseFromItem(
 96            final String id, final Conference conference, final Account account) {
 97        if (id == null || conference == null) {
 98            return null;
 99        }
100        final Bookmark bookmark = new Bookmark(account);
101        bookmark.jid = Jid.Invalid.getNullForInvalid(Jid.ofOrInvalid(id));
102        // TODO verify that we only use bare jids and ignore full jids
103        if (bookmark.jid == null) {
104            return null;
105        }
106        bookmark.setBookmarkName(conference.getAttribute("name"));
107        bookmark.setAutojoin(conference.getAttributeAsBoolean("autojoin"));
108        bookmark.setNick(conference.findChildContent("nick"));
109        bookmark.setPassword(conference.findChildContent("password"));
110        final Element extensions = conference.findChild("extensions", Namespace.BOOKMARKS2);
111        if (extensions != null) {
112            bookmark.extensions = extensions;
113        }
114        return bookmark;
115    }
116
117    public Element getExtensions() {
118        return extensions;
119    }
120
121    public void setAutojoin(boolean autojoin) {
122        if (autojoin) {
123            this.setAttribute("autojoin", "true");
124        } else {
125            this.setAttribute("autojoin", "false");
126        }
127    }
128
129    @Override
130    public int compareTo(final @NonNull ListItem another) {
131        return this.getDisplayName().compareToIgnoreCase(another.getDisplayName());
132    }
133
134    @Override
135    public String getDisplayName() {
136        final Conversation c = getConversation();
137        final String name = getBookmarkName();
138        if (c != null) {
139            return c.getName().toString();
140        } else if (printableValue(name, false)) {
141            return name.trim();
142        } else {
143            Jid jid = this.getJid();
144            return jid != null && jid.getLocal() != null ? jid.getLocal() : "";
145        }
146    }
147
148    public static boolean printableValue(@Nullable String value, boolean permitNone) {
149        return value != null && !value.trim().isEmpty() && (permitNone || !"None".equals(value));
150    }
151
152    public static boolean printableValue(@Nullable String value) {
153        return printableValue(value, true);
154    }
155
156    @Override
157    public Jid getJid() {
158        return this.jid;
159    }
160
161    public Jid getFullJid() {
162        final String nick = Strings.nullToEmpty(getNick()).trim();
163        if (jid == null || nick.isEmpty()) {
164            return jid;
165        }
166        try {
167            return jid.withResource(nick);
168        } catch (final IllegalArgumentException e) {
169            return jid;
170        }
171    }
172
173    @Override
174    public List<Tag> getTags(final Context context) {
175        final ImmutableList.Builder<Tag> tags = new ImmutableList.Builder<>();
176        for (final Element element : getChildren()) {
177            final String content = element.getContent();
178            if (Strings.isNullOrEmpty(content)) {
179                continue;
180            }
181            if (element.getName().equals("group")) {
182                tags.add(new Tag(content));
183            }
184        }
185        return tags.build();
186    }
187
188    public String getNick() {
189        return Strings.emptyToNull(this.findChildContent("nick"));
190    }
191
192    public void setNick(String nick) {
193        Element element = this.findChild("nick");
194        if (element == null) {
195            element = this.addChild("nick");
196        }
197        element.setContent(nick);
198    }
199
200    public boolean autojoin() {
201        return this.getAttributeAsBoolean("autojoin");
202    }
203
204    public String getPassword() {
205        return this.findChildContent("password");
206    }
207
208    public void setPassword(String password) {
209        Element element = this.findChild("password");
210        if (element != null) {
211            element.setContent(password);
212        }
213    }
214
215    @Override
216    public boolean match(Context context, String needle) {
217        if (needle == null) {
218            return true;
219        }
220        needle = needle.toLowerCase(Locale.US);
221        final Jid jid = getJid();
222        return (jid != null && jid.toString().contains(needle))
223                || getDisplayName().toLowerCase(Locale.US).contains(needle)
224                || matchInTag(context, needle);
225    }
226
227    private boolean matchInTag(Context context, String needle) {
228        needle = needle.toLowerCase(Locale.US);
229        for (Tag tag : getTags(context)) {
230            if (tag.getName().toLowerCase(Locale.US).contains(needle)) {
231                return true;
232            }
233        }
234        return false;
235    }
236
237    public Account getAccount() {
238        return this.account;
239    }
240
241    public synchronized Conversation getConversation() {
242        return this.conversation != null ? this.conversation.get() : null;
243    }
244
245    public synchronized void setConversation(Conversation conversation) {
246        if (this.conversation != null) {
247            this.conversation.clear();
248        }
249        if (conversation == null) {
250            this.conversation = null;
251        } else {
252            this.conversation = new WeakReference<>(conversation);
253        }
254    }
255
256    public String getBookmarkName() {
257        return this.getAttribute("name");
258    }
259
260    public boolean setBookmarkName(String name) {
261        String before = getBookmarkName();
262        if (name != null) {
263            this.setAttribute("name", name);
264        } else {
265            this.removeAttribute("name");
266        }
267        return StringUtils.changed(before, name);
268    }
269
270    @Override
271    public int getAvatarBackgroundColor() {
272        return UIHelper.getColorForName(
273                jid != null ? jid.asBareJid().toString() : getDisplayName());
274    }
275
276    @Override
277    public String getAvatarName() {
278        return getDisplayName();
279    }
280}