Skip to content

Commit

Permalink
5738: Skip alternate handling if already handled by previous step (#5971
Browse files Browse the repository at this point in the history
)

* 5738: Skip alternate handling if already handled by previous step

* Credit for #5738

---------

Co-authored-by: Stefan Lindström <[email protected]>
Co-authored-by: James Agnew <[email protected]>
  • Loading branch information
3 people committed May 28, 2024
1 parent a9815c8 commit 4ac65da
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 2 deletions.
10 changes: 9 additions & 1 deletion hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -1359,9 +1359,17 @@ private void parseChildren(BaseJsonLikeObject theObject, ParserState<?> theState
String alternateName = keyIter.next();
if (alternateName.startsWith("_") && alternateName.length() > 1) {
BaseJsonLikeValue nextValue = theObject.get(alternateName);
String nextName = alternateName.substring(1);

if (nextValue != null) {
BaseJsonLikeValue nonAlternativeValue = theObject.get(nextName);

// Only alternate values with no corresponding "normal" value is unhandled from previous step.
if (nonAlternativeValue != null) {
continue;
}

if (nextValue.isObject()) {
String nextName = alternateName.substring(1);
if (theObject.get(nextName) == null) {
theState.enteringNewElement(null, nextName);
parseAlternates(nextValue, theState, alternateName, alternateName);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
type: fix
issue: 5971
title: "The JSON Parser failed to parse alternate names (e.g. `_family`) containing extensions if the
corresponding regular named element (e.g. `family`) was not present. Thanks to Stefan Lindström for
the pull request!"
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import org.hl7.fhir.dstu2016may.model.Observation.ObservationStatus;
import org.hl7.fhir.dstu2016may.model.Parameters;
import org.hl7.fhir.dstu2016may.model.Patient;
import org.hl7.fhir.dstu2016may.model.Practitioner;
import org.hl7.fhir.dstu2016may.model.PrimitiveType;
import org.hl7.fhir.dstu2016may.model.Quantity;
import org.hl7.fhir.dstu2016may.model.QuestionnaireResponse;
Expand All @@ -55,6 +56,7 @@
import org.hl7.fhir.dstu2016may.model.StringType;
import org.hl7.fhir.dstu2016may.model.UriType;
import org.hl7.fhir.dstu2016may.model.ValueSet;
import org.hl7.fhir.dstu2016may.model.codesystems.DataAbsentReason;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
Expand All @@ -63,7 +65,6 @@
import org.mockito.ArgumentCaptor;

import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
Expand All @@ -78,6 +79,7 @@
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.stringContainsInOrder;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
Expand Down Expand Up @@ -1901,6 +1903,40 @@ public void testPreCommentsToFhirComments() {
assertEquals(expectedJson, patientString);
}

@Test
public void testObjectWithBothPrimitiverAndArrayAlternatives() {
String resource = "{\n" +
" \"resourceType\": \"Practitioner\",\n" +
" \"id\": \"1\",\n" +
" \"name\": [{\n" +
" \"_family\": {\n" +
" \"extension\": [{\n" +
" \"url\": \"http:https://hl7.org/fhir/StructureDefinition/data-absent-reason\",\n" +
" \"valueString\": \"masked\"\n" +
" }\n" +
" ]\n" +
" },\n" +
" \"given\": [\n" +
" null\n" +
" ],\n" +
" \"_given\": [{\n" +
" \"extension\": [{\n" +
" \"url\": \"http:https://hl7.org/fhir/StructureDefinition/data-absent-reason\",\n" +
" \"valueString\": \"masked\"\n" +
" }\n" +
" ]\n" +
" }\n" +
" ]\n" +
" }\n" +
" ]\n" +
"}\n";
Practitioner practitioner = assertDoesNotThrow(() -> ourCtx.newJsonParser().parseResource(Practitioner.class, resource));
HumanName humanName = practitioner.getName().get(0);
StringType given = humanName.getGiven().get(0);
assertTrue(given.getExtension().stream().allMatch(ext -> DataAbsentReason.MASKED.toCode().equals(ext.getValue().primitiveValue())));
assertTrue(humanName.getFamily().get(0).getExtension().stream().allMatch(ext -> DataAbsentReason.MASKED.toCode().equals(ext.getValue().primitiveValue())));
}

@AfterAll
public static void afterClassClearContext() {
TestUtil.randomizeLocaleAndTimezone();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
import org.hl7.fhir.dstu3.model.Organization;
import org.hl7.fhir.dstu3.model.Parameters;
import org.hl7.fhir.dstu3.model.Patient;
import org.hl7.fhir.dstu3.model.Practitioner;
import org.hl7.fhir.dstu3.model.PrimitiveType;
import org.hl7.fhir.dstu3.model.Quantity;
import org.hl7.fhir.dstu3.model.QuestionnaireResponse;
Expand All @@ -74,6 +75,7 @@
import org.hl7.fhir.dstu3.model.StringType;
import org.hl7.fhir.dstu3.model.UriType;
import org.hl7.fhir.dstu3.model.ValueSet;
import org.hl7.fhir.dstu3.model.codesystems.DataAbsentReason;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
Expand Down Expand Up @@ -101,6 +103,7 @@
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.stringContainsInOrder;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
Expand Down Expand Up @@ -2548,6 +2551,41 @@ public void testPreCommentsToFhirComments() {
assertThat(patientString, is(not(containsString("fhir_comment"))));
}

@Test
public void testObjectWithBothPrimitiverAndArrayAlternatives() {
String resource = "{\n" +
" \"resourceType\": \"Practitioner\",\n" +
" \"id\": \"1\",\n" +
" \"name\": [{\n" +
" \"_family\": {\n" +
" \"extension\": [{\n" +
" \"url\": \"http:https://hl7.org/fhir/StructureDefinition/data-absent-reason\",\n" +
" \"valueString\": \"masked\"\n" +
" }\n" +
" ]\n" +
" },\n" +
" \"given\": [\n" +
" null\n" +
" ],\n" +
" \"_given\": [{\n" +
" \"extension\": [{\n" +
" \"url\": \"http:https://hl7.org/fhir/StructureDefinition/data-absent-reason\",\n" +
" \"valueString\": \"masked\"\n" +
" }\n" +
" ]\n" +
" }\n" +
" ]\n" +
" }\n" +
" ]\n" +
"}\n";
Practitioner practitioner = assertDoesNotThrow(() -> ourCtx.newJsonParser().parseResource(Practitioner.class, resource));
HumanName humanName = practitioner.getName().get(0);
StringType given = humanName.getGiven().get(0);
assertTrue(given.getExtension().stream().allMatch(ext -> DataAbsentReason.MASKED.toCode().equals(ext.getValue().primitiveValue())));
assertTrue(humanName.getFamilyElement().getExtension().stream().allMatch(ext -> DataAbsentReason.MASKED.toCode().equals(ext.getValue().primitiveValue())));
}


@AfterAll
public static void afterClassClearContext() {
TestUtil.randomizeLocaleAndTimezone();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import org.hl7.fhir.r4.model.Reference;
import org.hl7.fhir.r4.model.StringType;
import org.hl7.fhir.r4.model.Type;
import org.hl7.fhir.r4.model.codesystems.DataAbsentReason;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
Expand Down Expand Up @@ -73,6 +74,7 @@
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.stringContainsInOrder;
import static org.hamcrest.core.IsNot.not;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
Expand Down Expand Up @@ -1190,6 +1192,40 @@ public void testEncodeToString_Resource() {
assertEquals(expected, actual);
}

@Test
public void testObjectWithBothPrimitiverAndArrayAlternatives() {
String resource = "{\n" +
" \"resourceType\": \"Practitioner\",\n" +
" \"id\": \"1\",\n" +
" \"name\": [{\n" +
" \"_family\": {\n" +
" \"extension\": [{\n" +
" \"url\": \"http:https://hl7.org/fhir/StructureDefinition/data-absent-reason\",\n" +
" \"valueString\": \"masked\"\n" +
" }\n" +
" ]\n" +
" },\n" +
" \"given\": [\n" +
" null\n" +
" ],\n" +
" \"_given\": [{\n" +
" \"extension\": [{\n" +
" \"url\": \"http:https://hl7.org/fhir/StructureDefinition/data-absent-reason\",\n" +
" \"valueString\": \"masked\"\n" +
" }\n" +
" ]\n" +
" }\n" +
" ]\n" +
" }\n" +
" ]\n" +
"}\n";
Practitioner practitioner = assertDoesNotThrow(() -> ourCtx.newJsonParser().parseResource(Practitioner.class, resource));
HumanName humanName = practitioner.getNameFirstRep();
StringType given = humanName.getGiven().get(0);
assertTrue(given.getExtension().stream().allMatch(ext -> DataAbsentReason.MASKED.toCode().equals(ext.getValue().primitiveValue())));
assertTrue(humanName.getFamilyElement().getExtension().stream().allMatch(ext -> DataAbsentReason.MASKED.toCode().equals(ext.getValue().primitiveValue())));
}

@Test
public void testEncodeToString_GeneralPurposeDataType() {
HumanName name = new HumanName();
Expand Down
5 changes: 5 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -917,6 +917,11 @@
<id>subigre</id>
<name>Renaud Subiger</name>
</developer>
<developer>
<id>stefan-lindstrom</id>
<name>Stefan Lindström</name>
<organization>Softhouse AB</organization>
</developer>
</developers>

<licenses>
Expand Down

0 comments on commit 4ac65da

Please sign in to comment.