From cd6d4302c34c38727265148b04d8b82d6e136b8c Mon Sep 17 00:00:00 2001 From: Diederik Muylwyk Date: Fri, 19 Oct 2018 15:13:51 -0400 Subject: [PATCH 1/6] Incremental work on FhirTerser.getValues(...) enhancements. --- .../java/ca/uhn/fhir/util/FhirTerser.java | 150 +++++++--- .../ca/uhn/fhir/util/FhirTerserDstu3Test.java | 264 ++++++++++++++++-- 2 files changed, 348 insertions(+), 66 deletions(-) diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java index bf8df49e182..082daaf122c 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java @@ -1,36 +1,5 @@ package ca.uhn.fhir.util; -import static org.apache.commons.lang3.StringUtils.defaultString; -import static org.apache.commons.lang3.StringUtils.isBlank; -import static org.apache.commons.lang3.StringUtils.isNotBlank; - -/* - * #%L - * HAPI FHIR - Core Library - * %% - * Copyright (C) 2014 - 2018 University Health Network - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * #L% - */ -import java.util.*; -import java.util.function.Predicate; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.commons.lang3.Validate; -import org.hl7.fhir.instance.model.api.*; - import ca.uhn.fhir.context.*; import ca.uhn.fhir.context.BaseRuntimeElementDefinition.ChildTypeEnum; import ca.uhn.fhir.model.api.ExtensionDt; @@ -40,6 +9,35 @@ import ca.uhn.fhir.model.base.composite.BaseContainedDt; import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt; import ca.uhn.fhir.model.primitive.StringDt; import ca.uhn.fhir.parser.DataFormatException; +import org.apache.commons.lang3.Validate; +import org.hl7.fhir.instance.model.api.*; + +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import static org.apache.commons.lang3.StringUtils.*; + +/* + * #%L + * HAPI FHIR - Core Library + * %% + * Copyright (C) 2014 - 2018 University Health Network + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ public class FhirTerser { @@ -215,8 +213,12 @@ public class FhirTerser { return retVal.get(0); } - @SuppressWarnings("unchecked") private List getValues(BaseRuntimeElementCompositeDefinition theCurrentDef, Object theCurrentObj, List theSubList, Class theWantedClass) { + return getValues(theCurrentDef, theCurrentObj, theSubList, theWantedClass, false); + } + + @SuppressWarnings("unchecked") + private List getValues(BaseRuntimeElementCompositeDefinition theCurrentDef, Object theCurrentObj, List theSubList, Class theWantedClass, boolean theCreate) { String name = theSubList.get(0); List retVal = new ArrayList<>(); @@ -227,14 +229,71 @@ public class FhirTerser { extensionUrl = extensionUrl.substring(0, endIndex); } - List extensions= Collections.emptyList(); + // DSTU2 + List extensionDts = Collections.emptyList(); if (theCurrentObj instanceof ISupportsUndeclaredExtensions) { - extensions = ((ISupportsUndeclaredExtensions) theCurrentObj).getUndeclaredExtensionsByUrl(extensionUrl); + extensionDts = ((ISupportsUndeclaredExtensions) theCurrentObj).getUndeclaredExtensionsByUrl(extensionUrl); + + if (extensionDts.isEmpty() && theCreate) { + // FIXME: Add a new extension with extensionUrl and null value. + // FIXME: Discern between extensions and modifier extensions. + } } else if (theCurrentObj instanceof IBaseExtension) { - extensions = ((IBaseExtension)theCurrentObj).getExtension(); + extensionDts = ((IBaseExtension) theCurrentObj).getExtension(); + + if (extensionDts.isEmpty() && theCreate) { + // FIXME: Add a new extension with extensionUrl and null value. + } } - for (ExtensionDt next : extensions) { + for (ExtensionDt next : extensionDts) { + if (theWantedClass.isAssignableFrom(next.getClass())) { + retVal.add((T) next); + } + } + + // DSTU3+ + final String extensionUrlForLambda = extensionUrl; + List extensions = Collections.emptyList(); + if (theCurrentObj instanceof IBaseHasExtensions) { + extensions = ((IBaseHasExtensions) theCurrentObj).getExtension() + .stream() + .filter(t -> t.getUrl().equals(extensionUrlForLambda)) + .distinct() + .collect(Collectors.toList()); + + if (extensions.isEmpty() && theCreate) { + IBaseExtension extension = ((IBaseHasExtensions) theCurrentObj).addExtension(); + extension.setUrl(extensionUrl); + extensions.add(extension); + } + } +// List modifierExtensions = Collections.emptyList(); +// if (theCurrentObj instanceof IBaseHasModifierExtensions) { +// modifierExtensions = ((IBaseHasModifierExtensions) theCurrentObj).getModifierExtension() +// .stream() +// .filter(t -> t.getUrl().equals(extensionUrlForLambda)) +// .collect(Collectors.toList()); +// +// if (modifierExtensions.isEmpty() && theCreate) { +// IBaseExtension modifierExtension = ((IBaseHasModifierExtensions) theCurrentObj).addModifierExtension(); +// modifierExtension.setUrl(extensionUrl); +// modifierExtensions.add(modifierExtension); +// } +// } +// +// List allExtensions = Stream.of(extensions, modifierExtensions) +// .flatMap(Collection::stream) +// .distinct() +// .collect(Collectors.toList()); +// +// for (IBaseExtension next : allExtensions) { +// if (theWantedClass.isAssignableFrom(next.getClass())) { +// retVal.add((T) next); +// } +// } + + for (IBaseExtension next : extensions) { if (theWantedClass.isAssignableFrom(next.getClass())) { retVal.add((T) next); } @@ -256,6 +315,14 @@ public class FhirTerser { BaseRuntimeChildDefinition nextDef = theCurrentDef.getChildByNameOrThrowDataFormatException(name); List values = nextDef.getAccessor().getValues(theCurrentObj); + if (values.isEmpty() && theCreate) { + IBase value = nextDef.getChildByName(name).newInstance(); + nextDef.getMutator().addValue(theCurrentObj, value); + List list = new ArrayList<>(); + list.add(value); + values = list; + } + if (theSubList.size() == 1) { if (nextDef instanceof RuntimeChildChoiceDefinition) { for (IBase next : values) { @@ -297,7 +364,12 @@ public class FhirTerser { Class wantedClass = Object.class; return getValues(theResource, thePath, wantedClass); + } + public List getValues(IBaseResource theResource, String thePath, boolean theCreate) { + Class wantedClass = Object.class; + + return getValues(theResource, thePath, wantedClass, theCreate); } public List getValues(IBaseResource theResource, String thePath, Class theWantedClass) { @@ -306,6 +378,12 @@ public class FhirTerser { return getValues(def, theResource, parts, theWantedClass); } + public List getValues(IBaseResource theResource, String thePath, Class theWantedClass, boolean theCreate) { + RuntimeResourceDefinition def = myContext.getResourceDefinition(theResource); + List parts = parsePath(def, thePath); + return getValues(def, theResource, parts, theWantedClass, theCreate); + } + private List parsePath(BaseRuntimeElementCompositeDefinition theElementDef, String thePath) { List parts = new ArrayList<>(); diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/util/FhirTerserDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/util/FhirTerserDstu3Test.java index dadc87e9b62..2cdfcba8030 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/util/FhirTerserDstu3Test.java +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/util/FhirTerserDstu3Test.java @@ -1,41 +1,27 @@ package ca.uhn.fhir.util; -import static org.hamcrest.Matchers.containsInAnyOrder; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; +import ca.uhn.fhir.context.BaseRuntimeChildDefinition; +import ca.uhn.fhir.context.BaseRuntimeElementDefinition; +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.parser.DataFormatException; +import org.hl7.fhir.dstu3.model.*; +import org.hl7.fhir.dstu3.model.Patient.LinkType; +import org.hl7.fhir.instance.model.api.IBase; +import org.hl7.fhir.instance.model.api.IBaseExtension; +import org.hl7.fhir.instance.model.api.IBaseReference; +import org.junit.AfterClass; +import org.junit.Test; +import org.mockito.ArgumentCaptor; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; -import org.hl7.fhir.dstu3.model.Bundle; -import org.hl7.fhir.dstu3.model.Extension; -import org.hl7.fhir.dstu3.model.Identifier; -import org.hl7.fhir.dstu3.model.MarkdownType; -import org.hl7.fhir.dstu3.model.Money; -import org.hl7.fhir.dstu3.model.Observation; -import org.hl7.fhir.dstu3.model.Organization; -import org.hl7.fhir.dstu3.model.Patient; -import org.hl7.fhir.dstu3.model.Patient.LinkType; -import org.hl7.fhir.dstu3.model.Quantity; -import org.hl7.fhir.dstu3.model.Reference; -import org.hl7.fhir.dstu3.model.StringType; -import org.hl7.fhir.instance.model.api.IBase; -import org.hl7.fhir.instance.model.api.IBaseReference; -import org.junit.AfterClass; -import org.junit.Test; -import org.mockito.ArgumentCaptor; - -import ca.uhn.fhir.context.BaseRuntimeChildDefinition; -import ca.uhn.fhir.context.BaseRuntimeElementDefinition; -import ca.uhn.fhir.context.FhirContext; -import ca.uhn.fhir.parser.DataFormatException; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.junit.Assert.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class FhirTerserDstu3Test { @@ -183,6 +169,224 @@ public class FhirTerserDstu3Test { assertSame(ref, refs.get(0)); } + @Test + public void testGetValues() { + Patient p = new Patient(); + p.setActive(true); + p.addExtension() + .setUrl("http://acme.org/extension") + .setValue(new StringType("value")); + p.addExtension() + .setUrl("http://acme.org/otherExtension") + .setValue(new StringType("otherValue")); +// p.addModifierExtension() +// .setUrl("http://acme.org/extension") +// .setValue(new StringType("modifierValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + List values = ourCtx.newTerser().getValues(p, "Patient.active"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof PrimitiveType); + assertTrue(values.get(0) instanceof BooleanType); + assertTrue(((BooleanType) values.get(0)).booleanValue()); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof Extension); + assertEquals("http://acme.org/extension", ((Extension) values.get(0)).getUrl()); + assertEquals("value", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); + +// values = ourCtx.newTerser().getValues(p, "Patient.modifierExtension('http://acme.org/extension')"); +// assertEquals(1, values.size()); +// assertTrue(values.get(0) instanceof IBaseExtension); +// assertTrue(values.get(0) instanceof Extension); +// assertEquals("http://acme.org/extension", ((Extension) values.get(0)).getUrl()); +// assertEquals("value", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); + } + + @Test + public void testGetValuesAndModify() { + Patient p = new Patient(); + p.setActive(true); + p.addExtension() + .setUrl("http://acme.org/extension") + .setValue(new StringType("value")); + p.addExtension() + .setUrl("http://acme.org/otherExtension") + .setValue(new StringType("otherValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + List values = ourCtx.newTerser().getValues(p, "Patient.active"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof PrimitiveType); + assertTrue(values.get(0) instanceof BooleanType); + assertTrue(((BooleanType) values.get(0)).booleanValue()); + + ((BooleanType) values.get(0)).setValue(Boolean.FALSE); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + values = ourCtx.newTerser().getValues(p, "Patient.active"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof PrimitiveType); + assertTrue(values.get(0) instanceof BooleanType); + assertFalse(((BooleanType) values.get(0)).booleanValue()); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof Extension); + assertEquals("http://acme.org/extension", ((Extension) values.get(0)).getUrl()); + assertEquals("value", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); + + ((Extension) values.get(0)).setValue(new StringType("modifiedValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof Extension); + assertEquals("http://acme.org/extension", ((Extension) values.get(0)).getUrl()); + assertEquals("modifiedValue", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); + } + + @Test + public void testGetValuesWithWantedClass() { + Patient p = new Patient(); + p.setActive(true); + p.addExtension() + .setUrl("http://acme.org/extension") + .setValue(new StringType("value")); + p.addExtension() + .setUrl("http://acme.org/otherExtension") + .setValue(new StringType("otherValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + List values = ourCtx.newTerser().getValues(p, "Patient.active", PrimitiveType.class); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof BooleanType); + assertTrue(((BooleanType) values.get(0)).booleanValue()); + + List extValues = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')", Extension.class); + assertEquals(1, extValues.size()); + assertTrue(extValues.get(0).getValue() instanceof StringType); + assertEquals("http://acme.org/extension", extValues.get(0).getUrl()); + assertEquals("value", ((StringType) (extValues.get(0).getValue())).getValueAsString()); + } + + @Test + public void testGetValuesWithWantedClassAndModify() { + Patient p = new Patient(); + p.setActive(true); + p.addExtension() + .setUrl("http://acme.org/extension") + .setValue(new StringType("value")); + p.addExtension() + .setUrl("http://acme.org/otherExtension") + .setValue(new StringType("otherValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + List values = ourCtx.newTerser().getValues(p, "Patient.active", PrimitiveType.class); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof BooleanType); + assertTrue(((BooleanType) values.get(0)).booleanValue()); + + ((BooleanType) values.get(0)).setValue(Boolean.FALSE); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + values = ourCtx.newTerser().getValues(p, "Patient.active", PrimitiveType.class); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof BooleanType); + assertFalse(((BooleanType) values.get(0)).booleanValue()); + + List extValues = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')", Extension.class); + assertEquals(1, extValues.size()); + assertTrue(extValues.get(0).getValue() instanceof StringType); + assertEquals("http://acme.org/extension", extValues.get(0).getUrl()); + assertEquals("value", ((StringType) (extValues.get(0).getValue())).getValueAsString()); + + extValues.get(0).setValue(new StringType("modifiedValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + extValues = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')", Extension.class); + assertEquals(1, extValues.size()); + assertTrue(extValues.get(0).getValue() instanceof StringType); + assertEquals("http://acme.org/extension", extValues.get(0).getUrl()); + assertEquals("modifiedValue", ((StringType) (extValues.get(0).getValue())).getValueAsString()); + } + + @Test + public void testGetValuesWithWantedClassAndTheCreate() { + Patient p = new Patient(); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + List values = ourCtx.newTerser().getValues(p, "Patient.active", PrimitiveType.class, true); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof BooleanType); + assertNull(((BooleanType) values.get(0)).getValue()); + + List extValues = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')", Extension.class, true); + assertEquals(1, extValues.size()); + assertEquals("http://acme.org/extension", extValues.get(0).getUrl()); + assertNull(extValues.get(0).getValue()); + } + + @Test + public void testGetValuesWithTheCreate() { + Patient p = new Patient(); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + List values = ourCtx.newTerser().getValues(p, "Patient.active", true); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof PrimitiveType); + assertTrue(values.get(0) instanceof BooleanType); + assertNull(((BooleanType) values.get(0)).getValue()); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')", true); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof Extension); + assertEquals("http://acme.org/extension", ((Extension) values.get(0)).getUrl()); + assertNull(((Extension) values.get(0)).getValue()); + } + + @Test + public void testGetValuesWithTheCreateAndNoOverwrite() { + Patient p = new Patient(); + p.setActive(true); + p.addExtension() + .setUrl("http://acme.org/extension") + .setValue(new StringType("value")); + p.addExtension() + .setUrl("http://acme.org/otherExtension") + .setValue(new StringType("otherValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + List values = ourCtx.newTerser().getValues(p, "Patient.active", true); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof PrimitiveType); + assertTrue(values.get(0) instanceof BooleanType); + assertTrue(((BooleanType) values.get(0)).booleanValue()); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof Extension); + assertEquals("http://acme.org/extension", ((Extension) values.get(0)).getUrl()); + assertEquals("value", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); + } + @Test public void testVisitWithModelVisitor2() { IModelVisitor2 visitor = mock(IModelVisitor2.class); From 225007d681fb1cd45511cfc02d524dc28852a9ac Mon Sep 17 00:00:00 2001 From: Diederik Muylwyk Date: Fri, 19 Oct 2018 18:24:26 -0400 Subject: [PATCH 2/6] Completed work on FhirTerser.getValues(...) enhancements. --- .../java/ca/uhn/fhir/util/FhirTerser.java | 184 +++++++++---- .../ca/uhn/fhir/util/FhirTerserDstu2Test.java | 245 ++++++++++++++++-- .../ca/uhn/fhir/util/FhirTerserDstu3Test.java | 133 +++++++++- 3 files changed, 481 insertions(+), 81 deletions(-) diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java index 082daaf122c..44550187d2b 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java @@ -230,72 +230,100 @@ public class FhirTerser { } // DSTU2 - List extensionDts = Collections.emptyList(); - if (theCurrentObj instanceof ISupportsUndeclaredExtensions) { - extensionDts = ((ISupportsUndeclaredExtensions) theCurrentObj).getUndeclaredExtensionsByUrl(extensionUrl); + if (myContext.getVersion().getVersion().isOlderThan(FhirVersionEnum.DSTU3)) { + List extensionDts = Collections.emptyList(); + if (theCurrentObj instanceof ISupportsUndeclaredExtensions) { + extensionDts = ((ISupportsUndeclaredExtensions) theCurrentObj).getUndeclaredExtensionsByUrl(extensionUrl); - if (extensionDts.isEmpty() && theCreate) { - // FIXME: Add a new extension with extensionUrl and null value. - // FIXME: Discern between extensions and modifier extensions. + if (extensionDts.isEmpty() && theCreate) { + // We assume the extension is not a modifier extension. + extensionDts = new ArrayList<>(); // Implementation of ISupportsUndeclaredExtensions.getUndeclaredExtensionsByUrl(...) returns unmodifiable list. + ExtensionDt extensionDt = ((ISupportsUndeclaredExtensions) theCurrentObj).addUndeclaredExtension(false, extensionUrl); + extensionDts.add(extensionDt); + } + } else if (theCurrentObj instanceof IBaseExtension) { + extensionDts = ((IBaseExtension) theCurrentObj).getExtension(); + + if (extensionDts.isEmpty() && theCreate) { + // We assume the extension is not a modifier extension. + ExtensionDt extensionDt = new ExtensionDt(); + extensionDt.setUrl(extensionUrl); + ((IBaseExtension) theCurrentObj).getExtension().add(extensionDt); + extensionDts.add(extensionDt); + } } - } else if (theCurrentObj instanceof IBaseExtension) { - extensionDts = ((IBaseExtension) theCurrentObj).getExtension(); - if (extensionDts.isEmpty() && theCreate) { - // FIXME: Add a new extension with extensionUrl and null value. + for (ExtensionDt next : extensionDts) { + if (theWantedClass.isAssignableFrom(next.getClass())) { + retVal.add((T) next); + } + } + } else { + // DSTU3+ + final String extensionUrlForLambda = extensionUrl; + List extensions = Collections.emptyList(); + if (theCurrentObj instanceof IBaseHasExtensions) { + extensions = ((IBaseHasExtensions) theCurrentObj).getExtension() + .stream() + .filter(t -> t.getUrl().equals(extensionUrlForLambda)) + .collect(Collectors.toList()); + + if (extensions.isEmpty() && theCreate) { + IBaseExtension extension = ((IBaseHasExtensions) theCurrentObj).addExtension(); + extension.setUrl(extensionUrl); + extensions.add(extension); + } + } + + for (IBaseExtension next : extensions) { + if (theWantedClass.isAssignableFrom(next.getClass())) { + retVal.add((T) next); + } } } - for (ExtensionDt next : extensionDts) { - if (theWantedClass.isAssignableFrom(next.getClass())) { - retVal.add((T) next); + if (theSubList.size() > 1) { + List values = retVal; + retVal = new ArrayList<>(); + for (T nextElement : values) { + BaseRuntimeElementCompositeDefinition nextChildDef = (BaseRuntimeElementCompositeDefinition) myContext.getElementDefinition((Class) nextElement.getClass()); + List foundValues = getValues(nextChildDef, nextElement, theSubList.subList(1, theSubList.size()), theWantedClass); + retVal.addAll(foundValues); } } + return retVal; + } + + if (name.startsWith("modifierExtension('")) { + String extensionUrl = name.substring("modifierExtension('".length()); + int endIndex = extensionUrl.indexOf('\''); + if (endIndex != -1) { + extensionUrl = extensionUrl.substring(0, endIndex); + } + // DSTU3+ - final String extensionUrlForLambda = extensionUrl; - List extensions = Collections.emptyList(); - if (theCurrentObj instanceof IBaseHasExtensions) { - extensions = ((IBaseHasExtensions) theCurrentObj).getExtension() - .stream() - .filter(t -> t.getUrl().equals(extensionUrlForLambda)) - .distinct() - .collect(Collectors.toList()); + if (myContext.getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.DSTU3)) { + final String extensionUrlForLambda = extensionUrl; + List extensions = Collections.emptyList(); - if (extensions.isEmpty() && theCreate) { - IBaseExtension extension = ((IBaseHasExtensions) theCurrentObj).addExtension(); - extension.setUrl(extensionUrl); - extensions.add(extension); + if (theCurrentObj instanceof IBaseHasModifierExtensions) { + extensions = ((IBaseHasModifierExtensions) theCurrentObj).getModifierExtension() + .stream() + .filter(t -> t.getUrl().equals(extensionUrlForLambda)) + .collect(Collectors.toList()); + + if (extensions.isEmpty() && theCreate) { + IBaseExtension modifierExtension = ((IBaseHasModifierExtensions) theCurrentObj).addModifierExtension(); + modifierExtension.setUrl(extensionUrl); + extensions.add(modifierExtension); + } } - } -// List modifierExtensions = Collections.emptyList(); -// if (theCurrentObj instanceof IBaseHasModifierExtensions) { -// modifierExtensions = ((IBaseHasModifierExtensions) theCurrentObj).getModifierExtension() -// .stream() -// .filter(t -> t.getUrl().equals(extensionUrlForLambda)) -// .collect(Collectors.toList()); -// -// if (modifierExtensions.isEmpty() && theCreate) { -// IBaseExtension modifierExtension = ((IBaseHasModifierExtensions) theCurrentObj).addModifierExtension(); -// modifierExtension.setUrl(extensionUrl); -// modifierExtensions.add(modifierExtension); -// } -// } -// -// List allExtensions = Stream.of(extensions, modifierExtensions) -// .flatMap(Collection::stream) -// .distinct() -// .collect(Collectors.toList()); -// -// for (IBaseExtension next : allExtensions) { -// if (theWantedClass.isAssignableFrom(next.getClass())) { -// retVal.add((T) next); -// } -// } - for (IBaseExtension next : extensions) { - if (theWantedClass.isAssignableFrom(next.getClass())) { - retVal.add((T) next); + for (IBaseExtension next : extensions) { + if (theWantedClass.isAssignableFrom(next.getClass())) { + retVal.add((T) next); + } } } @@ -360,24 +388,74 @@ public class FhirTerser { return retVal; } + /** + * Returns values stored in an element identified by its path. The list of values is of + * type {@link Object}. + * + *

Note: this method does not support creation of null-valued modifier extensions for + * versions of FHIR prior to DSTU3.

+ * + * @param theResource The resource instance to be accessed. Must not be null. + * @param thePath The path for the element to be accessed. + * @return A list of values of type {@link Object}. + */ public List getValues(IBaseResource theResource, String thePath) { Class wantedClass = Object.class; return getValues(theResource, thePath, wantedClass); } + /** + * Returns values stored in an element identified by its path. The list of values is of + * type {@link Object}. + * + *

Note: this method does not support creation of null-valued modifier extensions for + * versions of FHIR prior to DSTU3.

+ * + * @param theResource The resource instance to be accessed. Must not be null. + * @param thePath The path for the element to be accessed. + * @param theCreate When set to true, the terser will create a null-valued element where none exists. + * @return A list of values of type {@link Object}. + */ public List getValues(IBaseResource theResource, String thePath, boolean theCreate) { Class wantedClass = Object.class; return getValues(theResource, thePath, wantedClass, theCreate); } + /** + * Returns values stored in an element identified by its path. The list of values is of + * type theWantedClass. + * + *

Note: this method does not support creation of null-valued modifier extensions for + * versions of FHIR prior to DSTU3.

+ * + * @param theResource The resource instance to be accessed. Must not be null. + * @param thePath The path for the element to be accessed. + * @param theWantedClass The desired class to be returned in a list. + * @param Type declared by theWantedClass + * @return A list of values of type theWantedClass. + */ public List getValues(IBaseResource theResource, String thePath, Class theWantedClass) { RuntimeResourceDefinition def = myContext.getResourceDefinition(theResource); List parts = parsePath(def, thePath); return getValues(def, theResource, parts, theWantedClass); } + /** + * Returns values stored in an element identified by its path. The list of values is of + * type theWantedClass. + * + *

Note: this method does not support creation of null-valued modifier extensions for + * versions of FHIR prior to DSTU3.

+ * + * @param theResource The resource instance to be accessed. Must not be null. + * @param thePath The path for the element to be accessed. + * @param theWantedClass The desired class to be returned in a list. + * @param theCreate When set to true, the terser will create a null-valued element where none exists. + * @param Type declared by theWantedClass + * @return A list of values of type theWantedClass. + */ public List getValues(IBaseResource theResource, String thePath, Class theWantedClass, boolean theCreate) { RuntimeResourceDefinition def = myContext.getResourceDefinition(theResource); List parts = parsePath(def, thePath); diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/util/FhirTerserDstu2Test.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/util/FhirTerserDstu2Test.java index d4816152d0a..0139b2d6b13 100644 --- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/util/FhirTerserDstu2Test.java +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/util/FhirTerserDstu2Test.java @@ -1,24 +1,5 @@ package ca.uhn.fhir.util; -import static org.hamcrest.Matchers.containsInAnyOrder; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.List; - -import org.hl7.fhir.instance.model.api.IBase; -import org.hl7.fhir.instance.model.api.IBaseReference; -import org.junit.AfterClass; -import org.junit.Test; -import org.mockito.ArgumentCaptor; - import ca.uhn.fhir.context.BaseRuntimeChildDefinition; import ca.uhn.fhir.context.BaseRuntimeElementDefinition; import ca.uhn.fhir.context.FhirContext; @@ -31,9 +12,26 @@ import ca.uhn.fhir.model.dstu2.resource.Bundle; import ca.uhn.fhir.model.dstu2.resource.Observation; import ca.uhn.fhir.model.dstu2.resource.Organization; import ca.uhn.fhir.model.dstu2.resource.Patient; +import ca.uhn.fhir.model.primitive.BooleanDt; import ca.uhn.fhir.model.primitive.MarkdownDt; import ca.uhn.fhir.model.primitive.StringDt; import ca.uhn.fhir.parser.DataFormatException; +import org.hl7.fhir.instance.model.api.IBase; +import org.hl7.fhir.instance.model.api.IBaseExtension; +import org.hl7.fhir.instance.model.api.IBaseReference; +import org.hl7.fhir.instance.model.api.IPrimitiveType; +import org.junit.AfterClass; +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.List; + +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.junit.Assert.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class FhirTerserDstu2Test { @@ -180,6 +178,215 @@ public class FhirTerserDstu2Test { assertEquals(1, refs.size()); assertSame(ref, refs.get(0)); } + + @Test + public void testGetValues() { + Patient p = new Patient(); + p.setActive(true); + p.addUndeclaredExtension(false, "http://acme.org/extension", new StringDt("value")); + p.addUndeclaredExtension(false, "http://acme.org/otherExtension", new StringDt("otherValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + List values = ourCtx.newTerser().getValues(p, "Patient.active"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IPrimitiveType); + assertTrue(values.get(0) instanceof BooleanDt); + assertTrue(((BooleanDt) values.get(0)).getValue()); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof ExtensionDt); + assertEquals("http://acme.org/extension", ((ExtensionDt) values.get(0)).getUrl()); + assertEquals("value", ((StringDt) ((ExtensionDt) values.get(0)).getValue()).getValueAsString()); + } + + @Test + public void testGetValuesAndModify() { + Patient p = new Patient(); + p.setActive(true); + p.addUndeclaredExtension(false, "http://acme.org/extension", new StringDt("value")); + p.addUndeclaredExtension(false, "http://acme.org/otherExtension", new StringDt("otherValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + List values = ourCtx.newTerser().getValues(p, "Patient.active"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IPrimitiveType); + assertTrue(values.get(0) instanceof BooleanDt); + assertTrue(((BooleanDt) values.get(0)).getValue()); + + ((BooleanDt) values.get(0)).setValue(Boolean.FALSE); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + values = ourCtx.newTerser().getValues(p, "Patient.active"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IPrimitiveType); + assertTrue(values.get(0) instanceof BooleanDt); + assertFalse(((BooleanDt) values.get(0)).getValue()); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof ExtensionDt); + assertEquals("http://acme.org/extension", ((ExtensionDt) values.get(0)).getUrl()); + assertEquals("value", ((StringDt) ((ExtensionDt) values.get(0)).getValue()).getValueAsString()); + + ((ExtensionDt) values.get(0)).setValue(new StringDt("modifiedValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof ExtensionDt); + assertEquals("http://acme.org/extension", ((ExtensionDt) values.get(0)).getUrl()); + assertEquals("modifiedValue", ((StringDt) ((ExtensionDt) values.get(0)).getValue()).getValueAsString()); + } + + @Test + public void testGetValuesMultiple() { + Patient p = new Patient(); + p.addUndeclaredExtension(false, "http://acme.org/extension", new StringDt("value1")); + p.addUndeclaredExtension(false, "http://acme.org/extension", new StringDt("value2")); + p.addUndeclaredExtension(false, "http://acme.org/otherExtension", new StringDt("otherValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + List values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')"); + assertEquals(2, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof ExtensionDt); + assertEquals("http://acme.org/extension", ((ExtensionDt) values.get(0)).getUrl()); + assertEquals("value1", ((StringDt) ((ExtensionDt) values.get(0)).getValue()).getValueAsString()); + assertTrue(values.get(1) instanceof IBaseExtension); + assertTrue(values.get(1) instanceof ExtensionDt); + assertEquals("http://acme.org/extension", ((ExtensionDt) values.get(1)).getUrl()); + assertEquals("value2", ((StringDt) ((ExtensionDt) values.get(1)).getValue()).getValueAsString()); + } + + @Test + public void testGetValuesWithWantedClass() { + Patient p = new Patient(); + p.setActive(true); + p.addUndeclaredExtension(false, "http://acme.org/extension", new StringDt("value")); + p.addUndeclaredExtension(false, "http://acme.org/otherExtension", new StringDt("otherValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + List values = ourCtx.newTerser().getValues(p, "Patient.active", IPrimitiveType.class); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof BooleanDt); + assertTrue(((BooleanDt) values.get(0)).getValue()); + + List extValues = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')", ExtensionDt.class); + assertEquals(1, extValues.size()); + assertTrue(extValues.get(0).getValue() instanceof StringDt); + assertEquals("http://acme.org/extension", extValues.get(0).getUrl()); + assertEquals("value", ((StringDt) (extValues.get(0).getValue())).getValueAsString()); + } + + @Test + public void testGetValuesWithWantedClassAndModify() { + Patient p = new Patient(); + p.setActive(true); + p.addUndeclaredExtension(false, "http://acme.org/extension", new StringDt("value")); + p.addUndeclaredExtension(false, "http://acme.org/otherExtension", new StringDt("otherValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + List values = ourCtx.newTerser().getValues(p, "Patient.active", IPrimitiveType.class); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof BooleanDt); + assertTrue(((BooleanDt) values.get(0)).getValue()); + + ((BooleanDt) values.get(0)).setValue(Boolean.FALSE); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + values = ourCtx.newTerser().getValues(p, "Patient.active", IPrimitiveType.class); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof BooleanDt); + assertFalse(((BooleanDt) values.get(0)).getValue()); + + List extValues = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')", ExtensionDt.class); + assertEquals(1, extValues.size()); + assertTrue(extValues.get(0).getValue() instanceof StringDt); + assertEquals("http://acme.org/extension", extValues.get(0).getUrl()); + assertEquals("value", ((StringDt) (extValues.get(0).getValue())).getValueAsString()); + + extValues.get(0).setValue(new StringDt("modifiedValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + extValues = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')", ExtensionDt.class); + assertEquals(1, extValues.size()); + assertTrue(extValues.get(0).getValue() instanceof StringDt); + assertEquals("http://acme.org/extension", extValues.get(0).getUrl()); + assertEquals("modifiedValue", ((StringDt) (extValues.get(0).getValue())).getValueAsString()); + } + + @Test + public void testGetValuesWithWantedClassAndTheCreate() { + Patient p = new Patient(); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + List values = ourCtx.newTerser().getValues(p, "Patient.active", IPrimitiveType.class, true); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof BooleanDt); + assertNull(((BooleanDt) values.get(0)).getValue()); + + List extValues = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')", ExtensionDt.class, true); + assertEquals(1, extValues.size()); + assertEquals("http://acme.org/extension", extValues.get(0).getUrl()); + assertNull(extValues.get(0).getValue()); + } + + @Test + public void testGetValuesWithTheCreate() { + Patient p = new Patient(); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + List values = ourCtx.newTerser().getValues(p, "Patient.active", true); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IPrimitiveType); + assertTrue(values.get(0) instanceof BooleanDt); + assertNull(((BooleanDt) values.get(0)).getValue()); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')", true); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof ExtensionDt); + assertEquals("http://acme.org/extension", ((ExtensionDt) values.get(0)).getUrl()); + assertNull(((ExtensionDt) values.get(0)).getValue()); + } + + @Test + public void testGetValuesWithTheCreateAndNoOverwrite() { + Patient p = new Patient(); + p.setActive(true); + p.addUndeclaredExtension(false, "http://acme.org/extension", new StringDt("value")); + p.addUndeclaredExtension(false, "http://acme.org/otherExtension", new StringDt("otherValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + List values = ourCtx.newTerser().getValues(p, "Patient.active", true); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IPrimitiveType); + assertTrue(values.get(0) instanceof BooleanDt); + assertTrue(((BooleanDt) values.get(0)).getValue()); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof ExtensionDt); + assertEquals("http://acme.org/extension", ((ExtensionDt) values.get(0)).getUrl()); + assertEquals("value", ((StringDt) ((ExtensionDt) values.get(0)).getValue()).getValueAsString()); + } @Test public void testVisitWithModelVisitor2() { diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/util/FhirTerserDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/util/FhirTerserDstu3Test.java index 2cdfcba8030..bf0ffde4ee0 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/util/FhirTerserDstu3Test.java +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/util/FhirTerserDstu3Test.java @@ -179,9 +179,9 @@ public class FhirTerserDstu3Test { p.addExtension() .setUrl("http://acme.org/otherExtension") .setValue(new StringType("otherValue")); -// p.addModifierExtension() -// .setUrl("http://acme.org/extension") -// .setValue(new StringType("modifierValue")); + p.addModifierExtension() + .setUrl("http://acme.org/modifierExtension") + .setValue(new StringType("modifierValue")); System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); @@ -198,12 +198,12 @@ public class FhirTerserDstu3Test { assertEquals("http://acme.org/extension", ((Extension) values.get(0)).getUrl()); assertEquals("value", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); -// values = ourCtx.newTerser().getValues(p, "Patient.modifierExtension('http://acme.org/extension')"); -// assertEquals(1, values.size()); -// assertTrue(values.get(0) instanceof IBaseExtension); -// assertTrue(values.get(0) instanceof Extension); -// assertEquals("http://acme.org/extension", ((Extension) values.get(0)).getUrl()); -// assertEquals("value", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); + values = ourCtx.newTerser().getValues(p, "Patient.modifierExtension('http://acme.org/modifierExtension')"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof Extension); + assertEquals("http://acme.org/modifierExtension", ((Extension) values.get(0)).getUrl()); + assertEquals("modifierValue", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); } @Test @@ -216,6 +216,9 @@ public class FhirTerserDstu3Test { p.addExtension() .setUrl("http://acme.org/otherExtension") .setValue(new StringType("otherValue")); + p.addModifierExtension() + .setUrl("http://acme.org/modifierExtension") + .setValue(new StringType("modifierValue")); System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); @@ -252,6 +255,68 @@ public class FhirTerserDstu3Test { assertTrue(values.get(0) instanceof Extension); assertEquals("http://acme.org/extension", ((Extension) values.get(0)).getUrl()); assertEquals("modifiedValue", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); + + values = ourCtx.newTerser().getValues(p, "Patient.modifierExtension('http://acme.org/modifierExtension')"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof Extension); + assertEquals("http://acme.org/modifierExtension", ((Extension) values.get(0)).getUrl()); + assertEquals("modifierValue", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); + + ((Extension) values.get(0)).setValue(new StringType("modifiedModifierValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + values = ourCtx.newTerser().getValues(p, "Patient.modifierExtension('http://acme.org/modifierExtension')"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof Extension); + assertEquals("http://acme.org/modifierExtension", ((Extension) values.get(0)).getUrl()); + assertEquals("modifiedModifierValue", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); + } + + @Test + public void testGetValuesMultiple() { + Patient p = new Patient(); + p.addExtension() + .setUrl("http://acme.org/extension") + .setValue(new StringType("value1")); + p.addExtension() + .setUrl("http://acme.org/extension") + .setValue(new StringType("value2")); + p.addExtension() + .setUrl("http://acme.org/otherExtension") + .setValue(new StringType("otherValue")); + p.addModifierExtension() + .setUrl("http://acme.org/modifierExtension") + .setValue(new StringType("modifierValue1")); + p.addModifierExtension() + .setUrl("http://acme.org/modifierExtension") + .setValue(new StringType("modifierValue2")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + List values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')"); + assertEquals(2, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof Extension); + assertEquals("http://acme.org/extension", ((Extension) values.get(0)).getUrl()); + assertEquals("value1", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); + assertTrue(values.get(1) instanceof IBaseExtension); + assertTrue(values.get(1) instanceof Extension); + assertEquals("http://acme.org/extension", ((Extension) values.get(1)).getUrl()); + assertEquals("value2", ((StringType) ((Extension) values.get(1)).getValue()).getValueAsString()); + + values = ourCtx.newTerser().getValues(p, "Patient.modifierExtension('http://acme.org/modifierExtension')"); + assertEquals(2, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof Extension); + assertEquals("http://acme.org/modifierExtension", ((Extension) values.get(0)).getUrl()); + assertEquals("modifierValue1", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); + assertTrue(values.get(1) instanceof IBaseExtension); + assertTrue(values.get(1) instanceof Extension); + assertEquals("http://acme.org/modifierExtension", ((Extension) values.get(1)).getUrl()); + assertEquals("modifierValue2", ((StringType) ((Extension) values.get(1)).getValue()).getValueAsString()); } @Test @@ -264,6 +329,9 @@ public class FhirTerserDstu3Test { p.addExtension() .setUrl("http://acme.org/otherExtension") .setValue(new StringType("otherValue")); + p.addModifierExtension() + .setUrl("http://acme.org/modifierExtension") + .setValue(new StringType("modifierValue")); System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); @@ -277,6 +345,12 @@ public class FhirTerserDstu3Test { assertTrue(extValues.get(0).getValue() instanceof StringType); assertEquals("http://acme.org/extension", extValues.get(0).getUrl()); assertEquals("value", ((StringType) (extValues.get(0).getValue())).getValueAsString()); + + extValues = ourCtx.newTerser().getValues(p, "Patient.modifierExtension('http://acme.org/modifierExtension')", Extension.class); + assertEquals(1, extValues.size()); + assertTrue(extValues.get(0).getValue() instanceof StringType); + assertEquals("http://acme.org/modifierExtension", extValues.get(0).getUrl()); + assertEquals("modifierValue", ((StringType) (extValues.get(0).getValue())).getValueAsString()); } @Test @@ -289,6 +363,9 @@ public class FhirTerserDstu3Test { p.addExtension() .setUrl("http://acme.org/otherExtension") .setValue(new StringType("otherValue")); + p.addModifierExtension() + .setUrl("http://acme.org/modifierExtension") + .setValue(new StringType("modifierValue")); System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); @@ -321,6 +398,22 @@ public class FhirTerserDstu3Test { assertTrue(extValues.get(0).getValue() instanceof StringType); assertEquals("http://acme.org/extension", extValues.get(0).getUrl()); assertEquals("modifiedValue", ((StringType) (extValues.get(0).getValue())).getValueAsString()); + + extValues = ourCtx.newTerser().getValues(p, "Patient.modifierExtension('http://acme.org/modifierExtension')", Extension.class); + assertEquals(1, extValues.size()); + assertTrue(extValues.get(0).getValue() instanceof StringType); + assertEquals("http://acme.org/modifierExtension", extValues.get(0).getUrl()); + assertEquals("modifierValue", ((StringType) (extValues.get(0).getValue())).getValueAsString()); + + extValues.get(0).setValue(new StringType("modifiedModifierValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + extValues = ourCtx.newTerser().getValues(p, "Patient.modifierExtension('http://acme.org/modifierExtension')", Extension.class); + assertEquals(1, extValues.size()); + assertTrue(extValues.get(0).getValue() instanceof StringType); + assertEquals("http://acme.org/modifierExtension", extValues.get(0).getUrl()); + assertEquals("modifiedModifierValue", ((StringType) (extValues.get(0).getValue())).getValueAsString()); } @Test @@ -338,6 +431,11 @@ public class FhirTerserDstu3Test { assertEquals(1, extValues.size()); assertEquals("http://acme.org/extension", extValues.get(0).getUrl()); assertNull(extValues.get(0).getValue()); + + extValues = ourCtx.newTerser().getValues(p, "Patient.modifierExtension('http://acme.org/modifierExtension')", Extension.class, true); + assertEquals(1, extValues.size()); + assertEquals("http://acme.org/modifierExtension", extValues.get(0).getUrl()); + assertNull(extValues.get(0).getValue()); } @Test @@ -358,6 +456,13 @@ public class FhirTerserDstu3Test { assertTrue(values.get(0) instanceof Extension); assertEquals("http://acme.org/extension", ((Extension) values.get(0)).getUrl()); assertNull(((Extension) values.get(0)).getValue()); + + values = ourCtx.newTerser().getValues(p, "Patient.modifierExtension('http://acme.org/modifierExtension')", true); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof Extension); + assertEquals("http://acme.org/modifierExtension", ((Extension) values.get(0)).getUrl()); + assertNull(((Extension) values.get(0)).getValue()); } @Test @@ -370,6 +475,9 @@ public class FhirTerserDstu3Test { p.addExtension() .setUrl("http://acme.org/otherExtension") .setValue(new StringType("otherValue")); + p.addModifierExtension() + .setUrl("http://acme.org/modifierExtension") + .setValue(new StringType("modifierValue")); System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); @@ -385,6 +493,13 @@ public class FhirTerserDstu3Test { assertTrue(values.get(0) instanceof Extension); assertEquals("http://acme.org/extension", ((Extension) values.get(0)).getUrl()); assertEquals("value", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); + + values = ourCtx.newTerser().getValues(p, "Patient.modifierExtension('http://acme.org/modifierExtension')"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof Extension); + assertEquals("http://acme.org/modifierExtension", ((Extension) values.get(0)).getUrl()); + assertEquals("modifierValue", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); } @Test From 688e159493b16bf290a1cb6c2fe6284645862f4f Mon Sep 17 00:00:00 2001 From: Diederik Muylwyk Date: Mon, 22 Oct 2018 18:22:03 -0400 Subject: [PATCH 3/6] Additional work on FhirTerser.getValues(...) enhancements. --- .../java/ca/uhn/fhir/util/FhirTerser.java | 6 +- .../ca/uhn/fhir/util/FhirTerserDstu2Test.java | 88 ++++++++++++- .../ca/uhn/fhir/util/FhirTerserDstu3Test.java | 121 +++++++++++++++++- 3 files changed, 208 insertions(+), 7 deletions(-) diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java index 44550187d2b..ca32e26447c 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java @@ -287,7 +287,7 @@ public class FhirTerser { retVal = new ArrayList<>(); for (T nextElement : values) { BaseRuntimeElementCompositeDefinition nextChildDef = (BaseRuntimeElementCompositeDefinition) myContext.getElementDefinition((Class) nextElement.getClass()); - List foundValues = getValues(nextChildDef, nextElement, theSubList.subList(1, theSubList.size()), theWantedClass); + List foundValues = getValues(nextChildDef, nextElement, theSubList.subList(1, theSubList.size()), theWantedClass, theCreate); retVal.addAll(foundValues); } } @@ -332,7 +332,7 @@ public class FhirTerser { retVal = new ArrayList<>(); for (T nextElement : values) { BaseRuntimeElementCompositeDefinition nextChildDef = (BaseRuntimeElementCompositeDefinition) myContext.getElementDefinition((Class) nextElement.getClass()); - List foundValues = getValues(nextChildDef, nextElement, theSubList.subList(1, theSubList.size()), theWantedClass); + List foundValues = getValues(nextChildDef, nextElement, theSubList.subList(1, theSubList.size()), theWantedClass, theCreate); retVal.addAll(foundValues); } } @@ -381,7 +381,7 @@ public class FhirTerser { } else { for (IBase nextElement : values) { BaseRuntimeElementCompositeDefinition nextChildDef = (BaseRuntimeElementCompositeDefinition) myContext.getElementDefinition(nextElement.getClass()); - List foundValues = getValues(nextChildDef, nextElement, theSubList.subList(1, theSubList.size()), theWantedClass); + List foundValues = getValues(nextChildDef, nextElement, theSubList.subList(1, theSubList.size()), theWantedClass, theCreate); retVal.addAll(foundValues); } } diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/util/FhirTerserDstu2Test.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/util/FhirTerserDstu2Test.java index 0139b2d6b13..e66eabdc9cd 100644 --- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/util/FhirTerserDstu2Test.java +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/util/FhirTerserDstu2Test.java @@ -185,6 +185,7 @@ public class FhirTerserDstu2Test { p.setActive(true); p.addUndeclaredExtension(false, "http://acme.org/extension", new StringDt("value")); p.addUndeclaredExtension(false, "http://acme.org/otherExtension", new StringDt("otherValue")); + p.addUndeclaredExtension(false, "http://acme.org/parentExtension").addUndeclaredExtension(false, "http://acme.org/childExtension", new StringDt("nestedValue")); System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); @@ -200,6 +201,13 @@ public class FhirTerserDstu2Test { assertTrue(values.get(0) instanceof ExtensionDt); assertEquals("http://acme.org/extension", ((ExtensionDt) values.get(0)).getUrl()); assertEquals("value", ((StringDt) ((ExtensionDt) values.get(0)).getValue()).getValueAsString()); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof ExtensionDt); + assertEquals("http://acme.org/childExtension", ((ExtensionDt) values.get(0)).getUrl()); + assertEquals("nestedValue", ((StringDt) ((ExtensionDt) values.get(0)).getValue()).getValueAsString()); } @Test @@ -208,6 +216,7 @@ public class FhirTerserDstu2Test { p.setActive(true); p.addUndeclaredExtension(false, "http://acme.org/extension", new StringDt("value")); p.addUndeclaredExtension(false, "http://acme.org/otherExtension", new StringDt("otherValue")); + p.addUndeclaredExtension(false, "http://acme.org/parentExtension").addUndeclaredExtension(false, "http://acme.org/childExtension", new StringDt("nestedValue")); System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); @@ -244,6 +253,24 @@ public class FhirTerserDstu2Test { assertTrue(values.get(0) instanceof ExtensionDt); assertEquals("http://acme.org/extension", ((ExtensionDt) values.get(0)).getUrl()); assertEquals("modifiedValue", ((StringDt) ((ExtensionDt) values.get(0)).getValue()).getValueAsString()); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof ExtensionDt); + assertEquals("http://acme.org/childExtension", ((ExtensionDt) values.get(0)).getUrl()); + assertEquals("nestedValue", ((StringDt) ((ExtensionDt) values.get(0)).getValue()).getValueAsString()); + + ((ExtensionDt) values.get(0)).setValue(new StringDt("modifiedNestedValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof ExtensionDt); + assertEquals("http://acme.org/childExtension", ((ExtensionDt) values.get(0)).getUrl()); + assertEquals("modifiedNestedValue", ((StringDt) ((ExtensionDt) values.get(0)).getValue()).getValueAsString()); } @Test @@ -252,6 +279,8 @@ public class FhirTerserDstu2Test { p.addUndeclaredExtension(false, "http://acme.org/extension", new StringDt("value1")); p.addUndeclaredExtension(false, "http://acme.org/extension", new StringDt("value2")); p.addUndeclaredExtension(false, "http://acme.org/otherExtension", new StringDt("otherValue")); + p.addUndeclaredExtension(false, "http://acme.org/parentExtension").addUndeclaredExtension(false, "http://acme.org/childExtension", new StringDt("nestedValue1")); + p.addUndeclaredExtension(false, "http://acme.org/parentExtension").addUndeclaredExtension(false, "http://acme.org/childExtension", new StringDt("nestedValue2")); System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); @@ -265,6 +294,17 @@ public class FhirTerserDstu2Test { assertTrue(values.get(1) instanceof ExtensionDt); assertEquals("http://acme.org/extension", ((ExtensionDt) values.get(1)).getUrl()); assertEquals("value2", ((StringDt) ((ExtensionDt) values.get(1)).getValue()).getValueAsString()); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')"); + assertEquals(2, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof ExtensionDt); + assertEquals("http://acme.org/childExtension", ((ExtensionDt) values.get(0)).getUrl()); + assertEquals("nestedValue1", ((StringDt) ((ExtensionDt) values.get(0)).getValue()).getValueAsString()); + assertTrue(values.get(1) instanceof IBaseExtension); + assertTrue(values.get(1) instanceof ExtensionDt); + assertEquals("http://acme.org/childExtension", ((ExtensionDt) values.get(1)).getUrl()); + assertEquals("nestedValue2", ((StringDt) ((ExtensionDt) values.get(1)).getValue()).getValueAsString()); } @Test @@ -273,6 +313,7 @@ public class FhirTerserDstu2Test { p.setActive(true); p.addUndeclaredExtension(false, "http://acme.org/extension", new StringDt("value")); p.addUndeclaredExtension(false, "http://acme.org/otherExtension", new StringDt("otherValue")); + p.addUndeclaredExtension(false, "http://acme.org/parentExtension").addUndeclaredExtension(false, "http://acme.org/childExtension", new StringDt("nestedValue")); System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); @@ -285,7 +326,13 @@ public class FhirTerserDstu2Test { assertEquals(1, extValues.size()); assertTrue(extValues.get(0).getValue() instanceof StringDt); assertEquals("http://acme.org/extension", extValues.get(0).getUrl()); - assertEquals("value", ((StringDt) (extValues.get(0).getValue())).getValueAsString()); + assertEquals("value", ((StringDt) extValues.get(0).getValue()).getValueAsString()); + + extValues = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')", ExtensionDt.class); + assertEquals(1, extValues.size()); + assertTrue(extValues.get(0).getValue() instanceof StringDt); + assertEquals("http://acme.org/childExtension", extValues.get(0).getUrl()); + assertEquals("nestedValue", ((StringDt) extValues.get(0).getValue()).getValueAsString()); } @Test @@ -294,6 +341,7 @@ public class FhirTerserDstu2Test { p.setActive(true); p.addUndeclaredExtension(false, "http://acme.org/extension", new StringDt("value")); p.addUndeclaredExtension(false, "http://acme.org/otherExtension", new StringDt("otherValue")); + p.addUndeclaredExtension(false, "http://acme.org/parentExtension").addUndeclaredExtension(false, "http://acme.org/childExtension", new StringDt("nestedValue")); System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); @@ -326,6 +374,22 @@ public class FhirTerserDstu2Test { assertTrue(extValues.get(0).getValue() instanceof StringDt); assertEquals("http://acme.org/extension", extValues.get(0).getUrl()); assertEquals("modifiedValue", ((StringDt) (extValues.get(0).getValue())).getValueAsString()); + + extValues = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')", ExtensionDt.class); + assertEquals(1, extValues.size()); + assertTrue(extValues.get(0).getValue() instanceof StringDt); + assertEquals("http://acme.org/childExtension", extValues.get(0).getUrl()); + assertEquals("nestedValue", ((StringDt) extValues.get(0).getValue()).getValueAsString()); + + extValues.get(0).setValue(new StringDt("modifiedNestedValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + extValues = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')", ExtensionDt.class); + assertEquals(1, extValues.size()); + assertTrue(extValues.get(0).getValue() instanceof StringDt); + assertEquals("http://acme.org/childExtension", extValues.get(0).getUrl()); + assertEquals("modifiedNestedValue", ((StringDt) extValues.get(0).getValue()).getValueAsString()); } @Test @@ -343,6 +407,11 @@ public class FhirTerserDstu2Test { assertEquals(1, extValues.size()); assertEquals("http://acme.org/extension", extValues.get(0).getUrl()); assertNull(extValues.get(0).getValue()); + + extValues = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')", ExtensionDt.class, true); + assertEquals(1, extValues.size()); + assertEquals("http://acme.org/childExtension", extValues.get(0).getUrl()); + assertNull(extValues.get(0).getValue()); } @Test @@ -363,6 +432,13 @@ public class FhirTerserDstu2Test { assertTrue(values.get(0) instanceof ExtensionDt); assertEquals("http://acme.org/extension", ((ExtensionDt) values.get(0)).getUrl()); assertNull(((ExtensionDt) values.get(0)).getValue()); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')", true); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof ExtensionDt); + assertEquals("http://acme.org/childExtension", ((ExtensionDt) values.get(0)).getUrl()); + assertNull(((ExtensionDt) values.get(0)).getValue()); } @Test @@ -371,6 +447,7 @@ public class FhirTerserDstu2Test { p.setActive(true); p.addUndeclaredExtension(false, "http://acme.org/extension", new StringDt("value")); p.addUndeclaredExtension(false, "http://acme.org/otherExtension", new StringDt("otherValue")); + p.addUndeclaredExtension(false, "http://acme.org/parentExtension").addUndeclaredExtension(false, "http://acme.org/childExtension", new StringDt("nestedValue")); System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); @@ -380,12 +457,19 @@ public class FhirTerserDstu2Test { assertTrue(values.get(0) instanceof BooleanDt); assertTrue(((BooleanDt) values.get(0)).getValue()); - values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')"); + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')", true); assertEquals(1, values.size()); assertTrue(values.get(0) instanceof IBaseExtension); assertTrue(values.get(0) instanceof ExtensionDt); assertEquals("http://acme.org/extension", ((ExtensionDt) values.get(0)).getUrl()); assertEquals("value", ((StringDt) ((ExtensionDt) values.get(0)).getValue()).getValueAsString()); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')", true); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof ExtensionDt); + assertEquals("http://acme.org/childExtension", ((ExtensionDt) values.get(0)).getUrl()); + assertEquals("nestedValue", ((StringDt) ((ExtensionDt) values.get(0)).getValue()).getValueAsString()); } @Test diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/util/FhirTerserDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/util/FhirTerserDstu3Test.java index bf0ffde4ee0..923762241f8 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/util/FhirTerserDstu3Test.java +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/util/FhirTerserDstu3Test.java @@ -182,6 +182,11 @@ public class FhirTerserDstu3Test { p.addModifierExtension() .setUrl("http://acme.org/modifierExtension") .setValue(new StringType("modifierValue")); + p.addExtension() + .setUrl("http://acme.org/parentExtension") + .addExtension() + .setUrl("http://acme.org/childExtension") + .setValue(new StringType("nestedValue")); System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); @@ -204,6 +209,13 @@ public class FhirTerserDstu3Test { assertTrue(values.get(0) instanceof Extension); assertEquals("http://acme.org/modifierExtension", ((Extension) values.get(0)).getUrl()); assertEquals("modifierValue", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof Extension); + assertEquals("http://acme.org/childExtension", ((Extension) values.get(0)).getUrl()); + assertEquals("nestedValue", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); } @Test @@ -219,6 +231,11 @@ public class FhirTerserDstu3Test { p.addModifierExtension() .setUrl("http://acme.org/modifierExtension") .setValue(new StringType("modifierValue")); + p.addExtension() + .setUrl("http://acme.org/parentExtension") + .addExtension() + .setUrl("http://acme.org/childExtension") + .setValue(new StringType("nestedValue")); System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); @@ -273,6 +290,24 @@ public class FhirTerserDstu3Test { assertTrue(values.get(0) instanceof Extension); assertEquals("http://acme.org/modifierExtension", ((Extension) values.get(0)).getUrl()); assertEquals("modifiedModifierValue", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof Extension); + assertEquals("http://acme.org/childExtension", ((Extension) values.get(0)).getUrl()); + assertEquals("nestedValue", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); + + ((Extension) values.get(0)).setValue(new StringType("modifiedNestedValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof Extension); + assertEquals("http://acme.org/childExtension", ((Extension) values.get(0)).getUrl()); + assertEquals("modifiedNestedValue", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); } @Test @@ -293,6 +328,16 @@ public class FhirTerserDstu3Test { p.addModifierExtension() .setUrl("http://acme.org/modifierExtension") .setValue(new StringType("modifierValue2")); + p.addExtension() + .setUrl("http://acme.org/parentExtension") + .addExtension() + .setUrl("http://acme.org/childExtension") + .setValue(new StringType("nestedValue1")); + p.addExtension() + .setUrl("http://acme.org/parentExtension") + .addExtension() + .setUrl("http://acme.org/childExtension") + .setValue(new StringType("nestedValue2")); System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); @@ -317,6 +362,17 @@ public class FhirTerserDstu3Test { assertTrue(values.get(1) instanceof Extension); assertEquals("http://acme.org/modifierExtension", ((Extension) values.get(1)).getUrl()); assertEquals("modifierValue2", ((StringType) ((Extension) values.get(1)).getValue()).getValueAsString()); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')"); + assertEquals(2, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof Extension); + assertEquals("http://acme.org/childExtension", ((Extension) values.get(0)).getUrl()); + assertEquals("nestedValue1", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); + assertTrue(values.get(1) instanceof IBaseExtension); + assertTrue(values.get(1) instanceof Extension); + assertEquals("http://acme.org/childExtension", ((Extension) values.get(1)).getUrl()); + assertEquals("nestedValue2", ((StringType) ((Extension) values.get(1)).getValue()).getValueAsString()); } @Test @@ -332,6 +388,11 @@ public class FhirTerserDstu3Test { p.addModifierExtension() .setUrl("http://acme.org/modifierExtension") .setValue(new StringType("modifierValue")); + p.addExtension() + .setUrl("http://acme.org/parentExtension") + .addExtension() + .setUrl("http://acme.org/childExtension") + .setValue(new StringType("nestedValue")); System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); @@ -351,6 +412,12 @@ public class FhirTerserDstu3Test { assertTrue(extValues.get(0).getValue() instanceof StringType); assertEquals("http://acme.org/modifierExtension", extValues.get(0).getUrl()); assertEquals("modifierValue", ((StringType) (extValues.get(0).getValue())).getValueAsString()); + + extValues = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')", Extension.class); + assertEquals(1, extValues.size()); + assertTrue(extValues.get(0).getValue() instanceof StringType); + assertEquals("http://acme.org/childExtension", extValues.get(0).getUrl()); + assertEquals("nestedValue", ((StringType) extValues.get(0).getValue()).getValueAsString()); } @Test @@ -366,6 +433,11 @@ public class FhirTerserDstu3Test { p.addModifierExtension() .setUrl("http://acme.org/modifierExtension") .setValue(new StringType("modifierValue")); + p.addExtension() + .setUrl("http://acme.org/parentExtension") + .addExtension() + .setUrl("http://acme.org/childExtension") + .setValue(new StringType("nestedValue")); System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); @@ -414,6 +486,22 @@ public class FhirTerserDstu3Test { assertTrue(extValues.get(0).getValue() instanceof StringType); assertEquals("http://acme.org/modifierExtension", extValues.get(0).getUrl()); assertEquals("modifiedModifierValue", ((StringType) (extValues.get(0).getValue())).getValueAsString()); + + extValues = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')", Extension.class); + assertEquals(1, extValues.size()); + assertTrue(extValues.get(0).getValue() instanceof StringType); + assertEquals("http://acme.org/childExtension", extValues.get(0).getUrl()); + assertEquals("nestedValue", ((StringType) extValues.get(0).getValue()).getValueAsString()); + + extValues.get(0).setValue(new StringType("modifiedNestedValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + extValues = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')", Extension.class); + assertEquals(1, extValues.size()); + assertTrue(extValues.get(0).getValue() instanceof StringType); + assertEquals("http://acme.org/childExtension", extValues.get(0).getUrl()); + assertEquals("modifiedNestedValue", ((StringType) extValues.get(0).getValue()).getValueAsString()); } @Test @@ -436,6 +524,11 @@ public class FhirTerserDstu3Test { assertEquals(1, extValues.size()); assertEquals("http://acme.org/modifierExtension", extValues.get(0).getUrl()); assertNull(extValues.get(0).getValue()); + + extValues = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')", Extension.class, true); + assertEquals(1, extValues.size()); + assertEquals("http://acme.org/childExtension", extValues.get(0).getUrl()); + assertNull(extValues.get(0).getValue()); } @Test @@ -463,6 +556,18 @@ public class FhirTerserDstu3Test { assertTrue(values.get(0) instanceof Extension); assertEquals("http://acme.org/modifierExtension", ((Extension) values.get(0)).getUrl()); assertNull(((Extension) values.get(0)).getValue()); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')", true); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof Extension); + assertEquals("http://acme.org/childExtension", ((Extension) values.get(0)).getUrl()); + assertNull(((Extension) values.get(0)).getValue()); } @Test @@ -478,6 +583,11 @@ public class FhirTerserDstu3Test { p.addModifierExtension() .setUrl("http://acme.org/modifierExtension") .setValue(new StringType("modifierValue")); + p.addExtension() + .setUrl("http://acme.org/parentExtension") + .addExtension() + .setUrl("http://acme.org/childExtension") + .setValue(new StringType("nestedValue")); System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); @@ -487,19 +597,26 @@ public class FhirTerserDstu3Test { assertTrue(values.get(0) instanceof BooleanType); assertTrue(((BooleanType) values.get(0)).booleanValue()); - values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')"); + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')", true); assertEquals(1, values.size()); assertTrue(values.get(0) instanceof IBaseExtension); assertTrue(values.get(0) instanceof Extension); assertEquals("http://acme.org/extension", ((Extension) values.get(0)).getUrl()); assertEquals("value", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); - values = ourCtx.newTerser().getValues(p, "Patient.modifierExtension('http://acme.org/modifierExtension')"); + values = ourCtx.newTerser().getValues(p, "Patient.modifierExtension('http://acme.org/modifierExtension')", true); assertEquals(1, values.size()); assertTrue(values.get(0) instanceof IBaseExtension); assertTrue(values.get(0) instanceof Extension); assertEquals("http://acme.org/modifierExtension", ((Extension) values.get(0)).getUrl()); assertEquals("modifierValue", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')", true); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof Extension); + assertEquals("http://acme.org/childExtension", ((Extension) values.get(0)).getUrl()); + assertEquals("nestedValue", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); } @Test From 4e414a16fb7d08021f5467a12dede76659f3a155 Mon Sep 17 00:00:00 2001 From: Diederik Muylwyk Date: Mon, 22 Oct 2018 18:37:34 -0400 Subject: [PATCH 4/6] More additional work on FhirTerser.getValues(...) enhancements. Ready for review. --- .../test/java/ca/uhn/fhir/util/FhirTerserDstu3Test.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/util/FhirTerserDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/util/FhirTerserDstu3Test.java index 923762241f8..047256fff6d 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/util/FhirTerserDstu3Test.java +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/util/FhirTerserDstu3Test.java @@ -535,8 +535,6 @@ public class FhirTerserDstu3Test { public void testGetValuesWithTheCreate() { Patient p = new Patient(); - System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); - List values = ourCtx.newTerser().getValues(p, "Patient.active", true); assertEquals(1, values.size()); assertTrue(values.get(0) instanceof PrimitiveType); @@ -557,12 +555,7 @@ public class FhirTerserDstu3Test { assertEquals("http://acme.org/modifierExtension", ((Extension) values.get(0)).getUrl()); assertNull(((Extension) values.get(0)).getValue()); - System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); - values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')", true); - - System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); - assertEquals(1, values.size()); assertTrue(values.get(0) instanceof IBaseExtension); assertTrue(values.get(0) instanceof Extension); From 21a0390e6e906e88c1525ae308b92abb30f85fcc Mon Sep 17 00:00:00 2001 From: Diederik Muylwyk Date: Wed, 24 Oct 2018 11:43:19 -0400 Subject: [PATCH 5/6] Even more additional work on FhirTerser.getValues(...) enhancements. Almost ready for review. --- .../api/ISupportsUndeclaredExtensions.java | 7 +- .../java/ca/uhn/fhir/util/FhirTerser.java | 183 ++++++++--- .../ca/uhn/fhir/util/FhirTerserDstu2Test.java | 298 ++++++++++++++++++ .../ca/uhn/fhir/util/FhirTerserDstu3Test.java | 234 ++++++++++++++ 4 files changed, 681 insertions(+), 41 deletions(-) diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/ISupportsUndeclaredExtensions.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/ISupportsUndeclaredExtensions.java index afd252ed349..ee6402578bc 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/ISupportsUndeclaredExtensions.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/ISupportsUndeclaredExtensions.java @@ -20,10 +20,10 @@ package ca.uhn.fhir.model.api; * #L% */ -import java.util.List; - import org.hl7.fhir.instance.model.api.IBaseDatatype; +import java.util.List; + public interface ISupportsUndeclaredExtensions extends IElement { /** @@ -42,7 +42,8 @@ public interface ISupportsUndeclaredExtensions extends IElement { /** * Returns an immutable list containing all extensions (modifier and non-modifier). * - * @see #getUndeclaredExtensions() To return a mutable list which may be used to remove extensions + * @see #getUndeclaredExtensions() To return a mutable list which may be used to remove undeclared non-modifier extensions + * @see #getUndeclaredModifierExtensions() To return a mutable list which may be used to remove undeclared modifier extensions */ List getAllUndeclaredExtensions(); diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java index ca32e26447c..354d52d6201 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java @@ -58,7 +58,41 @@ public class FhirTerser { newList.add(theChildDefinition.getElementName()); return newList; } - + + private ExtensionDt createEmptyExtensionDt(IBaseExtension theBaseExtension, String theUrl) { + return createEmptyExtensionDt(theBaseExtension, false, theUrl); + } + + @SuppressWarnings("unchecked") + private ExtensionDt createEmptyExtensionDt(IBaseExtension theBaseExtension, boolean theIsModifier, String theUrl) { + ExtensionDt retVal = new ExtensionDt(theIsModifier, theUrl); + theBaseExtension.getExtension().add(retVal); + return retVal; + } + + private ExtensionDt createEmptyExtensionDt(ISupportsUndeclaredExtensions theSupportsUndeclaredExtensions, String theUrl) { + return createEmptyExtensionDt(theSupportsUndeclaredExtensions, false, theUrl); + } + + private ExtensionDt createEmptyExtensionDt(ISupportsUndeclaredExtensions theSupportsUndeclaredExtensions, boolean theIsModifier, String theUrl) { + return theSupportsUndeclaredExtensions.addUndeclaredExtension(theIsModifier, theUrl); + } + + private IBaseExtension createEmptyExtension(IBaseHasExtensions theBaseHasExtensions, String theUrl) { + return (IBaseExtension) theBaseHasExtensions.addExtension().setUrl(theUrl); + } + + private IBaseExtension createEmptyModifierExtension(IBaseHasModifierExtensions theBaseHasModifierExtensions, String theUrl) { + return (IBaseExtension) theBaseHasModifierExtensions.addModifierExtension().setUrl(theUrl); + } + + private ExtensionDt createEmptyModifierExtensionDt(IBaseExtension theBaseExtension, String theUrl) { + return createEmptyExtensionDt(theBaseExtension, true, theUrl); + } + + private ExtensionDt createEmptyModifierExtensionDt(ISupportsUndeclaredExtensions theSupportsUndeclaredExtensions, String theUrl) { + return createEmptyExtensionDt(theSupportsUndeclaredExtensions, true, theUrl); + } /** * Clones all values from a source object into the equivalent fields in a target object @@ -214,11 +248,11 @@ public class FhirTerser { } private List getValues(BaseRuntimeElementCompositeDefinition theCurrentDef, Object theCurrentObj, List theSubList, Class theWantedClass) { - return getValues(theCurrentDef, theCurrentObj, theSubList, theWantedClass, false); + return getValues(theCurrentDef, theCurrentObj, theSubList, theWantedClass, false, false); } @SuppressWarnings("unchecked") - private List getValues(BaseRuntimeElementCompositeDefinition theCurrentDef, Object theCurrentObj, List theSubList, Class theWantedClass, boolean theCreate) { + private List getValues(BaseRuntimeElementCompositeDefinition theCurrentDef, Object theCurrentObj, List theSubList, Class theWantedClass, boolean theCreate, boolean theAddExtension) { String name = theSubList.get(0); List retVal = new ArrayList<>(); @@ -229,27 +263,35 @@ public class FhirTerser { extensionUrl = extensionUrl.substring(0, endIndex); } - // DSTU2 if (myContext.getVersion().getVersion().isOlderThan(FhirVersionEnum.DSTU3)) { + // DTSU2 + final String extensionDtUrlForLambda = extensionUrl; List extensionDts = Collections.emptyList(); if (theCurrentObj instanceof ISupportsUndeclaredExtensions) { - extensionDts = ((ISupportsUndeclaredExtensions) theCurrentObj).getUndeclaredExtensionsByUrl(extensionUrl); + extensionDts = ((ISupportsUndeclaredExtensions) theCurrentObj).getUndeclaredExtensions() + .stream() + .filter(t -> t.getUrl().equals(extensionDtUrlForLambda)) + .collect(Collectors.toList()); + + if (theAddExtension + && (!(theCurrentObj instanceof IBaseExtension) || (extensionDts.isEmpty() && theSubList.size() == 1))) { + extensionDts.add(createEmptyExtensionDt((ISupportsUndeclaredExtensions) theCurrentObj, extensionUrl)); + } if (extensionDts.isEmpty() && theCreate) { - // We assume the extension is not a modifier extension. - extensionDts = new ArrayList<>(); // Implementation of ISupportsUndeclaredExtensions.getUndeclaredExtensionsByUrl(...) returns unmodifiable list. - ExtensionDt extensionDt = ((ISupportsUndeclaredExtensions) theCurrentObj).addUndeclaredExtension(false, extensionUrl); - extensionDts.add(extensionDt); + extensionDts.add(createEmptyExtensionDt((ISupportsUndeclaredExtensions) theCurrentObj, extensionUrl)); } + } else if (theCurrentObj instanceof IBaseExtension) { extensionDts = ((IBaseExtension) theCurrentObj).getExtension(); + if (theAddExtension + && (extensionDts.isEmpty() && theSubList.size() == 1)) { + extensionDts.add(createEmptyExtensionDt((IBaseExtension) theCurrentObj, extensionUrl)); + } + if (extensionDts.isEmpty() && theCreate) { - // We assume the extension is not a modifier extension. - ExtensionDt extensionDt = new ExtensionDt(); - extensionDt.setUrl(extensionUrl); - ((IBaseExtension) theCurrentObj).getExtension().add(extensionDt); - extensionDts.add(extensionDt); + extensionDts.add(createEmptyExtensionDt((IBaseExtension) theCurrentObj, extensionUrl)); } } @@ -268,10 +310,13 @@ public class FhirTerser { .filter(t -> t.getUrl().equals(extensionUrlForLambda)) .collect(Collectors.toList()); + if (theAddExtension + && (!(theCurrentObj instanceof IBaseExtension) || (extensions.isEmpty() && theSubList.size() == 1))) { + extensions.add(createEmptyExtension((IBaseHasExtensions) theCurrentObj, extensionUrl)); + } + if (extensions.isEmpty() && theCreate) { - IBaseExtension extension = ((IBaseHasExtensions) theCurrentObj).addExtension(); - extension.setUrl(extensionUrl); - extensions.add(extension); + extensions.add(createEmptyExtension((IBaseHasExtensions) theCurrentObj, extensionUrl)); } } @@ -287,7 +332,7 @@ public class FhirTerser { retVal = new ArrayList<>(); for (T nextElement : values) { BaseRuntimeElementCompositeDefinition nextChildDef = (BaseRuntimeElementCompositeDefinition) myContext.getElementDefinition((Class) nextElement.getClass()); - List foundValues = getValues(nextChildDef, nextElement, theSubList.subList(1, theSubList.size()), theWantedClass, theCreate); + List foundValues = getValues(nextChildDef, nextElement, theSubList.subList(1, theSubList.size()), theWantedClass, theCreate, theAddExtension); retVal.addAll(foundValues); } } @@ -302,8 +347,45 @@ public class FhirTerser { extensionUrl = extensionUrl.substring(0, endIndex); } - // DSTU3+ - if (myContext.getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.DSTU3)) { + if (myContext.getVersion().getVersion().isOlderThan(FhirVersionEnum.DSTU3)) { + // DSTU2 + final String extensionDtUrlForLambda = extensionUrl; + List extensionDts = Collections.emptyList(); + if (theCurrentObj instanceof ISupportsUndeclaredExtensions) { + extensionDts = ((ISupportsUndeclaredExtensions) theCurrentObj).getUndeclaredModifierExtensions() + .stream() + .filter(t -> t.getUrl().equals(extensionDtUrlForLambda)) + .collect(Collectors.toList()); + + if (theAddExtension + && (!(theCurrentObj instanceof IBaseExtension) || (extensionDts.isEmpty() && theSubList.size() == 1))) { + extensionDts.add(createEmptyModifierExtensionDt((ISupportsUndeclaredExtensions) theCurrentObj, extensionUrl)); + } + + if (extensionDts.isEmpty() && theCreate) { + extensionDts.add(createEmptyModifierExtensionDt((ISupportsUndeclaredExtensions) theCurrentObj, extensionUrl)); + } + + } else if (theCurrentObj instanceof IBaseExtension) { + extensionDts = ((IBaseExtension) theCurrentObj).getExtension(); + + if (theAddExtension + && (extensionDts.isEmpty() && theSubList.size() == 1)) { + extensionDts.add(createEmptyExtensionDt((IBaseExtension) theCurrentObj, extensionUrl)); + } + + if (extensionDts.isEmpty() && theCreate) { + extensionDts.add(createEmptyExtensionDt((IBaseExtension) theCurrentObj, extensionUrl)); + } + } + + for (ExtensionDt next : extensionDts) { + if (theWantedClass.isAssignableFrom(next.getClass())) { + retVal.add((T) next); + } + } + } else { + // DSTU3+ final String extensionUrlForLambda = extensionUrl; List extensions = Collections.emptyList(); @@ -313,10 +395,13 @@ public class FhirTerser { .filter(t -> t.getUrl().equals(extensionUrlForLambda)) .collect(Collectors.toList()); + if (theAddExtension + && (!(theCurrentObj instanceof IBaseExtension) || (extensions.isEmpty() && theSubList.size() == 1))) { + extensions.add(createEmptyModifierExtension((IBaseHasModifierExtensions) theCurrentObj, extensionUrl)); + } + if (extensions.isEmpty() && theCreate) { - IBaseExtension modifierExtension = ((IBaseHasModifierExtensions) theCurrentObj).addModifierExtension(); - modifierExtension.setUrl(extensionUrl); - extensions.add(modifierExtension); + extensions.add(createEmptyModifierExtension((IBaseHasModifierExtensions) theCurrentObj, extensionUrl)); } } @@ -332,7 +417,7 @@ public class FhirTerser { retVal = new ArrayList<>(); for (T nextElement : values) { BaseRuntimeElementCompositeDefinition nextChildDef = (BaseRuntimeElementCompositeDefinition) myContext.getElementDefinition((Class) nextElement.getClass()); - List foundValues = getValues(nextChildDef, nextElement, theSubList.subList(1, theSubList.size()), theWantedClass, theCreate); + List foundValues = getValues(nextChildDef, nextElement, theSubList.subList(1, theSubList.size()), theWantedClass, theCreate, theAddExtension); retVal.addAll(foundValues); } } @@ -381,7 +466,7 @@ public class FhirTerser { } else { for (IBase nextElement : values) { BaseRuntimeElementCompositeDefinition nextChildDef = (BaseRuntimeElementCompositeDefinition) myContext.getElementDefinition(nextElement.getClass()); - List foundValues = getValues(nextChildDef, nextElement, theSubList.subList(1, theSubList.size()), theWantedClass, theCreate); + List foundValues = getValues(nextChildDef, nextElement, theSubList.subList(1, theSubList.size()), theWantedClass, theCreate, theAddExtension); retVal.addAll(foundValues); } } @@ -392,9 +477,6 @@ public class FhirTerser { * Returns values stored in an element identified by its path. The list of values is of * type {@link Object}. * - *

Note: this method does not support creation of null-valued modifier extensions for - * versions of FHIR prior to DSTU3.

- * * @param theResource The resource instance to be accessed. Must not be null. * @param thePath The path for the element to be accessed. * @return A list of values of type {@link Object}. @@ -409,9 +491,6 @@ public class FhirTerser { * Returns values stored in an element identified by its path. The list of values is of * type {@link Object}. * - *

Note: this method does not support creation of null-valued modifier extensions for - * versions of FHIR prior to DSTU3.

- * * @param theResource The resource instance to be accessed. Must not be null. * @param thePath The path for the element to be accessed. * @param theCreate When set to true, the terser will create a null-valued element where none exists. @@ -425,10 +504,23 @@ public class FhirTerser { /** * Returns values stored in an element identified by its path. The list of values is of - * type theWantedClass. + * type {@link Object}. * - *

Note: this method does not support creation of null-valued modifier extensions for - * versions of FHIR prior to DSTU3.

+ * @param theResource The resource instance to be accessed. Must not be null. + * @param thePath The path for the element to be accessed. + * @param theCreate When set to true, the terser will create a null-valued element where none exists. + * @param theAddExtension When set to true, the terser will add a null-valued extension where one or more such extensions already exist. + * @return A list of values of type {@link Object}. + */ + public List getValues(IBaseResource theResource, String thePath, boolean theCreate, boolean theAddExtension) { + Class wantedClass = Object.class; + + return getValues(theResource, thePath, wantedClass, theCreate, theAddExtension); + } + + /** + * Returns values stored in an element identified by its path. The list of values is of + * type theWantedClass. * * @param theResource The resource instance to be accessed. Must not be null. * @param thePath The path for the element to be accessed. @@ -446,9 +538,6 @@ public class FhirTerser { * Returns values stored in an element identified by its path. The list of values is of * type theWantedClass. * - *

Note: this method does not support creation of null-valued modifier extensions for - * versions of FHIR prior to DSTU3.

- * * @param theResource The resource instance to be accessed. Must not be null. * @param thePath The path for the element to be accessed. * @param theWantedClass The desired class to be returned in a list. @@ -459,7 +548,25 @@ public class FhirTerser { public List getValues(IBaseResource theResource, String thePath, Class theWantedClass, boolean theCreate) { RuntimeResourceDefinition def = myContext.getResourceDefinition(theResource); List parts = parsePath(def, thePath); - return getValues(def, theResource, parts, theWantedClass, theCreate); + return getValues(def, theResource, parts, theWantedClass, theCreate, false); + } + + /** + * Returns values stored in an element identified by its path. The list of values is of + * type theWantedClass. + * + * @param theResource The resource instance to be accessed. Must not be null. + * @param thePath The path for the element to be accessed. + * @param theWantedClass The desired class to be returned in a list. + * @param theCreate When set to true, the terser will create a null-valued element where none exists. + * @param theAddExtension When set to true, the terser will add a null-valued extension where one or more such extensions already exist. + * @param Type declared by theWantedClass + * @return A list of values of type theWantedClass. + */ + public List getValues(IBaseResource theResource, String thePath, Class theWantedClass, boolean theCreate, boolean theAddExtension) { + RuntimeResourceDefinition def = myContext.getResourceDefinition(theResource); + List parts = parsePath(def, thePath); + return getValues(def, theResource, parts, theWantedClass, theCreate, theAddExtension); } private List parsePath(BaseRuntimeElementCompositeDefinition theElementDef, String thePath) { diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/util/FhirTerserDstu2Test.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/util/FhirTerserDstu2Test.java index e66eabdc9cd..f1312e16850 100644 --- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/util/FhirTerserDstu2Test.java +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/util/FhirTerserDstu2Test.java @@ -185,6 +185,7 @@ public class FhirTerserDstu2Test { p.setActive(true); p.addUndeclaredExtension(false, "http://acme.org/extension", new StringDt("value")); p.addUndeclaredExtension(false, "http://acme.org/otherExtension", new StringDt("otherValue")); + p.addUndeclaredExtension(true, "http://acme.org/modifierExtension", new StringDt("modifierValue")); p.addUndeclaredExtension(false, "http://acme.org/parentExtension").addUndeclaredExtension(false, "http://acme.org/childExtension", new StringDt("nestedValue")); System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); @@ -202,6 +203,13 @@ public class FhirTerserDstu2Test { assertEquals("http://acme.org/extension", ((ExtensionDt) values.get(0)).getUrl()); assertEquals("value", ((StringDt) ((ExtensionDt) values.get(0)).getValue()).getValueAsString()); + values = ourCtx.newTerser().getValues(p, "Patient.modifierExtension('http://acme.org/modifierExtension')"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof ExtensionDt); + assertEquals("http://acme.org/modifierExtension", ((ExtensionDt) values.get(0)).getUrl()); + assertEquals("modifierValue", ((StringDt) ((ExtensionDt) values.get(0)).getValue()).getValueAsString()); + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')"); assertEquals(1, values.size()); assertTrue(values.get(0) instanceof IBaseExtension); @@ -216,6 +224,7 @@ public class FhirTerserDstu2Test { p.setActive(true); p.addUndeclaredExtension(false, "http://acme.org/extension", new StringDt("value")); p.addUndeclaredExtension(false, "http://acme.org/otherExtension", new StringDt("otherValue")); + p.addUndeclaredExtension(true, "http://acme.org/modifierExtension", new StringDt("modifierValue")); p.addUndeclaredExtension(false, "http://acme.org/parentExtension").addUndeclaredExtension(false, "http://acme.org/childExtension", new StringDt("nestedValue")); System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); @@ -254,6 +263,24 @@ public class FhirTerserDstu2Test { assertEquals("http://acme.org/extension", ((ExtensionDt) values.get(0)).getUrl()); assertEquals("modifiedValue", ((StringDt) ((ExtensionDt) values.get(0)).getValue()).getValueAsString()); + values = ourCtx.newTerser().getValues(p, "Patient.modifierExtension('http://acme.org/modifierExtension')"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof ExtensionDt); + assertEquals("http://acme.org/modifierExtension", ((ExtensionDt) values.get(0)).getUrl()); + assertEquals("modifierValue", ((StringDt) ((ExtensionDt) values.get(0)).getValue()).getValueAsString()); + + ((ExtensionDt) values.get(0)).setValue(new StringDt("modifiedModifierValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + values = ourCtx.newTerser().getValues(p, "Patient.modifierExtension('http://acme.org/modifierExtension')"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof ExtensionDt); + assertEquals("http://acme.org/modifierExtension", ((ExtensionDt) values.get(0)).getUrl()); + assertEquals("modifiedModifierValue", ((StringDt) ((ExtensionDt) values.get(0)).getValue()).getValueAsString()); + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')"); assertEquals(1, values.size()); assertTrue(values.get(0) instanceof IBaseExtension); @@ -279,6 +306,8 @@ public class FhirTerserDstu2Test { p.addUndeclaredExtension(false, "http://acme.org/extension", new StringDt("value1")); p.addUndeclaredExtension(false, "http://acme.org/extension", new StringDt("value2")); p.addUndeclaredExtension(false, "http://acme.org/otherExtension", new StringDt("otherValue")); + p.addUndeclaredExtension(true, "http://acme.org/modifierExtension", new StringDt("modifierValue1")); + p.addUndeclaredExtension(true, "http://acme.org/modifierExtension", new StringDt("modifierValue2")); p.addUndeclaredExtension(false, "http://acme.org/parentExtension").addUndeclaredExtension(false, "http://acme.org/childExtension", new StringDt("nestedValue1")); p.addUndeclaredExtension(false, "http://acme.org/parentExtension").addUndeclaredExtension(false, "http://acme.org/childExtension", new StringDt("nestedValue2")); @@ -295,6 +324,17 @@ public class FhirTerserDstu2Test { assertEquals("http://acme.org/extension", ((ExtensionDt) values.get(1)).getUrl()); assertEquals("value2", ((StringDt) ((ExtensionDt) values.get(1)).getValue()).getValueAsString()); + values = ourCtx.newTerser().getValues(p, "Patient.modifierExtension('http://acme.org/modifierExtension')"); + assertEquals(2, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof ExtensionDt); + assertEquals("http://acme.org/modifierExtension", ((ExtensionDt) values.get(0)).getUrl()); + assertEquals("modifierValue1", ((StringDt) ((ExtensionDt) values.get(0)).getValue()).getValueAsString()); + assertTrue(values.get(1) instanceof IBaseExtension); + assertTrue(values.get(1) instanceof ExtensionDt); + assertEquals("http://acme.org/modifierExtension", ((ExtensionDt) values.get(1)).getUrl()); + assertEquals("modifierValue2", ((StringDt) ((ExtensionDt) values.get(1)).getValue()).getValueAsString()); + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')"); assertEquals(2, values.size()); assertTrue(values.get(0) instanceof IBaseExtension); @@ -313,6 +353,7 @@ public class FhirTerserDstu2Test { p.setActive(true); p.addUndeclaredExtension(false, "http://acme.org/extension", new StringDt("value")); p.addUndeclaredExtension(false, "http://acme.org/otherExtension", new StringDt("otherValue")); + p.addUndeclaredExtension(true, "http://acme.org/modifierExtension", new StringDt("modifierValue")); p.addUndeclaredExtension(false, "http://acme.org/parentExtension").addUndeclaredExtension(false, "http://acme.org/childExtension", new StringDt("nestedValue")); System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); @@ -328,6 +369,12 @@ public class FhirTerserDstu2Test { assertEquals("http://acme.org/extension", extValues.get(0).getUrl()); assertEquals("value", ((StringDt) extValues.get(0).getValue()).getValueAsString()); + extValues = ourCtx.newTerser().getValues(p, "Patient.modifierExtension('http://acme.org/modifierExtension')", ExtensionDt.class); + assertEquals(1, extValues.size()); + assertTrue(extValues.get(0).getValue() instanceof StringDt); + assertEquals("http://acme.org/modifierExtension", extValues.get(0).getUrl()); + assertEquals("modifierValue", ((StringDt) (extValues.get(0).getValue())).getValueAsString()); + extValues = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')", ExtensionDt.class); assertEquals(1, extValues.size()); assertTrue(extValues.get(0).getValue() instanceof StringDt); @@ -341,6 +388,7 @@ public class FhirTerserDstu2Test { p.setActive(true); p.addUndeclaredExtension(false, "http://acme.org/extension", new StringDt("value")); p.addUndeclaredExtension(false, "http://acme.org/otherExtension", new StringDt("otherValue")); + p.addUndeclaredExtension(true, "http://acme.org/modifierExtension", new StringDt("modifierValue")); p.addUndeclaredExtension(false, "http://acme.org/parentExtension").addUndeclaredExtension(false, "http://acme.org/childExtension", new StringDt("nestedValue")); System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); @@ -375,6 +423,22 @@ public class FhirTerserDstu2Test { assertEquals("http://acme.org/extension", extValues.get(0).getUrl()); assertEquals("modifiedValue", ((StringDt) (extValues.get(0).getValue())).getValueAsString()); + extValues = ourCtx.newTerser().getValues(p, "Patient.modifierExtension('http://acme.org/modifierExtension')", ExtensionDt.class); + assertEquals(1, extValues.size()); + assertTrue(extValues.get(0).getValue() instanceof StringDt); + assertEquals("http://acme.org/modifierExtension", extValues.get(0).getUrl()); + assertEquals("modifierValue", ((StringDt) (extValues.get(0).getValue())).getValueAsString()); + + extValues.get(0).setValue(new StringDt("modifiedModifierValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + extValues = ourCtx.newTerser().getValues(p, "Patient.modifierExtension('http://acme.org/modifierExtension')", ExtensionDt.class); + assertEquals(1, extValues.size()); + assertTrue(extValues.get(0).getValue() instanceof StringDt); + assertEquals("http://acme.org/modifierExtension", extValues.get(0).getUrl()); + assertEquals("modifiedModifierValue", ((StringDt) (extValues.get(0).getValue())).getValueAsString()); + extValues = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')", ExtensionDt.class); assertEquals(1, extValues.size()); assertTrue(extValues.get(0).getValue() instanceof StringDt); @@ -408,12 +472,125 @@ public class FhirTerserDstu2Test { assertEquals("http://acme.org/extension", extValues.get(0).getUrl()); assertNull(extValues.get(0).getValue()); + extValues = ourCtx.newTerser().getValues(p, "Patient.modifierExtension('http://acme.org/modifierExtension')", ExtensionDt.class, true); + assertEquals(1, extValues.size()); + assertEquals("http://acme.org/modifierExtension", extValues.get(0).getUrl()); + assertNull(extValues.get(0).getValue()); + extValues = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')", ExtensionDt.class, true); assertEquals(1, extValues.size()); assertEquals("http://acme.org/childExtension", extValues.get(0).getUrl()); assertNull(extValues.get(0).getValue()); } + @Test + public void testGetValuesWithTheAddExtensionAndModify() { + Patient p = new Patient(); + p.setActive(true); + p.addUndeclaredExtension(false, "http://acme.org/extension", new StringDt("value")); + p.addUndeclaredExtension(false, "http://acme.org/otherExtension", new StringDt("otherValue")); + p.addUndeclaredExtension(true, "http://acme.org/modifierExtension", new StringDt("modifierValue")); + p.addUndeclaredExtension(false, "http://acme.org/parentExtension").addUndeclaredExtension(false, "http://acme.org/childExtension", new StringDt("nestedValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + List values = ourCtx.newTerser().getValues(p, "Patient.active"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IPrimitiveType); + assertTrue(values.get(0) instanceof BooleanDt); + assertTrue(((BooleanDt) values.get(0)).getValue()); + + // No change. + values = ourCtx.newTerser().getValues(p, "Patient.active", false, true); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IPrimitiveType); + assertTrue(values.get(0) instanceof BooleanDt); + assertTrue(((BooleanDt) values.get(0)).getValue()); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof ExtensionDt); + assertEquals("http://acme.org/extension", ((ExtensionDt) values.get(0)).getUrl()); + assertEquals("value", ((StringDt) ((ExtensionDt) values.get(0)).getValue()).getValueAsString()); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')", false, true); + assertEquals(2, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof ExtensionDt); + assertEquals("http://acme.org/extension", ((ExtensionDt) values.get(0)).getUrl()); + assertEquals("value", ((StringDt) ((ExtensionDt) values.get(0)).getValue()).getValueAsString()); + assertTrue(values.get(1) instanceof IBaseExtension); + assertTrue(values.get(1) instanceof ExtensionDt); + assertEquals("http://acme.org/extension", ((ExtensionDt) values.get(1)).getUrl()); + assertNull(((ExtensionDt) values.get(1)).getValue()); + + ((ExtensionDt) values.get(1)).setValue(new StringDt("addedValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + assertTrue(values.get(1) instanceof IBaseExtension); + assertTrue(values.get(1) instanceof ExtensionDt); + assertEquals("http://acme.org/extension", ((ExtensionDt) values.get(1)).getUrl()); + assertEquals("addedValue", ((StringDt) ((ExtensionDt) values.get(1)).getValue()).getValueAsString()); + + values = ourCtx.newTerser().getValues(p, "Patient.modifierExtension('http://acme.org/modifierExtension')"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof ExtensionDt); + assertEquals("http://acme.org/modifierExtension", ((ExtensionDt) values.get(0)).getUrl()); + assertEquals("modifierValue", ((StringDt) ((ExtensionDt) values.get(0)).getValue()).getValueAsString()); + + values = ourCtx.newTerser().getValues(p, "Patient.modifierExtension('http://acme.org/modifierExtension')", false, true); + assertEquals(2, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof ExtensionDt); + assertEquals("http://acme.org/modifierExtension", ((ExtensionDt) values.get(0)).getUrl()); + assertEquals("modifierValue", ((StringDt) ((ExtensionDt) values.get(0)).getValue()).getValueAsString()); + assertTrue(values.get(1) instanceof IBaseExtension); + assertTrue(values.get(1) instanceof ExtensionDt); + assertEquals("http://acme.org/modifierExtension", ((ExtensionDt) values.get(1)).getUrl()); + assertNull(((ExtensionDt) values.get(1)).getValue()); + + ((ExtensionDt) values.get(1)).setValue(new StringDt("addedModifierValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + assertTrue(values.get(1) instanceof IBaseExtension); + assertTrue(values.get(1) instanceof ExtensionDt); + assertEquals("http://acme.org/modifierExtension", ((ExtensionDt) values.get(1)).getUrl()); + assertEquals("addedModifierValue", ((StringDt) ((ExtensionDt) values.get(1)).getValue()).getValueAsString()); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof ExtensionDt); + assertEquals("http://acme.org/childExtension", ((ExtensionDt) values.get(0)).getUrl()); + assertEquals("nestedValue", ((StringDt) ((ExtensionDt) values.get(0)).getValue()).getValueAsString()); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')", false, true); + assertEquals(2, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof ExtensionDt); + assertEquals("http://acme.org/childExtension", ((ExtensionDt) values.get(0)).getUrl()); + assertEquals("nestedValue", ((StringDt) ((ExtensionDt) values.get(0)).getValue()).getValueAsString()); + assertTrue(values.get(1) instanceof IBaseExtension); + assertTrue(values.get(1) instanceof ExtensionDt); + assertEquals("http://acme.org/childExtension", ((ExtensionDt) values.get(1)).getUrl()); + assertNull(((ExtensionDt) values.get(1)).getValue()); + + ((ExtensionDt) values.get(1)).setValue(new StringDt("addedNestedValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + assertTrue(values.get(1) instanceof IBaseExtension); + assertTrue(values.get(1) instanceof ExtensionDt); + assertEquals("http://acme.org/childExtension", ((ExtensionDt) values.get(1)).getUrl()); + assertEquals("addedNestedValue", ((StringDt) ((ExtensionDt) values.get(1)).getValue()).getValueAsString()); + } + @Test public void testGetValuesWithTheCreate() { Patient p = new Patient(); @@ -433,6 +610,13 @@ public class FhirTerserDstu2Test { assertEquals("http://acme.org/extension", ((ExtensionDt) values.get(0)).getUrl()); assertNull(((ExtensionDt) values.get(0)).getValue()); + values = ourCtx.newTerser().getValues(p, "Patient.modifierExtension('http://acme.org/modifierExtension')", true); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof ExtensionDt); + assertEquals("http://acme.org/modifierExtension", ((ExtensionDt) values.get(0)).getUrl()); + assertNull(((ExtensionDt) values.get(0)).getValue()); + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')", true); assertEquals(1, values.size()); assertTrue(values.get(0) instanceof IBaseExtension); @@ -441,12 +625,119 @@ public class FhirTerserDstu2Test { assertNull(((ExtensionDt) values.get(0)).getValue()); } + @Test + public void testGetValuesWithTheCreateAndTheAddExtensionAndModify() { + Patient p = new Patient(); + p.setActive(true); + p.addUndeclaredExtension(false, "http://acme.org/extension", new StringDt("value")); + p.addUndeclaredExtension(false, "http://acme.org/otherExtension", new StringDt("otherValue")); + p.addUndeclaredExtension(true, "http://acme.org/modifierExtension", new StringDt("modifierValue")); + p.addUndeclaredExtension(false, "http://acme.org/parentExtension").addUndeclaredExtension(false, "http://acme.org/childExtension", new StringDt("nestedValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + List values = ourCtx.newTerser().getValues(p, "Patient.active"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IPrimitiveType); + assertTrue(values.get(0) instanceof BooleanDt); + assertTrue(((BooleanDt) values.get(0)).getValue()); + + // No change. + values = ourCtx.newTerser().getValues(p, "Patient.active", true, true); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IPrimitiveType); + assertTrue(values.get(0) instanceof BooleanDt); + assertTrue(((BooleanDt) values.get(0)).getValue()); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof ExtensionDt); + assertEquals("http://acme.org/extension", ((ExtensionDt) values.get(0)).getUrl()); + assertEquals("value", ((StringDt) ((ExtensionDt) values.get(0)).getValue()).getValueAsString()); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')", true, true); + assertEquals(2, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof ExtensionDt); + assertEquals("http://acme.org/extension", ((ExtensionDt) values.get(0)).getUrl()); + assertEquals("value", ((StringDt) ((ExtensionDt) values.get(0)).getValue()).getValueAsString()); + assertTrue(values.get(1) instanceof IBaseExtension); + assertTrue(values.get(1) instanceof ExtensionDt); + assertEquals("http://acme.org/extension", ((ExtensionDt) values.get(1)).getUrl()); + assertNull(((ExtensionDt) values.get(1)).getValue()); + + ((ExtensionDt) values.get(1)).setValue(new StringDt("addedValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + assertTrue(values.get(1) instanceof IBaseExtension); + assertTrue(values.get(1) instanceof ExtensionDt); + assertEquals("http://acme.org/extension", ((ExtensionDt) values.get(1)).getUrl()); + assertEquals("addedValue", ((StringDt) ((ExtensionDt) values.get(1)).getValue()).getValueAsString()); + + values = ourCtx.newTerser().getValues(p, "Patient.modifierExtension('http://acme.org/modifierExtension')"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof ExtensionDt); + assertEquals("http://acme.org/modifierExtension", ((ExtensionDt) values.get(0)).getUrl()); + assertEquals("modifierValue", ((StringDt) ((ExtensionDt) values.get(0)).getValue()).getValueAsString()); + + values = ourCtx.newTerser().getValues(p, "Patient.modifierExtension('http://acme.org/modifierExtension')", true, true); + assertEquals(2, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof ExtensionDt); + assertEquals("http://acme.org/modifierExtension", ((ExtensionDt) values.get(0)).getUrl()); + assertEquals("modifierValue", ((StringDt) ((ExtensionDt) values.get(0)).getValue()).getValueAsString()); + assertTrue(values.get(1) instanceof IBaseExtension); + assertTrue(values.get(1) instanceof ExtensionDt); + assertEquals("http://acme.org/modifierExtension", ((ExtensionDt) values.get(1)).getUrl()); + assertNull(((ExtensionDt) values.get(1)).getValue()); + + ((ExtensionDt) values.get(1)).setValue(new StringDt("addedModifierValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + assertTrue(values.get(1) instanceof IBaseExtension); + assertTrue(values.get(1) instanceof ExtensionDt); + assertEquals("http://acme.org/modifierExtension", ((ExtensionDt) values.get(1)).getUrl()); + assertEquals("addedModifierValue", ((StringDt) ((ExtensionDt) values.get(1)).getValue()).getValueAsString()); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof ExtensionDt); + assertEquals("http://acme.org/childExtension", ((ExtensionDt) values.get(0)).getUrl()); + assertEquals("nestedValue", ((StringDt) ((ExtensionDt) values.get(0)).getValue()).getValueAsString()); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')", true, true); + assertEquals(2, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof ExtensionDt); + assertEquals("http://acme.org/childExtension", ((ExtensionDt) values.get(0)).getUrl()); + assertEquals("nestedValue", ((StringDt) ((ExtensionDt) values.get(0)).getValue()).getValueAsString()); + assertTrue(values.get(1) instanceof IBaseExtension); + assertTrue(values.get(1) instanceof ExtensionDt); + assertEquals("http://acme.org/childExtension", ((ExtensionDt) values.get(1)).getUrl()); + assertNull(((ExtensionDt) values.get(1)).getValue()); + + ((ExtensionDt) values.get(1)).setValue(new StringDt("addedNestedValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + assertTrue(values.get(1) instanceof IBaseExtension); + assertTrue(values.get(1) instanceof ExtensionDt); + assertEquals("http://acme.org/childExtension", ((ExtensionDt) values.get(1)).getUrl()); + assertEquals("addedNestedValue", ((StringDt) ((ExtensionDt) values.get(1)).getValue()).getValueAsString()); + } + @Test public void testGetValuesWithTheCreateAndNoOverwrite() { Patient p = new Patient(); p.setActive(true); p.addUndeclaredExtension(false, "http://acme.org/extension", new StringDt("value")); p.addUndeclaredExtension(false, "http://acme.org/otherExtension", new StringDt("otherValue")); + p.addUndeclaredExtension(true, "http://acme.org/modifierExtension", new StringDt("modifierValue")); p.addUndeclaredExtension(false, "http://acme.org/parentExtension").addUndeclaredExtension(false, "http://acme.org/childExtension", new StringDt("nestedValue")); System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); @@ -464,6 +755,13 @@ public class FhirTerserDstu2Test { assertEquals("http://acme.org/extension", ((ExtensionDt) values.get(0)).getUrl()); assertEquals("value", ((StringDt) ((ExtensionDt) values.get(0)).getValue()).getValueAsString()); + values = ourCtx.newTerser().getValues(p, "Patient.modifierExtension('http://acme.org/modifierExtension')", true); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof ExtensionDt); + assertEquals("http://acme.org/modifierExtension", ((ExtensionDt) values.get(0)).getUrl()); + assertEquals("modifierValue", ((StringDt) ((ExtensionDt) values.get(0)).getValue()).getValueAsString()); + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')", true); assertEquals(1, values.size()); assertTrue(values.get(0) instanceof IBaseExtension); diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/util/FhirTerserDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/util/FhirTerserDstu3Test.java index 047256fff6d..b8cece751d7 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/util/FhirTerserDstu3Test.java +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/util/FhirTerserDstu3Test.java @@ -531,6 +531,124 @@ public class FhirTerserDstu3Test { assertNull(extValues.get(0).getValue()); } + @Test + public void testGetValuesWithTheAddExtensionAndModify() { + Patient p = new Patient(); + p.setActive(true); + p.addExtension() + .setUrl("http://acme.org/extension") + .setValue(new StringType("value")); + p.addExtension() + .setUrl("http://acme.org/otherExtension") + .setValue(new StringType("otherValue")); + p.addModifierExtension() + .setUrl("http://acme.org/modifierExtension") + .setValue(new StringType("modifierValue")); + p.addExtension() + .setUrl("http://acme.org/parentExtension") + .addExtension() + .setUrl("http://acme.org/childExtension") + .setValue(new StringType("nestedValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + List values = ourCtx.newTerser().getValues(p, "Patient.active"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof PrimitiveType); + assertTrue(values.get(0) instanceof BooleanType); + assertTrue(((BooleanType) values.get(0)).booleanValue()); + + // No change. + values = ourCtx.newTerser().getValues(p, "Patient.active", false, true); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof PrimitiveType); + assertTrue(values.get(0) instanceof BooleanType); + assertTrue(((BooleanType) values.get(0)).booleanValue()); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof Extension); + assertEquals("http://acme.org/extension", ((Extension) values.get(0)).getUrl()); + assertEquals("value", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')", false, true); + assertEquals(2, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof Extension); + assertEquals("http://acme.org/extension", ((Extension) values.get(0)).getUrl()); + assertEquals("value", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); + assertTrue(values.get(1) instanceof IBaseExtension); + assertTrue(values.get(1) instanceof Extension); + assertEquals("http://acme.org/extension", ((Extension) values.get(1)).getUrl()); + assertNull(((Extension) values.get(1)).getValue()); + + ((Extension) values.get(1)).setValue(new StringType("addedValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + assertTrue(values.get(1) instanceof IBaseExtension); + assertTrue(values.get(1) instanceof Extension); + assertEquals("http://acme.org/extension", ((Extension) values.get(1)).getUrl()); + assertEquals("addedValue", ((StringType) ((Extension) values.get(1)).getValue()).getValueAsString()); + + values = ourCtx.newTerser().getValues(p, "Patient.modifierExtension('http://acme.org/modifierExtension')"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof Extension); + assertEquals("http://acme.org/modifierExtension", ((Extension) values.get(0)).getUrl()); + assertEquals("modifierValue", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); + + values = ourCtx.newTerser().getValues(p, "Patient.modifierExtension('http://acme.org/modifierExtension')", false, true); + assertEquals(2, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof Extension); + assertEquals("http://acme.org/modifierExtension", ((Extension) values.get(0)).getUrl()); + assertEquals("modifierValue", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); + assertTrue(values.get(1) instanceof IBaseExtension); + assertTrue(values.get(1) instanceof Extension); + assertEquals("http://acme.org/modifierExtension", ((Extension) values.get(1)).getUrl()); + assertNull(((Extension) values.get(1)).getValue()); + + ((Extension) values.get(1)).setValue(new StringType("addedModifierValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + assertTrue(values.get(1) instanceof IBaseExtension); + assertTrue(values.get(1) instanceof Extension); + assertEquals("http://acme.org/modifierExtension", ((Extension) values.get(1)).getUrl()); + assertEquals("addedModifierValue", ((StringType) ((Extension) values.get(1)).getValue()).getValueAsString()); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof Extension); + assertEquals("http://acme.org/childExtension", ((Extension) values.get(0)).getUrl()); + assertEquals("nestedValue", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')", false, true); + assertEquals(2, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof Extension); + assertEquals("http://acme.org/childExtension", ((Extension) values.get(0)).getUrl()); + assertEquals("nestedValue", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); + assertTrue(values.get(1) instanceof IBaseExtension); + assertTrue(values.get(1) instanceof Extension); + assertEquals("http://acme.org/childExtension", ((Extension) values.get(1)).getUrl()); + assertNull(((Extension) values.get(1)).getValue()); + + ((Extension) values.get(1)).setValue(new StringType("addedNestedValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + assertTrue(values.get(1) instanceof IBaseExtension); + assertTrue(values.get(1) instanceof Extension); + assertEquals("http://acme.org/childExtension", ((Extension) values.get(1)).getUrl()); + assertEquals("addedNestedValue", ((StringType) ((Extension) values.get(1)).getValue()).getValueAsString()); + } + @Test public void testGetValuesWithTheCreate() { Patient p = new Patient(); @@ -563,6 +681,122 @@ public class FhirTerserDstu3Test { assertNull(((Extension) values.get(0)).getValue()); } + @Test + public void testGetValuesWithTheCreateAndTheAddExtensionAndModify() { + Patient p = new Patient(); + p.setActive(true); + p.addExtension() + .setUrl("http://acme.org/extension") + .setValue(new StringType("value")); + p.addExtension() + .setUrl("http://acme.org/otherExtension") + .setValue(new StringType("otherValue")); + p.addModifierExtension() + .setUrl("http://acme.org/modifierExtension") + .setValue(new StringType("modifierValue")); + p.addExtension() + .setUrl("http://acme.org/parentExtension") + .addExtension() + .setUrl("http://acme.org/childExtension") + .setValue(new StringType("nestedValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + List values = ourCtx.newTerser().getValues(p, "Patient.active"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof PrimitiveType); + assertTrue(values.get(0) instanceof BooleanType); + assertTrue(((BooleanType) values.get(0)).booleanValue()); + + // No change. + values = ourCtx.newTerser().getValues(p, "Patient.active", true, true); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof PrimitiveType); + assertTrue(values.get(0) instanceof BooleanType); + assertTrue(((BooleanType) values.get(0)).booleanValue()); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof Extension); + assertEquals("http://acme.org/extension", ((Extension) values.get(0)).getUrl()); + assertEquals("value", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')", true, true); + assertEquals(2, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof Extension); + assertEquals("http://acme.org/extension", ((Extension) values.get(0)).getUrl()); + assertEquals("value", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); + assertTrue(values.get(1) instanceof IBaseExtension); + assertTrue(values.get(1) instanceof Extension); + assertEquals("http://acme.org/extension", ((Extension) values.get(1)).getUrl()); + assertNull(((Extension) values.get(1)).getValue()); + + ((Extension) values.get(1)).setValue(new StringType("addedValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + assertTrue(values.get(1) instanceof IBaseExtension); + assertTrue(values.get(1) instanceof Extension); + assertEquals("http://acme.org/extension", ((Extension) values.get(1)).getUrl()); + assertEquals("addedValue", ((StringType) ((Extension) values.get(1)).getValue()).getValueAsString()); + + values = ourCtx.newTerser().getValues(p, "Patient.modifierExtension('http://acme.org/modifierExtension')"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof Extension); + assertEquals("http://acme.org/modifierExtension", ((Extension) values.get(0)).getUrl()); + assertEquals("modifierValue", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); + + values = ourCtx.newTerser().getValues(p, "Patient.modifierExtension('http://acme.org/modifierExtension')", true, true); + assertEquals(2, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof Extension); + assertEquals("http://acme.org/modifierExtension", ((Extension) values.get(0)).getUrl()); + assertEquals("modifierValue", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); + assertTrue(values.get(1) instanceof IBaseExtension); + assertTrue(values.get(1) instanceof Extension); + assertEquals("http://acme.org/modifierExtension", ((Extension) values.get(1)).getUrl()); + assertNull(((Extension) values.get(1)).getValue()); + + ((Extension) values.get(1)).setValue(new StringType("addedModifierValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + assertTrue(values.get(1) instanceof IBaseExtension); + assertTrue(values.get(1) instanceof Extension); + assertEquals("http://acme.org/modifierExtension", ((Extension) values.get(1)).getUrl()); + assertEquals("addedModifierValue", ((StringType) ((Extension) values.get(1)).getValue()).getValueAsString()); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')"); + assertEquals(1, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof Extension); + assertEquals("http://acme.org/childExtension", ((Extension) values.get(0)).getUrl()); + assertEquals("nestedValue", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); + + values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/parentExtension').extension('http://acme.org/childExtension')", true, true); + assertEquals(2, values.size()); + assertTrue(values.get(0) instanceof IBaseExtension); + assertTrue(values.get(0) instanceof Extension); + assertEquals("http://acme.org/childExtension", ((Extension) values.get(0)).getUrl()); + assertEquals("nestedValue", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString()); + assertTrue(values.get(1) instanceof IBaseExtension); + assertTrue(values.get(1) instanceof Extension); + assertEquals("http://acme.org/childExtension", ((Extension) values.get(1)).getUrl()); + assertNull(((Extension) values.get(1)).getValue()); + + ((Extension) values.get(1)).setValue(new StringType("addedNestedValue")); + + System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p)); + + assertTrue(values.get(1) instanceof IBaseExtension); + assertTrue(values.get(1) instanceof Extension); + assertEquals("http://acme.org/childExtension", ((Extension) values.get(1)).getUrl()); + assertEquals("addedNestedValue", ((StringType) ((Extension) values.get(1)).getValue()).getValueAsString()); + } + @Test public void testGetValuesWithTheCreateAndNoOverwrite() { Patient p = new Patient(); From c669bba4bdd099adf78d792aca9425fb9900d778 Mon Sep 17 00:00:00 2001 From: Diederik Muylwyk Date: Wed, 24 Oct 2018 12:08:17 -0400 Subject: [PATCH 6/6] FhirTerser.getValues(...) enhancements are completed. Added changelog entry. --- src/changes/changes.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 9a8f49cd6e1..539e91b4d02 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -116,6 +116,16 @@ the example project]]> if they are not already. + + The FhirTerser getValues(...)]]> methods have been overloaded. The terser can now be + used to create a null-valued element where none exists. Additionally, the terser can now add a null-valued + extension where one or more such extensions already exist. These changes allow better population of FHIR + elements provided an arbitrary FHIR path. + + + The FhirTerser getValues(...)]]> methods were not properly handling modifier + extensions for verions of FHIR prior to DSTU3. This has been corrected. +