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 bf8df49e182..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 @@ -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 { @@ -60,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 @@ -215,8 +247,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, false); + } + + @SuppressWarnings("unchecked") + private List getValues(BaseRuntimeElementCompositeDefinition theCurrentDef, Object theCurrentObj, List theSubList, Class theWantedClass, boolean theCreate, boolean theAddExtension) { String name = theSubList.get(0); List retVal = new ArrayList<>(); @@ -227,16 +263,67 @@ public class FhirTerser { extensionUrl = extensionUrl.substring(0, endIndex); } - List extensions= Collections.emptyList(); - if (theCurrentObj instanceof ISupportsUndeclaredExtensions) { - extensions = ((ISupportsUndeclaredExtensions) theCurrentObj).getUndeclaredExtensionsByUrl(extensionUrl); - } else if (theCurrentObj instanceof IBaseExtension) { - extensions = ((IBaseExtension)theCurrentObj).getExtension(); - } + if (myContext.getVersion().getVersion().isOlderThan(FhirVersionEnum.DSTU3)) { + // DTSU2 + final String extensionDtUrlForLambda = extensionUrl; + List extensionDts = Collections.emptyList(); + if (theCurrentObj instanceof ISupportsUndeclaredExtensions) { + extensionDts = ((ISupportsUndeclaredExtensions) theCurrentObj).getUndeclaredExtensions() + .stream() + .filter(t -> t.getUrl().equals(extensionDtUrlForLambda)) + .collect(Collectors.toList()); - for (ExtensionDt next : extensions) { - if (theWantedClass.isAssignableFrom(next.getClass())) { - retVal.add((T) next); + if (theAddExtension + && (!(theCurrentObj instanceof IBaseExtension) || (extensionDts.isEmpty() && theSubList.size() == 1))) { + extensionDts.add(createEmptyExtensionDt((ISupportsUndeclaredExtensions) theCurrentObj, extensionUrl)); + } + + if (extensionDts.isEmpty() && theCreate) { + 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) { + 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(); + if (theCurrentObj instanceof IBaseHasExtensions) { + extensions = ((IBaseHasExtensions) theCurrentObj).getExtension() + .stream() + .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) { + extensions.add(createEmptyExtension((IBaseHasExtensions) theCurrentObj, extensionUrl)); + } + } + + for (IBaseExtension next : extensions) { + if (theWantedClass.isAssignableFrom(next.getClass())) { + retVal.add((T) next); + } } } @@ -245,7 +332,92 @@ 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, theAddExtension); + 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); + } + + 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(); + + if (theCurrentObj instanceof IBaseHasModifierExtensions) { + extensions = ((IBaseHasModifierExtensions) theCurrentObj).getModifierExtension() + .stream() + .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) { + extensions.add(createEmptyModifierExtension((IBaseHasModifierExtensions) theCurrentObj, extensionUrl)); + } + } + + for (IBaseExtension next : extensions) { + 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, theCreate, theAddExtension); retVal.addAll(foundValues); } } @@ -256,6 +428,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) { @@ -286,26 +466,109 @@ 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, theAddExtension); retVal.addAll(foundValues); } } return retVal; } + /** + * Returns values stored in an element identified by its path. The list of values is of + * type {@link Object}. + * + * @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}. + * + * @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 {@link Object}. + * + * @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. + * @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. + * + * @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); + 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) { List parts = new ArrayList<>(); 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..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 @@ -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,597 @@ 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")); + 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()); + + 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.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); + 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 + 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")); + 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()); + + ((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()); + + 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); + 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 + 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")); + 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")); + + 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()); + + 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); + 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 + 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")); + 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", 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()); + + 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); + assertEquals("http://acme.org/childExtension", extValues.get(0).getUrl()); + assertEquals("nestedValue", ((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")); + 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", 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()); + + 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); + 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 + 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()); + + 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(); + + 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()); + + 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); + assertTrue(values.get(0) instanceof ExtensionDt); + assertEquals("http://acme.org/childExtension", ((ExtensionDt) values.get(0)).getUrl()); + 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)); + + 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')", 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.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); + 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 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 dadc87e9b62..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 @@ -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,683 @@ 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/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()); + + 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/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.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 + 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")); + 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()); + + ((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()); + + 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()); + + 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 + 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")); + 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)); + + 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()); + + 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 + 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")); + 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", 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()); + + 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 = 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 + 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")); + 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", 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()); + + 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()); + + 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 + 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()); + + 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()); + + 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 + 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(); + + 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()); + + 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()); + + 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()); + 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(); + 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", 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')", 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')", 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 public void testVisitWithModelVisitor2() { IModelVisitor2 visitor = mock(IModelVisitor2.class); diff --git a/src/changes/changes.xml b/src/changes/changes.xml index f374f02af8e..c1562231fa3 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -116,6 +116,15 @@ 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. When updating resources in the JPA server, a bug caused index table entries to be refreshed sometimes even though the index value hadn't changed. This issue did not cause incorrect search