1package eu.siacs.conversations.entities;
2
3import eu.siacs.conversations.xmpp.Jid;
4import java.util.Collection;
5import java.util.Objects;
6import java.util.Set;
7import java.util.concurrent.CopyOnWriteArraySet;
8import org.json.JSONArray;
9import org.json.JSONException;
10import org.json.JSONObject;
11
12public class ReadByMarker {
13
14 private ReadByMarker() {}
15
16 @Override
17 public boolean equals(Object o) {
18 if (this == o) return true;
19 if (o == null || getClass() != o.getClass()) return false;
20
21 ReadByMarker marker = (ReadByMarker) o;
22
23 if (!Objects.equals(fullJid, marker.fullJid)) return false;
24 return Objects.equals(realJid, marker.realJid);
25 }
26
27 @Override
28 public int hashCode() {
29 int result = fullJid != null ? fullJid.hashCode() : 0;
30 result = 31 * result + (realJid != null ? realJid.hashCode() : 0);
31 return result;
32 }
33
34 private Jid fullJid;
35 private Jid realJid;
36
37 public Jid getFullJid() {
38 return fullJid;
39 }
40
41 public Jid getRealJid() {
42 return realJid;
43 }
44
45 public JSONObject toJson() {
46 JSONObject jsonObject = new JSONObject();
47 if (fullJid != null) {
48 try {
49 jsonObject.put("fullJid", fullJid.toString());
50 } catch (JSONException e) {
51 // ignore
52 }
53 }
54 if (realJid != null) {
55 try {
56 jsonObject.put("realJid", realJid.toString());
57 } catch (JSONException e) {
58 // ignore
59 }
60 }
61 return jsonObject;
62 }
63
64 public static Set<ReadByMarker> fromJson(final JSONArray jsonArray) {
65 final Set<ReadByMarker> readByMarkers = new CopyOnWriteArraySet<>();
66 for (int i = 0; i < jsonArray.length(); ++i) {
67 try {
68 readByMarkers.add(fromJson(jsonArray.getJSONObject(i)));
69 } catch (JSONException e) {
70 // ignored
71 }
72 }
73 return readByMarkers;
74 }
75
76 public static ReadByMarker from(Jid fullJid, Jid realJid) {
77 final ReadByMarker marker = new ReadByMarker();
78 marker.fullJid = fullJid;
79 marker.realJid = realJid == null ? null : realJid.asBareJid();
80 return marker;
81 }
82
83 public static ReadByMarker from(Message message) {
84 final ReadByMarker marker = new ReadByMarker();
85 marker.fullJid = message.getCounterpart();
86 marker.realJid = message.getTrueCounterpart();
87 return marker;
88 }
89
90 public static ReadByMarker from(MucOptions.User user) {
91 final ReadByMarker marker = new ReadByMarker();
92 marker.fullJid = user.getFullJid();
93 marker.realJid = user.getRealJid();
94 return marker;
95 }
96
97 public static Set<ReadByMarker> from(Collection<MucOptions.User> users) {
98 final Set<ReadByMarker> markers = new CopyOnWriteArraySet<>();
99 for (MucOptions.User user : users) {
100 markers.add(from(user));
101 }
102 return markers;
103 }
104
105 public static ReadByMarker fromJson(JSONObject jsonObject) {
106 ReadByMarker marker = new ReadByMarker();
107 try {
108 marker.fullJid = Jid.of(jsonObject.getString("fullJid"));
109 } catch (JSONException | IllegalArgumentException e) {
110 marker.fullJid = null;
111 }
112 try {
113 marker.realJid = Jid.of(jsonObject.getString("realJid"));
114 } catch (JSONException | IllegalArgumentException e) {
115 marker.realJid = null;
116 }
117 return marker;
118 }
119
120 public static Set<ReadByMarker> fromJsonString(String json) {
121 try {
122 return fromJson(new JSONArray(json));
123 } catch (final JSONException | NullPointerException e) {
124 return new CopyOnWriteArraySet<>();
125 }
126 }
127
128 public static JSONArray toJson(final Set<ReadByMarker> readByMarkers) {
129 final JSONArray jsonArray = new JSONArray();
130 for (final ReadByMarker marker : readByMarkers) {
131 jsonArray.put(marker.toJson());
132 }
133 return jsonArray;
134 }
135
136 public static boolean contains(ReadByMarker needle, final Set<ReadByMarker> readByMarkers) {
137 for (final ReadByMarker marker : readByMarkers) {
138 if (marker.realJid != null && needle.realJid != null) {
139 if (marker.realJid.asBareJid().equals(needle.realJid.asBareJid())) {
140 return true;
141 }
142 } else if (marker.fullJid != null && needle.fullJid != null) {
143 if (marker.fullJid.equals(needle.fullJid)) {
144 return true;
145 }
146 }
147 }
148 return false;
149 }
150
151 public static boolean allUsersRepresented(
152 Collection<MucOptions.User> users, Set<ReadByMarker> markers) {
153 for (MucOptions.User user : users) {
154 if (!contains(from(user), markers)) {
155 return false;
156 }
157 }
158 return true;
159 }
160
161 public static boolean allUsersRepresented(
162 Collection<MucOptions.User> users, Set<ReadByMarker> markers, ReadByMarker marker) {
163 final Set<ReadByMarker> markersCopy = new CopyOnWriteArraySet<>(markers);
164 markersCopy.add(marker);
165 return allUsersRepresented(users, markersCopy);
166 }
167}