Merge branch 'master' of github.com:jamesagnew/hapi-fhir
This commit is contained in:
commit
600f4585d1
|
@ -20,10 +20,10 @@ package ca.uhn.fhir.model.api;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public interface ISupportsUndeclaredExtensions extends IElement {
|
public interface ISupportsUndeclaredExtensions extends IElement {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -42,7 +42,8 @@ public interface ISupportsUndeclaredExtensions extends IElement {
|
||||||
/**
|
/**
|
||||||
* Returns an <b>immutable</b> list containing all extensions (modifier and non-modifier).
|
* Returns an <b>immutable</b> 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<ExtensionDt> getAllUndeclaredExtensions();
|
List<ExtensionDt> getAllUndeclaredExtensions();
|
||||||
|
|
||||||
|
|
|
@ -1,36 +1,5 @@
|
||||||
package ca.uhn.fhir.util;
|
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.*;
|
||||||
import ca.uhn.fhir.context.BaseRuntimeElementDefinition.ChildTypeEnum;
|
import ca.uhn.fhir.context.BaseRuntimeElementDefinition.ChildTypeEnum;
|
||||||
import ca.uhn.fhir.model.api.ExtensionDt;
|
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.base.composite.BaseResourceReferenceDt;
|
||||||
import ca.uhn.fhir.model.primitive.StringDt;
|
import ca.uhn.fhir.model.primitive.StringDt;
|
||||||
import ca.uhn.fhir.parser.DataFormatException;
|
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 {
|
public class FhirTerser {
|
||||||
|
|
||||||
|
@ -60,7 +58,41 @@ public class FhirTerser {
|
||||||
newList.add(theChildDefinition.getElementName());
|
newList.add(theChildDefinition.getElementName());
|
||||||
return newList;
|
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
|
* 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);
|
return retVal.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private <T> List<T> getValues(BaseRuntimeElementCompositeDefinition<?> theCurrentDef, Object theCurrentObj, List<String> theSubList, Class<T> theWantedClass) {
|
private <T> List<T> getValues(BaseRuntimeElementCompositeDefinition<?> theCurrentDef, Object theCurrentObj, List<String> theSubList, Class<T> theWantedClass) {
|
||||||
|
return getValues(theCurrentDef, theCurrentObj, theSubList, theWantedClass, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private <T> List<T> getValues(BaseRuntimeElementCompositeDefinition<?> theCurrentDef, Object theCurrentObj, List<String> theSubList, Class<T> theWantedClass, boolean theCreate, boolean theAddExtension) {
|
||||||
String name = theSubList.get(0);
|
String name = theSubList.get(0);
|
||||||
List<T> retVal = new ArrayList<>();
|
List<T> retVal = new ArrayList<>();
|
||||||
|
|
||||||
|
@ -227,16 +263,67 @@ public class FhirTerser {
|
||||||
extensionUrl = extensionUrl.substring(0, endIndex);
|
extensionUrl = extensionUrl.substring(0, endIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<ExtensionDt> extensions= Collections.emptyList();
|
if (myContext.getVersion().getVersion().isOlderThan(FhirVersionEnum.DSTU3)) {
|
||||||
if (theCurrentObj instanceof ISupportsUndeclaredExtensions) {
|
// DTSU2
|
||||||
extensions = ((ISupportsUndeclaredExtensions) theCurrentObj).getUndeclaredExtensionsByUrl(extensionUrl);
|
final String extensionDtUrlForLambda = extensionUrl;
|
||||||
} else if (theCurrentObj instanceof IBaseExtension) {
|
List<ExtensionDt> extensionDts = Collections.emptyList();
|
||||||
extensions = ((IBaseExtension)theCurrentObj).getExtension();
|
if (theCurrentObj instanceof ISupportsUndeclaredExtensions) {
|
||||||
}
|
extensionDts = ((ISupportsUndeclaredExtensions) theCurrentObj).getUndeclaredExtensions()
|
||||||
|
.stream()
|
||||||
|
.filter(t -> t.getUrl().equals(extensionDtUrlForLambda))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
for (ExtensionDt next : extensions) {
|
if (theAddExtension
|
||||||
if (theWantedClass.isAssignableFrom(next.getClass())) {
|
&& (!(theCurrentObj instanceof IBaseExtension) || (extensionDts.isEmpty() && theSubList.size() == 1))) {
|
||||||
retVal.add((T) next);
|
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<IBaseExtension> 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<>();
|
retVal = new ArrayList<>();
|
||||||
for (T nextElement : values) {
|
for (T nextElement : values) {
|
||||||
BaseRuntimeElementCompositeDefinition<?> nextChildDef = (BaseRuntimeElementCompositeDefinition<?>) myContext.getElementDefinition((Class<? extends IBase>) nextElement.getClass());
|
BaseRuntimeElementCompositeDefinition<?> nextChildDef = (BaseRuntimeElementCompositeDefinition<?>) myContext.getElementDefinition((Class<? extends IBase>) nextElement.getClass());
|
||||||
List<T> foundValues = getValues(nextChildDef, nextElement, theSubList.subList(1, theSubList.size()), theWantedClass);
|
List<T> 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<ExtensionDt> 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<IBaseExtension> 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<T> values = retVal;
|
||||||
|
retVal = new ArrayList<>();
|
||||||
|
for (T nextElement : values) {
|
||||||
|
BaseRuntimeElementCompositeDefinition<?> nextChildDef = (BaseRuntimeElementCompositeDefinition<?>) myContext.getElementDefinition((Class<? extends IBase>) nextElement.getClass());
|
||||||
|
List<T> foundValues = getValues(nextChildDef, nextElement, theSubList.subList(1, theSubList.size()), theWantedClass, theCreate, theAddExtension);
|
||||||
retVal.addAll(foundValues);
|
retVal.addAll(foundValues);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -256,6 +428,14 @@ public class FhirTerser {
|
||||||
BaseRuntimeChildDefinition nextDef = theCurrentDef.getChildByNameOrThrowDataFormatException(name);
|
BaseRuntimeChildDefinition nextDef = theCurrentDef.getChildByNameOrThrowDataFormatException(name);
|
||||||
List<? extends IBase> values = nextDef.getAccessor().getValues(theCurrentObj);
|
List<? extends IBase> values = nextDef.getAccessor().getValues(theCurrentObj);
|
||||||
|
|
||||||
|
if (values.isEmpty() && theCreate) {
|
||||||
|
IBase value = nextDef.getChildByName(name).newInstance();
|
||||||
|
nextDef.getMutator().addValue(theCurrentObj, value);
|
||||||
|
List<IBase> list = new ArrayList<>();
|
||||||
|
list.add(value);
|
||||||
|
values = list;
|
||||||
|
}
|
||||||
|
|
||||||
if (theSubList.size() == 1) {
|
if (theSubList.size() == 1) {
|
||||||
if (nextDef instanceof RuntimeChildChoiceDefinition) {
|
if (nextDef instanceof RuntimeChildChoiceDefinition) {
|
||||||
for (IBase next : values) {
|
for (IBase next : values) {
|
||||||
|
@ -286,26 +466,109 @@ public class FhirTerser {
|
||||||
} else {
|
} else {
|
||||||
for (IBase nextElement : values) {
|
for (IBase nextElement : values) {
|
||||||
BaseRuntimeElementCompositeDefinition<?> nextChildDef = (BaseRuntimeElementCompositeDefinition<?>) myContext.getElementDefinition(nextElement.getClass());
|
BaseRuntimeElementCompositeDefinition<?> nextChildDef = (BaseRuntimeElementCompositeDefinition<?>) myContext.getElementDefinition(nextElement.getClass());
|
||||||
List<T> foundValues = getValues(nextChildDef, nextElement, theSubList.subList(1, theSubList.size()), theWantedClass);
|
List<T> foundValues = getValues(nextChildDef, nextElement, theSubList.subList(1, theSubList.size()), theWantedClass, theCreate, theAddExtension);
|
||||||
retVal.addAll(foundValues);
|
retVal.addAll(foundValues);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return retVal;
|
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<Object> getValues(IBaseResource theResource, String thePath) {
|
public List<Object> getValues(IBaseResource theResource, String thePath) {
|
||||||
Class<Object> wantedClass = Object.class;
|
Class<Object> wantedClass = Object.class;
|
||||||
|
|
||||||
return getValues(theResource, thePath, wantedClass);
|
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 <code>true</code>, the terser will create a null-valued element where none exists.
|
||||||
|
* @return A list of values of type {@link Object}.
|
||||||
|
*/
|
||||||
|
public List<Object> getValues(IBaseResource theResource, String thePath, boolean theCreate) {
|
||||||
|
Class<Object> 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 <code>true</code>, the terser will create a null-valued element where none exists.
|
||||||
|
* @param theAddExtension When set to <code>true</code>, 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<Object> getValues(IBaseResource theResource, String thePath, boolean theCreate, boolean theAddExtension) {
|
||||||
|
Class<Object> 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 <code>theWantedClass</code>.
|
||||||
|
*
|
||||||
|
* @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 <T> Type declared by <code>theWantedClass</code>
|
||||||
|
* @return A list of values of type <code>theWantedClass</code>.
|
||||||
|
*/
|
||||||
public <T> List<T> getValues(IBaseResource theResource, String thePath, Class<T> theWantedClass) {
|
public <T> List<T> getValues(IBaseResource theResource, String thePath, Class<T> theWantedClass) {
|
||||||
RuntimeResourceDefinition def = myContext.getResourceDefinition(theResource);
|
RuntimeResourceDefinition def = myContext.getResourceDefinition(theResource);
|
||||||
List<String> parts = parsePath(def, thePath);
|
List<String> parts = parsePath(def, thePath);
|
||||||
return getValues(def, theResource, parts, theWantedClass);
|
return getValues(def, theResource, parts, theWantedClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns values stored in an element identified by its path. The list of values is of
|
||||||
|
* type <code>theWantedClass</code>.
|
||||||
|
*
|
||||||
|
* @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 <code>true</code>, the terser will create a null-valued element where none exists.
|
||||||
|
* @param <T> Type declared by <code>theWantedClass</code>
|
||||||
|
* @return A list of values of type <code>theWantedClass</code>.
|
||||||
|
*/
|
||||||
|
public <T> List<T> getValues(IBaseResource theResource, String thePath, Class<T> theWantedClass, boolean theCreate) {
|
||||||
|
RuntimeResourceDefinition def = myContext.getResourceDefinition(theResource);
|
||||||
|
List<String> 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 <code>theWantedClass</code>.
|
||||||
|
*
|
||||||
|
* @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 <code>true</code>, the terser will create a null-valued element where none exists.
|
||||||
|
* @param theAddExtension When set to <code>true</code>, the terser will add a null-valued extension where one or more such extensions already exist.
|
||||||
|
* @param <T> Type declared by <code>theWantedClass</code>
|
||||||
|
* @return A list of values of type <code>theWantedClass</code>.
|
||||||
|
*/
|
||||||
|
public <T> List<T> getValues(IBaseResource theResource, String thePath, Class<T> theWantedClass, boolean theCreate, boolean theAddExtension) {
|
||||||
|
RuntimeResourceDefinition def = myContext.getResourceDefinition(theResource);
|
||||||
|
List<String> parts = parsePath(def, thePath);
|
||||||
|
return getValues(def, theResource, parts, theWantedClass, theCreate, theAddExtension);
|
||||||
|
}
|
||||||
|
|
||||||
private List<String> parsePath(BaseRuntimeElementCompositeDefinition<?> theElementDef, String thePath) {
|
private List<String> parsePath(BaseRuntimeElementCompositeDefinition<?> theElementDef, String thePath) {
|
||||||
List<String> parts = new ArrayList<>();
|
List<String> parts = new ArrayList<>();
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -25,6 +25,7 @@ import ca.uhn.fhir.jpa.dao.data.IForcedIdDao;
|
||||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamUriDao;
|
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamUriDao;
|
||||||
import ca.uhn.fhir.jpa.dao.data.IResourceSearchViewDao;
|
import ca.uhn.fhir.jpa.dao.data.IResourceSearchViewDao;
|
||||||
import ca.uhn.fhir.jpa.dao.data.IResourceTagDao;
|
import ca.uhn.fhir.jpa.dao.data.IResourceTagDao;
|
||||||
|
import ca.uhn.fhir.jpa.dao.index.ResourceIndexedSearchParams;
|
||||||
import ca.uhn.fhir.jpa.entity.*;
|
import ca.uhn.fhir.jpa.entity.*;
|
||||||
import ca.uhn.fhir.jpa.search.JpaRuntimeSearchParam;
|
import ca.uhn.fhir.jpa.search.JpaRuntimeSearchParam;
|
||||||
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
|
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
|
||||||
|
@ -1496,7 +1497,7 @@ public class SearchBuilder implements ISearchBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<String> uniqueQueryStrings = BaseHapiFhirDao.extractCompositeStringUniquesValueChains(myResourceName, params);
|
Set<String> uniqueQueryStrings = ResourceIndexedSearchParams.extractCompositeStringUniquesValueChains(myResourceName, params);
|
||||||
if (ourTrackHandlersForUnitTest) {
|
if (ourTrackHandlersForUnitTest) {
|
||||||
ourLastHandlerParamsForUnitTest = theParams;
|
ourLastHandlerParamsForUnitTest = theParams;
|
||||||
ourLastHandlerMechanismForUnitTest = HandlerTypeEnum.UNIQUE_INDEX;
|
ourLastHandlerMechanismForUnitTest = HandlerTypeEnum.UNIQUE_INDEX;
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package ca.uhn.fhir.jpa.dao.index;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||||
|
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||||
|
import ca.uhn.fhir.jpa.dao.ISearchParamExtractor;
|
||||||
|
import ca.uhn.fhir.jpa.dao.ISearchParamRegistry;
|
||||||
|
import ca.uhn.fhir.jpa.dao.data.IForcedIdDao;
|
||||||
|
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedCompositeStringUniqueDao;
|
||||||
|
|
||||||
|
public interface IndexingSupport {
|
||||||
|
public DaoConfig getConfig();
|
||||||
|
public ISearchParamExtractor getSearchParamExtractor();
|
||||||
|
public ISearchParamRegistry getSearchParamRegistry();
|
||||||
|
public FhirContext getContext();
|
||||||
|
public EntityManager getEntityManager();
|
||||||
|
public <R extends IBaseResource> IFhirResourceDao<R> getDao(Class<R> theType);
|
||||||
|
public Map<Class<? extends IBaseResource>, IFhirResourceDao<?>> getResourceTypeToDao();
|
||||||
|
public boolean isLogicalReference(IIdType nextId);
|
||||||
|
public IForcedIdDao getForcedIdDao();
|
||||||
|
public <R extends IBaseResource> Set<Long> processMatchUrl(String theMatchUrl, Class<R> theResourceType);
|
||||||
|
public Long translateForcedIdToPid(String theResourceName, String theResourceId);
|
||||||
|
public String toResourceName(Class<? extends IBaseResource> theResourceType);
|
||||||
|
public IResourceIndexedCompositeStringUniqueDao getResourceIndexedCompositeStringUniqueDao();
|
||||||
|
}
|
|
@ -0,0 +1,852 @@
|
||||||
|
package ca.uhn.fhir.jpa.dao.index;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.StringUtils.compare;
|
||||||
|
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
|
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBase;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseExtension;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseReference;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
import org.hl7.fhir.r4.model.CanonicalType;
|
||||||
|
import org.hl7.fhir.r4.model.Reference;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.ConfigurationException;
|
||||||
|
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||||
|
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||||
|
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
|
||||||
|
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||||
|
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||||
|
import ca.uhn.fhir.jpa.dao.PathAndRef;
|
||||||
|
import ca.uhn.fhir.jpa.entity.BaseResourceIndexedSearchParam;
|
||||||
|
import ca.uhn.fhir.jpa.entity.ForcedId;
|
||||||
|
import ca.uhn.fhir.jpa.entity.ResourceIndexedCompositeStringUnique;
|
||||||
|
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamCoords;
|
||||||
|
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamDate;
|
||||||
|
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamNumber;
|
||||||
|
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamQuantity;
|
||||||
|
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString;
|
||||||
|
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamToken;
|
||||||
|
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamUri;
|
||||||
|
import ca.uhn.fhir.jpa.entity.ResourceLink;
|
||||||
|
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||||
|
import ca.uhn.fhir.jpa.search.JpaRuntimeSearchParam;
|
||||||
|
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||||
|
import ca.uhn.fhir.parser.DataFormatException;
|
||||||
|
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||||
|
import ca.uhn.fhir.util.FhirTerser;
|
||||||
|
import ca.uhn.fhir.util.UrlUtil;
|
||||||
|
|
||||||
|
public class ResourceIndexedSearchParams {
|
||||||
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceIndexedSearchParams.class);
|
||||||
|
|
||||||
|
// FIXME rename
|
||||||
|
private final IndexingSupport myIndexingService;
|
||||||
|
|
||||||
|
private final Collection<ResourceIndexedSearchParamString> stringParams;
|
||||||
|
private final Collection<ResourceIndexedSearchParamToken> tokenParams;
|
||||||
|
private final Collection<ResourceIndexedSearchParamNumber> numberParams;
|
||||||
|
private final Collection<ResourceIndexedSearchParamQuantity> quantityParams;
|
||||||
|
private final Collection<ResourceIndexedSearchParamDate> dateParams;
|
||||||
|
private final Collection<ResourceIndexedSearchParamUri> uriParams;
|
||||||
|
private final Collection<ResourceIndexedSearchParamCoords> coordsParams;
|
||||||
|
private final Collection<ResourceIndexedCompositeStringUnique> compositeStringUniques;
|
||||||
|
private final Collection<ResourceLink> links;
|
||||||
|
|
||||||
|
private Set<String> populatedResourceLinkParameters = Collections.emptySet();
|
||||||
|
|
||||||
|
public ResourceIndexedSearchParams(IndexingSupport indexingService, ResourceTable theEntity) {
|
||||||
|
this.myIndexingService = indexingService;
|
||||||
|
|
||||||
|
stringParams = new ArrayList<>();
|
||||||
|
if (theEntity.isParamsStringPopulated()) {
|
||||||
|
stringParams.addAll(theEntity.getParamsString());
|
||||||
|
}
|
||||||
|
tokenParams = new ArrayList<>();
|
||||||
|
if (theEntity.isParamsTokenPopulated()) {
|
||||||
|
tokenParams.addAll(theEntity.getParamsToken());
|
||||||
|
}
|
||||||
|
numberParams = new ArrayList<>();
|
||||||
|
if (theEntity.isParamsNumberPopulated()) {
|
||||||
|
numberParams.addAll(theEntity.getParamsNumber());
|
||||||
|
}
|
||||||
|
quantityParams = new ArrayList<>();
|
||||||
|
if (theEntity.isParamsQuantityPopulated()) {
|
||||||
|
quantityParams.addAll(theEntity.getParamsQuantity());
|
||||||
|
}
|
||||||
|
dateParams = new ArrayList<>();
|
||||||
|
if (theEntity.isParamsDatePopulated()) {
|
||||||
|
dateParams.addAll(theEntity.getParamsDate());
|
||||||
|
}
|
||||||
|
uriParams = new ArrayList<>();
|
||||||
|
if (theEntity.isParamsUriPopulated()) {
|
||||||
|
uriParams.addAll(theEntity.getParamsUri());
|
||||||
|
}
|
||||||
|
coordsParams = new ArrayList<>();
|
||||||
|
if (theEntity.isParamsCoordsPopulated()) {
|
||||||
|
coordsParams.addAll(theEntity.getParamsCoords());
|
||||||
|
}
|
||||||
|
links = new ArrayList<>();
|
||||||
|
if (theEntity.isHasLinks()) {
|
||||||
|
links.addAll(theEntity.getResourceLinks());
|
||||||
|
}
|
||||||
|
|
||||||
|
compositeStringUniques = new ArrayList<>();
|
||||||
|
if (theEntity.isParamsCompositeStringUniquePresent()) {
|
||||||
|
compositeStringUniques.addAll(theEntity.getParamsCompositeStringUnique());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResourceIndexedSearchParams(IndexingSupport indexingService) {
|
||||||
|
this.myIndexingService = indexingService;
|
||||||
|
|
||||||
|
stringParams = Collections.emptySet();
|
||||||
|
tokenParams = Collections.emptySet();
|
||||||
|
numberParams = Collections.emptySet();
|
||||||
|
quantityParams = Collections.emptySet();
|
||||||
|
dateParams = Collections.emptySet();
|
||||||
|
uriParams = Collections.emptySet();
|
||||||
|
coordsParams = Collections.emptySet();
|
||||||
|
links = Collections.emptySet();
|
||||||
|
compositeStringUniques = Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResourceIndexedSearchParams(IndexingSupport indexingService, Date theUpdateTime, ResourceTable theEntity, IBaseResource theResource, ResourceIndexedSearchParams existingParams) {
|
||||||
|
this.myIndexingService = indexingService;
|
||||||
|
|
||||||
|
stringParams = extractSearchParamStrings(theEntity, theResource);
|
||||||
|
numberParams = extractSearchParamNumber(theEntity, theResource);
|
||||||
|
quantityParams = extractSearchParamQuantity(theEntity, theResource);
|
||||||
|
dateParams = extractSearchParamDates(theEntity, theResource);
|
||||||
|
uriParams = extractSearchParamUri(theEntity, theResource);
|
||||||
|
coordsParams = extractSearchParamCoords(theEntity, theResource);
|
||||||
|
|
||||||
|
ourLog.trace("Storing date indexes: {}", dateParams);
|
||||||
|
|
||||||
|
tokenParams = new HashSet<>();
|
||||||
|
for (BaseResourceIndexedSearchParam next : extractSearchParamTokens(theEntity, theResource)) {
|
||||||
|
if (next instanceof ResourceIndexedSearchParamToken) {
|
||||||
|
tokenParams.add((ResourceIndexedSearchParamToken) next);
|
||||||
|
} else {
|
||||||
|
stringParams.add((ResourceIndexedSearchParamString) next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<Entry<String, RuntimeSearchParam>> activeSearchParams = myIndexingService.getSearchParamRegistry().getActiveSearchParams(theEntity.getResourceType()).entrySet();
|
||||||
|
DaoConfig myConfig = indexingService.getConfig();
|
||||||
|
if (myConfig .getIndexMissingFields() == DaoConfig.IndexEnabledEnum.ENABLED) {
|
||||||
|
findMissingSearchParams(theEntity, activeSearchParams, RestSearchParameterTypeEnum.STRING, stringParams);
|
||||||
|
findMissingSearchParams(theEntity, activeSearchParams, RestSearchParameterTypeEnum.NUMBER, numberParams);
|
||||||
|
findMissingSearchParams(theEntity, activeSearchParams, RestSearchParameterTypeEnum.QUANTITY, quantityParams);
|
||||||
|
findMissingSearchParams(theEntity, activeSearchParams, RestSearchParameterTypeEnum.DATE, dateParams);
|
||||||
|
findMissingSearchParams(theEntity, activeSearchParams, RestSearchParameterTypeEnum.URI, uriParams);
|
||||||
|
findMissingSearchParams(theEntity, activeSearchParams, RestSearchParameterTypeEnum.TOKEN, tokenParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
setUpdatedTime(stringParams, theUpdateTime);
|
||||||
|
setUpdatedTime(numberParams, theUpdateTime);
|
||||||
|
setUpdatedTime(quantityParams, theUpdateTime);
|
||||||
|
setUpdatedTime(dateParams, theUpdateTime);
|
||||||
|
setUpdatedTime(uriParams, theUpdateTime);
|
||||||
|
setUpdatedTime(coordsParams, theUpdateTime);
|
||||||
|
setUpdatedTime(tokenParams, theUpdateTime);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle references within the resource that are match URLs, for example references like "Patient?identifier=foo". These match URLs are resolved and replaced with the ID of the
|
||||||
|
* matching resource.
|
||||||
|
*/
|
||||||
|
if (myConfig.isAllowInlineMatchUrlReferences()) {
|
||||||
|
FhirTerser terser = myIndexingService.getContext().newTerser();
|
||||||
|
List<IBaseReference> allRefs = terser.getAllPopulatedChildElementsOfType(theResource, IBaseReference.class);
|
||||||
|
for (IBaseReference nextRef : allRefs) {
|
||||||
|
IIdType nextId = nextRef.getReferenceElement();
|
||||||
|
String nextIdText = nextId.getValue();
|
||||||
|
if (nextIdText == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int qmIndex = nextIdText.indexOf('?');
|
||||||
|
if (qmIndex != -1) {
|
||||||
|
for (int i = qmIndex - 1; i >= 0; i--) {
|
||||||
|
if (nextIdText.charAt(i) == '/') {
|
||||||
|
if (i < nextIdText.length() - 1 && nextIdText.charAt(i + 1) == '?') {
|
||||||
|
// Just in case the URL is in the form Patient/?foo=bar
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
nextIdText = nextIdText.substring(i + 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String resourceTypeString = nextIdText.substring(0, nextIdText.indexOf('?')).replace("/", "");
|
||||||
|
RuntimeResourceDefinition matchResourceDef = myIndexingService.getContext().getResourceDefinition(resourceTypeString);
|
||||||
|
if (matchResourceDef == null) {
|
||||||
|
String msg = myIndexingService.getContext().getLocalizer().getMessage(BaseHapiFhirDao.class, "invalidMatchUrlInvalidResourceType", nextId.getValue(), resourceTypeString);
|
||||||
|
throw new InvalidRequestException(msg);
|
||||||
|
}
|
||||||
|
Class<? extends IBaseResource> matchResourceType = matchResourceDef.getImplementingClass();
|
||||||
|
Set<Long> matches = myIndexingService.processMatchUrl(nextIdText, matchResourceType);
|
||||||
|
if (matches.isEmpty()) {
|
||||||
|
String msg = indexingService.getContext().getLocalizer().getMessage(BaseHapiFhirDao.class, "invalidMatchUrlNoMatches", nextId.getValue());
|
||||||
|
throw new ResourceNotFoundException(msg);
|
||||||
|
}
|
||||||
|
if (matches.size() > 1) {
|
||||||
|
String msg = indexingService.getContext().getLocalizer().getMessage(BaseHapiFhirDao.class, "invalidMatchUrlMultipleMatches", nextId.getValue());
|
||||||
|
throw new PreconditionFailedException(msg);
|
||||||
|
}
|
||||||
|
Long next = matches.iterator().next();
|
||||||
|
String newId = translatePidIdToForcedId(resourceTypeString, next);
|
||||||
|
ourLog.debug("Replacing inline match URL[{}] with ID[{}}", nextId.getValue(), newId);
|
||||||
|
nextRef.setReference(newId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
links = new HashSet<>();
|
||||||
|
populatedResourceLinkParameters = extractResourceLinks(theEntity, theResource, links, theUpdateTime);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the existing resource already has links and those match links we still want, use them instead of removing them and re adding them
|
||||||
|
*/
|
||||||
|
for (Iterator<ResourceLink> existingLinkIter = existingParams.getResourceLinks().iterator(); existingLinkIter.hasNext(); ) {
|
||||||
|
ResourceLink nextExisting = existingLinkIter.next();
|
||||||
|
if (links.remove(nextExisting)) {
|
||||||
|
existingLinkIter.remove();
|
||||||
|
links.add(nextExisting);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle composites
|
||||||
|
*/
|
||||||
|
compositeStringUniques = extractCompositeStringUniques(theEntity, stringParams, tokenParams, numberParams, quantityParams, dateParams, uriParams, links);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<ResourceLink> getResourceLinks() {
|
||||||
|
return links;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected Set<ResourceIndexedSearchParamCoords> extractSearchParamCoords(ResourceTable theEntity, IBaseResource theResource) {
|
||||||
|
return myIndexingService.getSearchParamExtractor().extractSearchParamCoords(theEntity, theResource);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Set<ResourceIndexedSearchParamDate> extractSearchParamDates(ResourceTable theEntity, IBaseResource theResource) {
|
||||||
|
return myIndexingService.getSearchParamExtractor().extractSearchParamDates(theEntity, theResource);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Set<ResourceIndexedSearchParamNumber> extractSearchParamNumber(ResourceTable theEntity, IBaseResource theResource) {
|
||||||
|
return myIndexingService.getSearchParamExtractor().extractSearchParamNumber(theEntity, theResource);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Set<ResourceIndexedSearchParamQuantity> extractSearchParamQuantity(ResourceTable theEntity, IBaseResource theResource) {
|
||||||
|
return myIndexingService.getSearchParamExtractor().extractSearchParamQuantity(theEntity, theResource);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Set<ResourceIndexedSearchParamString> extractSearchParamStrings(ResourceTable theEntity, IBaseResource theResource) {
|
||||||
|
return myIndexingService.getSearchParamExtractor().extractSearchParamStrings(theEntity, theResource);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Set<BaseResourceIndexedSearchParam> extractSearchParamTokens(ResourceTable theEntity, IBaseResource theResource) {
|
||||||
|
return myIndexingService.getSearchParamExtractor().extractSearchParamTokens(theEntity, theResource);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Set<ResourceIndexedSearchParamUri> extractSearchParamUri(ResourceTable theEntity, IBaseResource theResource) {
|
||||||
|
return myIndexingService.getSearchParamExtractor().extractSearchParamUri(theEntity, theResource);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private <RT extends BaseResourceIndexedSearchParam> void findMissingSearchParams(ResourceTable theEntity, Set<Entry<String, RuntimeSearchParam>> activeSearchParams, RestSearchParameterTypeEnum type,
|
||||||
|
Collection<RT> paramCollection) {
|
||||||
|
for (Entry<String, RuntimeSearchParam> nextEntry : activeSearchParams) {
|
||||||
|
String nextParamName = nextEntry.getKey();
|
||||||
|
if (nextEntry.getValue().getParamType() == type) {
|
||||||
|
boolean haveParam = false;
|
||||||
|
for (BaseResourceIndexedSearchParam nextParam : paramCollection) {
|
||||||
|
if (nextParam.getParamName().equals(nextParamName)) {
|
||||||
|
haveParam = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!haveParam) {
|
||||||
|
BaseResourceIndexedSearchParam param;
|
||||||
|
switch (type) {
|
||||||
|
case DATE:
|
||||||
|
param = new ResourceIndexedSearchParamDate();
|
||||||
|
break;
|
||||||
|
case NUMBER:
|
||||||
|
param = new ResourceIndexedSearchParamNumber();
|
||||||
|
break;
|
||||||
|
case QUANTITY:
|
||||||
|
param = new ResourceIndexedSearchParamQuantity();
|
||||||
|
break;
|
||||||
|
case STRING:
|
||||||
|
param = new ResourceIndexedSearchParamString()
|
||||||
|
.setDaoConfig(myIndexingService.getConfig());
|
||||||
|
break;
|
||||||
|
case TOKEN:
|
||||||
|
param = new ResourceIndexedSearchParamToken();
|
||||||
|
break;
|
||||||
|
case URI:
|
||||||
|
param = new ResourceIndexedSearchParamUri();
|
||||||
|
break;
|
||||||
|
case COMPOSITE:
|
||||||
|
case HAS:
|
||||||
|
case REFERENCE:
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
param.setResource(theEntity);
|
||||||
|
param.setMissing(true);
|
||||||
|
param.setParamName(nextParamName);
|
||||||
|
paramCollection.add((RT) param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParams(ResourceTable theEntity) {
|
||||||
|
theEntity.setParamsString(stringParams);
|
||||||
|
theEntity.setParamsStringPopulated(stringParams.isEmpty() == false);
|
||||||
|
theEntity.setParamsToken(tokenParams);
|
||||||
|
theEntity.setParamsTokenPopulated(tokenParams.isEmpty() == false);
|
||||||
|
theEntity.setParamsNumber(numberParams);
|
||||||
|
theEntity.setParamsNumberPopulated(numberParams.isEmpty() == false);
|
||||||
|
theEntity.setParamsQuantity(quantityParams);
|
||||||
|
theEntity.setParamsQuantityPopulated(quantityParams.isEmpty() == false);
|
||||||
|
theEntity.setParamsDate(dateParams);
|
||||||
|
theEntity.setParamsDatePopulated(dateParams.isEmpty() == false);
|
||||||
|
theEntity.setParamsUri(uriParams);
|
||||||
|
theEntity.setParamsUriPopulated(uriParams.isEmpty() == false);
|
||||||
|
theEntity.setParamsCoords(coordsParams);
|
||||||
|
theEntity.setParamsCoordsPopulated(coordsParams.isEmpty() == false);
|
||||||
|
theEntity.setParamsCompositeStringUniquePresent(compositeStringUniques.isEmpty() == false);
|
||||||
|
theEntity.setResourceLinks(links);
|
||||||
|
theEntity.setHasLinks(links.isEmpty() == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Set<ResourceIndexedCompositeStringUnique> extractCompositeStringUniques(ResourceTable theEntity, Collection<ResourceIndexedSearchParamString> theStringParams, Collection<ResourceIndexedSearchParamToken> theTokenParams, Collection<ResourceIndexedSearchParamNumber> theNumberParams, Collection<ResourceIndexedSearchParamQuantity> theQuantityParams, Collection<ResourceIndexedSearchParamDate> theDateParams, Collection<ResourceIndexedSearchParamUri> theUriParams, Collection<ResourceLink> theLinks) {
|
||||||
|
Set<ResourceIndexedCompositeStringUnique> compositeStringUniques;
|
||||||
|
compositeStringUniques = new HashSet<>();
|
||||||
|
List<JpaRuntimeSearchParam> uniqueSearchParams = myIndexingService.getSearchParamRegistry().getActiveUniqueSearchParams(theEntity.getResourceType());
|
||||||
|
for (JpaRuntimeSearchParam next : uniqueSearchParams) {
|
||||||
|
|
||||||
|
List<List<String>> partsChoices = new ArrayList<>();
|
||||||
|
|
||||||
|
for (RuntimeSearchParam nextCompositeOf : next.getCompositeOf()) {
|
||||||
|
Collection<? extends BaseResourceIndexedSearchParam> paramsListForCompositePart = null;
|
||||||
|
Collection<ResourceLink> linksForCompositePart = null;
|
||||||
|
Collection<String> linksForCompositePartWantPaths = null;
|
||||||
|
switch (nextCompositeOf.getParamType()) {
|
||||||
|
case NUMBER:
|
||||||
|
paramsListForCompositePart = theNumberParams;
|
||||||
|
break;
|
||||||
|
case DATE:
|
||||||
|
paramsListForCompositePart = theDateParams;
|
||||||
|
break;
|
||||||
|
case STRING:
|
||||||
|
paramsListForCompositePart = theStringParams;
|
||||||
|
break;
|
||||||
|
case TOKEN:
|
||||||
|
paramsListForCompositePart = theTokenParams;
|
||||||
|
break;
|
||||||
|
case REFERENCE:
|
||||||
|
linksForCompositePart = theLinks;
|
||||||
|
linksForCompositePartWantPaths = new HashSet<>();
|
||||||
|
linksForCompositePartWantPaths.addAll(nextCompositeOf.getPathsSplit());
|
||||||
|
break;
|
||||||
|
case QUANTITY:
|
||||||
|
paramsListForCompositePart = theQuantityParams;
|
||||||
|
break;
|
||||||
|
case URI:
|
||||||
|
paramsListForCompositePart = theUriParams;
|
||||||
|
break;
|
||||||
|
case COMPOSITE:
|
||||||
|
case HAS:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<String> nextChoicesList = new ArrayList<>();
|
||||||
|
partsChoices.add(nextChoicesList);
|
||||||
|
|
||||||
|
String key = UrlUtil.escapeUrlParam(nextCompositeOf.getName());
|
||||||
|
if (paramsListForCompositePart != null) {
|
||||||
|
for (BaseResourceIndexedSearchParam nextParam : paramsListForCompositePart) {
|
||||||
|
if (nextParam.getParamName().equals(nextCompositeOf.getName())) {
|
||||||
|
IQueryParameterType nextParamAsClientParam = nextParam.toQueryParameterType();
|
||||||
|
String value = nextParamAsClientParam.getValueAsQueryToken(myIndexingService.getContext());
|
||||||
|
if (isNotBlank(value)) {
|
||||||
|
value = UrlUtil.escapeUrlParam(value);
|
||||||
|
nextChoicesList.add(key + "=" + value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (linksForCompositePart != null) {
|
||||||
|
for (ResourceLink nextLink : linksForCompositePart) {
|
||||||
|
if (linksForCompositePartWantPaths.contains(nextLink.getSourcePath())) {
|
||||||
|
String value = nextLink.getTargetResource().getIdDt().toUnqualifiedVersionless().getValue();
|
||||||
|
if (isNotBlank(value)) {
|
||||||
|
value = UrlUtil.escapeUrlParam(value);
|
||||||
|
nextChoicesList.add(key + "=" + value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<String> queryStringsToPopulate = extractCompositeStringUniquesValueChains(theEntity.getResourceType(), partsChoices);
|
||||||
|
|
||||||
|
for (String nextQueryString : queryStringsToPopulate) {
|
||||||
|
if (isNotBlank(nextQueryString)) {
|
||||||
|
compositeStringUniques.add(new ResourceIndexedCompositeStringUnique(theEntity, nextQueryString));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return compositeStringUniques;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is used to create a set of all possible combinations of
|
||||||
|
* parameters across a set of search parameters. An example of why
|
||||||
|
* this is needed:
|
||||||
|
* <p>
|
||||||
|
* Let's say we have a unique index on (Patient:gender AND Patient:name).
|
||||||
|
* Then we pass in <code>SMITH, John</code> with a gender of <code>male</code>.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* In this case, because the name parameter matches both first and last name,
|
||||||
|
* we now need two unique indexes:
|
||||||
|
* <ul>
|
||||||
|
* <li>Patient?gender=male&name=SMITH</li>
|
||||||
|
* <li>Patient?gender=male&name=JOHN</li>
|
||||||
|
* </ul>
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* So this recursive algorithm calculates those
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param theResourceType E.g. <code>Patient
|
||||||
|
* @param thePartsChoices E.g. <code>[[gender=male], [name=SMITH, name=JOHN]]</code>
|
||||||
|
*/
|
||||||
|
public static Set<String> extractCompositeStringUniquesValueChains(String
|
||||||
|
theResourceType, List<List<String>> thePartsChoices) {
|
||||||
|
|
||||||
|
for (List<String> next : thePartsChoices) {
|
||||||
|
next.removeIf(StringUtils::isBlank);
|
||||||
|
if (next.isEmpty()) {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thePartsChoices.isEmpty()) {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
thePartsChoices.sort((o1, o2) -> {
|
||||||
|
String str1 = null;
|
||||||
|
String str2 = null;
|
||||||
|
if (o1.size() > 0) {
|
||||||
|
str1 = o1.get(0);
|
||||||
|
}
|
||||||
|
if (o2.size() > 0) {
|
||||||
|
str2 = o2.get(0);
|
||||||
|
}
|
||||||
|
return compare(str1, str2);
|
||||||
|
});
|
||||||
|
|
||||||
|
List<String> values = new ArrayList<>();
|
||||||
|
Set<String> queryStringsToPopulate = new HashSet<>();
|
||||||
|
extractCompositeStringUniquesValueChains(theResourceType, thePartsChoices, values, queryStringsToPopulate);
|
||||||
|
return queryStringsToPopulate;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void extractCompositeStringUniquesValueChains(String
|
||||||
|
theResourceType, List<List<String>> thePartsChoices, List<String> theValues, Set<String> theQueryStringsToPopulate) {
|
||||||
|
if (thePartsChoices.size() > 0) {
|
||||||
|
List<String> nextList = thePartsChoices.get(0);
|
||||||
|
Collections.sort(nextList);
|
||||||
|
for (String nextChoice : nextList) {
|
||||||
|
theValues.add(nextChoice);
|
||||||
|
extractCompositeStringUniquesValueChains(theResourceType, thePartsChoices.subList(1, thePartsChoices.size()), theValues, theQueryStringsToPopulate);
|
||||||
|
theValues.remove(theValues.size() - 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (theValues.size() > 0) {
|
||||||
|
StringBuilder uniqueString = new StringBuilder();
|
||||||
|
uniqueString.append(theResourceType);
|
||||||
|
|
||||||
|
for (int i = 0; i < theValues.size(); i++) {
|
||||||
|
uniqueString.append(i == 0 ? "?" : "&");
|
||||||
|
uniqueString.append(theValues.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
theQueryStringsToPopulate.add(uniqueString.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Returns a set containing all of the parameter names that
|
||||||
|
* were found to have a value
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
protected Set<String> extractResourceLinks(ResourceTable theEntity, IBaseResource theResource, Collection<ResourceLink> theLinks, Date theUpdateTime) {
|
||||||
|
HashSet<String> retVal = new HashSet<>();
|
||||||
|
String resourceType = theEntity.getResourceType();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For now we don't try to load any of the links in a bundle if it's the actual bundle we're storing..
|
||||||
|
*/
|
||||||
|
if (theResource instanceof IBaseBundle) {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, RuntimeSearchParam> searchParams = myIndexingService.getSearchParamRegistry().getActiveSearchParams(myIndexingService.toResourceName(theResource.getClass()));
|
||||||
|
for (RuntimeSearchParam nextSpDef : searchParams.values()) {
|
||||||
|
|
||||||
|
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.REFERENCE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String nextPathsUnsplit = nextSpDef.getPath();
|
||||||
|
if (isBlank(nextPathsUnsplit)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean multiType = false;
|
||||||
|
if (nextPathsUnsplit.endsWith("[x]")) {
|
||||||
|
multiType = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<PathAndRef> refs = myIndexingService.getSearchParamExtractor().extractResourceLinks(theResource, nextSpDef);
|
||||||
|
for (PathAndRef nextPathAndRef : refs) {
|
||||||
|
Object nextObject = nextPathAndRef.getRef();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A search parameter on an extension field that contains
|
||||||
|
* references should index those references
|
||||||
|
*/
|
||||||
|
if (nextObject instanceof IBaseExtension<?, ?>) {
|
||||||
|
nextObject = ((IBaseExtension<?, ?>) nextObject).getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextObject instanceof CanonicalType) {
|
||||||
|
nextObject = new Reference(((CanonicalType) nextObject).getValueAsString());
|
||||||
|
}
|
||||||
|
|
||||||
|
IIdType nextId;
|
||||||
|
if (nextObject instanceof IBaseReference) {
|
||||||
|
IBaseReference nextValue = (IBaseReference) nextObject;
|
||||||
|
if (nextValue.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
nextId = nextValue.getReferenceElement();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This can only really happen if the DAO is being called
|
||||||
|
* programatically with a Bundle (not through the FHIR REST API)
|
||||||
|
* but Smile does this
|
||||||
|
*/
|
||||||
|
if (nextId.isEmpty() && nextValue.getResource() != null) {
|
||||||
|
nextId = nextValue.getResource().getIdElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextId.isEmpty() || nextId.getValue().startsWith("#")) {
|
||||||
|
// This is a blank or contained resource reference
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else if (nextObject instanceof IBaseResource) {
|
||||||
|
nextId = ((IBaseResource) nextObject).getIdElement();
|
||||||
|
if (nextId == null || nextId.hasIdPart() == false) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else if (myIndexingService.getContext().getElementDefinition((Class<? extends IBase>) nextObject.getClass()).getName().equals("uri")) {
|
||||||
|
continue;
|
||||||
|
} else if (resourceType.equals("Consent") && nextPathAndRef.getPath().equals("Consent.source")) {
|
||||||
|
// Consent#source-identifier has a path that isn't typed - This is a one-off to deal with that
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
if (!multiType) {
|
||||||
|
if (nextSpDef.getName().equals("sourceuri")) {
|
||||||
|
continue; // TODO: disable this eventually - ConceptMap:sourceuri is of type reference but points to a URI
|
||||||
|
}
|
||||||
|
throw new ConfigurationException("Search param " + nextSpDef.getName() + " is of unexpected datatype: " + nextObject.getClass());
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal.add(nextSpDef.getName());
|
||||||
|
|
||||||
|
if (myIndexingService.isLogicalReference(nextId)) {
|
||||||
|
ResourceLink resourceLink = new ResourceLink(nextPathAndRef.getPath(), theEntity, nextId, theUpdateTime);
|
||||||
|
if (theLinks.add(resourceLink)) {
|
||||||
|
ourLog.debug("Indexing remote resource reference URL: {}", nextId);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String baseUrl = nextId.getBaseUrl();
|
||||||
|
String typeString = nextId.getResourceType();
|
||||||
|
if (isBlank(typeString)) {
|
||||||
|
throw new InvalidRequestException("Invalid resource reference found at path[" + nextPathsUnsplit + "] - Does not contain resource type - " + nextId.getValue());
|
||||||
|
}
|
||||||
|
RuntimeResourceDefinition resourceDefinition;
|
||||||
|
try {
|
||||||
|
resourceDefinition = myIndexingService.getContext().getResourceDefinition(typeString);
|
||||||
|
} catch (DataFormatException e) {
|
||||||
|
throw new InvalidRequestException(
|
||||||
|
"Invalid resource reference found at path[" + nextPathsUnsplit + "] - Resource type is unknown or not supported on this server - " + nextId.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNotBlank(baseUrl)) {
|
||||||
|
if (!myIndexingService.getConfig().getTreatBaseUrlsAsLocal().contains(baseUrl) && !myIndexingService.getConfig().isAllowExternalReferences()) {
|
||||||
|
String msg = myIndexingService.getContext().getLocalizer().getMessage(BaseHapiFhirDao.class, "externalReferenceNotAllowed", nextId.getValue());
|
||||||
|
throw new InvalidRequestException(msg);
|
||||||
|
} else {
|
||||||
|
ResourceLink resourceLink = new ResourceLink(nextPathAndRef.getPath(), theEntity, nextId, theUpdateTime);
|
||||||
|
if (theLinks.add(resourceLink)) {
|
||||||
|
ourLog.debug("Indexing remote resource reference URL: {}", nextId);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Class<? extends IBaseResource> type = resourceDefinition.getImplementingClass();
|
||||||
|
String id = nextId.getIdPart();
|
||||||
|
if (StringUtils.isBlank(id)) {
|
||||||
|
throw new InvalidRequestException("Invalid resource reference found at path[" + nextPathsUnsplit + "] - Does not contain resource ID - " + nextId.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
IFhirResourceDao<?> dao = myIndexingService.getDao(type);
|
||||||
|
if (dao == null) {
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
b.append("This server (version ");
|
||||||
|
b.append(myIndexingService.getContext().getVersion().getVersion());
|
||||||
|
b.append(") is not able to handle resources of type[");
|
||||||
|
b.append(nextId.getResourceType());
|
||||||
|
b.append("] - Valid resource types for this server: ");
|
||||||
|
b.append(myIndexingService.getResourceTypeToDao().keySet().toString());
|
||||||
|
|
||||||
|
throw new InvalidRequestException(b.toString());
|
||||||
|
}
|
||||||
|
Long valueOf;
|
||||||
|
try {
|
||||||
|
valueOf = myIndexingService.translateForcedIdToPid(typeString, id);
|
||||||
|
} catch (ResourceNotFoundException e) {
|
||||||
|
if (myIndexingService.getConfig().isEnforceReferentialIntegrityOnWrite() == false) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
RuntimeResourceDefinition missingResourceDef = myIndexingService.getContext().getResourceDefinition(type);
|
||||||
|
String resName = missingResourceDef.getName();
|
||||||
|
|
||||||
|
if (myIndexingService.getConfig().isAutoCreatePlaceholderReferenceTargets()) {
|
||||||
|
IBaseResource newResource = missingResourceDef.newInstance();
|
||||||
|
newResource.setId(resName + "/" + id);
|
||||||
|
IFhirResourceDao<IBaseResource> placeholderResourceDao = (IFhirResourceDao<IBaseResource>) myIndexingService.getDao(newResource.getClass());
|
||||||
|
ourLog.debug("Automatically creating empty placeholder resource: {}", newResource.getIdElement().getValue());
|
||||||
|
valueOf = placeholderResourceDao.update(newResource).getEntity().getId();
|
||||||
|
} else {
|
||||||
|
throw new InvalidRequestException("Resource " + resName + "/" + id + " not found, specified in path: " + nextPathsUnsplit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ResourceTable target = myIndexingService.getEntityManager().find(ResourceTable.class, valueOf);
|
||||||
|
RuntimeResourceDefinition targetResourceDef = myIndexingService.getContext().getResourceDefinition(type);
|
||||||
|
if (target == null) {
|
||||||
|
String resName = targetResourceDef.getName();
|
||||||
|
throw new InvalidRequestException("Resource " + resName + "/" + id + " not found, specified in path: " + nextPathsUnsplit);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!typeString.equals(target.getResourceType())) {
|
||||||
|
throw new UnprocessableEntityException(
|
||||||
|
"Resource contains reference to " + nextId.getValue() + " but resource with ID " + nextId.getIdPart() + " is actually of type " + target.getResourceType());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target.getDeleted() != null) {
|
||||||
|
String resName = targetResourceDef.getName();
|
||||||
|
throw new InvalidRequestException("Resource " + resName + "/" + id + " is deleted, specified in path: " + nextPathsUnsplit);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextSpDef.getTargets() != null && !nextSpDef.getTargets().contains(typeString)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceLink resourceLink = new ResourceLink(nextPathAndRef.getPath(), theEntity, target, theUpdateTime);
|
||||||
|
theLinks.add(resourceLink);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
theEntity.setHasLinks(theLinks.size() > 0);
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setUpdatedTime(Collection<? extends BaseResourceIndexedSearchParam> theParams, Date theUpdateTime) {
|
||||||
|
for (BaseResourceIndexedSearchParam nextSearchParam : theParams) {
|
||||||
|
nextSearchParam.setUpdated(theUpdateTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String translatePidIdToForcedId(String theResourceType, Long theId) {
|
||||||
|
ForcedId forcedId = myIndexingService.getForcedIdDao().findByResourcePid(theId);
|
||||||
|
if (forcedId != null) {
|
||||||
|
return forcedId.getResourceType() + '/' + forcedId.getForcedId();
|
||||||
|
} else {
|
||||||
|
return theResourceType + '/' + theId.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeCommon(ResourceTable theEntity, ResourceIndexedSearchParams existingParams) {
|
||||||
|
EntityManager myEntityManager = myIndexingService.getEntityManager();
|
||||||
|
|
||||||
|
calculateHashes(stringParams);
|
||||||
|
for (ResourceIndexedSearchParamString next : removeCommon(existingParams.stringParams, stringParams)) {
|
||||||
|
next.setDaoConfig(myIndexingService.getConfig());
|
||||||
|
myEntityManager .remove(next);
|
||||||
|
theEntity.getParamsString().remove(next);
|
||||||
|
}
|
||||||
|
for (ResourceIndexedSearchParamString next : removeCommon(stringParams, existingParams.stringParams)) {
|
||||||
|
myEntityManager.persist(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateHashes(tokenParams);
|
||||||
|
for (ResourceIndexedSearchParamToken next : removeCommon(existingParams.tokenParams, tokenParams)) {
|
||||||
|
myEntityManager.remove(next);
|
||||||
|
theEntity.getParamsToken().remove(next);
|
||||||
|
}
|
||||||
|
for (ResourceIndexedSearchParamToken next : removeCommon(tokenParams, existingParams.tokenParams)) {
|
||||||
|
myEntityManager.persist(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateHashes(numberParams);
|
||||||
|
for (ResourceIndexedSearchParamNumber next : removeCommon(existingParams.numberParams, numberParams)) {
|
||||||
|
myEntityManager.remove(next);
|
||||||
|
theEntity.getParamsNumber().remove(next);
|
||||||
|
}
|
||||||
|
for (ResourceIndexedSearchParamNumber next : removeCommon(numberParams, existingParams.numberParams)) {
|
||||||
|
myEntityManager.persist(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateHashes(quantityParams);
|
||||||
|
for (ResourceIndexedSearchParamQuantity next : removeCommon(existingParams.quantityParams, quantityParams)) {
|
||||||
|
myEntityManager.remove(next);
|
||||||
|
theEntity.getParamsQuantity().remove(next);
|
||||||
|
}
|
||||||
|
for (ResourceIndexedSearchParamQuantity next : removeCommon(quantityParams, existingParams.quantityParams)) {
|
||||||
|
myEntityManager.persist(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store date SP's
|
||||||
|
calculateHashes(dateParams);
|
||||||
|
for (ResourceIndexedSearchParamDate next : removeCommon(existingParams.dateParams, dateParams)) {
|
||||||
|
myEntityManager.remove(next);
|
||||||
|
theEntity.getParamsDate().remove(next);
|
||||||
|
}
|
||||||
|
for (ResourceIndexedSearchParamDate next : removeCommon(dateParams, existingParams.dateParams)) {
|
||||||
|
myEntityManager.persist(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store URI SP's
|
||||||
|
calculateHashes(uriParams);
|
||||||
|
for (ResourceIndexedSearchParamUri next : removeCommon(existingParams.uriParams, uriParams)) {
|
||||||
|
myEntityManager.remove(next);
|
||||||
|
theEntity.getParamsUri().remove(next);
|
||||||
|
}
|
||||||
|
for (ResourceIndexedSearchParamUri next : removeCommon(uriParams, existingParams.uriParams)) {
|
||||||
|
myEntityManager.persist(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store Coords SP's
|
||||||
|
calculateHashes(coordsParams);
|
||||||
|
for (ResourceIndexedSearchParamCoords next : removeCommon(existingParams.coordsParams, coordsParams)) {
|
||||||
|
myEntityManager.remove(next);
|
||||||
|
theEntity.getParamsCoords().remove(next);
|
||||||
|
}
|
||||||
|
for (ResourceIndexedSearchParamCoords next : removeCommon(coordsParams, existingParams.coordsParams)) {
|
||||||
|
myEntityManager.persist(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store resource links
|
||||||
|
for (ResourceLink next : removeCommon(existingParams.links, links)) {
|
||||||
|
myEntityManager.remove(next);
|
||||||
|
theEntity.getResourceLinks().remove(next);
|
||||||
|
}
|
||||||
|
for (ResourceLink next : removeCommon(links, existingParams.links)) {
|
||||||
|
myEntityManager.persist(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure links are indexed
|
||||||
|
theEntity.setResourceLinks(links);
|
||||||
|
|
||||||
|
// Store composite string uniques
|
||||||
|
if (myIndexingService.getConfig().isUniqueIndexesEnabled()) {
|
||||||
|
for (ResourceIndexedCompositeStringUnique next : removeCommon(existingParams.compositeStringUniques, compositeStringUniques)) {
|
||||||
|
ourLog.debug("Removing unique index: {}", next);
|
||||||
|
myEntityManager.remove(next);
|
||||||
|
theEntity.getParamsCompositeStringUnique().remove(next);
|
||||||
|
}
|
||||||
|
for (ResourceIndexedCompositeStringUnique next : removeCommon(compositeStringUniques, existingParams.compositeStringUniques)) {
|
||||||
|
if (myIndexingService.getConfig().isUniqueIndexesCheckedBeforeSave()) {
|
||||||
|
ResourceIndexedCompositeStringUnique existing = myIndexingService.getResourceIndexedCompositeStringUniqueDao().findByQueryString(next.getIndexString());
|
||||||
|
if (existing != null) {
|
||||||
|
String msg = myIndexingService.getContext().getLocalizer().getMessage(BaseHapiFhirDao.class, "uniqueIndexConflictFailure", theEntity.getResourceType(), next.getIndexString(), existing.getResource().getIdDt().toUnqualifiedVersionless().getValue());
|
||||||
|
throw new PreconditionFailedException(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ourLog.debug("Persisting unique index: {}", next);
|
||||||
|
myEntityManager.persist(next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void calculateHashes(Collection<? extends BaseResourceIndexedSearchParam> theStringParams) {
|
||||||
|
for (BaseResourceIndexedSearchParam next : theStringParams) {
|
||||||
|
next.calculateHashes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> Collection<T> removeCommon(Collection<T> theInput, Collection<T> theToRemove) {
|
||||||
|
assert theInput != theToRemove;
|
||||||
|
|
||||||
|
if (theInput.isEmpty()) {
|
||||||
|
return theInput;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<T> retVal = new ArrayList<>(theInput);
|
||||||
|
retVal.removeAll(theToRemove);
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getPopulatedResourceLinkParameters() {
|
||||||
|
return populatedResourceLinkParameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -27,6 +27,8 @@ import ca.uhn.fhir.jpa.config.BaseConfig;
|
||||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||||
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
|
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
|
||||||
import ca.uhn.fhir.jpa.provider.ServletSubRequestDetails;
|
import ca.uhn.fhir.jpa.provider.ServletSubRequestDetails;
|
||||||
|
import ca.uhn.fhir.jpa.subscription.matcher.ISubscriptionMatcher;
|
||||||
|
import ca.uhn.fhir.jpa.subscription.matcher.SubscriptionMatcherDatabase;
|
||||||
import ca.uhn.fhir.jpa.util.JpaConstants;
|
import ca.uhn.fhir.jpa.util.JpaConstants;
|
||||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||||
|
@ -284,6 +286,7 @@ public abstract class BaseSubscriptionInterceptor<S extends IBaseResource> exten
|
||||||
|
|
||||||
public abstract Subscription.SubscriptionChannelType getChannelType();
|
public abstract Subscription.SubscriptionChannelType getChannelType();
|
||||||
|
|
||||||
|
// TODO KHS move out
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <R extends IBaseResource> IFhirResourceDao<R> getDao(Class<R> theType) {
|
public <R extends IBaseResource> IFhirResourceDao<R> getDao(Class<R> theType) {
|
||||||
if (myResourceTypeToDao == null) {
|
if (myResourceTypeToDao == null) {
|
||||||
|
@ -433,7 +436,8 @@ public abstract class BaseSubscriptionInterceptor<S extends IBaseResource> exten
|
||||||
|
|
||||||
protected void registerSubscriptionCheckingSubscriber() {
|
protected void registerSubscriptionCheckingSubscriber() {
|
||||||
if (mySubscriptionCheckingSubscriber == null) {
|
if (mySubscriptionCheckingSubscriber == null) {
|
||||||
mySubscriptionCheckingSubscriber = new SubscriptionCheckingSubscriber(getSubscriptionDao(), getChannelType(), this);
|
ISubscriptionMatcher subscriptionMatcher = new SubscriptionMatcherDatabase(getSubscriptionDao(), this);
|
||||||
|
mySubscriptionCheckingSubscriber = new SubscriptionCheckingSubscriber(getSubscriptionDao(), getChannelType(), this, subscriptionMatcher );
|
||||||
}
|
}
|
||||||
getProcessingChannel().subscribe(mySubscriptionCheckingSubscriber);
|
getProcessingChannel().subscribe(mySubscriptionCheckingSubscriber);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,17 @@
|
||||||
package ca.uhn.fhir.jpa.subscription;
|
package ca.uhn.fhir.jpa.subscription;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
import org.hl7.fhir.r4.model.Subscription;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.messaging.Message;
|
||||||
|
import org.springframework.messaging.MessageChannel;
|
||||||
|
import org.springframework.messaging.MessagingException;
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* #%L
|
* #%L
|
||||||
* HAPI FHIR JPA Server
|
* HAPI FHIR JPA Server
|
||||||
|
@ -25,27 +37,20 @@ import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
|
||||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||||
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
|
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
|
||||||
import ca.uhn.fhir.jpa.provider.ServletSubRequestDetails;
|
import ca.uhn.fhir.jpa.provider.ServletSubRequestDetails;
|
||||||
|
import ca.uhn.fhir.jpa.subscription.matcher.ISubscriptionMatcher;
|
||||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
|
||||||
import org.hl7.fhir.r4.model.Subscription;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.messaging.Message;
|
|
||||||
import org.springframework.messaging.MessageChannel;
|
|
||||||
import org.springframework.messaging.MessagingException;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
|
|
||||||
public class SubscriptionCheckingSubscriber extends BaseSubscriptionSubscriber {
|
public class SubscriptionCheckingSubscriber extends BaseSubscriptionSubscriber {
|
||||||
private Logger ourLog = LoggerFactory.getLogger(SubscriptionCheckingSubscriber.class);
|
private Logger ourLog = LoggerFactory.getLogger(SubscriptionCheckingSubscriber.class);
|
||||||
|
|
||||||
public SubscriptionCheckingSubscriber(IFhirResourceDao theSubscriptionDao, Subscription.SubscriptionChannelType theChannelType, BaseSubscriptionInterceptor theSubscriptionInterceptor) {
|
private final ISubscriptionMatcher mySubscriptionMatcher;
|
||||||
|
|
||||||
|
public SubscriptionCheckingSubscriber(IFhirResourceDao theSubscriptionDao, Subscription.SubscriptionChannelType theChannelType, BaseSubscriptionInterceptor theSubscriptionInterceptor, ISubscriptionMatcher theSubscriptionMatcher) {
|
||||||
super(theSubscriptionDao, theChannelType, theSubscriptionInterceptor);
|
super(theSubscriptionDao, theChannelType, theSubscriptionInterceptor);
|
||||||
|
this.mySubscriptionMatcher = theSubscriptionMatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -107,16 +112,7 @@ public class SubscriptionCheckingSubscriber extends BaseSubscriptionSubscriber {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// run the subscriptions query and look for matches, add the id as part of the criteria to avoid getting matches of previous resources rather than the recent resource
|
if (!mySubscriptionMatcher.match(nextCriteriaString, msg)) {
|
||||||
String criteria = nextCriteriaString;
|
|
||||||
criteria += "&_id=" + resourceType + "/" + resourceId;
|
|
||||||
criteria = massageCriteria(criteria);
|
|
||||||
|
|
||||||
IBundleProvider results = performSearch(criteria);
|
|
||||||
|
|
||||||
ourLog.debug("Subscription check found {} results for query: {}", results.size(), criteria);
|
|
||||||
|
|
||||||
if (results.size() == 0) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
package ca.uhn.fhir.jpa.subscription.matcher;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.jpa.subscription.ResourceModifiedMessage;
|
||||||
|
|
||||||
|
public interface ISubscriptionMatcher {
|
||||||
|
boolean match(String criteria, ResourceModifiedMessage msg);
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
package ca.uhn.fhir.jpa.subscription.matcher;
|
||||||
|
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||||
|
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
|
||||||
|
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||||
|
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
|
||||||
|
import ca.uhn.fhir.jpa.provider.ServletSubRequestDetails;
|
||||||
|
import ca.uhn.fhir.jpa.subscription.BaseSubscriptionInterceptor;
|
||||||
|
import ca.uhn.fhir.jpa.subscription.ResourceModifiedMessage;
|
||||||
|
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||||
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
|
|
||||||
|
public class SubscriptionMatcherDatabase implements ISubscriptionMatcher {
|
||||||
|
private Logger ourLog = LoggerFactory.getLogger(SubscriptionMatcherDatabase.class);
|
||||||
|
|
||||||
|
private final IFhirResourceDao<?> mySubscriptionDao;
|
||||||
|
|
||||||
|
private final BaseSubscriptionInterceptor mySubscriptionInterceptor;
|
||||||
|
|
||||||
|
public SubscriptionMatcherDatabase(IFhirResourceDao<?> theSubscriptionDao, BaseSubscriptionInterceptor theSubscriptionInterceptor) {
|
||||||
|
mySubscriptionDao = theSubscriptionDao;
|
||||||
|
mySubscriptionInterceptor = theSubscriptionInterceptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean match(String criteria, ResourceModifiedMessage msg) {
|
||||||
|
IIdType id = msg.getId(getContext());
|
||||||
|
String resourceType = id.getResourceType();
|
||||||
|
String resourceId = id.getIdPart();
|
||||||
|
|
||||||
|
// run the subscriptions query and look for matches, add the id as part of the criteria to avoid getting matches of previous resources rather than the recent resource
|
||||||
|
criteria += "&_id=" + resourceType + "/" + resourceId;
|
||||||
|
|
||||||
|
IBundleProvider results = performSearch(criteria);
|
||||||
|
|
||||||
|
ourLog.debug("Subscription check found {} results for query: {}", results.size(), criteria);
|
||||||
|
|
||||||
|
return results.size() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search based on a query criteria
|
||||||
|
*/
|
||||||
|
protected IBundleProvider performSearch(String theCriteria) {
|
||||||
|
RuntimeResourceDefinition responseResourceDef = mySubscriptionDao.validateCriteriaAndReturnResourceDefinition(theCriteria);
|
||||||
|
SearchParameterMap responseCriteriaUrl = BaseHapiFhirDao.translateMatchUrl(mySubscriptionDao, getContext(), theCriteria, responseResourceDef);
|
||||||
|
|
||||||
|
RequestDetails req = new ServletSubRequestDetails();
|
||||||
|
req.setSubRequest(true);
|
||||||
|
|
||||||
|
IFhirResourceDao<? extends IBaseResource> responseDao = mySubscriptionInterceptor.getDao(responseResourceDef.getImplementingClass());
|
||||||
|
responseCriteriaUrl.setLoadSynchronousUpTo(1);
|
||||||
|
|
||||||
|
IBundleProvider responseResults = responseDao.search(responseCriteriaUrl, req);
|
||||||
|
return responseResults;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FhirContext getContext() {
|
||||||
|
return mySubscriptionDao.getContext();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package ca.uhn.fhir.jpa.subscription.matcher;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.jpa.subscription.ResourceModifiedMessage;
|
||||||
|
|
||||||
|
public class SubscriptionMatcherInMemory implements ISubscriptionMatcher {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean match(String criteria, ResourceModifiedMessage msg) {
|
||||||
|
// FIXME KHS implement
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,6 +26,7 @@ import org.junit.*;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.containsString;
|
import static org.hamcrest.CoreMatchers.containsString;
|
||||||
|
@ -44,8 +45,8 @@ public class SubscriptionTriggeringDstu3Test extends BaseResourceProviderDstu3Te
|
||||||
private static RestfulServer ourListenerRestServer;
|
private static RestfulServer ourListenerRestServer;
|
||||||
private static Server ourListenerServer;
|
private static Server ourListenerServer;
|
||||||
private static String ourListenerServerBase;
|
private static String ourListenerServerBase;
|
||||||
private static List<Observation> ourCreatedObservations = Lists.newArrayList();
|
private static List<Observation> ourCreatedObservations = Collections.synchronizedList(Lists.newArrayList());
|
||||||
private static List<Observation> ourUpdatedObservations = Lists.newArrayList();
|
private static List<Observation> ourUpdatedObservations = Collections.synchronizedList(Lists.newArrayList());
|
||||||
private static List<Patient> ourCreatedPatients = Lists.newArrayList();
|
private static List<Patient> ourCreatedPatients = Lists.newArrayList();
|
||||||
private static List<Patient> ourUpdatedPatients = Lists.newArrayList();
|
private static List<Patient> ourUpdatedPatients = Lists.newArrayList();
|
||||||
private static List<String> ourContentTypes = new ArrayList<>();
|
private static List<String> ourContentTypes = new ArrayList<>();
|
||||||
|
|
|
@ -1,24 +1,5 @@
|
||||||
package ca.uhn.fhir.util;
|
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.BaseRuntimeChildDefinition;
|
||||||
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
|
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
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.Observation;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Organization;
|
import ca.uhn.fhir.model.dstu2.resource.Organization;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
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.MarkdownDt;
|
||||||
import ca.uhn.fhir.model.primitive.StringDt;
|
import ca.uhn.fhir.model.primitive.StringDt;
|
||||||
import ca.uhn.fhir.parser.DataFormatException;
|
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 {
|
public class FhirTerserDstu2Test {
|
||||||
|
|
||||||
|
@ -180,6 +178,597 @@ public class FhirTerserDstu2Test {
|
||||||
assertEquals(1, refs.size());
|
assertEquals(1, refs.size());
|
||||||
assertSame(ref, refs.get(0));
|
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<Object> 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<Object> 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<Object> 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<IPrimitiveType> 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<ExtensionDt> 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<IPrimitiveType> 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<ExtensionDt> 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<IPrimitiveType> 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<ExtensionDt> 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<Object> 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<Object> 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<Object> 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<Object> 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
|
@Test
|
||||||
public void testVisitWithModelVisitor2() {
|
public void testVisitWithModelVisitor2() {
|
||||||
|
|
|
@ -1,41 +1,27 @@
|
||||||
package ca.uhn.fhir.util;
|
package ca.uhn.fhir.util;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
|
||||||
import static org.junit.Assert.assertEquals;
|
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
|
||||||
import static org.junit.Assert.assertSame;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import static org.junit.Assert.assertThat;
|
import ca.uhn.fhir.parser.DataFormatException;
|
||||||
import static org.junit.Assert.assertTrue;
|
import org.hl7.fhir.dstu3.model.*;
|
||||||
import static org.junit.Assert.fail;
|
import org.hl7.fhir.dstu3.model.Patient.LinkType;
|
||||||
import static org.mockito.Mockito.mock;
|
import org.hl7.fhir.instance.model.api.IBase;
|
||||||
import static org.mockito.Mockito.when;
|
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.ParameterizedType;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.hl7.fhir.dstu3.model.Bundle;
|
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||||
import org.hl7.fhir.dstu3.model.Extension;
|
import static org.junit.Assert.*;
|
||||||
import org.hl7.fhir.dstu3.model.Identifier;
|
import static org.mockito.Mockito.mock;
|
||||||
import org.hl7.fhir.dstu3.model.MarkdownType;
|
import static org.mockito.Mockito.when;
|
||||||
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;
|
|
||||||
|
|
||||||
public class FhirTerserDstu3Test {
|
public class FhirTerserDstu3Test {
|
||||||
|
|
||||||
|
@ -183,6 +169,683 @@ public class FhirTerserDstu3Test {
|
||||||
assertSame(ref, refs.get(0));
|
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<Object> 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<Object> 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<Object> 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<PrimitiveType> 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<Extension> 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<PrimitiveType> 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<Extension> 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<PrimitiveType> 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<Extension> 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<Object> 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<Object> 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<Object> 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<Object> 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
|
@Test
|
||||||
public void testVisitWithModelVisitor2() {
|
public void testVisitWithModelVisitor2() {
|
||||||
IModelVisitor2 visitor = mock(IModelVisitor2.class);
|
IModelVisitor2 visitor = mock(IModelVisitor2.class);
|
||||||
|
|
|
@ -116,6 +116,15 @@
|
||||||
<![CDATA[<a href="https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfig.java#L62">the example project</a>]]>
|
<![CDATA[<a href="https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfig.java#L62">the example project</a>]]>
|
||||||
if they are not already.
|
if they are not already.
|
||||||
</action>
|
</action>
|
||||||
|
<action type="add">
|
||||||
|
The FhirTerser <![CDATA[<code>getValues(...)</code>]]> 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.
|
||||||
|
</action>
|
||||||
|
<action type="fix">
|
||||||
|
The FhirTerser <![CDATA[<code>getValues(...)</code>]]> methods were not properly handling modifier
|
||||||
|
extensions for verions of FHIR prior to DSTU3. This has been corrected.
|
||||||
<action type="fix">
|
<action type="fix">
|
||||||
When updating resources in the JPA server, a bug caused index table entries to be refreshed
|
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
|
sometimes even though the index value hadn't changed. This issue did not cause incorrect search
|
||||||
|
|
Loading…
Reference in New Issue