From 952e6c6e6b808df38cbca98dcd2bc60767110488 Mon Sep 17 00:00:00 2001 From: John Grimes Date: Sun, 12 Apr 2020 11:35:13 +1000 Subject: [PATCH 1/4] Make XhtmlNode$Location serializable Addresses jamesagnew/hapi-fhir#1422. --- .../java/org/hl7/fhir/utilities/xhtml/XhtmlNode.java | 4 +++- .../org/hl7/fhir/utilities/tests/XhtmlNodeTest.java | 12 ++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/xhtml/XhtmlNode.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/xhtml/XhtmlNode.java index 965d88563..1a61fd560 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/xhtml/XhtmlNode.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/xhtml/XhtmlNode.java @@ -50,6 +50,7 @@ package org.hl7.fhir.utilities.xhtml; import java.io.IOException; +import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -67,7 +68,8 @@ public class XhtmlNode implements IBaseXhtml { private static final long serialVersionUID = -4362547161441436492L; - public static class Location { + public static class Location implements Serializable { + private static final long serialVersionUID = -4079302502900219721L; private int line; private int column; public Location(int line, int column) { diff --git a/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/tests/XhtmlNodeTest.java b/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/tests/XhtmlNodeTest.java index ced5e7935..646196d01 100644 --- a/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/tests/XhtmlNodeTest.java +++ b/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/tests/XhtmlNodeTest.java @@ -1,5 +1,8 @@ package org.hl7.fhir.utilities.tests; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectOutputStream; import org.hl7.fhir.utilities.xhtml.XhtmlNode; import org.junit.Test; import org.slf4j.Logger; @@ -71,4 +74,13 @@ public class XhtmlNodeTest { assertEquals("
\"Twitter@fhirabend
", output); } + @Test + public void testSerializable() throws IOException { + XhtmlNode node = new XhtmlNode(); + node.setValueAsString("
Test
"); + + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + ObjectOutputStream oout = new ObjectOutputStream(bout); + oout.writeObject(node); + } } \ No newline at end of file From 55622f53cbb3e47cb1a9a7861608890b6acf0d2a Mon Sep 17 00:00:00 2001 From: markiantorno Date: Tue, 14 Apr 2020 22:28:32 -0400 Subject: [PATCH 2/4] Fix for NPEs in Base64BinaryType. Added tests to cover the cases. Updated for all FHIR versions. --- org.hl7.fhir.dstu2/pom.xml | 8 +++- .../fhir/dstu2/model/Base64BinaryType.java | 22 ++++++++++- .../dstu2/model/Base64BinaryTypeTest.java | 38 ++++++++++++++++++ org.hl7.fhir.dstu2016may/pom.xml | 8 +++- .../dstu2016may/model/Base64BinaryType.java | 22 ++++++++++- .../model/Base64BinaryTypeTest.java | 38 ++++++++++++++++++ org.hl7.fhir.dstu3/pom.xml | 6 +++ .../fhir/dstu3/model/Base64BinaryType.java | 23 ++++++++++- .../dstu3/model/Base64BinaryTypeTest.java | 38 ++++++++++++++++++ org.hl7.fhir.r4/pom.xml | 12 ++++++ .../hl7/fhir/r4/model/Base64BinaryType.java | 22 ++++++++++- .../fhir/r4/model/Base64BinaryTypeTest.java | 38 ++++++++++++++++++ .../org/hl7/fhir/r5/formats/JsonParser.java | 4 +- .../hl7/fhir/r5/model/Base64BinaryType.java | 24 +++++++++++- .../fhir/r5/model/Base64BinaryTypeTest.java | 39 +++++++++++++++++++ 15 files changed, 331 insertions(+), 11 deletions(-) create mode 100644 org.hl7.fhir.dstu2/src/test/java/org/hl7/fhir/dstu2/model/Base64BinaryTypeTest.java create mode 100644 org.hl7.fhir.dstu2016may/src/test/java/org/hl7/fhir/dstu2016may/model/Base64BinaryTypeTest.java create mode 100644 org.hl7.fhir.dstu3/src/test/java/org/hl7/fhir/dstu3/model/Base64BinaryTypeTest.java create mode 100644 org.hl7.fhir.r4/src/test/java/org/hl7/fhir/r4/model/Base64BinaryTypeTest.java create mode 100644 org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/model/Base64BinaryTypeTest.java diff --git a/org.hl7.fhir.dstu2/pom.xml b/org.hl7.fhir.dstu2/pom.xml index f04c9d29f..99ce2f2cd 100644 --- a/org.hl7.fhir.dstu2/pom.xml +++ b/org.hl7.fhir.dstu2/pom.xml @@ -95,7 +95,13 @@ Saxon-HE test + + org.junit.jupiter + junit-jupiter + RELEASE + test + - + diff --git a/org.hl7.fhir.dstu2/src/main/java/org/hl7/fhir/dstu2/model/Base64BinaryType.java b/org.hl7.fhir.dstu2/src/main/java/org/hl7/fhir/dstu2/model/Base64BinaryType.java index 12fa68eb9..60500850a 100644 --- a/org.hl7.fhir.dstu2/src/main/java/org/hl7/fhir/dstu2/model/Base64BinaryType.java +++ b/org.hl7.fhir.dstu2/src/main/java/org/hl7/fhir/dstu2/model/Base64BinaryType.java @@ -49,6 +49,7 @@ package org.hl7.fhir.dstu2.model; */ +import ca.uhn.fhir.parser.DataFormatException; import org.apache.commons.codec.binary.Base64; import ca.uhn.fhir.model.api.annotation.DatatypeDef; @@ -74,11 +75,17 @@ public class Base64BinaryType extends PrimitiveType { public Base64BinaryType(String theValue) { super(); + // Null values still result in non-null instance being created + if (theValue != null) checkValidBase64(theValue); setValueAsString(theValue); } protected byte[] parse(String theValue) { - return Base64.decodeBase64(theValue.getBytes(ca.uhn.fhir.rest.api.Constants.CHARSET_UTF8)); + if (theValue != null) { + return Base64.decodeBase64(theValue.getBytes(ca.uhn.fhir.rest.api.Constants.CHARSET_UTF8)); + } else { + return null; + } } protected String encode(byte[] theValue) { @@ -96,4 +103,17 @@ public class Base64BinaryType extends PrimitiveType { public String fhirType() { return "base64Binary"; } + + /** + * Checks if the passed in String is a valid {@link Base64} encoded String. Will throw a {@link DataFormatException} if not + * formatted correctly. + * + * @param toCheck {@link String} to check if valid {@link Base64} + * @throws DataFormatException + */ + public void checkValidBase64(String toCheck) throws DataFormatException { + if (!Base64.isBase64(toCheck.getBytes())) { + throw new DataFormatException(""); + } + } } diff --git a/org.hl7.fhir.dstu2/src/test/java/org/hl7/fhir/dstu2/model/Base64BinaryTypeTest.java b/org.hl7.fhir.dstu2/src/test/java/org/hl7/fhir/dstu2/model/Base64BinaryTypeTest.java new file mode 100644 index 000000000..f92ed0c22 --- /dev/null +++ b/org.hl7.fhir.dstu2/src/test/java/org/hl7/fhir/dstu2/model/Base64BinaryTypeTest.java @@ -0,0 +1,38 @@ +package org.hl7.fhir.dstu2.model; + +import ca.uhn.fhir.parser.DataFormatException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class Base64BinaryTypeTest { + + @Test + @DisplayName("Passing a non Base64 encoded String to constructor causes exception.") + public void testNonBase64String() { + String nonBase64 = "Picard was the best starship captain."; + assertThrows(DataFormatException.class, () -> new Base64BinaryType(nonBase64)); + } + + @Test + @DisplayName("Null String value creates non-null instance with null value.") + public void testNullInstance() throws DataFormatException { + String v = null; + Base64BinaryType b64 = new Base64BinaryType(v); + Assertions.assertNotNull(b64); + Assertions.assertNull(b64.getValue()); + Assertions.assertNull(b64.getValueAsString()); + } + + @Test + @DisplayName("Valid Base64 String creates non-null instance with non-null values.") + public void testValid() { + String v = "dGhpcyBpcyB2YWxpZCBiYXNlNjQ="; + Base64BinaryType b64 = new Base64BinaryType(v); + Assertions.assertNotNull(b64); + Assertions.assertNotNull(b64.getValue()); + Assertions.assertEquals(v, b64.asStringValue()); + } +} \ No newline at end of file diff --git a/org.hl7.fhir.dstu2016may/pom.xml b/org.hl7.fhir.dstu2016may/pom.xml index acbdba752..2ec8e6183 100644 --- a/org.hl7.fhir.dstu2016may/pom.xml +++ b/org.hl7.fhir.dstu2016may/pom.xml @@ -109,7 +109,13 @@ Saxon-HE test + + org.junit.jupiter + junit-jupiter + RELEASE + test + - + diff --git a/org.hl7.fhir.dstu2016may/src/main/java/org/hl7/fhir/dstu2016may/model/Base64BinaryType.java b/org.hl7.fhir.dstu2016may/src/main/java/org/hl7/fhir/dstu2016may/model/Base64BinaryType.java index f75be514c..9241aed7a 100644 --- a/org.hl7.fhir.dstu2016may/src/main/java/org/hl7/fhir/dstu2016may/model/Base64BinaryType.java +++ b/org.hl7.fhir.dstu2016may/src/main/java/org/hl7/fhir/dstu2016may/model/Base64BinaryType.java @@ -49,6 +49,7 @@ package org.hl7.fhir.dstu2016may.model; */ +import ca.uhn.fhir.parser.DataFormatException; import org.apache.commons.codec.binary.Base64; import ca.uhn.fhir.model.api.annotation.DatatypeDef; @@ -75,11 +76,17 @@ public class Base64BinaryType extends PrimitiveType { public Base64BinaryType(String theValue) { super(); + // Null values still result in non-null instance being created + if (theValue != null) checkValidBase64(theValue); setValueAsString(theValue); } protected byte[] parse(String theValue) { - return Base64.decodeBase64(theValue.getBytes(ca.uhn.fhir.rest.api.Constants.CHARSET_UTF8)); + if (theValue != null) { + return Base64.decodeBase64(theValue.getBytes(ca.uhn.fhir.rest.api.Constants.CHARSET_UTF8)); + } else { + return null; + } } protected String encode(byte[] theValue) { @@ -97,4 +104,17 @@ public class Base64BinaryType extends PrimitiveType { public String fhirType() { return "base64Binary"; } + + /** + * Checks if the passed in String is a valid {@link Base64} encoded String. Will throw a {@link DataFormatException} if not + * formatted correctly. + * + * @param toCheck {@link String} to check if valid {@link Base64} + * @throws DataFormatException + */ + public void checkValidBase64(String toCheck) throws DataFormatException { + if (!Base64.isBase64(toCheck.getBytes())) { + throw new DataFormatException(""); + } + } } diff --git a/org.hl7.fhir.dstu2016may/src/test/java/org/hl7/fhir/dstu2016may/model/Base64BinaryTypeTest.java b/org.hl7.fhir.dstu2016may/src/test/java/org/hl7/fhir/dstu2016may/model/Base64BinaryTypeTest.java new file mode 100644 index 000000000..1487a2f47 --- /dev/null +++ b/org.hl7.fhir.dstu2016may/src/test/java/org/hl7/fhir/dstu2016may/model/Base64BinaryTypeTest.java @@ -0,0 +1,38 @@ +package org.hl7.fhir.dstu2016may.model; + +import ca.uhn.fhir.parser.DataFormatException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class Base64BinaryTypeTest { + + @Test + @DisplayName("Passing a non Base64 encoded String to constructor causes exception.") + public void testNonBase64String() { + String nonBase64 = "Picard was the best starship captain."; + assertThrows(DataFormatException.class, () -> new Base64BinaryType(nonBase64)); + } + + @Test + @DisplayName("Null String value creates non-null instance with null value.") + public void testNullInstance() throws DataFormatException { + String v = null; + Base64BinaryType b64 = new Base64BinaryType(v); + Assertions.assertNotNull(b64); + Assertions.assertNull(b64.getValue()); + Assertions.assertNull(b64.getValueAsString()); + } + + @Test + @DisplayName("Valid Base64 String creates non-null instance with non-null values.") + public void testValid() { + String v = "dGhpcyBpcyB2YWxpZCBiYXNlNjQ="; + Base64BinaryType b64 = new Base64BinaryType(v); + Assertions.assertNotNull(b64); + Assertions.assertNotNull(b64.getValue()); + Assertions.assertEquals(v, b64.asStringValue()); + } +} \ No newline at end of file diff --git a/org.hl7.fhir.dstu3/pom.xml b/org.hl7.fhir.dstu3/pom.xml index dd14b47e7..2de2cf724 100644 --- a/org.hl7.fhir.dstu3/pom.xml +++ b/org.hl7.fhir.dstu3/pom.xml @@ -95,6 +95,12 @@ Saxon-HE test + + org.junit.jupiter + junit-jupiter + RELEASE + test + diff --git a/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/model/Base64BinaryType.java b/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/model/Base64BinaryType.java index 7e62a955b..a640bdb07 100644 --- a/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/model/Base64BinaryType.java +++ b/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/model/Base64BinaryType.java @@ -51,6 +51,7 @@ package org.hl7.fhir.dstu3.model; import ca.uhn.fhir.model.api.IElement; import ca.uhn.fhir.model.api.annotation.DatatypeDef; +import ca.uhn.fhir.parser.DataFormatException; import org.apache.commons.codec.binary.Base64; import org.hl7.fhir.instance.model.api.IBaseHasExtensions; import org.hl7.fhir.instance.model.api.IPrimitiveType; @@ -83,11 +84,17 @@ public class Base64BinaryType extends PrimitiveType implements IPrimitiv public Base64BinaryType(String theValue) { super(); + // Null values still result in non-null instance being created + if (theValue != null) checkValidBase64(theValue); setValueAsString(theValue); } protected byte[] parse(String theValue) { - return Base64.decodeBase64(theValue.getBytes(ca.uhn.fhir.rest.api.Constants.CHARSET_UTF8)); + if (theValue != null) { + return Base64.decodeBase64(theValue.getBytes(ca.uhn.fhir.rest.api.Constants.CHARSET_UTF8)); + } else { + return null; + } } protected String encode(byte[] theValue) { @@ -128,6 +135,7 @@ public class Base64BinaryType extends PrimitiveType implements IPrimitiv @Override public void setValueAsString(String theValue) throws IllegalArgumentException { + fromStringValue(theValue); setValue(parse(theValue)); } @@ -153,5 +161,16 @@ public class Base64BinaryType extends PrimitiveType implements IPrimitiv return ca.uhn.fhir.util.ElementUtil.isEmpty(id, extension) && !hasValue(); } - + /** + * Checks if the passed in String is a valid {@link Base64} encoded String. Will throw a {@link DataFormatException} if not + * formatted correctly. + * + * @param toCheck {@link String} to check if valid {@link Base64} + * @throws DataFormatException + */ + public void checkValidBase64(String toCheck) throws DataFormatException { + if (!Base64.isBase64(toCheck.getBytes())) { + throw new DataFormatException(""); + } + } } diff --git a/org.hl7.fhir.dstu3/src/test/java/org/hl7/fhir/dstu3/model/Base64BinaryTypeTest.java b/org.hl7.fhir.dstu3/src/test/java/org/hl7/fhir/dstu3/model/Base64BinaryTypeTest.java new file mode 100644 index 000000000..68a8687c4 --- /dev/null +++ b/org.hl7.fhir.dstu3/src/test/java/org/hl7/fhir/dstu3/model/Base64BinaryTypeTest.java @@ -0,0 +1,38 @@ +package org.hl7.fhir.dstu3.model; + +import ca.uhn.fhir.parser.DataFormatException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class Base64BinaryTypeTest { + + @Test + @DisplayName("Passing a non Base64 encoded String to constructor causes exception.") + public void testNonBase64String() { + String nonBase64 = "Picard was the best starship captain."; + assertThrows(DataFormatException.class, () -> new Base64BinaryType(nonBase64)); + } + + @Test + @DisplayName("Null String value creates non-null instance with null value.") + public void testNullInstance() throws DataFormatException { + String v = null; + Base64BinaryType b64 = new Base64BinaryType(v); + Assertions.assertNotNull(b64); + Assertions.assertNull(b64.getValue()); + Assertions.assertNull(b64.getValueAsString()); + } + + @Test + @DisplayName("Valid Base64 String creates non-null instance with non-null values.") + public void testValid() { + String v = "dGhpcyBpcyB2YWxpZCBiYXNlNjQ="; + Base64BinaryType b64 = new Base64BinaryType(v); + Assertions.assertNotNull(b64); + Assertions.assertNotNull(b64.getValue()); + Assertions.assertEquals(v, b64.asStringValue()); + } +} \ No newline at end of file diff --git a/org.hl7.fhir.r4/pom.xml b/org.hl7.fhir.r4/pom.xml index 22af04ec4..d67d49ae7 100644 --- a/org.hl7.fhir.r4/pom.xml +++ b/org.hl7.fhir.r4/pom.xml @@ -101,6 +101,18 @@ Saxon-HE test + + org.junit.jupiter + junit-jupiter + RELEASE + test + + + org.junit.jupiter + junit-jupiter + RELEASE + test + diff --git a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/model/Base64BinaryType.java b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/model/Base64BinaryType.java index 6721f1649..c3c0321ad 100644 --- a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/model/Base64BinaryType.java +++ b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/model/Base64BinaryType.java @@ -50,6 +50,7 @@ package org.hl7.fhir.r4.model; import ca.uhn.fhir.model.api.IElement; +import ca.uhn.fhir.parser.DataFormatException; import org.apache.commons.codec.binary.Base64; import ca.uhn.fhir.model.api.annotation.DatatypeDef; @@ -84,11 +85,17 @@ public class Base64BinaryType extends PrimitiveType implements IPrimitiv public Base64BinaryType(String theValue) { super(); + // Null values still result in non-null instance being created + if (theValue != null) checkValidBase64(theValue); setValueAsString(theValue); } protected byte[] parse(String theValue) { - return Base64.decodeBase64(theValue.getBytes(ca.uhn.fhir.rest.api.Constants.CHARSET_UTF8)); + if (theValue != null) { + return Base64.decodeBase64(theValue.getBytes(ca.uhn.fhir.rest.api.Constants.CHARSET_UTF8)); + } else { + return null; + } } protected String encode(byte[] theValue) { @@ -129,6 +136,7 @@ public class Base64BinaryType extends PrimitiveType implements IPrimitiv @Override public void setValueAsString(String theValue) throws IllegalArgumentException { + fromStringValue(theValue); setValue(parse(theValue)); } @@ -154,4 +162,16 @@ public class Base64BinaryType extends PrimitiveType implements IPrimitiv return ca.uhn.fhir.util.ElementUtil.isEmpty(id, extension) && !hasValue(); } + /** + * Checks if the passed in String is a valid {@link Base64} encoded String. Will throw a {@link DataFormatException} if not + * formatted correctly. + * + * @param toCheck {@link String} to check if valid {@link Base64} + * @throws DataFormatException + */ + public void checkValidBase64(String toCheck) throws DataFormatException { + if (!Base64.isBase64(toCheck.getBytes())) { + throw new DataFormatException(""); + } + } } diff --git a/org.hl7.fhir.r4/src/test/java/org/hl7/fhir/r4/model/Base64BinaryTypeTest.java b/org.hl7.fhir.r4/src/test/java/org/hl7/fhir/r4/model/Base64BinaryTypeTest.java new file mode 100644 index 000000000..d00ef03ee --- /dev/null +++ b/org.hl7.fhir.r4/src/test/java/org/hl7/fhir/r4/model/Base64BinaryTypeTest.java @@ -0,0 +1,38 @@ +package org.hl7.fhir.r4.model; + +import ca.uhn.fhir.parser.DataFormatException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class Base64BinaryTypeTest { + + @Test + @DisplayName("Passing a non Base64 encoded String to constructor causes exception.") + public void testNonBase64String() { + String nonBase64 = "Picard was the best starship captain."; + assertThrows(DataFormatException.class, () -> new Base64BinaryType(nonBase64)); + } + + @Test + @DisplayName("Null String value creates non-null instance with null value.") + public void testNullInstance() throws DataFormatException { + String v = null; + Base64BinaryType b64 = new Base64BinaryType(v); + Assertions.assertNotNull(b64); + Assertions.assertNull(b64.getValue()); + Assertions.assertNull(b64.getValueAsString()); + } + + @Test + @DisplayName("Valid Base64 String creates non-null instance with non-null values.") + public void testValid() { + String v = "dGhpcyBpcyB2YWxpZCBiYXNlNjQ="; + Base64BinaryType b64 = new Base64BinaryType(v); + Assertions.assertNotNull(b64); + Assertions.assertNotNull(b64.getValue()); + Assertions.assertEquals(v, b64.asStringValue()); + } +} \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/formats/JsonParser.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/formats/JsonParser.java index ca1164dbf..15d841321 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/formats/JsonParser.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/formats/JsonParser.java @@ -54,6 +54,7 @@ package org.hl7.fhir.r5.formats; +import ca.uhn.fhir.parser.DataFormatException; import org.hl7.fhir.r5.model.*; import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.xhtml.XhtmlNode; @@ -160,8 +161,7 @@ public class JsonParser extends JsonParserBase { } protected Base64BinaryType parseBase64Binary(String v) throws IOException, FHIRFormatError { - Base64BinaryType res = new Base64BinaryType(v); - return res; + return new Base64BinaryType(v); } protected UnsignedIntType parseUnsignedInt(String v) throws IOException, FHIRFormatError { diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/Base64BinaryType.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/Base64BinaryType.java index 23bf557eb..3810d370b 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/Base64BinaryType.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/Base64BinaryType.java @@ -51,8 +51,8 @@ package org.hl7.fhir.r5.model; import ca.uhn.fhir.model.api.IElement; import ca.uhn.fhir.model.api.annotation.DatatypeDef; +import ca.uhn.fhir.parser.DataFormatException; import org.apache.commons.codec.binary.Base64; -import org.apache.commons.lang3.StringUtils; import org.hl7.fhir.instance.model.api.IBaseHasExtensions; import org.hl7.fhir.instance.model.api.IPrimitiveType; @@ -84,11 +84,17 @@ public class Base64BinaryType extends PrimitiveType implements IPrimitiv public Base64BinaryType(String theValue) { super(); + // Null values still result in non-null instance being created + if (theValue != null) checkValidBase64(theValue); setValueAsString(theValue); } protected byte[] parse(String theValue) { - return Base64.decodeBase64(theValue.getBytes(ca.uhn.fhir.rest.api.Constants.CHARSET_UTF8)); + if (theValue != null) { + return Base64.decodeBase64(theValue.getBytes(ca.uhn.fhir.rest.api.Constants.CHARSET_UTF8)); + } else { + return null; + } } protected String encode(byte[] theValue) { @@ -129,6 +135,7 @@ public class Base64BinaryType extends PrimitiveType implements IPrimitiv @Override public void setValueAsString(String theValue) throws IllegalArgumentException { + fromStringValue(theValue); setValue(parse(theValue)); } @@ -158,4 +165,17 @@ public class Base64BinaryType extends PrimitiveType implements IPrimitiv public String primitiveValue() { return encode(myValue); } + + /** + * Checks if the passed in String is a valid {@link Base64} encoded String. Will throw a {@link DataFormatException} if not + * formatted correctly. + * + * @param toCheck {@link String} to check if valid {@link Base64} + * @throws DataFormatException + */ + public void checkValidBase64(String toCheck) throws DataFormatException { + if (!Base64.isBase64(toCheck.getBytes())) { + throw new DataFormatException(""); + } + } } diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/model/Base64BinaryTypeTest.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/model/Base64BinaryTypeTest.java new file mode 100644 index 000000000..0a193fca6 --- /dev/null +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/model/Base64BinaryTypeTest.java @@ -0,0 +1,39 @@ +package org.hl7.fhir.r5.model; + +import ca.uhn.fhir.parser.DataFormatException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class Base64BinaryTypeTest { + + @Test + @DisplayName("Passing a non Base64 encoded String to constructor causes exception.") + public void testNonBase64String() { + String nonBase64 = "Picard was the best starship captain."; + assertThrows(DataFormatException.class, () -> new Base64BinaryType(nonBase64)); + } + + @Test + @DisplayName("Null String value creates non-null instance with null value.") + public void testNullInstance() throws DataFormatException { + String v = null; + Base64BinaryType b64 = new Base64BinaryType(v); + Assertions.assertNotNull(b64); + Assertions.assertNull(b64.getValue()); + Assertions.assertNull(b64.getValueAsString()); + } + + @Test + @DisplayName("Valid Base64 String creates non-null instance with non-null values.") + public void testValid() { + String v = "dGhpcyBpcyB2YWxpZCBiYXNlNjQ="; + Base64BinaryType b64 = new Base64BinaryType(v); + Assertions.assertNotNull(b64); + Assertions.assertNotNull(b64.getValue()); + Assertions.assertEquals(v, b64.asStringValue()); + } + +} \ No newline at end of file From d767fc6e3848c8ebc13c8fb64597d8e161db9666 Mon Sep 17 00:00:00 2001 From: markiantorno Date: Tue, 14 Apr 2020 22:30:42 -0400 Subject: [PATCH 3/4] Apparently the dependency got added twice. --- org.hl7.fhir.r4/pom.xml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/org.hl7.fhir.r4/pom.xml b/org.hl7.fhir.r4/pom.xml index d67d49ae7..4b18e185d 100644 --- a/org.hl7.fhir.r4/pom.xml +++ b/org.hl7.fhir.r4/pom.xml @@ -107,12 +107,6 @@ RELEASE test - - org.junit.jupiter - junit-jupiter - RELEASE - test - From 118fe3d7e3f4a55b9e2dace0f78249b6d401a3a6 Mon Sep 17 00:00:00 2001 From: Rob Hausam Date: Wed, 15 Apr 2020 02:24:36 -0500 Subject: [PATCH 4/4] Restore expansion version notice capability for multiple versions of same code system. --- .../hl7/fhir/r5/utils/NarrativeGenerator.java | 40 ++++++++++++------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/NarrativeGenerator.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/NarrativeGenerator.java index d3386f7ee..65e7fc78b 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/NarrativeGenerator.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/NarrativeGenerator.java @@ -59,6 +59,8 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashMap; +import com.google.common.collect.Multimap; +import com.google.common.collect.HashMultimap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -3357,7 +3359,7 @@ public class NarrativeGenerator implements INarrativeGenerator { @SuppressWarnings("rawtypes") private void generateVersionNotice(XhtmlNode x, ValueSetExpansionComponent expansion) { - Map versions = new HashMap(); + Multimap versions = HashMultimap.create(); for (ValueSetExpansionParameterComponent p : expansion.getParameter()) { if (p.getName().equals("version")) { String[] parts = ((PrimitiveType) p.getValue()).asStringValue().split("\\|"); @@ -3365,20 +3367,30 @@ public class NarrativeGenerator implements INarrativeGenerator { versions.put(parts[0], parts[1]); } } - if (versions.size() > 1) { - XhtmlNode div = x.div().style("border: black 1px dotted; background-color: #EEEEEE; padding: 8px; margin-bottom: 8px"); - div.para().tx("Expansion based on: "); - XhtmlNode ul = div.ul(); - for (String s : versions.keySet()) { // though there'll only be one - expRef(ul.li(), s, versions.get(s)); + if (versions.size() > 0) { + XhtmlNode div = null; + XhtmlNode ul = null; + boolean first = true; + for (String s : versions.keySet()) { + if (versions.size() == 1 && versions.get(s).size() == 1) { + for (String v : versions.get(s)) { // though there'll only be one + XhtmlNode p = x.para().style("border: black 1px dotted; background-color: #EEEEEE; padding: 8px; margin-bottom: 8px"); + p.tx("Expansion based on "); + expRef(p, s, v); + } + } else { + for (String v : versions.get(s)) { + if (first) { + div = x.div().style("border: black 1px dotted; background-color: #EEEEEE; padding: 8px; margin-bottom: 8px"); + div.para().tx("Expansion based on: "); + ul = div.ul(); + first = false; + } + expRef(ul.li(), s, v); + } + } } - } else if (versions.size() == 1) { - XhtmlNode p = x.para().style("border: black 1px dotted; background-color: #EEEEEE; padding: 8px; margin-bottom: 8px"); - p.tx("Expansion based on "); - for (String s : versions.keySet()) { // though there'll only be one - expRef(p, s, versions.get(s)); - } - } + } } private void expRef(XhtmlNode x, String u, String v) {