1package eu.siacs.conversations.entities;
2
3import android.util.Base64;
4
5import com.google.common.base.Charsets;
6import com.google.common.hash.Hashing;
7
8import java.security.MessageDigest;
9import java.security.NoSuchAlgorithmException;
10import java.util.ArrayList;
11import java.util.Collection;
12import java.util.Collections;
13import java.util.List;
14
15import eu.siacs.conversations.android.PhoneNumberContact;
16import eu.siacs.conversations.xml.Element;
17import eu.siacs.conversations.xmpp.Jid;
18
19public class Entry implements Comparable<Entry> {
20 private final List<Jid> jids;
21 private final String number;
22
23 private Entry(String number, List<Jid> jids) {
24 this.number = number;
25 this.jids = jids;
26 }
27
28 public static Entry of(Element element) {
29 final String number = element.getAttribute("number");
30 final List<Jid> jids = new ArrayList<>();
31 for (Element jidElement : element.getChildren()) {
32 String content = jidElement.getContent();
33 if (content != null) {
34 jids.add(Jid.of(content));
35 }
36 }
37 return new Entry(number, jids);
38 }
39
40 public static List<Entry> ofPhoneBook(Element phoneBook) {
41 List<Entry> entries = new ArrayList<>();
42 for (Element entry : phoneBook.getChildren()) {
43 if ("entry".equals(entry.getName())) {
44 entries.add(of(entry));
45 }
46 }
47 return entries;
48 }
49
50 public static String statusQuo(final Collection<PhoneNumberContact> phoneNumberContacts, Collection<Contact> systemContacts) {
51 return statusQuo(ofPhoneNumberContactsAndContacts(phoneNumberContacts, systemContacts));
52 }
53
54 private static String statusQuo(final List<Entry> entries) {
55 Collections.sort(entries);
56 StringBuilder builder = new StringBuilder();
57 for(Entry entry : entries) {
58 if (builder.length() != 0) {
59 builder.append('\u001d');
60 }
61 builder.append(entry.getNumber());
62 List<Jid> jids = entry.getJids();
63 Collections.sort(jids);
64 for(Jid jid : jids) {
65 builder.append('\u001e');
66 builder.append(jid.asBareJid().toEscapedString());
67 }
68 }
69 @SuppressWarnings("deprecation")
70 final byte[] sha1 = Hashing.sha1().hashString(builder.toString(), Charsets.UTF_8).asBytes();
71 return new String(Base64.encode(sha1, Base64.DEFAULT)).trim();
72 }
73
74 private static List<Entry> ofPhoneNumberContactsAndContacts(final Collection<PhoneNumberContact> phoneNumberContacts, Collection<Contact> systemContacts) {
75 final ArrayList<Entry> entries = new ArrayList<>();
76 for(Contact contact : systemContacts) {
77 final PhoneNumberContact phoneNumberContact = PhoneNumberContact.findByUri(phoneNumberContacts, contact.getSystemAccount());
78 if (phoneNumberContact != null && phoneNumberContact.getPhoneNumber() != null) {
79 Entry entry = findOrCreateByPhoneNumber(entries, phoneNumberContact.getPhoneNumber());
80 entry.jids.add(contact.getJid().asBareJid());
81 }
82 }
83 return entries;
84 }
85
86 private static Entry findOrCreateByPhoneNumber(final List<Entry> entries, String number) {
87 for(Entry entry : entries) {
88 if (entry.number.equals(number)) {
89 return entry;
90 }
91 }
92 Entry entry = new Entry(number, new ArrayList<>());
93 entries.add(entry);
94 return entry;
95 }
96
97 public List<Jid> getJids() {
98 return jids;
99 }
100
101 public String getNumber() {
102 return number;
103 }
104
105 @Override
106 public int compareTo(Entry o) {
107 return number.compareTo(o.number);
108 }
109}