Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*-
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2024 Smile CDR, Inc.
* %%
* 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%
*/
package ca.uhn.fhir.util;
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeChildChoiceDefinition;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.i18n.Msg;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.tuple.Triple;
import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseBackboneElement;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import org.slf4j.Logger;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.slf4j.LoggerFactory.getLogger;
public final class TerserUtil {
public static final String FIELD_NAME_IDENTIFIER = "identifier";
/**
* Exclude for id, identifier and meta fields of a resource.
*/
public static final Collection IDS_AND_META_EXCLUDES =
Collections.unmodifiableSet(Stream.of("id", "identifier", "meta").collect(Collectors.toSet()));
/**
* Exclusion predicate for id, identifier, meta fields.
*/
public static final Predicate EXCLUDE_IDS_AND_META = new Predicate() {
@Override
public boolean test(String s) {
return !IDS_AND_META_EXCLUDES.contains(s);
}
};
/**
* Exclusion predicate for id/identifier, meta and fields with empty values. This ensures that source / target resources,
* empty source fields will not results in erasure of target fields.
*/
public static final Predicate> EXCLUDE_IDS_META_AND_EMPTY =
new Predicate>() {
@Override
public boolean test(Triple theTriple) {
if (!EXCLUDE_IDS_AND_META.test(theTriple.getLeft().getElementName())) {
return false;
}
BaseRuntimeChildDefinition childDefinition = theTriple.getLeft();
boolean isSourceFieldEmpty = childDefinition
.getAccessor()
.getValues(theTriple.getMiddle())
.isEmpty();
return !isSourceFieldEmpty;
}
};
/**
* Exclusion predicate for keeping all fields.
*/
public static final Predicate INCLUDE_ALL = new Predicate() {
@Override
public boolean test(String s) {
return true;
}
};
private static final Logger ourLog = getLogger(TerserUtil.class);
private static final String EQUALS_DEEP = "equalsDeep";
private TerserUtil() {}
/**
* Given an Child Definition of `identifier`, a R4/DSTU3 Identifier, and a new resource, clone the identifier into that resources' identifier list if it is not already present.
*/
public static void cloneIdentifierIntoResource(
FhirContext theFhirContext,
BaseRuntimeChildDefinition theIdentifierDefinition,
IBase theNewIdentifier,
IBaseResource theResourceToCloneInto) {
// FHIR choice types - fields within fhir where we have a choice of ids
BaseRuntimeElementCompositeDefinition> childIdentifierElementDefinition =
(BaseRuntimeElementCompositeDefinition>)
theIdentifierDefinition.getChildByName(FIELD_NAME_IDENTIFIER);
List existingIdentifiers = getValues(theFhirContext, theResourceToCloneInto, FIELD_NAME_IDENTIFIER);
if (existingIdentifiers != null) {
for (IBase existingIdentifier : existingIdentifiers) {
if (equals(existingIdentifier, theNewIdentifier)) {
ourLog.trace(
"Identifier {} already exists in resource {}", theNewIdentifier, theResourceToCloneInto);
return;
}
}
}
IBase newIdentifierBase = childIdentifierElementDefinition.newInstance();
FhirTerser terser = theFhirContext.newTerser();
terser.cloneInto(theNewIdentifier, newIdentifierBase, true);
theIdentifierDefinition.getMutator().addValue(theResourceToCloneInto, newIdentifierBase);
}
/**
* Checks if the specified fields has any values
*
* @param theFhirContext Context holding resource definition
* @param theResource Resource to check if the specified field is set
* @param theFieldName name of the field to check
* @return Returns true if field exists and has any values set, and false otherwise
*/
public static boolean hasValues(FhirContext theFhirContext, IBaseResource theResource, String theFieldName) {
RuntimeResourceDefinition resourceDefinition = theFhirContext.getResourceDefinition(theResource);
BaseRuntimeChildDefinition resourceIdentifier = resourceDefinition.getChildByName(theFieldName);
if (resourceIdentifier == null) {
return false;
}
return !(resourceIdentifier.getAccessor().getValues(theResource).isEmpty());
}
/**
* Gets all values of the specified field.
*
* @param theFhirContext Context holding resource definition
* @param theResource Resource to check if the specified field is set
* @param theFieldName name of the field to check
* @return Returns all values for the specified field or null if field with the provided name doesn't exist
*/
public static List getValues(FhirContext theFhirContext, IBaseResource theResource, String theFieldName) {
RuntimeResourceDefinition resourceDefinition = theFhirContext.getResourceDefinition(theResource);
BaseRuntimeChildDefinition resourceIdentifier = resourceDefinition.getChildByName(theFieldName);
if (resourceIdentifier == null) {
ourLog.info("There is no field named {} in Resource {}", theFieldName, resourceDefinition.getName());
return null;
}
return resourceIdentifier.getAccessor().getValues(theResource);
}
/**
* Gets the first available value for the specified field.
*
* @param theFhirContext Context holding resource definition
* @param theResource Resource to check if the specified field is set
* @param theFieldName name of the field to check
* @return Returns the first value for the specified field or null if field with the provided name doesn't exist or
* has no values
*/
public static IBase getValueFirstRep(FhirContext theFhirContext, IBaseResource theResource, String theFieldName) {
List values = getValues(theFhirContext, theResource, theFieldName);
if (values == null || values.isEmpty()) {
return null;
}
return values.get(0);
}
/**
* Clones specified composite field (collection). Composite field values must conform to the collections
* contract.
*
* @param theFrom Resource to clone the specified field from
* @param theTo Resource to clone the specified field to
* @param theField Field name to be copied
*/
public static void cloneCompositeField(
FhirContext theFhirContext, IBaseResource theFrom, IBaseResource theTo, String theField) {
FhirTerser terser = theFhirContext.newTerser();
RuntimeResourceDefinition definition = theFhirContext.getResourceDefinition(theFrom);
BaseRuntimeChildDefinition childDefinition = definition.getChildByName(theField);
Validate.notNull(childDefinition);
List theFromFieldValues = childDefinition.getAccessor().getValues(theFrom);
List theToFieldValues = childDefinition.getAccessor().getValues(theTo);
for (IBase theFromFieldValue : theFromFieldValues) {
if (containsPrimitiveValue(theFromFieldValue, theToFieldValues)) {
continue;
}
IBase newFieldValue = newElement(terser, childDefinition, theFromFieldValue, null);
terser.cloneInto(theFromFieldValue, newFieldValue, true);
try {
theToFieldValues.add(newFieldValue);
} catch (Exception e) {
childDefinition.getMutator().setValue(theTo, newFieldValue);
}
}
}
private static boolean containsPrimitiveValue(IBase theItem, List theItems) {
PrimitiveTypeEqualsPredicate predicate = new PrimitiveTypeEqualsPredicate();
return theItems.stream().anyMatch(i -> {
return predicate.test(i, theItem);
});
}
private static Method getMethod(IBase theBase, String theMethodName) {
Method method = null;
for (Method m : theBase.getClass().getDeclaredMethods()) {
if (m.getName().equals(theMethodName)) {
method = m;
break;
}
}
return method;
}
/**
* Checks if two items are equal via {@link #EQUALS_DEEP} method
*
* @param theItem1 First item to compare
* @param theItem2 Second item to compare
* @return Returns true if they are equal and false otherwise
*/
public static boolean equals(IBase theItem1, IBase theItem2) {
if (theItem1 == null) {
return theItem2 == null;
}
final Method method = getMethod(theItem1, EQUALS_DEEP);
Validate.notNull(method);
return equals(theItem1, theItem2, method);
}
private static boolean equals(IBase theItem1, IBase theItem2, Method theMethod) {
if (theMethod != null) {
try {
return (Boolean) theMethod.invoke(theItem1, theItem2);
} catch (Exception e) {
throw new RuntimeException(
Msg.code(1746) + String.format("Unable to compare equality via %s", EQUALS_DEEP), e);
}
}
return theItem1.equals(theItem2);
}
private static boolean contains(IBase theItem, List theItems) {
final Method method = getMethod(theItem, EQUALS_DEEP);
return theItems.stream().anyMatch(i -> equals(i, theItem, method));
}
/**
* Merges all fields on the provided instance. theTo will contain a union of all values from theFrom
* instance and theTo instance.
*
* @param theFhirContext Context holding resource definition
* @param theFrom The resource to merge the fields from
* @param theTo The resource to merge the fields into
*/
public static void mergeAllFields(FhirContext theFhirContext, IBaseResource theFrom, IBaseResource theTo) {
mergeFields(theFhirContext, theFrom, theTo, INCLUDE_ALL);
}
/**
* Replaces all fields that have matching field names by the given inclusion strategy. theTo will contain a copy of the
* values from theFrom instance.
*
* @param theFhirContext Context holding resource definition
* @param theFrom The resource to merge the fields from
* @param theTo The resource to merge the fields into
* @param theFieldNameInclusion Inclusion strategy that checks if a given field should be replaced
*/
public static void replaceFields(
FhirContext theFhirContext,
IBaseResource theFrom,
IBaseResource theTo,
Predicate theFieldNameInclusion) {
Predicate> predicate =
(t) -> theFieldNameInclusion.test(t.getLeft().getElementName());
replaceFieldsByPredicate(theFhirContext, theFrom, theTo, predicate);
}
/**
* Replaces fields on theTo resource that test positive by the given predicate. theTo will contain a copy of the
* values from theFrom for which predicate tests positive. Please note that composite fields will be replaced fully.
*
* @param theFhirContext Context holding resource definition
* @param theFrom The resource to merge the fields from
* @param theTo The resource to merge the fields into
* @param thePredicate Predicate that checks if a given field should be replaced
*/
public static void replaceFieldsByPredicate(
FhirContext theFhirContext,
IBaseResource theFrom,
IBaseResource theTo,
Predicate> thePredicate) {
RuntimeResourceDefinition definition = theFhirContext.getResourceDefinition(theFrom);
FhirTerser terser = theFhirContext.newTerser();
for (BaseRuntimeChildDefinition childDefinition : definition.getChildrenAndExtension()) {
if (thePredicate.test(Triple.of(childDefinition, theFrom, theTo))) {
replaceField(terser, theFrom, theTo, childDefinition);
}
}
}
/**
* Checks if the field exists on the resource
*
* @param theFhirContext Context holding resource definition
* @param theFieldName Name of the field to check
* @param theInstance Resource instance to check
* @return Returns true if resource definition has a child with the specified name and false otherwise
*/
public static boolean fieldExists(FhirContext theFhirContext, String theFieldName, IBaseResource theInstance) {
RuntimeResourceDefinition definition = theFhirContext.getResourceDefinition(theInstance);
return definition.getChildByName(theFieldName) != null;
}
/**
* Replaces the specified fields on theTo resource with the value from theFrom resource.
*
* @param theFhirContext Context holding resource definition
* @param theFrom The resource to replace the field from
* @param theTo The resource to replace the field on
*/
public static void replaceField(
FhirContext theFhirContext, String theFieldName, IBaseResource theFrom, IBaseResource theTo) {
RuntimeResourceDefinition definition = theFhirContext.getResourceDefinition(theFrom);
Validate.notNull(definition);
replaceField(
theFhirContext.newTerser(),
theFrom,
theTo,
theFhirContext.getResourceDefinition(theFrom).getChildByName(theFieldName));
}
/**
* Clears the specified field on the resource provided
*
* @param theFhirContext Context holding resource definition
* @param theResource
* @param theFieldName
*/
public static void clearField(FhirContext theFhirContext, IBaseResource theResource, String theFieldName) {
BaseRuntimeChildDefinition childDefinition =
getBaseRuntimeChildDefinition(theFhirContext, theFieldName, theResource);
childDefinition.getMutator().setValue(theResource, null);
}
/**
* Clears the specified field on the resource provided by the FHIRPath. If more than one value matches
* the FHIRPath, all values will be cleared.
*
* @param theFhirContext
* @param theResource
* @param theFhirPath
*/
public static void clearFieldByFhirPath(FhirContext theFhirContext, IBaseResource theResource, String theFhirPath) {
if (theFhirPath.contains(".")) {
String parentPath = theFhirPath.substring(0, theFhirPath.lastIndexOf("."));
String fieldName = theFhirPath.substring(theFhirPath.lastIndexOf(".") + 1);
FhirTerser terser = theFhirContext.newTerser();
List parents = terser.getValues(theResource, parentPath);
for (IBase parent : parents) {
clearField(theFhirContext, fieldName, parent);
}
} else {
clearField(theFhirContext, theResource, theFhirPath);
}
}
/**
* Clears the specified field on the element provided
*
* @param theFhirContext Context holding resource definition
* @param theFieldName Name of the field to clear values for
* @param theBase The element definition to clear values on
*/
public static void clearField(FhirContext theFhirContext, String theFieldName, IBase theBase) {
BaseRuntimeElementDefinition definition = theFhirContext.getElementDefinition(theBase.getClass());
BaseRuntimeChildDefinition childDefinition = definition.getChildByName(theFieldName);
Validate.notNull(childDefinition);
BaseRuntimeChildDefinition.IAccessor accessor = childDefinition.getAccessor();
clear(accessor.getValues(theBase));
List newValue = accessor.getValues(theBase);
if (newValue != null && !newValue.isEmpty()) {
// Our clear failed, probably because it was an immutable SingletonList returned by a FieldPlainAccessor
// that cannot be cleared.
// Let's just null it out instead.
childDefinition.getMutator().setValue(theBase, null);
}
}
/**
* Sets the provided field with the given values. This method will add to the collection of existing field values
* in case of multiple cardinality. Use {@link #clearField(FhirContext, IBaseResource, String)}
* to remove values before setting
*
* @param theFhirContext Context holding resource definition
* @param theFieldName Child field name of the resource to set
* @param theResource The resource to set the values on
* @param theValues The values to set on the resource child field name
*/
public static void setField(
FhirContext theFhirContext, String theFieldName, IBaseResource theResource, IBase... theValues) {
setField(theFhirContext, theFhirContext.newTerser(), theFieldName, theResource, theValues);
}
/**
* Sets the provided field with the given values. This method will add to the collection of existing field values
* in case of multiple cardinality. Use {@link #clearField(FhirContext, IBaseResource, String)}
* to remove values before setting
*
* @param theFhirContext Context holding resource definition
* @param theTerser Terser to be used when cloning field values
* @param theFieldName Child field name of the resource to set
* @param theResource The resource to set the values on
* @param theValues The values to set on the resource child field name
*/
public static void setField(
FhirContext theFhirContext,
FhirTerser theTerser,
String theFieldName,
IBaseResource theResource,
IBase... theValues) {
BaseRuntimeChildDefinition childDefinition =
getBaseRuntimeChildDefinition(theFhirContext, theFieldName, theResource);
List theFromFieldValues = childDefinition.getAccessor().getValues(theResource);
if (theFromFieldValues.isEmpty()) {
for (IBase value : theValues) {
try {
childDefinition.getMutator().addValue(theResource, value);
} catch (UnsupportedOperationException e) {
ourLog.warn(
"Resource {} does not support multiple values, but an attempt to set {} was made. Setting the first item only",
theResource,
theValues);
childDefinition.getMutator().setValue(theResource, value);
break;
}
}
return;
}
List theToFieldValues = Arrays.asList(theValues);
mergeFields(theTerser, theResource, childDefinition, theFromFieldValues, theToFieldValues);
}
/**
* Sets the provided field with the given values. This method will add to the collection of existing field values
* in case of multiple cardinality. Use {@link #clearField(FhirContext, IBaseResource, String)}
* to remove values before setting
*
* @param theFhirContext Context holding resource definition
* @param theFieldName Child field name of the resource to set
* @param theResource The resource to set the values on
* @param theValue The String value to set on the resource child field name. This value is converted to the appropriate primitive type before the value is set
*/
public static void setStringField(
FhirContext theFhirContext, String theFieldName, IBaseResource theResource, String theValue) {
setField(theFhirContext, theFieldName, theResource, theFhirContext.newPrimitiveString(theValue));
}
/**
* Sets the specified value at the FHIR path provided.
*
* @param theTerser The terser that should be used for cloning the field value.
* @param theFhirPath The FHIR path to set the field at
* @param theResource The resource on which the value should be set
* @param theValue The value to set
*/
public static void setFieldByFhirPath(
FhirTerser theTerser, String theFhirPath, IBaseResource theResource, IBase theValue) {
List theFromFieldValues = theTerser.getValues(theResource, theFhirPath, true, false);
for (IBase theFromFieldValue : theFromFieldValues) {
theTerser.cloneInto(theValue, theFromFieldValue, true);
}
}
/**
* Sets the specified value at the FHIR path provided.
*
* @param theFhirContext Context holding resource definition
* @param theFhirPath The FHIR path to set the field at
* @param theResource The resource on which the value should be set
* @param theValue The value to set
*/
public static void setFieldByFhirPath(
FhirContext theFhirContext, String theFhirPath, IBaseResource theResource, IBase theValue) {
setFieldByFhirPath(theFhirContext.newTerser(), theFhirPath, theResource, theValue);
}
/**
* Sets the specified String value at the FHIR path provided.
*
* @param theFhirContext Context holding resource definition
* @param theFhirPath The FHIR path to set the field at
* @param theResource The resource on which the value should be set
* @param theValue The String value to set. The string is converted to the appropriate primitive type before setting the field
*/
public static void setStringFieldByFhirPath(
FhirContext theFhirContext, String theFhirPath, IBaseResource theResource, String theValue) {
setFieldByFhirPath(
theFhirContext.newTerser(), theFhirPath, theResource, theFhirContext.newPrimitiveString(theValue));
}
/**
* Returns field values ant the specified FHIR path from the resource.
*
* @param theFhirContext Context holding resource definition
* @param theFhirPath The FHIR path to get the field from
* @param theResource The resource from which the value should be retrieved
* @return Returns the list of field values at the given FHIR path
*/
public static List getFieldByFhirPath(FhirContext theFhirContext, String theFhirPath, IBase theResource) {
return theFhirContext.newTerser().getValues(theResource, theFhirPath, false, false);
}
/**
* Returns the first available field value at the specified FHIR path from the resource.
*
* @param theFhirContext Context holding resource definition
* @param theFhirPath The FHIR path to get the field from
* @param theResource The resource from which the value should be retrieved
* @return Returns the first available value or null if no values can be retrieved
*/
public static IBase getFirstFieldByFhirPath(FhirContext theFhirContext, String theFhirPath, IBase theResource) {
List values = getFieldByFhirPath(theFhirContext, theFhirPath, theResource);
if (values == null || values.isEmpty()) {
return null;
}
return values.get(0);
}
private static void replaceField(
FhirTerser theTerser,
IBaseResource theFrom,
IBaseResource theTo,
BaseRuntimeChildDefinition childDefinition) {
List fromValues = childDefinition.getAccessor().getValues(theFrom);
List toValues = childDefinition.getAccessor().getValues(theTo);
if (fromValues.isEmpty() && !toValues.isEmpty()) {
childDefinition.getMutator().setValue(theTo, null);
} else if (fromValues != toValues) {
clear(toValues);
mergeFields(theTerser, theTo, childDefinition, fromValues, toValues);
}
}
/**
* Merges values of all fields except for "identifier" and "meta" from theFrom resource to
* theTo resource. Fields values are compared via the equalsDeep method, or via object identity if this
* method is not available.
*
* @param theFhirContext Context holding resource definition
* @param theFrom Resource to merge the specified field from
* @param theTo Resource to merge the specified field into
*/
public static void mergeFieldsExceptIdAndMeta(
FhirContext theFhirContext, IBaseResource theFrom, IBaseResource theTo) {
mergeFields(theFhirContext, theFrom, theTo, EXCLUDE_IDS_AND_META);
}
/**
* Merges values of all field from theFrom resource to theTo resource. Fields
* values are compared via the equalsDeep method, or via object identity if this method is not available.
*
* @param theFhirContext Context holding resource definition
* @param theFrom Resource to merge the specified field from
* @param theTo Resource to merge the specified field into
* @param inclusionStrategy Predicate to test which fields should be merged
*/
public static void mergeFields(
FhirContext theFhirContext,
IBaseResource theFrom,
IBaseResource theTo,
Predicate inclusionStrategy) {
FhirTerser terser = theFhirContext.newTerser();
RuntimeResourceDefinition definition = theFhirContext.getResourceDefinition(theFrom);
for (BaseRuntimeChildDefinition childDefinition : definition.getChildrenAndExtension()) {
if (!inclusionStrategy.test(childDefinition.getElementName())) {
continue;
}
List theFromFieldValues = childDefinition.getAccessor().getValues(theFrom);
List theToFieldValues = childDefinition.getAccessor().getValues(theTo);
mergeFields(terser, theTo, childDefinition, theFromFieldValues, theToFieldValues);
}
}
/**
* Merges value of the specified field from theFrom resource to theTo resource. Fields
* values are compared via the equalsDeep method, or via object identity if this method is not available.
*
* @param theFhirContext Context holding resource definition
* @param theFieldName Name of the child filed to merge
* @param theFrom Resource to merge the specified field from
* @param theTo Resource to merge the specified field into
*/
public static void mergeField(
FhirContext theFhirContext, String theFieldName, IBaseResource theFrom, IBaseResource theTo) {
mergeField(theFhirContext, theFhirContext.newTerser(), theFieldName, theFrom, theTo);
}
/**
* Merges value of the specified field from theFrom resource to theTo resource. Fields
* values are compared via the equalsDeep method, or via object identity if this method is not available.
*
* @param theFhirContext Context holding resource definition
* @param theTerser Terser to be used when cloning the field values
* @param theFieldName Name of the child filed to merge
* @param theFrom Resource to merge the specified field from
* @param theTo Resource to merge the specified field into
*/
public static void mergeField(
FhirContext theFhirContext,
FhirTerser theTerser,
String theFieldName,
IBaseResource theFrom,
IBaseResource theTo) {
BaseRuntimeChildDefinition childDefinition =
getBaseRuntimeChildDefinition(theFhirContext, theFieldName, theFrom);
List theFromFieldValues = childDefinition.getAccessor().getValues(theFrom);
List theToFieldValues = childDefinition.getAccessor().getValues(theTo);
mergeFields(theTerser, theTo, childDefinition, theFromFieldValues, theToFieldValues);
}
private static BaseRuntimeChildDefinition getBaseRuntimeChildDefinition(
FhirContext theFhirContext, String theFieldName, IBaseResource theFrom) {
RuntimeResourceDefinition definition = theFhirContext.getResourceDefinition(theFrom);
BaseRuntimeChildDefinition childDefinition = definition.getChildByName(theFieldName);
Validate.notNull(childDefinition);
return childDefinition;
}
/**
* Creates a new element taking into consideration elements with choice that are not directly retrievable by element
* name
*
* @param theFhirTerser
* @param theChildDefinition Child to create a new instance for
* @param theFromFieldValue The base parent field
* @param theConstructorParam Optional constructor param
* @return Returns the new element with the given value if configured
*/
private static IBase newElement(
FhirTerser theFhirTerser,
BaseRuntimeChildDefinition theChildDefinition,
IBase theFromFieldValue,
Object theConstructorParam) {
BaseRuntimeElementDefinition runtimeElementDefinition;
if (theChildDefinition instanceof RuntimeChildChoiceDefinition) {
runtimeElementDefinition =
theChildDefinition.getChildElementDefinitionByDatatype(theFromFieldValue.getClass());
} else {
runtimeElementDefinition = theChildDefinition.getChildByName(theChildDefinition.getElementName());
}
if ("contained".equals(runtimeElementDefinition.getName())) {
IBaseResource sourceResource = (IBaseResource) theFromFieldValue;
return theFhirTerser.clone(sourceResource);
} else if (theConstructorParam == null) {
return runtimeElementDefinition.newInstance();
} else {
return runtimeElementDefinition.newInstance(theConstructorParam);
}
}
private static void mergeFields(
FhirTerser theTerser,
IBaseResource theTo,
BaseRuntimeChildDefinition childDefinition,
List theFromFieldValues,
List theToFieldValues) {
for (IBase theFromFieldValue : theFromFieldValues) {
if (contains(theFromFieldValue, theToFieldValues)) {
continue;
}
IBase newFieldValue = newElement(theTerser, childDefinition, theFromFieldValue, null);
if (theFromFieldValue instanceof IPrimitiveType) {
try {
Method copyMethod = getMethod(theFromFieldValue, "copy");
if (copyMethod != null) {
newFieldValue = (IBase) copyMethod.invoke(theFromFieldValue, new Object[] {});
}
} catch (Throwable t) {
((IPrimitiveType) newFieldValue)
.setValueAsString(((IPrimitiveType) theFromFieldValue).getValueAsString());
}
} else {
theTerser.cloneInto(theFromFieldValue, newFieldValue, true);
}
try {
theToFieldValues.add(newFieldValue);
} catch (UnsupportedOperationException e) {
childDefinition.getMutator().setValue(theTo, newFieldValue);
theToFieldValues = childDefinition.getAccessor().getValues(theTo);
}
}
}
/**
* Clones the specified resource.
*
* @param theFhirContext Context holding resource definition
* @param theInstance The instance to be cloned
* @param Base resource type
* @return Returns a cloned instance
*/
public static T clone(FhirContext theFhirContext, T theInstance) {
RuntimeResourceDefinition definition = theFhirContext.getResourceDefinition(theInstance.getClass());
T retVal = (T) definition.newInstance();
FhirTerser terser = theFhirContext.newTerser();
terser.cloneInto(theInstance, retVal, true);
return retVal;
}
/**
* Creates a new element instance
*
* @param theFhirContext Context holding resource definition
* @param theElementType Element type name
* @param Base element type
* @return Returns a new instance of the element
*/
public static T newElement(FhirContext theFhirContext, String theElementType) {
BaseRuntimeElementDefinition def = theFhirContext.getElementDefinition(theElementType);
return (T) def.newInstance();
}
/**
* Creates a new element instance
*
* @param theFhirContext Context holding resource definition
* @param theElementType Element type name
* @param theConstructorParam Initialization parameter for the element
* @param Base element type
* @return Returns a new instance of the element with the specified initial value
*/
public static T newElement(
FhirContext theFhirContext, String theElementType, Object theConstructorParam) {
BaseRuntimeElementDefinition def = theFhirContext.getElementDefinition(theElementType);
Validate.notNull(def);
return (T) def.newInstance(theConstructorParam);
}
/**
* Creates a new resource definition.
*
* @param theFhirContext Context holding resource definition
* @param theResourceName Name of the resource in the context
* @param Type of the resource
* @return Returns a new instance of the resource
*/
public static T newResource(FhirContext theFhirContext, String theResourceName) {
RuntimeResourceDefinition def = theFhirContext.getResourceDefinition(theResourceName);
return (T) def.newInstance();
}
/**
* Creates a new resource definition.
*
* @param theFhirContext Context holding resource definition
* @param theResourceName Name of the resource in the context
* @param theConstructorParam Initialization parameter for the new instance
* @param Type of the resource
* @return Returns a new instance of the resource
*/
public static T newResource(
FhirContext theFhirContext, String theResourceName, Object theConstructorParam) {
RuntimeResourceDefinition def = theFhirContext.getResourceDefinition(theResourceName);
return (T) def.newInstance(theConstructorParam);
}
/**
* Creates a new BackboneElement.
*
* @param theFhirContext Context holding resource definition
* @param theTargetResourceName Name of the resource in the context
* @param theTargetFieldName Name of the backbone element in the resource
* @return Returns a new instance of the element
*/
public static IBaseBackboneElement instantiateBackboneElement(
FhirContext theFhirContext, String theTargetResourceName, String theTargetFieldName) {
BaseRuntimeElementDefinition> targetParentElementDefinition =
theFhirContext.getResourceDefinition(theTargetResourceName);
BaseRuntimeChildDefinition childDefinition = targetParentElementDefinition.getChildByName(theTargetFieldName);
return (IBaseBackboneElement)
childDefinition.getChildByName(theTargetFieldName).newInstance();
}
private static void clear(List values) {
if (values == null) {
return;
}
try {
values.clear();
} catch (Throwable t) {
ourLog.debug("Unable to clear values " + String.valueOf(values), t);
}
}
}