Skip to content

Commit b3c2d7f

Browse files
authored
Merge pull request #43 from ssick/master
Add VendorConsent.getAllowedVendorIds()
2 parents 554cbb3 + fb19a7f commit b3c2d7f

File tree

3 files changed

+193
-16
lines changed

3 files changed

+193
-16
lines changed

src/main/java/com/iab/gdpr/consent/VendorConsent.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,12 @@ public interface VendorConsent {
7979
*/
8080
int getAllowedPurposesBits();
8181

82+
/**
83+
*
84+
* @return the set of allowed vendor id's which are permitted according to this consent string
85+
*/
86+
Set<Integer> getAllowedVendorIds();
87+
8288
/**
8389
*
8490
* @return the maximum VendorId for which consent values are given.

src/main/java/com/iab/gdpr/consent/implementation/v1/ByteBufferBackedVendorConsent.java

Lines changed: 61 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import java.util.HashSet;
1212
import java.util.Set;
1313
import java.util.stream.Collectors;
14+
import java.util.stream.IntStream;
1415

1516
import static com.iab.gdpr.GdprConstants.*;
1617

@@ -93,6 +94,49 @@ public int getAllowedPurposesBits() {
9394
return bits.getInt(PURPOSES_OFFSET, PURPOSES_SIZE);
9495
}
9596

97+
@Override
98+
public Set<Integer> getAllowedVendorIds() {
99+
final Set<Integer> allowedVendorIds = new HashSet<>();
100+
final int maxVendorId = getMaxVendorId();
101+
if (encodingType() == VENDOR_ENCODING_RANGE) {
102+
final Set<Integer> vendorIds = new HashSet<>();
103+
final boolean isDefaultConsent = bits.getBit(DEFAULT_CONSENT_OFFSET);
104+
final int numEntries = bits.getInt(NUM_ENTRIES_OFFSET, NUM_ENTRIES_SIZE);
105+
int currentOffset = RANGE_ENTRY_OFFSET;
106+
for (int i = 0; i < numEntries; i++) {
107+
final boolean isRange = bits.getBit(currentOffset);
108+
currentOffset++;
109+
if(isRange) {
110+
int startVendorId = bits.getInt(currentOffset, VENDOR_ID_SIZE);
111+
currentOffset += VENDOR_ID_SIZE;
112+
int endVendorId = bits.getInt(currentOffset, VENDOR_ID_SIZE);
113+
currentOffset += VENDOR_ID_SIZE;
114+
validate(startVendorId, endVendorId, maxVendorId);
115+
IntStream.rangeClosed(startVendorId, endVendorId).forEach(vendorIds::add);
116+
} else {
117+
int singleVendorId = bits.getInt(currentOffset, VENDOR_ID_SIZE);
118+
currentOffset += VENDOR_ID_SIZE;
119+
validate(singleVendorId, maxVendorId);
120+
vendorIds.add(singleVendorId);
121+
}
122+
}
123+
if (isDefaultConsent) {
124+
IntStream.rangeClosed(1, getMaxVendorId())
125+
.filter(id -> !vendorIds.contains(id))
126+
.forEach(allowedVendorIds::add);
127+
} else {
128+
allowedVendorIds.addAll(vendorIds);
129+
}
130+
} else {
131+
for (int i = VENDOR_BITFIELD_OFFSET; i < VENDOR_BITFIELD_OFFSET + maxVendorId; i++) {
132+
if(bits.getBit(i)) {
133+
allowedVendorIds.add(i - VENDOR_BITFIELD_OFFSET + 1);
134+
}
135+
}
136+
}
137+
return allowedVendorIds;
138+
}
139+
96140
@Override
97141
public int getMaxVendorId() {
98142
return bits.getInt(MAX_VENDOR_ID_OFFSET, MAX_VENDOR_ID_SIZE);
@@ -154,29 +198,34 @@ private boolean isVendorPresentInRange(int vendorId) {
154198
currentOffset += VENDOR_ID_SIZE;
155199
int endVendorId = bits.getInt(currentOffset, VENDOR_ID_SIZE);
156200
currentOffset += VENDOR_ID_SIZE;
157-
158-
if (startVendorId > endVendorId || endVendorId > maxVendorId) {
159-
throw new VendorConsentParseException(
160-
"Start VendorId must not be greater than End VendorId and "
161-
+ "End VendorId must not be greater than Max Vendor Id");
162-
}
201+
validate(startVendorId, endVendorId, maxVendorId);
163202
if (vendorId >= startVendorId && vendorId <= endVendorId) return true;
164203

165204
} else {
166205
int singleVendorId = bits.getInt(currentOffset, VENDOR_ID_SIZE);
167206
currentOffset += VENDOR_ID_SIZE;
168-
169-
if (singleVendorId > maxVendorId) {
170-
throw new VendorConsentParseException(
171-
"VendorId in the range entries must not be greater than Max VendorId");
172-
}
173-
207+
validate(singleVendorId, maxVendorId);
174208
if (singleVendorId == vendorId) return true;
175209
}
176210
}
177211
return false;
178212
}
179213

214+
private static void validate(int startVendorId, int endVendorId, int maxVendorId) throws VendorConsentParseException {
215+
if (startVendorId > endVendorId || endVendorId > maxVendorId) {
216+
throw new VendorConsentParseException(
217+
"Start VendorId must not be greater than End VendorId and "
218+
+ "End VendorId must not be greater than Max Vendor Id");
219+
}
220+
}
221+
222+
private static void validate(int singleVendorId, int maxVendorId) throws VendorConsentParseException{
223+
if (singleVendorId > maxVendorId) {
224+
throw new VendorConsentParseException(
225+
"VendorId in the range entries must not be greater than Max VendorId");
226+
}
227+
}
228+
180229
@Override
181230
public boolean equals(Object o) {
182231
if (this == o) return true;

src/test/java/com/iab/gdpr/consent/implementation/v1/ByteBufferBackedVendorConsentTest.java

Lines changed: 126 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
import java.time.format.DateTimeFormatter;
1313
import java.util.Arrays;
1414
import java.util.HashSet;
15+
import java.util.Set;
16+
import java.util.stream.Collectors;
17+
import java.util.stream.IntStream;
1518

1619
import static com.iab.gdpr.Purpose.*;
1720
import static org.hamcrest.Matchers.is;
@@ -209,7 +212,7 @@ public void testgetMaxVendorId() {
209212

210213
@Test
211214
public void testBitFieldEncoding() {
212-
// Given: vendors 1,25 and 30 in bit field, with max vendor of of 32
215+
// Given: vendors 1,25 and 30 in bit field, with max vendor ID of 32
213216
final String binaryString = "000011" + // Version
214217
"001110001110110011010000101000000000" + // Created
215218
"001110001110110011010000101000000000" + // Updated
@@ -231,6 +234,7 @@ public void testBitFieldEncoding() {
231234
assertTrue(vendorConsent.isVendorAllowed(1));
232235
assertTrue(vendorConsent.isVendorAllowed(25));
233236
assertTrue(vendorConsent.isVendorAllowed(30));
237+
assertThat(vendorConsent.getAllowedVendorIds(), is(new HashSet<>(Arrays.asList(1, 25, 30))));
234238

235239
assertFalse(vendorConsent.isVendorAllowed(2));
236240
assertFalse(vendorConsent.isVendorAllowed(3));
@@ -248,7 +252,7 @@ public void testBitFieldEncoding() {
248252

249253
@Test
250254
public void testRangeEncodingDefaultFalse() {
251-
// Given: vendors 1-25 and 30 with consent, with max vendor IF of 32
255+
// Given: vendors 1-25 and 30 with consent, with max vendor ID of 32
252256
final String binaryString = "000011" + // Version
253257
"001110001110110011010000101000000000" + // Created
254258
"001110001110110011010000101000000000" + // Updated
@@ -278,6 +282,12 @@ public void testRangeEncodingDefaultFalse() {
278282
assertTrue(vendorConsent.isVendorAllowed(25));
279283
assertTrue(vendorConsent.isVendorAllowed(30));
280284

285+
Set<Integer> expectedVendorIds = IntStream
286+
.concat(IntStream.rangeClosed(1, 25), IntStream.of(30))
287+
.boxed()
288+
.collect(Collectors.toSet());
289+
assertThat(vendorConsent.getAllowedVendorIds(), is(expectedVendorIds));
290+
281291
assertFalse(vendorConsent.isVendorAllowed(26));
282292
assertFalse(vendorConsent.isVendorAllowed(28));
283293
assertFalse(vendorConsent.isVendorAllowed(31));
@@ -294,7 +304,7 @@ public void testRangeEncodingDefaultFalse() {
294304

295305
@Test
296306
public void testRangeEncodingDefaultTrue() {
297-
// Given: vendors 1 and 25-30 without consent, with max vendor IF of 32
307+
// Given: vendors 1 and 25-30 without consent, with max vendor ID of 32
298308
final String binaryString = "000011" + // Version
299309
"001110001110110011010000101000000000" + // Created
300310
"001110001110110011010000101000000000" + // Updated
@@ -329,6 +339,12 @@ public void testRangeEncodingDefaultTrue() {
329339
assertTrue(vendorConsent.isVendorAllowed(31));
330340
assertTrue(vendorConsent.isVendorAllowed(32));
331341

342+
Set<Integer> expectedVendorIds = IntStream
343+
.concat(IntStream.rangeClosed(2, 24), IntStream.rangeClosed(31, 32))
344+
.boxed()
345+
.collect(Collectors.toSet());
346+
assertThat(vendorConsent.getAllowedVendorIds(), is(expectedVendorIds));
347+
332348
// Vendors outside range [1, MaxVendorId] are not allowed
333349
assertFalse(vendorConsent.isVendorAllowed(-99));
334350
assertFalse(vendorConsent.isVendorAllowed(-1));
@@ -402,11 +418,73 @@ public void testInvalidVendorId2() {
402418
// Then: exception is raised
403419
}
404420

421+
@Test(expected = VendorConsentParseException.class)
422+
public void testInvalidVendorId3() {
423+
// Given: invalid vendor ID in range
424+
final String binaryString = "000011" + // Version
425+
"001110001110110011010000101000000000" + // Created
426+
"001110001110110011010000101000000000" + // Updated
427+
"000000001111" + // CMP ID
428+
"000000000101" + // CMP version
429+
"010010" + // Content screen ID
430+
"000100001101" + // Language code
431+
"000010010110" + // Vendor list version
432+
"111110000000001000000001" + // Allowed purposes bitmap
433+
"0000000000100000" + // Max vendor ID
434+
"1" + // Range encoding
435+
"1" + // Default 1=Consent
436+
"000000000010" + // Number of entries = 2
437+
"0" + // First entry single = 0
438+
"0000000000101000" + // First entry value = 40 - INVALID
439+
"1" + // Second entry range = 1
440+
"0000000000011001" + // Second entry from = 25
441+
"0000000000011110" // Second entry to = 30
442+
;
443+
444+
// When: object is constructed
445+
ByteBufferBackedVendorConsent vendorConsent = new ByteBufferBackedVendorConsent(Utils.fromBinaryString(binaryString));
446+
447+
// And: allowed vendor IDs are obtained
448+
vendorConsent.getAllowedVendorIds();
449+
450+
// Then: exception is raised
451+
}
452+
453+
@Test(expected = VendorConsentParseException.class)
454+
public void testInvalidVendorId4() {
455+
// Given: invalid vendor ID in range
456+
final String binaryString = "000011" + // Version
457+
"001110001110110011010000101000000000" + // Created
458+
"001110001110110011010000101000000000" + // Updated
459+
"000000001111" + // CMP ID
460+
"000000000101" + // CMP version
461+
"010010" + // Content screen ID
462+
"000100001101" + // Language code
463+
"000010010110" + // Vendor list version
464+
"111110000000001000000001" + // Allowed purposes bitmap
465+
"0000000000100000" + // Max vendor ID
466+
"1" + // Range encoding
467+
"1" + // Default 1=Consent
468+
"000000000010" + // Number of entries = 2
469+
"0" + // First entry single = 0
470+
"0000000000101000" + // First entry value = 40 - INVALID
471+
"1" + // Second entry range = 1
472+
"0000000000011001" + // Second entry from = 25
473+
"0000000000011110" // Second entry to = 30
474+
;
475+
476+
// When: object is constructed
477+
ByteBufferBackedVendorConsent vendorConsent = new ByteBufferBackedVendorConsent(Utils.fromBinaryString(binaryString));
478+
479+
// And: allowed vendor IDs are obtained
480+
vendorConsent.getAllowedVendorIds();
481+
482+
// Then: exception is raised
483+
}
405484
/*
406485
Below are tests for encoded strings from previous version of the code
407486
*/
408487

409-
410488
@Test
411489
public void testRealString1() {
412490
// Given: known vendor consent string
@@ -419,6 +497,22 @@ public void testRealString1() {
419497
assertEquals(380, vendorConsent.getMaxVendorId());
420498
assertTrue(vendorConsent.isVendorAllowed(380));
421499
assertFalse(vendorConsent.isVendorAllowed(379));
500+
501+
Set<Integer> expectedVendorIds = new HashSet<>(Arrays.asList(1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
502+
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
503+
44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
504+
72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 97, 98, 100,
505+
101, 102, 104, 105, 108, 109, 110, 111, 112, 113, 114, 115, 119, 120, 122, 124, 125, 126, 127, 128, 129,
506+
130, 131, 132, 133, 134, 136, 138, 139, 140, 141, 142, 143, 144, 145, 147, 148, 149, 150, 151, 152, 153,
507+
154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 167, 168, 169, 170, 173, 174, 175, 177, 179,
508+
180, 182, 183, 184, 185, 188, 189, 190, 191, 192, 193, 194, 195, 197, 198, 199, 200, 201, 202, 203, 205,
509+
208, 209, 210, 211, 212, 213, 215, 216, 217, 218, 224, 225, 226, 227, 228, 229, 230, 231, 232, 234, 235,
510+
236, 237, 238, 239, 240, 241, 244, 245, 246, 248, 249, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260,
511+
261, 262, 264, 265, 266, 269, 270, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 284, 285, 288,
512+
289, 290, 291, 294, 295, 297, 299, 301, 302, 303, 304, 308, 309, 310, 311, 314, 315, 316, 317, 318, 319,
513+
320, 323, 325, 326, 328, 330, 331, 333, 339, 341, 343, 344, 345, 347, 349, 350, 351, 354, 358, 359, 360,
514+
361, 369, 371, 378, 380));
515+
assertThat(vendorConsent.getAllowedVendorIds(), is(expectedVendorIds));
422516
}
423517

424518
@Test
@@ -447,6 +541,9 @@ public void testRealString2() {
447541
assertTrue(vendorConsent.isVendorAllowed(9));
448542
assertFalse(vendorConsent.isVendorAllowed(0));
449543
assertFalse(vendorConsent.isVendorAllowed(10));
544+
545+
Set<Integer> expectedVendorIds = new HashSet<>(Arrays.asList(1, 2, 4, 5, 7, 9));
546+
assertThat(vendorConsent.getAllowedVendorIds(), is(expectedVendorIds));
450547
}
451548

452549
@Test
@@ -479,6 +576,13 @@ public void testRealString3() {
479576
assertFalse(vendorConsent.isVendorAllowed(0));
480577
assertFalse(vendorConsent.isVendorAllowed(411));
481578
assertFalse(vendorConsent.isVendorAllowed(3244));
579+
580+
Set<Integer> expectedVendorIds = IntStream.concat(IntStream.of(20), IntStream.rangeClosed(200, 410))
581+
.boxed()
582+
.collect(Collectors.toSet());
583+
expectedVendorIds.add(515);
584+
expectedVendorIds.addAll(IntStream.rangeClosed(5000, 5024).boxed().collect(Collectors.toSet()));
585+
assertThat(vendorConsent.getAllowedVendorIds(), is(expectedVendorIds));
482586
}
483587

484588
@Test
@@ -511,6 +615,17 @@ public void testRealString4() {
511615
assertFalse(vendorConsent.isVendorAllowed(47));
512616
assertFalse(vendorConsent.isVendorAllowed(146));
513617
assertTrue(vendorConsent.isVendorAllowed(147));
618+
619+
Set<Integer> expectedVendorIds = new HashSet<>(Arrays.asList(1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
620+
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
621+
45, 46, 48, 49, 50, 51, 52, 53, 55, 56, 57, 58, 59, 60, 61, 62, 63, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
622+
75, 76, 77, 78, 79, 80, 81, 82, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 97, 98, 100, 101, 102, 104,
623+
105, 108, 109, 110, 111, 112, 113, 114, 115, 118, 120, 122, 124, 125, 126, 127, 128, 129, 130, 131, 132,
624+
133, 136, 138, 140, 141, 142, 144, 145, 147, 149, 151, 153, 154, 155, 156, 157, 158, 159, 160, 162, 163,
625+
164, 167, 168, 169, 170, 173, 174, 175, 179, 180, 182, 183, 185, 188, 189, 190, 192, 193, 194, 195, 197,
626+
198, 200, 203, 205, 208, 209, 210, 211, 213, 215, 217, 224, 225, 226, 227, 229, 232, 234, 235, 237, 240,
627+
241, 244, 245, 246, 249, 254, 255, 256, 258, 260, 269, 273, 274, 276, 279, 280, 45811));
628+
assertThat(vendorConsent.getAllowedVendorIds(), is(expectedVendorIds));
514629
}
515630

516631
@Test
@@ -528,6 +643,9 @@ public void testRealString5() {
528643
assertFalse(vendorConsent.isVendorAllowed(1));
529644
assertFalse(vendorConsent.isVendorAllowed(3));
530645
assertTrue(vendorConsent.isVendorAllowed(27));
646+
647+
Set<Integer> expectedVendorIds = new HashSet<>(Arrays.asList(9, 25, 27, 28, 30));
648+
assertThat(vendorConsent.getAllowedVendorIds(), is(expectedVendorIds));
531649
}
532650

533651
@Test
@@ -569,6 +687,10 @@ public void testRealString6() {
569687
assertTrue(vendorConsent.isVendorAllowed(228));
570688
assertTrue(vendorConsent.isVendorAllowed(253));
571689
assertTrue(vendorConsent.isVendorAllowed(1000));
690+
691+
Set<Integer> expectedVendorIds = new HashSet<>(
692+
Arrays.asList(10, 13, 24, 25, 32, 36, 45, 50, 52, 56, 62, 69, 76, 81, 104, 138, 144, 228, 253, 1000));
693+
assertThat(vendorConsent.getAllowedVendorIds(), is(expectedVendorIds));
572694
}
573695

574696
@Test(expected = VendorConsentParseException.class)

0 commit comments

Comments
 (0)