|
2 | 2 |
|
3 | 3 | import com.google.gson.annotations.SerializedName; |
4 | 4 |
|
5 | | -import java.util.ArrayList; |
6 | | -import java.util.Collections; |
7 | | -import java.util.HashMap; |
8 | | -import java.util.List; |
| 5 | +import java.util.*; |
9 | 6 |
|
10 | 7 | public class IdentityMapV3Input { |
11 | 8 | /** |
12 | 9 | * @param emails a list of normalized or unnormalized email addresses |
13 | | - * @return a IdentityMapInput instance, to be used in {@link IdentityMapHelper#createEnvelopeForIdentityMapRequest} |
| 10 | + * @return a IdentityMapV3Input instance, to be used in {@link IdentityMapHelper#createEnvelopeForIdentityMapRequest} |
14 | 11 | */ |
15 | | - public static IdentityMapV3Input fromEmails(Iterable<String> emails) { |
16 | | - return new IdentityMapV3Input(IdentityType.Email, emails, false); |
| 12 | + public static IdentityMapV3Input fromEmails(List<String> emails) { |
| 13 | + return new IdentityMapV3Input().withEmails(emails); |
17 | 14 | } |
18 | 15 |
|
19 | 16 | /** |
20 | | - * @param phones a <a href="https://unifiedid.com/docs/getting-started/gs-normalization-encoding#phone-number-normalization">normalized</a> phone number |
21 | | - * @return an IdentityMapInput instance |
| 17 | + * @param hashedEmails a <a href="https://unifiedid.com/docs/getting-started/gs-normalization-encoding#email-address-normalization">normalized</a> and <a href="https://unifiedid.com/docs/getting-started/gs-normalization-encoding#email-address-hash-encoding">hashed</a> email address |
| 18 | + * @return an IdentityMapV3Input instance |
22 | 19 | */ |
23 | | - public static IdentityMapV3Input fromPhones(Iterable<String> phones) { |
24 | | - return new IdentityMapV3Input(IdentityType.Phone, phones, false); |
| 20 | + public static IdentityMapV3Input fromHashedEmails(List<String> hashedEmails) { |
| 21 | + return new IdentityMapV3Input().withHashedEmails(hashedEmails); |
25 | 22 | } |
26 | 23 |
|
27 | 24 | /** |
28 | | - * @param hashedEmails a <a href="https://unifiedid.com/docs/getting-started/gs-normalization-encoding#email-address-normalization">normalized</a> and <a href="https://unifiedid.com/docs/getting-started/gs-normalization-encoding#email-address-hash-encoding">hashed</a> email address |
29 | | - * @return an IdentityMapInput instance |
| 25 | + * @param phones a <a href="https://unifiedid.com/docs/getting-started/gs-normalization-encoding#phone-number-normalization">normalized</a> phone number |
| 26 | + * @return an IdentityMapV3Input instance |
30 | 27 | */ |
31 | | - public static IdentityMapV3Input fromHashedEmails(Iterable<String> hashedEmails) { |
32 | | - return new IdentityMapV3Input(IdentityType.Email, hashedEmails, true); |
| 28 | + public static IdentityMapV3Input fromPhones(List<String> phones) { |
| 29 | + return new IdentityMapV3Input().withPhones(phones); |
33 | 30 | } |
34 | 31 |
|
35 | 32 | /** |
36 | 33 | * @param hashedPhones a <a href="https://unifiedid.com/docs/getting-started/gs-normalization-encoding#phone-number-normalization">normalized</a> and <a href="https://unifiedid.com/docs/getting-started/gs-normalization-encoding#phone-number-hash-encoding">hashed</a> phone number |
37 | | - * @return an IdentityMapInput instance |
| 34 | + * @return an IdentityMapV3Input instance |
38 | 35 | */ |
39 | | - public static IdentityMapV3Input fromHashedPhones(Iterable<String> hashedPhones) { |
40 | | - return new IdentityMapV3Input(IdentityType.Phone, hashedPhones, true); |
| 36 | + public static IdentityMapV3Input fromHashedPhones(List<String> hashedPhones) { |
| 37 | + return new IdentityMapV3Input().withHashedPhones(hashedPhones); |
41 | 38 | } |
42 | 39 |
|
43 | | - private IdentityMapV3Input(IdentityType identityType, Iterable<String> emailsOrPhones, boolean alreadyHashed) { |
44 | | - if (identityType == IdentityType.Email) { |
45 | | - hashedNormalizedEmails = new ArrayList<>(); |
46 | | - for (String email : emailsOrPhones) { |
47 | | - if (alreadyHashed) { |
48 | | - hashedNormalizedEmails.add(new Identity(email)); |
49 | | - } else { |
50 | | - String hashedEmail = InputUtil.normalizeAndHashEmail(email); |
51 | | - hashedNormalizedEmails.add(new Identity(hashedEmail)); |
52 | | - addHashedToRawDiiMapping(hashedEmail, email); |
53 | | - } |
54 | | - } |
55 | | - } else { //phone |
56 | | - hashedNormalizedPhones = new ArrayList<>(); |
57 | | - for (String phone : emailsOrPhones) { |
58 | | - if (alreadyHashed) { |
59 | | - hashedNormalizedPhones.add(new Identity(phone)); |
60 | | - } else { |
61 | | - if (!InputUtil.isPhoneNumberNormalized(phone)) { |
62 | | - throw new IllegalArgumentException("phone number is not normalized: " + phone); |
63 | | - } |
64 | | - |
65 | | - String hashedNormalizedPhone = InputUtil.getBase64EncodedHash(phone); |
66 | | - addHashedToRawDiiMapping(hashedNormalizedPhone, phone); |
67 | | - hashedNormalizedPhones.add(new Identity(hashedNormalizedPhone)); |
68 | | - } |
69 | | - } |
| 40 | + private transient final Map<String, List<String>> diiMappings = new HashMap<>(); |
| 41 | + |
| 42 | + @SerializedName("email_hash") |
| 43 | + private final List<Identity> hashedEmails = new ArrayList<>(); |
| 44 | + |
| 45 | + @SerializedName("phone_hash") |
| 46 | + private final List<Identity> hashedPhones = new ArrayList<>(); |
| 47 | + |
| 48 | + private IdentityMapV3Input() {} |
| 49 | + |
| 50 | + public IdentityMapV3Input withHashedEmails(List<String> hashedEmails) { |
| 51 | + for (String hashedEmail : hashedEmails) { |
| 52 | + this.hashedEmails.add(new Identity(hashedEmail)); |
| 53 | + addToDiiMappings(hashedEmail, hashedEmail); |
| 54 | + } |
| 55 | + return this; |
| 56 | + } |
| 57 | + |
| 58 | + public IdentityMapV3Input withHashedPhones(List<String> hashedPhones) { |
| 59 | + for (String hashedPhone : hashedPhones) { |
| 60 | + this.hashedPhones.add(new Identity(hashedPhone)); |
| 61 | + addToDiiMappings(hashedPhone, hashedPhone); |
70 | 62 | } |
| 63 | + return this; |
71 | 64 | } |
72 | 65 |
|
73 | | - private void addHashedToRawDiiMapping(String hashedDii, String rawDii) { |
74 | | - hashedDiiToRawDiis.computeIfAbsent(hashedDii, k -> new ArrayList<>()).add(rawDii); |
| 66 | + public IdentityMapV3Input withEmails(List<String> emails) { |
| 67 | + for (String email : emails) { |
| 68 | + String hash = InputUtil.normalizeAndHashEmail(email); |
| 69 | + this.hashedEmails.add(new Identity(hash)); |
| 70 | + addToDiiMappings(hash, email); |
| 71 | + } |
| 72 | + return this; |
75 | 73 | } |
76 | 74 |
|
| 75 | + public IdentityMapV3Input withPhones(List<String> phones) { |
| 76 | + for (String phone : phones) { |
| 77 | + if (!InputUtil.isPhoneNumberNormalized(phone)) { |
| 78 | + throw new IllegalArgumentException("phone number is not normalized: " + phone); |
| 79 | + } |
77 | 80 |
|
78 | | - List<String> getRawDiis(String identifier) { |
79 | | - final boolean wasInputAlreadyHashed = hashedDiiToRawDiis.isEmpty(); |
80 | | - if (wasInputAlreadyHashed) |
81 | | - return Collections.singletonList(identifier); |
82 | | - return hashedDiiToRawDiis.get(identifier); |
| 81 | + String hash = InputUtil.getBase64EncodedHash(phone); |
| 82 | + this.hashedPhones.add(new Identity(hash)); |
| 83 | + addToDiiMappings(hash, phone); |
| 84 | + } |
| 85 | + return this; |
83 | 86 | } |
84 | 87 |
|
85 | | - @SerializedName("email_hash") |
86 | | - private List<Identity> hashedNormalizedEmails; |
87 | | - @SerializedName("phone_hash") |
88 | | - private List<Identity> hashedNormalizedPhones; |
| 88 | + private void addToDiiMappings(String hashedDii, String rawDii) { |
| 89 | + diiMappings.computeIfAbsent(hashedDii, k -> new ArrayList<>()).add(rawDii); |
| 90 | + } |
| 91 | + |
| 92 | + List<String> getRawDiis(String identityType, int i) { |
| 93 | + return diiMappings.get(getEncodedDii(identityType, i)); |
| 94 | + } |
| 95 | + |
| 96 | + private String getEncodedDii(String identityType, int i) { |
| 97 | + switch (identityType) { |
| 98 | + case "email_hash": return hashedEmails.get(i).identity; |
| 99 | + case "phone_hash": return hashedPhones.get(i).identity; |
| 100 | + } |
| 101 | + throw new Uid2Exception("Unexpected identity type: " + identityType); |
| 102 | + } |
89 | 103 |
|
90 | | - private final transient HashMap<String, List<String>> hashedDiiToRawDiis = new HashMap<>(); |
91 | 104 |
|
92 | 105 | private static class Identity { |
93 | 106 | @SerializedName("i") |
94 | | - private final String i; |
| 107 | + private final String identity; |
95 | 108 |
|
96 | 109 | public Identity(String value) { |
97 | | - this.i = value; |
| 110 | + this.identity = value; |
98 | 111 | } |
99 | 112 | } |
100 | 113 | } |
0 commit comments