Fix #312 - Don't fail if extension list contains a null

This commit is contained in:
James Agnew 2016-03-25 19:27:18 +01:00
parent f49130baf8
commit 6ffb1c8c56
5 changed files with 132 additions and 82 deletions

View File

@ -142,6 +142,9 @@ public abstract class BaseElement implements IElement, ISupportsUndeclaredExtens
protected boolean isBaseEmpty() { protected boolean isBaseEmpty() {
if (myUndeclaredExtensions != null) { if (myUndeclaredExtensions != null) {
for (ExtensionDt next : myUndeclaredExtensions) { for (ExtensionDt next : myUndeclaredExtensions) {
if (next == null) {
continue;
}
if (!next.isEmpty()) { if (!next.isEmpty()) {
return false; return false;
} }
@ -149,6 +152,9 @@ public abstract class BaseElement implements IElement, ISupportsUndeclaredExtens
} }
if (myUndeclaredModifierExtensions != null) { if (myUndeclaredModifierExtensions != null) {
for (ExtensionDt next : myUndeclaredModifierExtensions) { for (ExtensionDt next : myUndeclaredModifierExtensions) {
if (next == null) {
continue;
}
if (!next.isEmpty()) { if (!next.isEmpty()) {
return false; return false;
} }

View File

@ -78,6 +78,9 @@ public class FhirTerser {
if (theElement instanceof ISupportsUndeclaredExtensions) { if (theElement instanceof ISupportsUndeclaredExtensions) {
ISupportsUndeclaredExtensions containingElement = (ISupportsUndeclaredExtensions) theElement; ISupportsUndeclaredExtensions containingElement = (ISupportsUndeclaredExtensions) theElement;
for (ExtensionDt nextExt : containingElement.getUndeclaredExtensions()) { for (ExtensionDt nextExt : containingElement.getUndeclaredExtensions()) {
if (nextExt == null) {
continue;
}
theCallback.acceptUndeclaredExtension(containingElement, null, theChildDefinition, theDefinition, nextExt); theCallback.acceptUndeclaredExtension(containingElement, null, theChildDefinition, theDefinition, nextExt);
addUndeclaredExtensions(nextExt, theDefinition, theChildDefinition, theCallback); addUndeclaredExtensions(nextExt, theDefinition, theChildDefinition, theCallback);
} }
@ -85,6 +88,9 @@ public class FhirTerser {
if (theElement instanceof IBaseHasExtensions) { if (theElement instanceof IBaseHasExtensions) {
for (IBaseExtension<?, ?> nextExt : ((IBaseHasExtensions)theElement).getExtension()) { for (IBaseExtension<?, ?> nextExt : ((IBaseHasExtensions)theElement).getExtension()) {
if (nextExt == null) {
continue;
}
theCallback.acceptElement(nextExt.getValue(), null, theChildDefinition, theDefinition); theCallback.acceptElement(nextExt.getValue(), null, theChildDefinition, theDefinition);
addUndeclaredExtensions(nextExt, theDefinition, theChildDefinition, theCallback); addUndeclaredExtensions(nextExt, theDefinition, theChildDefinition, theCallback);
} }
@ -92,6 +98,9 @@ public class FhirTerser {
if (theElement instanceof IBaseHasModifierExtensions) { if (theElement instanceof IBaseHasModifierExtensions) {
for (IBaseExtension<?, ?> nextExt : ((IBaseHasModifierExtensions)theElement).getModifierExtension()) { for (IBaseExtension<?, ?> nextExt : ((IBaseHasModifierExtensions)theElement).getModifierExtension()) {
if (nextExt == null) {
continue;
}
theCallback.acceptElement(nextExt.getValue(), null, theChildDefinition, theDefinition); theCallback.acceptElement(nextExt.getValue(), null, theChildDefinition, theDefinition);
addUndeclaredExtensions(nextExt, theDefinition, theChildDefinition, theCallback); addUndeclaredExtensions(nextExt, theDefinition, theChildDefinition, theCallback);
} }

View File

@ -100,6 +100,25 @@ public class XmlParserDstu2Test {
private static final FhirContext ourCtx = FhirContext.forDstu2(); private static final FhirContext ourCtx = FhirContext.forDstu2();
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlParserDstu2Test.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlParserDstu2Test.class);
/**
* See #312
*/
@Test
public void testEncodeNullExtension() {
Patient patient = new Patient();
patient.getUndeclaredExtensions().add(null); // Purposely add null
patient.getUndeclaredModifierExtensions().add(null); // Purposely add null
patient.getUndeclaredExtensions().add(new ExtensionDt(false, "http://hello.world", new StringDt("Hello World")));
patient.getName().add(null);
patient.addName().getFamily().add(null);
IParser parser = ourCtx.newXmlParser();
String xml = parser.encodeResourceToString(patient);
ourLog.info(xml);
assertEquals("<Patient xmlns=\"http://hl7.org/fhir\"><extension url=\"http://hello.world\"><valueString value=\"Hello World\"/></extension></Patient>", xml);
}
@Test @Test
public void testBundleWithBinary() { public void testBundleWithBinary() {
//@formatter:off //@formatter:off

View File

@ -102,9 +102,6 @@ public class XmlParserDstu3Test {
ourCtx.setNarrativeGenerator(null); ourCtx.setNarrativeGenerator(null);
} }
@Test @Test
public void testBundleWithBinary() { public void testBundleWithBinary() {
//@formatter:off //@formatter:off
@ -159,7 +156,6 @@ public class XmlParserDstu3Test {
assertEquals("ORG", o.getName()); assertEquals("ORG", o.getName());
} }
@Test @Test
public void testDuration() { public void testDuration() {
Encounter enc = new Encounter(); Encounter enc = new Encounter();
@ -173,8 +169,7 @@ public class XmlParserDstu3Test {
assertThat(str, not(containsString("meta"))); assertThat(str, not(containsString("meta")));
assertThat(str, containsString("<length><value value=\"123\"/><unit value=\"day\"/></length>")); assertThat(str, containsString("<length><value value=\"123\"/><unit value=\"day\"/></length>"));
} }
@Test @Test
public void testEncodeAndParseContained() { public void testEncodeAndParseContained() {
IParser xmlParser = ourCtx.newXmlParser().setPrettyPrint(true); IParser xmlParser = ourCtx.newXmlParser().setPrettyPrint(true);
@ -243,7 +238,7 @@ public class XmlParserDstu3Test {
assertThat(encoded, not(stringContainsInOrder(Arrays.asList("<contained>", "<Org", "<contained>")))); assertThat(encoded, not(stringContainsInOrder(Arrays.asList("<contained>", "<Org", "<contained>"))));
} }
@Test @Test
public void testEncodeAndParseExtensionOnCode() { public void testEncodeAndParseExtensionOnCode() {
Organization o = new Organization(); Organization o = new Organization();
@ -262,7 +257,7 @@ public class XmlParserDstu3Test {
assertEquals("acode", code.getValue()); assertEquals("acode", code.getValue());
} }
@Test @Test
public void testEncodeAndParseExtensionOnReference() { public void testEncodeAndParseExtensionOnReference() {
DataElement de = new DataElement(); DataElement de = new DataElement();
@ -287,7 +282,7 @@ public class XmlParserDstu3Test {
assertEquals("ORG", o.getName()); assertEquals("ORG", o.getName());
} }
@Test @Test
public void testEncodeAndParseExtensions() throws Exception { public void testEncodeAndParseExtensions() throws Exception {
@ -405,7 +400,6 @@ public class XmlParserDstu3Test {
assertEquals("MR", patient.getIdentifier().get(0).getType().getCoding().get(0).getCode()); assertEquals("MR", patient.getIdentifier().get(0).getType().getCoding().get(0).getCode());
} }
@Test @Test
public void testEncodeAndParseMetaProfileAndTags() { public void testEncodeAndParseMetaProfileAndTags() {
Patient p = new Patient(); Patient p = new Patient();
@ -473,8 +467,7 @@ public class XmlParserDstu3Test {
assertEquals("sec_term2", tagList.get(1).getCode()); assertEquals("sec_term2", tagList.get(1).getCode());
assertEquals("sec_label2", tagList.get(1).getDisplay()); assertEquals("sec_label2", tagList.get(1).getDisplay());
} }
@Test @Test
public void testEncodeAndParseMetaProfiles() { public void testEncodeAndParseMetaProfiles() {
Patient p = new Patient(); Patient p = new Patient();
@ -844,8 +837,6 @@ public class XmlParserDstu3Test {
assertThat(encoded, not(containsString("tag"))); assertThat(encoded, not(containsString("tag")));
} }
/** /**
* #158 * #158
*/ */
@ -864,6 +855,8 @@ public class XmlParserDstu3Test {
assertThat(encoded, not(containsString("Label"))); assertThat(encoded, not(containsString("Label")));
} }
@Test @Test
public void testEncodeExtensionWithResourceContent() { public void testEncodeExtensionWithResourceContent() {
IParser parser = ourCtx.newXmlParser(); IParser parser = ourCtx.newXmlParser();
@ -945,6 +938,25 @@ public class XmlParserDstu3Test {
} }
/**
* See #312
*/
@Test
public void testEncodeNullExtension() {
Patient patient = new Patient();
patient.getExtension().add(null); // Purposely add null
patient.getModifierExtension().add(null); // Purposely add null
patient.getExtension().add(new Extension("http://hello.world", new StringType("Hello World")));
patient.getName().add(null);
patient.addName().getFamily().add(null);
IParser parser = ourCtx.newXmlParser();
String xml = parser.encodeResourceToString(patient);
ourLog.info(xml);
assertEquals("<Patient xmlns=\"http://hl7.org/fhir\"><extension url=\"http://hello.world\"><valueString value=\"Hello World\"/></extension></Patient>", xml);
}
@Test @Test
public void testEncodeReferenceUsingUnqualifiedResourceWorksCorrectly() { public void testEncodeReferenceUsingUnqualifiedResourceWorksCorrectly() {
@ -1022,55 +1034,6 @@ public class XmlParserDstu3Test {
assertThat(encoded, not(containsString("maritalStatus"))); assertThat(encoded, not(containsString("maritalStatus")));
} }
@Test
public void testEncodeWithEncodeElements() throws Exception {
Patient patient = new Patient();
patient.getMeta().addProfile("http://profile");
patient.addName().addFamily("FAMILY");
patient.addAddress().addLine("LINE1");
Bundle bundle = new Bundle();
bundle.setTotal(100);
bundle.addEntry().setResource(patient);
{
IParser p = ourCtx.newXmlParser();
p.setEncodeElements(new HashSet<String>(Arrays.asList("Patient.name", "Bundle.entry")));
p.setPrettyPrint(true);
String out = p.encodeResourceToString(bundle);
ourLog.info(out);
assertThat(out, not(containsString("total")));
assertThat(out, (containsString("Patient")));
assertThat(out, (containsString("name")));
assertThat(out, not(containsString("address")));
}
{
IParser p = ourCtx.newXmlParser();
p.setEncodeElements(new HashSet<String>(Arrays.asList("Patient.name")));
p.setEncodeElementsAppliesToResourceTypes(new HashSet<String>(Arrays.asList("Patient")));
p.setPrettyPrint(true);
String out = p.encodeResourceToString(bundle);
ourLog.info(out);
assertThat(out, (containsString("total")));
assertThat(out, (containsString("Patient")));
assertThat(out, (containsString("name")));
assertThat(out, not(containsString("address")));
}
{
IParser p = ourCtx.newXmlParser();
p.setEncodeElements(new HashSet<String>(Arrays.asList("Patient")));
p.setEncodeElementsAppliesToResourceTypes(new HashSet<String>(Arrays.asList("Patient")));
p.setPrettyPrint(true);
String out = p.encodeResourceToString(bundle);
ourLog.info(out);
assertThat(out, (containsString("total")));
assertThat(out, (containsString("Patient")));
assertThat(out, (containsString("name")));
assertThat(out, (containsString("address")));
}
}
@Test @Test
public void testEncodeWithDontEncodeElements() throws Exception { public void testEncodeWithDontEncodeElements() throws Exception {
Patient patient = new Patient(); Patient patient = new Patient();
@ -1138,6 +1101,55 @@ public class XmlParserDstu3Test {
assertThat(out, not(containsString("meta"))); assertThat(out, not(containsString("meta")));
} }
} }
@Test
public void testEncodeWithEncodeElements() throws Exception {
Patient patient = new Patient();
patient.getMeta().addProfile("http://profile");
patient.addName().addFamily("FAMILY");
patient.addAddress().addLine("LINE1");
Bundle bundle = new Bundle();
bundle.setTotal(100);
bundle.addEntry().setResource(patient);
{
IParser p = ourCtx.newXmlParser();
p.setEncodeElements(new HashSet<String>(Arrays.asList("Patient.name", "Bundle.entry")));
p.setPrettyPrint(true);
String out = p.encodeResourceToString(bundle);
ourLog.info(out);
assertThat(out, not(containsString("total")));
assertThat(out, (containsString("Patient")));
assertThat(out, (containsString("name")));
assertThat(out, not(containsString("address")));
}
{
IParser p = ourCtx.newXmlParser();
p.setEncodeElements(new HashSet<String>(Arrays.asList("Patient.name")));
p.setEncodeElementsAppliesToResourceTypes(new HashSet<String>(Arrays.asList("Patient")));
p.setPrettyPrint(true);
String out = p.encodeResourceToString(bundle);
ourLog.info(out);
assertThat(out, (containsString("total")));
assertThat(out, (containsString("Patient")));
assertThat(out, (containsString("name")));
assertThat(out, not(containsString("address")));
}
{
IParser p = ourCtx.newXmlParser();
p.setEncodeElements(new HashSet<String>(Arrays.asList("Patient")));
p.setEncodeElementsAppliesToResourceTypes(new HashSet<String>(Arrays.asList("Patient")));
p.setPrettyPrint(true);
String out = p.encodeResourceToString(bundle);
ourLog.info(out);
assertThat(out, (containsString("total")));
assertThat(out, (containsString("Patient")));
assertThat(out, (containsString("name")));
assertThat(out, (containsString("address")));
}
}
@Test @Test
public void testEncodeWithNarrative() { public void testEncodeWithNarrative() {
@ -1711,8 +1723,7 @@ public class XmlParserDstu3Test {
assertEquals(Reference.class, ext.getValue().getClass()); assertEquals(Reference.class, ext.getValue().getClass());
assertEquals("#2179414-cm", ((Reference) ext.getValue()).getReference()); assertEquals("#2179414-cm", ((Reference) ext.getValue()).getReference());
assertEquals(ConceptMap.class, ((Reference) ext.getValue()).getResource().getClass()); assertEquals(ConceptMap.class, ((Reference) ext.getValue()).getResource().getClass());
ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(de)); ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(de));
assertThat(output, containsString("http://hl7.org/fhir/StructureDefinition/11179-permitted-value-valueset")); assertThat(output, containsString("http://hl7.org/fhir/StructureDefinition/11179-permitted-value-valueset"));
@ -1721,7 +1732,7 @@ public class XmlParserDstu3Test {
ourLog.info("Actual : {}", output); ourLog.info("Actual : {}", output);
assertEquals(input, output); assertEquals(input, output);
} }
@Test @Test
public void testParseAndEncodeNestedExtensions() { public void testParseAndEncodeNestedExtensions() {
//@formatter:off //@formatter:off
@ -1735,24 +1746,24 @@ public class XmlParserDstu3Test {
" </birthDate>\n" + " </birthDate>\n" +
"</Patient>"; "</Patient>";
//@formatter:on //@formatter:on
Patient p = ourCtx.newXmlParser().parseResource(Patient.class, input); Patient p = ourCtx.newXmlParser().parseResource(Patient.class, input);
DateType bd = p.getBirthDateElement(); DateType bd = p.getBirthDateElement();
assertEquals("2005-03-04", bd.getValueAsString()); assertEquals("2005-03-04", bd.getValueAsString());
List<Extension> exts = bd.getExtensionsByUrl("http://my.fancy.extension.url"); List<Extension> exts = bd.getExtensionsByUrl("http://my.fancy.extension.url");
assertEquals(1, exts.size()); assertEquals(1, exts.size());
Extension ext = exts.get(0); Extension ext = exts.get(0);
assertEquals(null, ext.getValue()); assertEquals(null, ext.getValue());
exts = ext.getExtensionsByUrl("http://my.fancy.extension.url"); exts = ext.getExtensionsByUrl("http://my.fancy.extension.url");
assertEquals(1, exts.size()); assertEquals(1, exts.size());
ext = exts.get(0); ext = exts.get(0);
assertEquals("myNestedValue", ((StringType)ext.getValue()).getValue()); assertEquals("myNestedValue", ((StringType) ext.getValue()).getValue());
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p); String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p);
ourLog.info(encoded); ourLog.info(encoded);
//@formatter:off //@formatter:off
assertThat(encoded, stringContainsInOrder( assertThat(encoded, stringContainsInOrder(
"<Patient xmlns=\"http://hl7.org/fhir\">", "<Patient xmlns=\"http://hl7.org/fhir\">",
@ -1765,7 +1776,7 @@ public class XmlParserDstu3Test {
"</birthDate>", "</birthDate>",
"</Patient>")); "</Patient>"));
//@formatter:on //@formatter:on
} }
@Test @Test
@ -1788,8 +1799,7 @@ public class XmlParserDstu3Test {
assertEquals("urn:oid:0.1.2.3", parsed.getEntry().get(0).getResource().getIdElement().getValue()); assertEquals("urn:oid:0.1.2.3", parsed.getEntry().get(0).getResource().getIdElement().getValue());
} }
@Test @Test
public void testParseBundleNewWithPlaceholderIdsInBase1() { public void testParseBundleNewWithPlaceholderIdsInBase1() {
//@formatter:off //@formatter:off
@ -1945,7 +1955,8 @@ public class XmlParserDstu3Test {
/** /**
* see #144 and #146 * see #144 and #146
*/ */
@Test @Ignore @Test
@Ignore
public void testParseContained() { public void testParseContained() {
FhirContext c = FhirContext.forDstu3(); FhirContext c = FhirContext.forDstu3();
@ -2006,9 +2017,9 @@ public class XmlParserDstu3Test {
assertEquals(1, actual.getContent().size()); assertEquals(1, actual.getContent().size());
/* /*
* If this fails, it's possibe the DocumentManifest structure is wrong: * If this fails, it's possibe the DocumentManifest structure is wrong: It should be
* It should be *
* @Child(name = "p", type = {Attachment.class, ValueSet.class}, order=1, min=1, max=1, modifier=false, summary=true) * @Child(name = "p", type = {Attachment.class, ValueSet.class}, order=1, min=1, max=1, modifier=false, summary=true)
*/ */
assertNotNull(((Reference) actual.getContent().get(0).getP()).getResource()); assertNotNull(((Reference) actual.getContent().get(0).getP()).getResource());
} }
@ -2134,7 +2145,7 @@ public class XmlParserDstu3Test {
} }
//TODO: this should work // TODO: this should work
@Test @Test
@Ignore @Ignore
public void testParseNarrative() throws Exception { public void testParseNarrative() throws Exception {
@ -2167,7 +2178,7 @@ public class XmlParserDstu3Test {
" </birthDate>\n" + " </birthDate>\n" +
"</Patient>"; "</Patient>";
//@formatter:on //@formatter:on
try { try {
ourCtx.newXmlParser().parseResource(Patient.class, input); ourCtx.newXmlParser().parseResource(Patient.class, input);
fail(); fail();

View File

@ -327,6 +327,11 @@
<![CDATA[<br/><br/>]]> <![CDATA[<br/><br/>]]>
Thanks to Peter Van Houte from Agfa for the amazing work! Thanks to Peter Van Houte from Agfa for the amazing work!
</action> </action>
<action type="fix" issue="312">
Parser failed with a NPE while encoding resources if the
resource contained a null extension. Thanks to
steve1medix for reporting!
</action>
</release> </release>
<release version="1.4" date="2016-02-04"> <release version="1.4" date="2016-02-04">
<action type="add"> <action type="add">