diff --git a/iabgpp-encoder/src/main/java/com/iab/gpp/encoder/GppModel.java b/iabgpp-encoder/src/main/java/com/iab/gpp/encoder/GppModel.java index 2eef8aa5..7656bd2a 100644 --- a/iabgpp-encoder/src/main/java/com/iab/gpp/encoder/GppModel.java +++ b/iabgpp-encoder/src/main/java/com/iab/gpp/encoder/GppModel.java @@ -101,6 +101,9 @@ public void setFieldValue(String sectionName, String fieldName, Object value) { } else if (sectionName.equals(UsMn.NAME)) { section = new UsMn(); this.sections.put(UsMn.NAME, section); + } else if (sectionName.equals(UsMd.NAME)) { + section = new UsMd(); + this.sections.put(UsMd.NAME, section); } } else { section = this.sections.get(sectionName); @@ -302,6 +305,10 @@ public UsMn getUsMnSection() { return (UsMn) getSection(UsMn.NAME); } + public UsMd getUsMdSection() { + return (UsMd) getSection(UsMd.NAME); + } + public List getSectionIds() { if (!this.decoded) { this.sections = this.decodeModel(this.encodedString); @@ -416,6 +423,9 @@ protected Map decodeModel(String str) { } else if (sectionIds.get(i).equals(UsMn.ID)) { UsMn section = new UsMn(encodedSections[i + 1]); sections.put(UsMn.NAME, section); + } else if (sectionIds.get(i).equals(UsMd.ID)) { + UsMd section = new UsMd(encodedSections[i + 1]); + sections.put(UsMd.NAME, section); } } } @@ -529,6 +539,9 @@ public void decodeSection(String sectionName, String encodedString) { }else if (sectionName.equals(UsMn.NAME)) { section = new UsMn(); this.sections.put(UsMn.NAME, section); + }else if (sectionName.equals(UsMd.NAME)) { + section = new UsMd(); + this.sections.put(UsMd.NAME, section); } } else { section = this.sections.get(sectionName); diff --git a/iabgpp-encoder/src/main/java/com/iab/gpp/encoder/field/UsMdField.java b/iabgpp-encoder/src/main/java/com/iab/gpp/encoder/field/UsMdField.java new file mode 100644 index 00000000..5b61810d --- /dev/null +++ b/iabgpp-encoder/src/main/java/com/iab/gpp/encoder/field/UsMdField.java @@ -0,0 +1,42 @@ +package com.iab.gpp.encoder.field; + +import java.util.Arrays; +import java.util.List; + +public class UsMdField { + + public static String MSPA_VERSION = "MspaVersion"; + public static String MSPA_COVERED_TRANSACTION = "MspaCoveredTransaction"; + public static String MSPA_MODE = "MspaMode"; + public static String PROCESSING_NOTICE = "ProcessingNotice"; + public static String SALE_OPT_OUT_NOTICE = "SaleOptOutNotice"; + public static String TARGETED_ADVERTISING_OPT_OUT_NOTICE = "TargetedAdvertisingOptOutNotice"; + public static String SALE_OPT_OUT = "SaleOptOut"; + public static String TARGETED_ADVERTISING_OPT_OUT = "TargetedAdvertisingOptOut"; + public static String ADDITIONAL_DATA_PROCESSING_CONSENT = "AdditionalDataProcessingConsent"; + + public static String GPC_SEGMENT_TYPE = "GpcSegmentType"; + public static String GPC_SEGMENT_INCLUDED = "GpcSegmentIncluded"; + public static String GPC = "Gpc"; + + //@formatter:off + public static List USMD_CORE_SEGMENT_FIELD_NAMES = Arrays.asList(new String[] { + UsMdField.MSPA_VERSION, + UsMdField.MSPA_COVERED_TRANSACTION, + UsMdField.MSPA_MODE, + UsMdField.PROCESSING_NOTICE, + UsMdField.SALE_OPT_OUT_NOTICE, + UsMdField.TARGETED_ADVERTISING_OPT_OUT_NOTICE, + UsMdField.SALE_OPT_OUT, + UsMdField.TARGETED_ADVERTISING_OPT_OUT, + UsMdField.ADDITIONAL_DATA_PROCESSING_CONSENT + }); + //@formatter:on + + //@formatter:off + public static List USMD_GPC_SEGMENT_FIELD_NAMES = Arrays.asList(new String[] { + UsMdField.GPC_SEGMENT_TYPE, + UsMdField.GPC + }); + //@formatter:on +} diff --git a/iabgpp-encoder/src/main/java/com/iab/gpp/encoder/section/Sections.java b/iabgpp-encoder/src/main/java/com/iab/gpp/encoder/section/Sections.java index fb69587c..d9cad1a1 100644 --- a/iabgpp-encoder/src/main/java/com/iab/gpp/encoder/section/Sections.java +++ b/iabgpp-encoder/src/main/java/com/iab/gpp/encoder/section/Sections.java @@ -35,6 +35,7 @@ public class Sections { SECTION_ID_NAME_MAP.put(UsNj.ID, UsNj.NAME); SECTION_ID_NAME_MAP.put(UsTn.ID, UsTn.NAME); SECTION_ID_NAME_MAP.put(UsMn.ID, UsMn.NAME); + SECTION_ID_NAME_MAP.put(UsMd.ID, UsMd.NAME); SECTION_ORDER = new ArrayList(SECTION_ID_NAME_MAP.keySet()).stream().sorted() .map(id -> SECTION_ID_NAME_MAP.get(id)).collect(Collectors.toList()); diff --git a/iabgpp-encoder/src/main/java/com/iab/gpp/encoder/section/UsMd.java b/iabgpp-encoder/src/main/java/com/iab/gpp/encoder/section/UsMd.java new file mode 100644 index 00000000..dbcb8ece --- /dev/null +++ b/iabgpp-encoder/src/main/java/com/iab/gpp/encoder/section/UsMd.java @@ -0,0 +1,131 @@ +package com.iab.gpp.encoder.section; + +import com.iab.gpp.encoder.field.UsMdField; +import com.iab.gpp.encoder.segment.*; + +import java.util.ArrayList; +import java.util.List; + +public class UsMd extends AbstractLazilyEncodableSection { + + public static int ID = 24; + public static int VERSION = 1; + public static String NAME = "usmd"; + + public UsMd() { + super(); + } + + public UsMd(String encodedString) { + super(); + decode(encodedString); + } + + @Override + public int getId() { + return UsMd.ID; + } + + @Override + public String getName() { + return UsMd.NAME; + } + + @Override + public int getVersion() { + return UsMd.VERSION; + } + + @Override + protected List initializeSegments() { + List segments = new ArrayList<>(); + segments.add(new UsMdCoreSegment()); + segments.add(new UsMdGpcSegment()); + return segments; + } + + @Override + protected List decodeSection(String encodedString) { + List segments = initializeSegments(); + + if (encodedString != null && !encodedString.isEmpty()) { + String[] encodedSegments = encodedString.split("\\."); + + if (encodedSegments.length > 0) { + segments.get(0).decode(encodedSegments[0]); + } + + if (encodedSegments.length > 1) { + segments.get(1).setFieldValue(UsMdField.GPC_SEGMENT_INCLUDED, true); + segments.get(1).decode(encodedSegments[1]); + } else { + segments.get(1).setFieldValue(UsMdField.GPC_SEGMENT_INCLUDED, false); + } + } + + return segments; + } + + @Override + protected String encodeSection(List segments) { + List encodedSegments = new ArrayList<>(); + + if (!segments.isEmpty()) { + encodedSegments.add(segments.get(0).encode()); + if (segments.size() >= 2 && segments.get(1).getFieldValue(UsMdField.GPC_SEGMENT_INCLUDED).equals(true)) { + encodedSegments.add(segments.get(1).encode()); + } + } + + return String.join(".", encodedSegments); + } + + + public Integer getMspaVersion() { + return (Integer) this.getFieldValue(UsMdField.MSPA_VERSION); + } + + public Integer getMspaCoveredTransaction() { + return (Integer) this.getFieldValue(UsMdField.MSPA_COVERED_TRANSACTION); + } + + public Integer getMspaMode() { + return (Integer) this.getFieldValue(UsMdField.MSPA_MODE); + } + + public Integer getProcessingNotice() { + return (Integer) this.getFieldValue(UsMdField.PROCESSING_NOTICE); + } + + public Integer getSaleOptOutNotice() { + return (Integer) this.getFieldValue(UsMdField.SALE_OPT_OUT_NOTICE); + } + + public Integer getTargetedAdvertisingOptOutNotice() { + return (Integer) this.getFieldValue(UsMdField.TARGETED_ADVERTISING_OPT_OUT_NOTICE); + } + + public Integer getSaleOptOut() { + return (Integer) this.getFieldValue(UsMdField.SALE_OPT_OUT); + } + + public Integer getTargetedAdvertisingOptOut() { + return (Integer) this.getFieldValue(UsMdField.TARGETED_ADVERTISING_OPT_OUT); + } + + public Integer getAdditionalDataProcessingConsent() { + return (Integer) this.getFieldValue(UsMdField.ADDITIONAL_DATA_PROCESSING_CONSENT); + } + + public Integer getGpcSegmentType() { + return (Integer) this.getFieldValue(UsMdField.GPC_SEGMENT_TYPE); + } + + public Boolean getGpcSegmentIncluded() { + return (Boolean) this.getFieldValue(UsMdField.GPC_SEGMENT_INCLUDED); + } + + public Boolean getGpc() { + return (Boolean) this.getFieldValue(UsMdField.GPC); + } +} diff --git a/iabgpp-encoder/src/main/java/com/iab/gpp/encoder/segment/UsMdCoreSegment.java b/iabgpp-encoder/src/main/java/com/iab/gpp/encoder/segment/UsMdCoreSegment.java new file mode 100644 index 00000000..ae8d1253 --- /dev/null +++ b/iabgpp-encoder/src/main/java/com/iab/gpp/encoder/segment/UsMdCoreSegment.java @@ -0,0 +1,80 @@ +package com.iab.gpp.encoder.segment; + +import com.iab.gpp.encoder.base64.AbstractBase64UrlEncoder; +import com.iab.gpp.encoder.base64.CompressedBase64UrlEncoder; +import com.iab.gpp.encoder.bitstring.BitStringEncoder; +import com.iab.gpp.encoder.datatype.EncodableFixedInteger; +import com.iab.gpp.encoder.error.DecodingException; +import com.iab.gpp.encoder.field.EncodableBitStringFields; +import com.iab.gpp.encoder.field.UsMdField; +import com.iab.gpp.encoder.section.UsMd; + +import java.util.List; +import java.util.function.Predicate; + +public class UsMdCoreSegment extends AbstractLazilyEncodableSegment { + + private AbstractBase64UrlEncoder base64UrlEncoder = CompressedBase64UrlEncoder.getInstance(); + private BitStringEncoder bitStringEncoder = BitStringEncoder.getInstance(); + + public UsMdCoreSegment() { + super(); + } + + public UsMdCoreSegment(String encodedString) { + super(); + this.decode(encodedString); + } + + @Override + public List getFieldNames() { + return UsMdField.USMD_CORE_SEGMENT_FIELD_NAMES; + } + + @Override + protected EncodableBitStringFields initializeFields() { + Predicate nullableBooleanAsTwoBitIntegerValidator = (n -> n >= 0 && n <= 2); + Predicate nonNullableBooleanAsTwoBitIntegerValidator = (n -> n >= 1 && n <= 2); + + EncodableBitStringFields fields = new EncodableBitStringFields(); + fields.put(UsMdField.MSPA_VERSION, new EncodableFixedInteger(6, UsMd.VERSION)); + fields.put(UsMdField.MSPA_COVERED_TRANSACTION, + new EncodableFixedInteger(2, 1).withValidator(nonNullableBooleanAsTwoBitIntegerValidator)); + fields.put(UsMdField.MSPA_MODE, + new EncodableFixedInteger(2, 0).withValidator(nullableBooleanAsTwoBitIntegerValidator)); + fields.put(UsMdField.PROCESSING_NOTICE, + new EncodableFixedInteger(2, 0).withValidator(nullableBooleanAsTwoBitIntegerValidator)); + fields.put(UsMdField.SALE_OPT_OUT_NOTICE, + new EncodableFixedInteger(2, 0).withValidator(nullableBooleanAsTwoBitIntegerValidator)); + fields.put(UsMdField.TARGETED_ADVERTISING_OPT_OUT_NOTICE, + new EncodableFixedInteger(2, 0).withValidator(nullableBooleanAsTwoBitIntegerValidator)); + fields.put(UsMdField.SALE_OPT_OUT, + new EncodableFixedInteger(2, 0).withValidator(nullableBooleanAsTwoBitIntegerValidator)); + fields.put(UsMdField.TARGETED_ADVERTISING_OPT_OUT, + new EncodableFixedInteger(2, 0).withValidator(nullableBooleanAsTwoBitIntegerValidator)); + fields.put(UsMdField.ADDITIONAL_DATA_PROCESSING_CONSENT, + new EncodableFixedInteger(2, 0).withValidator(nullableBooleanAsTwoBitIntegerValidator)); + return fields; + } + + @Override + protected String encodeSegment(EncodableBitStringFields fields) { + String bitString = bitStringEncoder.encode(fields, getFieldNames()); + String encodedString = base64UrlEncoder.encode(bitString); + return encodedString; + } + + @Override + protected void decodeSegment(String encodedString, EncodableBitStringFields fields) { + if (encodedString == null || encodedString.isEmpty()) { + this.fields.reset(fields); + } + try { + String bitString = base64UrlEncoder.decode(encodedString); + bitStringEncoder.decode(bitString, getFieldNames(), fields); + } catch (Exception e) { + throw new DecodingException("Unable to decode UsMdCoreSegment '" + encodedString + "'", e); + } + } + +} diff --git a/iabgpp-encoder/src/main/java/com/iab/gpp/encoder/segment/UsMdGpcSegment.java b/iabgpp-encoder/src/main/java/com/iab/gpp/encoder/segment/UsMdGpcSegment.java new file mode 100644 index 00000000..4f10ae95 --- /dev/null +++ b/iabgpp-encoder/src/main/java/com/iab/gpp/encoder/segment/UsMdGpcSegment.java @@ -0,0 +1,61 @@ +package com.iab.gpp.encoder.segment; + +import com.iab.gpp.encoder.base64.AbstractBase64UrlEncoder; +import com.iab.gpp.encoder.base64.CompressedBase64UrlEncoder; +import com.iab.gpp.encoder.bitstring.BitStringEncoder; +import com.iab.gpp.encoder.datatype.EncodableBoolean; +import com.iab.gpp.encoder.datatype.EncodableFixedInteger; +import com.iab.gpp.encoder.error.DecodingException; +import com.iab.gpp.encoder.field.EncodableBitStringFields; +import com.iab.gpp.encoder.field.UsMdField; + +import java.util.List; + +public class UsMdGpcSegment extends AbstractLazilyEncodableSegment { + + private AbstractBase64UrlEncoder base64UrlEncoder = CompressedBase64UrlEncoder.getInstance(); + private BitStringEncoder bitStringEncoder = BitStringEncoder.getInstance(); + + public UsMdGpcSegment() { + super(); + } + + public UsMdGpcSegment(String encodedString) { + super(); + this.decode(encodedString); + } + + @Override + public List getFieldNames() { + return UsMdField.USMD_GPC_SEGMENT_FIELD_NAMES; + } + + @Override + protected EncodableBitStringFields initializeFields() { + EncodableBitStringFields fields = new EncodableBitStringFields(); + fields.put(UsMdField.GPC_SEGMENT_TYPE, new EncodableFixedInteger(2, 1)); + fields.put(UsMdField.GPC_SEGMENT_INCLUDED, new EncodableBoolean(true)); + fields.put(UsMdField.GPC, new EncodableBoolean(false)); + return fields; + } + + @Override + protected String encodeSegment(EncodableBitStringFields fields) { + String bitString = bitStringEncoder.encode(fields, getFieldNames()); + String encodedString = base64UrlEncoder.encode(bitString); + return encodedString; + } + + @Override + protected void decodeSegment(String encodedString, EncodableBitStringFields fields) { + if(encodedString == null || encodedString.isEmpty()) { + this.fields.reset(fields); + } + try { + String bitString = base64UrlEncoder.decode(encodedString); + bitStringEncoder.decode(bitString, getFieldNames(), fields); + } catch (Exception e) { + throw new DecodingException("Unable to decode UsMdGpcSegment '" + encodedString + "'", e); + } + } +} diff --git a/iabgpp-encoder/src/test/java/com/iab/gpp/encoder/GppModelTest.java b/iabgpp-encoder/src/test/java/com/iab/gpp/encoder/GppModelTest.java index bb5f2336..129a28b4 100644 --- a/iabgpp-encoder/src/test/java/com/iab/gpp/encoder/GppModelTest.java +++ b/iabgpp-encoder/src/test/java/com/iab/gpp/encoder/GppModelTest.java @@ -17,6 +17,7 @@ import com.iab.gpp.encoder.section.UsDe; import com.iab.gpp.encoder.section.UsFl; import com.iab.gpp.encoder.section.UsIa; +import com.iab.gpp.encoder.section.UsMd; import com.iab.gpp.encoder.section.UsMn; import com.iab.gpp.encoder.section.UsMt; import com.iab.gpp.encoder.section.UsNat; @@ -83,6 +84,7 @@ public void testEncodeDefaultAll() { Assertions.assertEquals(false, gppModel.hasSection(UsNj.NAME)); Assertions.assertEquals(false, gppModel.hasSection(UsTn.NAME)); Assertions.assertEquals(false, gppModel.hasSection(UsMn.NAME)); + Assertions.assertEquals(false, gppModel.hasSection(UsMd.NAME)); gppModel.setFieldValue(TcfEuV2.NAME, TcfEuV2Field.VERSION, TcfEuV2.VERSION); gppModel.setFieldValue(TcfEuV2.NAME, TcfCaV1Field.CREATED, utcDateTime); @@ -108,6 +110,7 @@ public void testEncodeDefaultAll() { gppModel.setFieldValue(UsNj.NAME, UsNjField.VERSION, UsNj.VERSION); gppModel.setFieldValue(UsTn.NAME, UsTnField.VERSION, UsTn.VERSION); gppModel.setFieldValue(UsMn.NAME, UsMnField.VERSION, UsMn.VERSION); + gppModel.setFieldValue(UsMd.NAME, UsMdField.MSPA_VERSION, UsMd.VERSION); Assertions.assertEquals(true, gppModel.hasSection(TcfEuV2.NAME)); @@ -130,10 +133,11 @@ public void testEncodeDefaultAll() { Assertions.assertEquals(true, gppModel.hasSection(UsNj.NAME)); Assertions.assertEquals(true, gppModel.hasSection(UsTn.NAME)); Assertions.assertEquals(true, gppModel.hasSection(UsMn.NAME)); + Assertions.assertEquals(true, gppModel.hasSection(UsMd.NAME)); String gppString = gppModel.encode(); Assertions.assertEquals( - "DBACOYs~CPSG_8APSG_8AAAAAAENAACAAAAAAAAAAAAAAAAAAAAA.QAAA.IAAA~BPSG_8APSG_8AAAAAAENAACAAAAAAAAAAAAAAAAAAA.YAAAAAAAAAA~1---~BAAAAAAAAABA.QA~BAAAAABA.QA~BAAAABA~BAAAAEA.QA~BAAAAAQA~BAAAAAEA.QA~BAAAAABA~BAAAAABA.QA~BAAAAAABAA.QA~BAAAAAQA.QA~BAAAAAABAA.QA~BAAAAAQA.QA~BAAAAAQA.QA~BAAAAABA.QA~BAAAAAAAQA.QA~BAAAAAQA.QA~BAAAAAQA.QA", + "DBACOcs~CPSG_8APSG_8AAAAAAENAACAAAAAAAAAAAAAAAAAAAAA.QAAA.IAAA~BPSG_8APSG_8AAAAAAENAACAAAAAAAAAAAAAAAAAAA.YAAAAAAAAAA~1---~BAAAAAAAAABA.QA~BAAAAABA.QA~BAAAABA~BAAAAEA.QA~BAAAAAQA~BAAAAAEA.QA~BAAAAABA~BAAAAABA.QA~BAAAAAABAA.QA~BAAAAAQA.QA~BAAAAAABAA.QA~BAAAAAQA.QA~BAAAAAQA.QA~BAAAAABA.QA~BAAAAAAAQA.QA~BAAAAAQA.QA~BAAAAAQA.QA~BQAA.QA", gppString); } @@ -406,7 +410,7 @@ public void testDecodeDefaults() { @Test public void testDecodeDefaultsAll() { String gppString = - "DBACOYs~CPSG_8APSG_8AAAAAAENAACAAAAAAAAAAAAAAAAAAAAA.QAAA.IAAA~BPSG_8APSG_8AAAAAAENAACAAAAAAAAAAAAAAAAAAA.YAAAAAAAAAA~1---~BAAAAAAAAABA.QA~BAAAAABA.QA~BAAAABA~BAAAAEA.QA~BAAAAAQA~BAAAAAEA.QA~BAAAAABA~BAAAAABA.QA~BAAAAAABAA.QA~BAAAAAQA.QA~BAAAAAABAA.QA~BAAAAAQA.QA~BAAAAAQA.QA~BAAAAABA.QA~BAAAAAAAQA.QA~BAAAAAQA.QA~BAAAAAABAA.QA"; + "DBACOcs~CPSG_8APSG_8AAAAAAENAACAAAAAAAAAAAAAAAAAAAAA.QAAA.IAAA~BPSG_8APSG_8AAAAAAENAACAAAAAAAAAAAAAAAAAAA.YAAAAAAAAAA~1---~BAAAAAAAAABA.QA~BAAAAABA.QA~BAAAABA~BAAAAEA.QA~BAAAAAQA~BAAAAAEA.QA~BAAAAABA~BAAAAABA.QA~BAAAAAABAA.QA~BAAAAAQA.QA~BAAAAAABAA.QA~BAAAAAQA.QA~BAAAAAQA.QA~BAAAAABA.QA~BAAAAAAAQA.QA~BAAAAAQA.QA~BAAAAAQA.QA~BQAA.QA"; GppModel gppModel = new GppModel(gppString); Assertions.assertEquals(true, gppModel.hasSection(TcfEuV2.NAME)); @@ -429,6 +433,7 @@ public void testDecodeDefaultsAll() { Assertions.assertEquals(true, gppModel.hasSection(UsNj.NAME)); Assertions.assertEquals(true, gppModel.hasSection(UsTn.NAME)); Assertions.assertEquals(true, gppModel.hasSection(UsMn.NAME)); + Assertions.assertEquals(true, gppModel.hasSection(UsMd.NAME)); } @Test diff --git a/iabgpp-encoder/src/test/java/com/iab/gpp/encoder/section/UsMdTest.java b/iabgpp-encoder/src/test/java/com/iab/gpp/encoder/section/UsMdTest.java new file mode 100644 index 00000000..b44b045f --- /dev/null +++ b/iabgpp-encoder/src/test/java/com/iab/gpp/encoder/section/UsMdTest.java @@ -0,0 +1,124 @@ +package com.iab.gpp.encoder.section; + + +import com.iab.gpp.encoder.error.DecodingException; +import com.iab.gpp.encoder.error.ValidationException; +import com.iab.gpp.encoder.field.UsMdField; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class UsMdTest { + + @Test + public void testEncode1() { + UsMd usMd = new UsMd(); + Assertions.assertEquals("BQAA.QA", usMd.encode()); + } + + @Test + public void testEncode2() { + UsMd usMd = new UsMd(); + + usMd.setFieldValue(UsMdField.MSPA_COVERED_TRANSACTION, 1); + usMd.setFieldValue(UsMdField.MSPA_MODE, 1); + usMd.setFieldValue(UsMdField.PROCESSING_NOTICE, 1); + usMd.setFieldValue(UsMdField.SALE_OPT_OUT_NOTICE, 1); + usMd.setFieldValue(UsMdField.TARGETED_ADVERTISING_OPT_OUT_NOTICE, 1); + usMd.setFieldValue(UsMdField.SALE_OPT_OUT, 1); + usMd.setFieldValue(UsMdField.TARGETED_ADVERTISING_OPT_OUT, 1); + usMd.setFieldValue(UsMdField.ADDITIONAL_DATA_PROCESSING_CONSENT, 1); + usMd.setFieldValue(UsMdField.GPC, true); + + Assertions.assertEquals("BVVU.YA", usMd.encode()); + } + + @Test + public void testSetInvalidValues() { + UsMd usMd = new UsMd(); + + try { + usMd.setFieldValue(UsMdField.MSPA_COVERED_TRANSACTION, 0); + Assertions.fail("Expected ValidationException"); + } catch (ValidationException e) { + + } + + try { + usMd.setFieldValue(UsMdField.MSPA_MODE, 3); + Assertions.fail("Expected ValidationException"); + } catch (ValidationException e) { + + } + + try { + usMd.setFieldValue(UsMdField.PROCESSING_NOTICE, 3); + Assertions.fail("Expected ValidationException"); + } catch (ValidationException e) { + + } + + try { + usMd.setFieldValue(UsMdField.SALE_OPT_OUT_NOTICE, 3); + Assertions.fail("Expected ValidationException"); + } catch (ValidationException e) { + + } + + try { + usMd.setFieldValue(UsMdField.TARGETED_ADVERTISING_OPT_OUT_NOTICE, 3); + Assertions.fail("Expected ValidationException"); + } catch (ValidationException e) { + + } + + try { + usMd.setFieldValue(UsMdField.SALE_OPT_OUT, 3); + Assertions.fail("Expected ValidationException"); + } catch (ValidationException e) { + + } + + try { + usMd.setFieldValue(UsMdField.TARGETED_ADVERTISING_OPT_OUT, -1); + Assertions.fail("Expected ValidationException"); + } catch (ValidationException e) { + + } + + try { + usMd.setFieldValue(UsMdField.ADDITIONAL_DATA_PROCESSING_CONSENT, 3); + Assertions.fail("Expected ValidationException"); + } catch (ValidationException e) { + + } + } + + @Test + public void testEncodeWithGpcSegmentExcluded() { + UsMd usMd = new UsMd(); + usMd.setFieldValue(UsMdField.GPC_SEGMENT_INCLUDED, false); + Assertions.assertEquals("BQAA", usMd.encode()); + } + + @Test + public void testDecode1() throws DecodingException { + UsMd usMd = new UsMd("BVVU.YA"); + + Assertions.assertEquals(1, usMd.getMspaCoveredTransaction()); + Assertions.assertEquals(1, usMd.getMspaMode()); + Assertions.assertEquals(1, usMd.getProcessingNotice()); + Assertions.assertEquals(1, usMd.getSaleOptOutNotice()); + Assertions.assertEquals(1, usMd.getTargetedAdvertisingOptOutNotice()); + Assertions.assertEquals(1, usMd.getSaleOptOut()); + Assertions.assertEquals(1, usMd.getTargetedAdvertisingOptOut()); + Assertions.assertEquals(1, usMd.getAdditionalDataProcessingConsent()); + Assertions.assertEquals(true, usMd.getGpc()); + } + + @Test() + public void testDecodeGarbage() { + Assertions.assertThrows(DecodingException.class, () -> { + new UsMd("z").getProcessingNotice(); + }); + } +}