Survivorship 6
This commit is contained in:
parent
684b77d396
commit
5aa85c7e17
|
@ -318,6 +318,14 @@ This operation takes the following parameters:
|
||||||
The id of the Golden Resource to merge data into.
|
The id of the Golden Resource to merge data into.
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>resource</td>
|
||||||
|
<td>Resource</td>
|
||||||
|
<td>0..1</td>
|
||||||
|
<td>
|
||||||
|
Optional manually merged Golden Resource. All values except for the metadata, PID and identifiers will be copied from this resource, if it is present. If no value is specified, all fields from the resource pointed to by "fromGoldenResourceId" will be copied instead.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
|
@ -437,7 +437,6 @@ public class IdHelperService {
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public Long getPidOrThrowException(IAnyResource theResource) {
|
public Long getPidOrThrowException(IAnyResource theResource) {
|
||||||
Long retVal = (Long) theResource.getUserData(RESOURCE_PID);
|
Long retVal = (Long) theResource.getUserData(RESOURCE_PID);
|
||||||
// FIXME NG Is this the intent?
|
|
||||||
if (retVal == null) {
|
if (retVal == null) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
String.format("Unable to find %s in the user data for %s with ID %s", RESOURCE_PID, theResource, theResource.getId())
|
String.format("Unable to find %s in the user data for %s with ID %s", RESOURCE_PID, theResource, theResource.getId())
|
||||||
|
|
|
@ -60,13 +60,16 @@ public class GoldenResourceMergerSvcImpl implements IGoldenResourceMergerSvc {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public IAnyResource mergeGoldenResources(IAnyResource theFromGoldenResource, IAnyResource theToGoldenResource, MdmTransactionContext theMdmTransactionContext) {
|
public IAnyResource mergeGoldenResources(IAnyResource theFromGoldenResource, IAnyResource theMergedResource, IAnyResource theToGoldenResource, MdmTransactionContext theMdmTransactionContext) {
|
||||||
Long fromGoldenResourcePid = myIdHelperService.getPidOrThrowException(theFromGoldenResource);
|
Long fromGoldenResourcePid = myIdHelperService.getPidOrThrowException(theFromGoldenResource);
|
||||||
Long toGoldenResourcePid = myIdHelperService.getPidOrThrowException(theToGoldenResource);
|
Long toGoldenResourcePid = myIdHelperService.getPidOrThrowException(theToGoldenResource);
|
||||||
String resourceType = theMdmTransactionContext.getResourceType();
|
String resourceType = theMdmTransactionContext.getResourceType();
|
||||||
|
|
||||||
//Merge attributes, to be determined when survivorship is solved.
|
// Merge attributes, to be determined when survivorship is solved.
|
||||||
myGoldenResourceHelper.mergeFields(theFromGoldenResource, theToGoldenResource, theMdmTransactionContext);
|
myGoldenResourceHelper.mergeIndentifierFields(theFromGoldenResource, theToGoldenResource, theMdmTransactionContext);
|
||||||
|
|
||||||
|
IAnyResource mergeSource = ( theMergedResource == null ) ? theFromGoldenResource : theMergedResource;
|
||||||
|
myGoldenResourceHelper.mergeNonIdentiferFields(mergeSource, theToGoldenResource, theMdmTransactionContext);
|
||||||
|
|
||||||
//Merge the links from the FROM to the TO resource. Clean up dangling links.
|
//Merge the links from the FROM to the TO resource. Clean up dangling links.
|
||||||
mergeGoldenResourceLinks(theFromGoldenResource, theToGoldenResource, toGoldenResourcePid, theMdmTransactionContext);
|
mergeGoldenResourceLinks(theFromGoldenResource, theToGoldenResource, toGoldenResourcePid, theMdmTransactionContext);
|
||||||
|
|
|
@ -44,6 +44,7 @@ import java.util.stream.Stream;
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class MdmControllerSvcImpl implements IMdmControllerSvc {
|
public class MdmControllerSvcImpl implements IMdmControllerSvc {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
MdmControllerHelper myMdmControllerHelper;
|
MdmControllerHelper myMdmControllerHelper;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
@ -54,22 +55,14 @@ public class MdmControllerSvcImpl implements IMdmControllerSvc {
|
||||||
IMdmLinkUpdaterSvc myIMdmLinkUpdaterSvc;
|
IMdmLinkUpdaterSvc myIMdmLinkUpdaterSvc;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IAnyResource mergeGoldenResources(String theFromGoldenResourceId, String theToGoldenResourceId, IAnyResource theFromGoldenResource, MdmTransactionContext theMdmTransactionContext) {
|
public IAnyResource mergeGoldenResources(String theFromGoldenResourceId, String theToGoldenResourceId, IAnyResource theManuallyMergedResource, MdmTransactionContext theMdmTransactionContext) {
|
||||||
boolean isOverwritingGoldenResource = (theFromGoldenResource != null);
|
IAnyResource fromGoldenResource = myMdmControllerHelper.getLatestGoldenResourceFromIdOrThrowException(ProviderConstants.MDM_MERGE_GR_FROM_GOLDEN_RESOURCE_ID, theFromGoldenResourceId);
|
||||||
|
|
||||||
IAnyResource fromGoldenResource;
|
|
||||||
if (theFromGoldenResource == null) {
|
|
||||||
fromGoldenResource = myMdmControllerHelper.getLatestGoldenResourceFromIdOrThrowException(ProviderConstants.MDM_MERGE_GR_FROM_GOLDEN_RESOURCE_ID, theFromGoldenResourceId);
|
|
||||||
} else {
|
|
||||||
fromGoldenResource = theFromGoldenResource;
|
|
||||||
}
|
|
||||||
|
|
||||||
IAnyResource toGoldenResource = myMdmControllerHelper.getLatestGoldenResourceFromIdOrThrowException(ProviderConstants.MDM_MERGE_GR_TO_GOLDEN_RESOURCE_ID, theToGoldenResourceId);
|
IAnyResource toGoldenResource = myMdmControllerHelper.getLatestGoldenResourceFromIdOrThrowException(ProviderConstants.MDM_MERGE_GR_TO_GOLDEN_RESOURCE_ID, theToGoldenResourceId);
|
||||||
myMdmControllerHelper.validateMergeResources(fromGoldenResource, toGoldenResource);
|
myMdmControllerHelper.validateMergeResources(fromGoldenResource, toGoldenResource);
|
||||||
myMdmControllerHelper.validateSameVersion(fromGoldenResource, theFromGoldenResourceId);
|
myMdmControllerHelper.validateSameVersion(fromGoldenResource, theFromGoldenResourceId);
|
||||||
myMdmControllerHelper.validateSameVersion(toGoldenResource, theToGoldenResourceId);
|
myMdmControllerHelper.validateSameVersion(toGoldenResource, theToGoldenResourceId);
|
||||||
|
|
||||||
return myGoldenResourceMergerSvc.mergeGoldenResources(fromGoldenResource, toGoldenResource, theMdmTransactionContext);
|
return myGoldenResourceMergerSvc.mergeGoldenResources(fromGoldenResource, theManuallyMergedResource, toGoldenResource, theMdmTransactionContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -34,30 +34,12 @@ public class MdmSurvivorshipSvcImpl implements IMdmSurvivorshipService {
|
||||||
private FhirContext myFhirContext;
|
private FhirContext myFhirContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Survivorship rules may include the following data consolidation methods:
|
* Merges two golden resources by overwriting all field values on theGoldenResource param for all REST operation methods
|
||||||
|
* except MERGE_GOLDEN_RESOURCES. In case of MERGE_GOLDEN_RESOURCES, it will attempt to copy field values from
|
||||||
|
* theTargetResource that do not exist in theGoldenResource. PID, indentifiers and meta values are not affected by
|
||||||
|
* this operation.
|
||||||
*
|
*
|
||||||
* <ul>
|
* @param theTargetResource Target resource to retrieve fields from
|
||||||
* <li>
|
|
||||||
* Length of field - apply the field value containing most or least number of characters - e.g. longest name
|
|
||||||
* </li>
|
|
||||||
* <li>
|
|
||||||
* Date time - all the field value from the oldest or the newest recrod - e.g. use the most recent phone number
|
|
||||||
* </li>
|
|
||||||
* <li>
|
|
||||||
* Frequency - use the most or least frequent number of occurrence - e.g. most common phone number
|
|
||||||
* </li>
|
|
||||||
* <li>
|
|
||||||
* Integer - number functions (largest, sum, avg) - e.g. number of patient encounters
|
|
||||||
* </li>
|
|
||||||
* <li>
|
|
||||||
* Quality of data - best quality data - e.g. data coming from a certain system is considered trusted and overrides all other values
|
|
||||||
* </li>
|
|
||||||
* <li>
|
|
||||||
* A hybrid approach combining all methods listed above as best fits
|
|
||||||
* </li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @param theTargetResource Target resource to merge fields from
|
|
||||||
* @param theGoldenResource Golden resource to merge fields into
|
* @param theGoldenResource Golden resource to merge fields into
|
||||||
* @param theMdmTransactionContext Current transaction context
|
* @param theMdmTransactionContext Current transaction context
|
||||||
* @param <T>
|
* @param <T>
|
||||||
|
@ -66,14 +48,10 @@ public class MdmSurvivorshipSvcImpl implements IMdmSurvivorshipService {
|
||||||
public <T extends IBase> void applySurvivorshipRulesToGoldenResource(T theTargetResource, T theGoldenResource, MdmTransactionContext theMdmTransactionContext) {
|
public <T extends IBase> void applySurvivorshipRulesToGoldenResource(T theTargetResource, T theGoldenResource, MdmTransactionContext theMdmTransactionContext) {
|
||||||
switch (theMdmTransactionContext.getRestOperation()) {
|
switch (theMdmTransactionContext.getRestOperation()) {
|
||||||
case MERGE_GOLDEN_RESOURCES:
|
case MERGE_GOLDEN_RESOURCES:
|
||||||
if (theMdmTransactionContext.isForceResourceUpdate()) {
|
|
||||||
TerserUtil.overwriteFields(myFhirContext, (IBaseResource) theTargetResource, (IBaseResource) theGoldenResource, TerserUtil.EXCLUDE_IDS_AND_META);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
TerserUtil.mergeFields(myFhirContext, (IBaseResource) theTargetResource, (IBaseResource) theGoldenResource, TerserUtil.EXCLUDE_IDS_AND_META);
|
TerserUtil.mergeFields(myFhirContext, (IBaseResource) theTargetResource, (IBaseResource) theGoldenResource, TerserUtil.EXCLUDE_IDS_AND_META);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
TerserUtil.overwriteFields(myFhirContext, (IBaseResource) theTargetResource, (IBaseResource) theGoldenResource, TerserUtil.EXCLUDE_IDS_AND_META);
|
TerserUtil.replaceFields(myFhirContext, (IBaseResource) theTargetResource, (IBaseResource) theGoldenResource, TerserUtil.EXCLUDE_IDS_AND_META);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,11 +101,13 @@ public class MdmGoldenResourceMergerSvcTest extends BaseMdmR4Test {
|
||||||
|
|
||||||
private Patient mergeGoldenPatients() {
|
private Patient mergeGoldenPatients() {
|
||||||
assertEquals(0, redirectLinkCount());
|
assertEquals(0, redirectLinkCount());
|
||||||
Patient retval = (Patient) myGoldenResourceMergerSvc.mergeGoldenResources(myFromGoldenPatient, myToGoldenPatient, createMdmContext());
|
Patient retval = (Patient) myGoldenResourceMergerSvc.mergeGoldenResources(myFromGoldenPatient, null, myToGoldenPatient, createMdmContext());
|
||||||
assertEquals(1, redirectLinkCount());
|
assertEquals(1, redirectLinkCount());
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO NG - add a test with a manually merged golden patient
|
||||||
|
|
||||||
private int redirectLinkCount() {
|
private int redirectLinkCount() {
|
||||||
MdmLink mdmLink = new MdmLink().setMatchResult(MdmMatchResultEnum.REDIRECT);
|
MdmLink mdmLink = new MdmLink().setMatchResult(MdmMatchResultEnum.REDIRECT);
|
||||||
Example<MdmLink> example = Example.of(mdmLink);
|
Example<MdmLink> example = Example.of(mdmLink);
|
||||||
|
|
|
@ -1,5 +1,25 @@
|
||||||
package ca.uhn.fhir.jpa.model.entity;
|
package ca.uhn.fhir.jpa.model.entity;
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR Model
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2021 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%
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Support different UCUM services level for FHIR Quantity data type.
|
* Support different UCUM services level for FHIR Quantity data type.
|
||||||
*
|
*
|
||||||
|
|
|
@ -197,4 +197,4 @@ public class ResourceIndexedSearchParamQuantity extends ResourceIndexedSearchPar
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,8 +29,9 @@ public interface IGoldenResourceMergerSvc {
|
||||||
* Merge all Golden Resource fields subject to survivorship rules.
|
* Merge all Golden Resource fields subject to survivorship rules.
|
||||||
*
|
*
|
||||||
* @param theFromGoldenResource the golden resource we are merging from
|
* @param theFromGoldenResource the golden resource we are merging from
|
||||||
|
* @param theManuallyMergedResource an optional golden resource that was manually merged
|
||||||
* @param theToGoldenResource the golden resource we are merging to
|
* @param theToGoldenResource the golden resource we are merging to
|
||||||
* @return updated theToGoldenResource with the merged fields and links.
|
* @return updated theToGoldenResource with the merged fields and links.
|
||||||
*/
|
*/
|
||||||
IAnyResource mergeGoldenResources(IAnyResource theFromGoldenResource, IAnyResource theToGoldenResource, MdmTransactionContext theMdmTransactionContext);
|
IAnyResource mergeGoldenResources(IAnyResource theFromGoldenResource, IAnyResource theManuallyMergedResource, IAnyResource theToGoldenResource, MdmTransactionContext theMdmTransactionContext);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,30 @@ import org.hl7.fhir.instance.model.api.IBase;
|
||||||
public interface IMdmSurvivorshipService {
|
public interface IMdmSurvivorshipService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies survivorship rules to merge fields from the specified target resource to the golden resource
|
* Applies survivorship rules to merge fields from the specified target resource to the golden resource. Survivorship
|
||||||
|
* rules may include, but not limited to the following data consolidation methods:
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
* <li>
|
||||||
|
* Length of field - apply the field value containing most or least number of characters - e.g. longest name
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* Date time - all the field value from the oldest or the newest recrod - e.g. use the most recent phone number
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* Frequency - use the most or least frequent number of occurrence - e.g. most common phone number
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* Integer - number functions (largest, sum, avg) - e.g. number of patient encounters
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* Quality of data - best quality data - e.g. data coming from a certain system is considered trusted and overrides
|
||||||
|
* all other values
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* A hybrid approach combining all methods listed above as best fits
|
||||||
|
* </li>
|
||||||
|
* </ul>
|
||||||
*
|
*
|
||||||
* @param theTargetResource Target resource to merge fields from
|
* @param theTargetResource Target resource to merge fields from
|
||||||
* @param theGoldenResource Golden resource to merge fields into
|
* @param theGoldenResource Golden resource to merge fields into
|
||||||
|
|
|
@ -32,7 +32,8 @@ public class MdmTransactionContext {
|
||||||
UPDATE_LINK,
|
UPDATE_LINK,
|
||||||
DUPLICATE_GOLDEN_RESOURCES,
|
DUPLICATE_GOLDEN_RESOURCES,
|
||||||
NOT_DUPLICATE,
|
NOT_DUPLICATE,
|
||||||
MERGE_GOLDEN_RESOURCES
|
MERGE_GOLDEN_RESOURCES,
|
||||||
|
MANUAL_MERGE_GOLDEN_RESOURCES
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -44,8 +45,6 @@ public class MdmTransactionContext {
|
||||||
|
|
||||||
private String myResourceType;
|
private String myResourceType;
|
||||||
|
|
||||||
private boolean myForceResourceUpdate;
|
|
||||||
|
|
||||||
public TransactionLogMessages getTransactionLogMessages() {
|
public TransactionLogMessages getTransactionLogMessages() {
|
||||||
return myTransactionLogMessages;
|
return myTransactionLogMessages;
|
||||||
}
|
}
|
||||||
|
@ -89,12 +88,4 @@ public class MdmTransactionContext {
|
||||||
public void setResourceType(String myResourceType) {
|
public void setResourceType(String myResourceType) {
|
||||||
this.myResourceType = myResourceType;
|
this.myResourceType = myResourceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isForceResourceUpdate() {
|
|
||||||
return myForceResourceUpdate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setForceResourceUpdate(boolean theForceResourceUpdate) {
|
|
||||||
myForceResourceUpdate = theForceResourceUpdate;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,8 @@ public abstract class BaseMdmProvider {
|
||||||
if (theFromGoldenResource == null) {
|
if (theFromGoldenResource == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME NG - ID is proveded as a param anyways - can always retrived it there
|
||||||
validateNotNull(ProviderConstants.MDM_MERGE_RESOURCE_ID, theFromGoldenResource.getIdElement());
|
validateNotNull(ProviderConstants.MDM_MERGE_RESOURCE_ID, theFromGoldenResource.getIdElement());
|
||||||
if (theFromGoldenResource.getIdElement().getValue().equals(theToGoldenResourceId.getValue())) {
|
if (theFromGoldenResource.getIdElement().getValue().equals(theToGoldenResourceId.getValue())) {
|
||||||
throw new InvalidRequestException("resource must be different from the one with toGoldenResourceId");
|
throw new InvalidRequestException("resource must be different from the one with toGoldenResourceId");
|
||||||
|
|
|
@ -149,9 +149,10 @@ public class MdmProviderDstu3Plus extends BaseMdmProvider {
|
||||||
validateMergeParameters(theFromGoldenResourceId, theToGoldenResourceId);
|
validateMergeParameters(theFromGoldenResourceId, theToGoldenResourceId);
|
||||||
validateOptionalMergeResource(theMergedResource, theToGoldenResourceId);
|
validateOptionalMergeResource(theMergedResource, theToGoldenResourceId);
|
||||||
|
|
||||||
MdmTransactionContext txContext = createMdmContext(theRequestDetails, MdmTransactionContext.OperationType.MERGE_GOLDEN_RESOURCES,
|
MdmTransactionContext.OperationType operationType = (theMergedResource == null) ?
|
||||||
|
MdmTransactionContext.OperationType.MERGE_GOLDEN_RESOURCES : MdmTransactionContext.OperationType.MANUAL_MERGE_GOLDEN_RESOURCES;
|
||||||
|
MdmTransactionContext txContext = createMdmContext(theRequestDetails, operationType,
|
||||||
getResourceType(ProviderConstants.MDM_MERGE_GR_FROM_GOLDEN_RESOURCE_ID, theFromGoldenResourceId));
|
getResourceType(ProviderConstants.MDM_MERGE_GR_FROM_GOLDEN_RESOURCE_ID, theFromGoldenResourceId));
|
||||||
txContext.setForceResourceUpdate(theMergedResource != null);
|
|
||||||
return myMdmControllerSvc.mergeGoldenResources(theFromGoldenResourceId.getValueAsString(), theToGoldenResourceId.getValueAsString(), theMergedResource, txContext);
|
return myMdmControllerSvc.mergeGoldenResources(theFromGoldenResourceId.getValueAsString(), theToGoldenResourceId.getValueAsString(), theMergedResource, txContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -241,8 +241,11 @@ public class GoldenResourceHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void mergeFields(IBaseResource theFromGoldenResource, IBaseResource theToGoldenResource, MdmTransactionContext theMdmTransactionContext) {
|
public void mergeIndentifierFields(IBaseResource theFromGoldenResource, IBaseResource theToGoldenResource, MdmTransactionContext theMdmTransactionContext) {
|
||||||
TerserUtil.cloneCompositeField(myFhirContext, theFromGoldenResource, theToGoldenResource, FIELD_NAME_IDENTIFIER);
|
TerserUtil.cloneCompositeField(myFhirContext, theFromGoldenResource, theToGoldenResource, FIELD_NAME_IDENTIFIER);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mergeNonIdentiferFields(IBaseResource theFromGoldenResource, IBaseResource theToGoldenResource, MdmTransactionContext theMdmTransactionContext) {
|
||||||
myMdmSurvivorshipService.applySurvivorshipRulesToGoldenResource(theFromGoldenResource, theToGoldenResource, theMdmTransactionContext);
|
myMdmSurvivorshipService.applySurvivorshipRulesToGoldenResource(theFromGoldenResource, theToGoldenResource, theMdmTransactionContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ import static ca.uhn.fhir.mdm.util.GoldenResourceHelper.FIELD_NAME_IDENTIFIER;
|
||||||
public final class TerserUtil {
|
public final class TerserUtil {
|
||||||
|
|
||||||
public static final Collection<String> IDS_AND_META_EXCLUDES =
|
public static final Collection<String> IDS_AND_META_EXCLUDES =
|
||||||
Collections.unmodifiableSet(Stream.of("id", "identifier", "meta", "active").collect(Collectors.toSet()));
|
Collections.unmodifiableSet(Stream.of("id", "identifier", "meta").collect(Collectors.toSet()));
|
||||||
|
|
||||||
public static final Predicate<String> EXCLUDE_IDS_AND_META = new Predicate<String>() {
|
public static final Predicate<String> EXCLUDE_IDS_AND_META = new Predicate<String>() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -151,7 +151,7 @@ public final class TerserUtil {
|
||||||
mergeFields(theFhirContext, theFrom, theTo, INCLUDE_ALL);
|
mergeFields(theFhirContext, theFrom, theTo, INCLUDE_ALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void overwriteFields(FhirContext theFhirContext, IBaseResource theFrom, IBaseResource theTo, Predicate<String> inclusionStrategy) {
|
public static void replaceFields(FhirContext theFhirContext, IBaseResource theFrom, IBaseResource theTo, Predicate<String> inclusionStrategy) {
|
||||||
FhirTerser terser = theFhirContext.newTerser();
|
FhirTerser terser = theFhirContext.newTerser();
|
||||||
|
|
||||||
RuntimeResourceDefinition definition = theFhirContext.getResourceDefinition(theFrom);
|
RuntimeResourceDefinition definition = theFhirContext.getResourceDefinition(theFrom);
|
||||||
|
@ -160,13 +160,25 @@ public final class TerserUtil {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
childDefinition.getAccessor().getFirstValueOrNull(theFrom).ifPresent( v -> {
|
replaceField(theFrom, theTo, childDefinition);
|
||||||
childDefinition.getMutator().setValue(theTo, v);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void replaceField(FhirContext theFhirContext, FhirTerser theTerser, String theFieldName, IBaseResource theFrom, IBaseResource theTo) {
|
||||||
|
FhirTerser terser = theFhirContext.newTerser();
|
||||||
|
|
||||||
|
RuntimeResourceDefinition definition = theFhirContext.getResourceDefinition(theFrom);
|
||||||
|
BaseRuntimeChildDefinition childDefinition = definition.getChildByName(theFieldName);
|
||||||
|
replaceField(theFrom, theTo, childDefinition);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void replaceField(IBaseResource theFrom, IBaseResource theTo, BaseRuntimeChildDefinition childDefinition) {
|
||||||
|
childDefinition.getAccessor().getFirstValueOrNull(theFrom).ifPresent(v -> {
|
||||||
|
childDefinition.getMutator().setValue(theTo, v);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public static void mergeFieldsExceptIdAndMeta(FhirContext theFhirContext, IBaseResource theFrom, IBaseResource theTo) {
|
public static void mergeFieldsExceptIdAndMeta(FhirContext theFhirContext, IBaseResource theFrom, IBaseResource theTo) {
|
||||||
mergeFields(theFhirContext, theFrom, theTo, EXCLUDE_IDS_AND_META);
|
mergeFields(theFhirContext, theFrom, theTo, EXCLUDE_IDS_AND_META);
|
||||||
}
|
}
|
||||||
|
@ -182,21 +194,45 @@ public final class TerserUtil {
|
||||||
|
|
||||||
List<IBase> theFromFieldValues = childDefinition.getAccessor().getValues(theFrom);
|
List<IBase> theFromFieldValues = childDefinition.getAccessor().getValues(theFrom);
|
||||||
List<IBase> theToFieldValues = childDefinition.getAccessor().getValues(theTo);
|
List<IBase> theToFieldValues = childDefinition.getAccessor().getValues(theTo);
|
||||||
|
|
||||||
for (IBase theFromFieldValue : theFromFieldValues) {
|
|
||||||
if (contains(theFromFieldValue, theToFieldValues)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
IBase newFieldValue = childDefinition.getChildByName(childDefinition.getElementName()).newInstance();
|
mergeFields(terser, theTo, childDefinition, theFromFieldValues, theToFieldValues);
|
||||||
terser.cloneInto(theFromFieldValue, newFieldValue, true);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
/**
|
||||||
theToFieldValues.add(newFieldValue);
|
* Merges value of the specified field from theFrom resource to theTo resource. Fields values are compared via
|
||||||
} catch (UnsupportedOperationException e) {
|
* the equalsDeep method, or via object identity if this method is not available.
|
||||||
childDefinition.getMutator().setValue(theTo, newFieldValue);
|
*
|
||||||
break;
|
* @param theFhirContext
|
||||||
}
|
* @param theTerser
|
||||||
|
* @param theFieldName
|
||||||
|
* @param theFrom
|
||||||
|
* @param theTo
|
||||||
|
*/
|
||||||
|
public static void mergeField(FhirContext theFhirContext, FhirTerser theTerser, String theFieldName, IBaseResource theFrom, IBaseResource theTo) {
|
||||||
|
RuntimeResourceDefinition definition = theFhirContext.getResourceDefinition(theFrom);
|
||||||
|
BaseRuntimeChildDefinition childDefinition = definition.getChildByName(theFieldName);
|
||||||
|
|
||||||
|
List<IBase> theFromFieldValues = childDefinition.getAccessor().getValues(theFrom);
|
||||||
|
List<IBase> theToFieldValues = childDefinition.getAccessor().getValues(theTo);
|
||||||
|
|
||||||
|
mergeFields(theTerser, theTo, childDefinition, theFromFieldValues, theToFieldValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void mergeFields(FhirTerser theTerser, IBaseResource theTo, BaseRuntimeChildDefinition childDefinition, List<IBase> theFromFieldValues, List<IBase> theToFieldValues) {
|
||||||
|
for (IBase theFromFieldValue : theFromFieldValues) {
|
||||||
|
if (contains(theFromFieldValue, theToFieldValues)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
IBase newFieldValue = childDefinition.getChildByName(childDefinition.getElementName()).newInstance();
|
||||||
|
theTerser.cloneInto(theFromFieldValue, newFieldValue, true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
theToFieldValues.add(newFieldValue);
|
||||||
|
} catch (UnsupportedOperationException e) {
|
||||||
|
childDefinition.getMutator().setValue(theTo, newFieldValue);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue