Presences.java

  1package eu.siacs.conversations.entities;
  2
  3import android.util.Pair;
  4
  5import java.util.ArrayList;
  6import java.util.HashMap;
  7import java.util.Hashtable;
  8import java.util.List;
  9import java.util.Map;
 10
 11public class Presences {
 12    private final Hashtable<String, Presence> presences = new Hashtable<>();
 13
 14    private static String nameWithoutVersion(String name) {
 15        String[] parts = name.split(" ");
 16        if (parts.length > 1 && Character.isDigit(parts[parts.length - 1].charAt(0))) {
 17            StringBuilder output = new StringBuilder();
 18            for (int i = 0; i < parts.length - 1; ++i) {
 19                if (output.length() != 0) {
 20                    output.append(' ');
 21                }
 22                output.append(parts[i]);
 23            }
 24            return output.toString();
 25        } else {
 26            return name;
 27        }
 28    }
 29
 30    public List<Presence> getPresences() {
 31        synchronized (this.presences) {
 32            return new ArrayList<>(this.presences.values());
 33        }
 34    }
 35
 36    public Map<String, Presence> getPresencesMap() {
 37        synchronized (this.presences) {
 38            return new HashMap<>(this.presences);
 39        }
 40    }
 41
 42    public Presence get(String resource) {
 43        synchronized (this.presences) {
 44            return this.presences.get(resource);
 45        }
 46    }
 47
 48    public void updatePresence(String resource, Presence presence) {
 49        synchronized (this.presences) {
 50            this.presences.put(resource, presence);
 51        }
 52    }
 53
 54    public void removePresence(String resource) {
 55        synchronized (this.presences) {
 56            this.presences.remove(resource);
 57        }
 58    }
 59
 60    public void clearPresences() {
 61        synchronized (this.presences) {
 62            this.presences.clear();
 63        }
 64    }
 65
 66    public Presence.Status getShownStatus() {
 67        Presence.Status status = Presence.Status.OFFLINE;
 68        synchronized (this.presences) {
 69            for (Presence p : presences.values()) {
 70                if (p.getStatus() == Presence.Status.DND) {
 71                    return p.getStatus();
 72                } else if (p.getStatus().compareTo(status) < 0) {
 73                    status = p.getStatus();
 74                }
 75            }
 76        }
 77        return status;
 78    }
 79
 80    public int size() {
 81        synchronized (this.presences) {
 82            return presences.size();
 83        }
 84    }
 85
 86    public boolean isEmpty() {
 87        synchronized (this.presences) {
 88            return this.presences.isEmpty();
 89        }
 90    }
 91
 92    public String[] toResourceArray() {
 93        synchronized (this.presences) {
 94            final String[] presencesArray = new String[presences.size()];
 95            presences.keySet().toArray(presencesArray);
 96            return presencesArray;
 97        }
 98    }
 99
100    public List<PresenceTemplate> asTemplates() {
101        synchronized (this.presences) {
102            ArrayList<PresenceTemplate> templates = new ArrayList<>(presences.size());
103            for (Presence p : presences.values()) {
104                if (p.getMessage() != null && !p.getMessage().trim().isEmpty()) {
105                    templates.add(new PresenceTemplate(p.getStatus(), p.getMessage()));
106                }
107            }
108            return templates;
109        }
110    }
111
112    public boolean has(String presence) {
113        synchronized (this.presences) {
114            return presences.containsKey(presence);
115        }
116    }
117
118    public List<String> getStatusMessages() {
119        ArrayList<String> messages = new ArrayList<>();
120        synchronized (this.presences) {
121            for (Presence presence : this.presences.values()) {
122                String message = presence.getMessage() == null ? null : presence.getMessage().trim();
123                if (message != null && !message.isEmpty() && !messages.contains(message)) {
124                    messages.add(message);
125                }
126            }
127        }
128        return messages;
129    }
130
131    public boolean allOrNonSupport(String namespace) {
132        synchronized (this.presences) {
133            for (Presence presence : this.presences.values()) {
134                ServiceDiscoveryResult disco = presence.getServiceDiscoveryResult();
135                if (disco == null || !disco.getFeatures().contains(namespace)) {
136                    return false;
137                }
138            }
139        }
140        return true;
141    }
142
143    public boolean anySupport(final String namespace) {
144        synchronized (this.presences) {
145            if (this.presences.size() == 0) {
146                return true;
147            }
148            for (Presence presence : this.presences.values()) {
149                ServiceDiscoveryResult disco = presence.getServiceDiscoveryResult();
150                if (disco != null && disco.getFeatures().contains(namespace)) {
151                    return true;
152                }
153            }
154        }
155        return false;
156    }
157
158    public String firstWhichSupport(final String namespace) {
159        synchronized (this.presences) {
160            for (Map.Entry<String, Presence> entry : this.presences.entrySet()) {
161                String resource = entry.getKey();
162                Presence presence = entry.getValue();
163                ServiceDiscoveryResult disco = presence.getServiceDiscoveryResult();
164                if (disco != null && disco.getFeatures().contains(namespace)) {
165                    return resource;
166                }
167            }
168        }
169        return null;
170    }
171
172    public boolean anyIdentity(final String category, final String type) {
173        synchronized (this.presences) {
174            if (this.presences.size() == 0) {
175                // https://github.com/iNPUTmice/Conversations/issues/4230
176                return false;
177            }
178            for (Presence presence : this.presences.values()) {
179                ServiceDiscoveryResult disco = presence.getServiceDiscoveryResult();
180                if (disco != null && disco.hasIdentity(category, type)) {
181                    return true;
182                }
183            }
184        }
185        return false;
186    }
187
188    public Pair<Map<String, String>, Map<String, String>> toTypeAndNameMap() {
189        Map<String, String> typeMap = new HashMap<>();
190        Map<String, String> nameMap = new HashMap<>();
191        synchronized (this.presences) {
192            for (Map.Entry<String, Presence> presenceEntry : this.presences.entrySet()) {
193                String resource = presenceEntry.getKey();
194                Presence presence = presenceEntry.getValue();
195                ServiceDiscoveryResult serviceDiscoveryResult = presence == null ? null : presence.getServiceDiscoveryResult();
196                if (serviceDiscoveryResult != null && serviceDiscoveryResult.getIdentities().size() > 0) {
197                    ServiceDiscoveryResult.Identity identity = serviceDiscoveryResult.getIdentities().get(0);
198                    String type = identity.getType();
199                    String name = identity.getName();
200                    if (type != null) {
201                        typeMap.put(resource, type);
202                    }
203                    if (name != null) {
204                        nameMap.put(resource, nameWithoutVersion(name));
205                    }
206                }
207            }
208        }
209        return new Pair<>(typeMap, nameMap);
210    }
211}