Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

create merge provenance resource #6596

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ public IBaseParameters replaceReferences(
RequestPartitionId partitionId = myRequestPartitionHelperSvc.determineReadPartitionForRequest(
theServletRequest, ReadPartitionIdRequestDetails.forRead(targetId));
ReplaceReferencesRequest replaceReferencesRequest =
new ReplaceReferencesRequest(sourceId, targetId, resourceLimit, partitionId);
new ReplaceReferencesRequest(sourceId, targetId, resourceLimit, partitionId, true);
IBaseParameters retval =
getReplaceReferencesSvc().replaceReferences(replaceReferencesRequest, theServletRequest);
if (ParametersUtil.getNamedParameter(getContext(), retval, OPERATION_REPLACE_REFERENCES_OUTPUT_PARAM_TASK)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import ca.uhn.fhir.batch2.api.IJobCoordinator;
import ca.uhn.fhir.batch2.jobs.replacereferences.ReplaceReferencesJobParameters;
import ca.uhn.fhir.batch2.jobs.replacereferences.ReplaceReferencesProvenanceSvc;
import ca.uhn.fhir.batch2.util.Batch2TaskHelper;
import ca.uhn.fhir.i18n.Msg;
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
Expand All @@ -42,6 +43,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;
import java.util.List;
import java.util.stream.Stream;

import static ca.uhn.fhir.batch2.jobs.replacereferences.ReplaceReferencesAppCtx.JOB_REPLACE_REFERENCES;
Expand All @@ -58,6 +61,7 @@ public class ReplaceReferencesSvcImpl implements IReplaceReferencesSvc {
private final ReplaceReferencesPatchBundleSvc myReplaceReferencesPatchBundleSvc;
private final Batch2TaskHelper myBatch2TaskHelper;
private final JpaStorageSettings myStorageSettings;
private final ReplaceReferencesProvenanceSvc myReplaceReferencesProvenanceSvc;

public ReplaceReferencesSvcImpl(
DaoRegistry theDaoRegistry,
Expand All @@ -74,6 +78,7 @@ public ReplaceReferencesSvcImpl(
myReplaceReferencesPatchBundleSvc = theReplaceReferencesPatchBundleSvc;
myBatch2TaskHelper = theBatch2TaskHelper;
myStorageSettings = theStorageSettings;
myReplaceReferencesProvenanceSvc = new ReplaceReferencesProvenanceSvc(theDaoRegistry);
}

@Override
Expand Down Expand Up @@ -123,6 +128,7 @@ private IBaseParameters replaceReferencesPreferAsync(
private IBaseParameters replaceReferencesPreferSync(
ReplaceReferencesRequest theReplaceReferencesRequest, RequestDetails theRequestDetails) {

Date startTime = new Date();
// TODO KHS get partition from request
StopLimitAccumulator<IdDt> accumulator = myHapiTransactionService
.withRequest(theRequestDetails)
Expand All @@ -139,6 +145,15 @@ private IBaseParameters replaceReferencesPreferSync(
Bundle result = myReplaceReferencesPatchBundleSvc.patchReferencingResources(
theReplaceReferencesRequest, accumulator.getItemList(), theRequestDetails);

if (theReplaceReferencesRequest.createProvenance) {
myReplaceReferencesProvenanceSvc.createProvenance(
theReplaceReferencesRequest.targetId,
theReplaceReferencesRequest.sourceId,
List.of(result),
startTime,
theRequestDetails);
}

Parameters retval = new Parameters();
retval.addParameter()
.setName(OPERATION_REPLACE_REFERENCES_OUTPUT_PARAM_OUTCOME)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import ca.uhn.fhir.batch2.api.IJobCoordinator;
import ca.uhn.fhir.batch2.jobs.merge.MergeJobParameters;
import ca.uhn.fhir.batch2.jobs.merge.MergeProvenanceSvc;
import ca.uhn.fhir.batch2.jobs.merge.MergeResourceHelper;
import ca.uhn.fhir.batch2.util.Batch2TaskHelper;
import ca.uhn.fhir.context.FhirContext;
Expand All @@ -36,17 +37,24 @@
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
import ca.uhn.fhir.util.OperationOutcomeUtil;
import ca.uhn.fhir.util.ParametersUtil;
import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
import org.hl7.fhir.instance.model.api.IBaseParameters;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.Patient;
import org.hl7.fhir.r4.model.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;
import java.util.List;

import static ca.uhn.fhir.batch2.jobs.merge.MergeAppCtx.JOB_MERGE;
import static ca.uhn.fhir.rest.api.Constants.STATUS_HTTP_200_OK;
import static ca.uhn.fhir.rest.api.Constants.STATUS_HTTP_202_ACCEPTED;
import static ca.uhn.fhir.rest.api.Constants.STATUS_HTTP_500_INTERNAL_ERROR;
import static ca.uhn.fhir.rest.server.provider.ProviderConstants.OPERATION_REPLACE_REFERENCES_OUTPUT_PARAM_OUTCOME;

/**
* Service for the FHIR $merge operation. Currently only supports Patient/$merge. The plan is to expand to other resource types.
Expand All @@ -65,6 +73,7 @@ public class ResourceMergeService {
private final MergeResourceHelper myMergeResourceHelper;
private final Batch2TaskHelper myBatch2TaskHelper;
private final MergeValidationService myMergeValidationService;
private final MergeProvenanceSvc myMergeProvenanceSvc;

public ResourceMergeService(
JpaStorageSettings theStorageSettings,
Expand All @@ -84,13 +93,18 @@ public ResourceMergeService(
myBatch2TaskHelper = theBatch2TaskHelper;
myFhirContext = myPatientDao.getContext();
myHapiTransactionService = theHapiTransactionService;
myMergeResourceHelper = new MergeResourceHelper(myPatientDao);
myMergeProvenanceSvc = new MergeProvenanceSvc(theDaoRegistry);
myMergeResourceHelper = new MergeResourceHelper(theDaoRegistry, myMergeProvenanceSvc);
myMergeValidationService = new MergeValidationService(myFhirContext, theDaoRegistry);
}

/**
* Perform the $merge operation. If the number of resources to be changed exceeds the provided batch size,
* then switch to async mode. See the <a href="https://build.fhir.org/patient-operation-merge.html">Patient $merge spec</a>
* Perform the $merge operation. Operation can be performed synchronously or asynchronously depending on
* the prefer-async request header.
* If the operation is requested to be performed synchronously and the number of
* resources to be changed exceeds the provided batch size,
* and error is returned indicating that operation needs to be performed asynchronously. See the
* <a href="https://build.fhir.org/patient-operation-merge.html">Patient $merge spec</a>
* for details on what the difference is between synchronous and asynchronous mode.
*
* @param theMergeOperationParameters the merge operation parameters
Expand Down Expand Up @@ -211,21 +225,33 @@ private void doMergeSync(
MergeOperationOutcome theMergeOutcome,
RequestPartitionId partitionId) {

Date startTime = new Date();
ReplaceReferencesRequest replaceReferencesRequest = new ReplaceReferencesRequest(
theSourceResource.getIdElement(),
theTargetResource.getIdElement(),
theMergeOperationParameters.getResourceLimit(),
partitionId);
partitionId,
// don't create provenance as part of replace-references,
// we create it after updating source and target for merge
false);

IBaseParameters outParams =
myReplaceReferencesSvc.replaceReferences(replaceReferencesRequest, theRequestDetails);

myReplaceReferencesSvc.replaceReferences(replaceReferencesRequest, theRequestDetails);
Bundle patchResultBundle = (Bundle) ParametersUtil.getNamedParameterResource(
myFhirContext, outParams, OPERATION_REPLACE_REFERENCES_OUTPUT_PARAM_OUTCOME)
.orElseThrow();

Patient updatedTarget = myMergeResourceHelper.updateMergedResourcesAfterReferencesReplaced(
Patient updatedTarget = myMergeResourceHelper.updateMergedResourcesAndCreateProvenance(
myHapiTransactionService,
theSourceResource,
theTargetResource,
List.of(patchResultBundle),
(Patient) theMergeOperationParameters.getResultResource(),
theMergeOperationParameters.getDeleteSource(),
theRequestDetails);
theRequestDetails,
startTime);

theMergeOutcome.setUpdatedTargetResource(updatedTarget);

String detailsText = "Merge operation completed successfully.";
Expand Down
Loading
Loading