From 9338a4e73e24b61832fbf2303a794da5cf2cd9f2 Mon Sep 17 00:00:00 2001 From: Nick Date: Fri, 8 Jan 2021 19:25:25 -0500 Subject: [PATCH] Survivorship 5 --- .../fhir/jpa/dao/index/IdHelperService.java | 9 +- .../mdm/svc/GoldenResourceMergerSvcImpl.java | 3 +- .../jpa/mdm/svc/MdmControllerSvcImpl.java | 12 ++- .../jpa/mdm/svc/MdmSurvivorshipSvcImpl.java | 16 ++- .../ca/uhn/fhir/jpa/mdm/BaseMdmR4Test.java | 4 +- .../mdm/provider/MdmProviderBatchR4Test.java | 3 - ...MdmProviderMergeGoldenResourcesR4Test.java | 97 ++++++++++++++++--- .../uhn/fhir/mdm/api/IMdmControllerSvc.java | 2 +- .../fhir/mdm/model/MdmTransactionContext.java | 9 ++ .../fhir/mdm/provider/BaseMdmProvider.java | 11 +++ .../mdm/provider/MdmProviderDstu3Plus.java | 11 ++- .../java/ca/uhn/fhir/mdm/util/TerserUtil.java | 2 +- .../server/provider/ProviderConstants.java | 4 +- 13 files changed, 150 insertions(+), 33 deletions(-) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/index/IdHelperService.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/index/IdHelperService.java index bffc285d902..e610938a5ca 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/index/IdHelperService.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/index/IdHelperService.java @@ -436,7 +436,14 @@ public class IdHelperService { @Nonnull public Long getPidOrThrowException(IAnyResource theResource) { - return (Long) theResource.getUserData(RESOURCE_PID); + Long retVal = (Long) theResource.getUserData(RESOURCE_PID); + // FIXME NG Is this the intent? + if (retVal == null) { + throw new IllegalStateException( + String.format("Unable to find %s in the user data for %s with ID %s", RESOURCE_PID, theResource, theResource.getId()) + ); + } + return retVal; } public IIdType resourceIdFromPidOrThrowException(Long thePid) { diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/GoldenResourceMergerSvcImpl.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/GoldenResourceMergerSvcImpl.java index f4e3c4e9eec..677fca9d423 100644 --- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/GoldenResourceMergerSvcImpl.java +++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/GoldenResourceMergerSvcImpl.java @@ -83,7 +83,8 @@ public class GoldenResourceMergerSvcImpl implements IGoldenResourceMergerSvc { //Save the deprecated resource. myMdmResourceDaoSvc.upsertGoldenResource(theFromGoldenResource, resourceType); - log(theMdmTransactionContext, "Merged " + theFromGoldenResource.getIdElement().toVersionless() + " into " + theToGoldenResource.getIdElement().toVersionless()); + log(theMdmTransactionContext, "Merged " + theFromGoldenResource.getIdElement().toVersionless() + + " into " + theToGoldenResource.getIdElement().toVersionless()); return theToGoldenResource; } diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmControllerSvcImpl.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmControllerSvcImpl.java index 6a5d3fc3a65..420e7f1df2e 100644 --- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmControllerSvcImpl.java +++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmControllerSvcImpl.java @@ -54,8 +54,16 @@ public class MdmControllerSvcImpl implements IMdmControllerSvc { IMdmLinkUpdaterSvc myIMdmLinkUpdaterSvc; @Override - public IAnyResource mergeGoldenResources(String theFromGoldenResourceId, String theToGoldenResourceId, MdmTransactionContext theMdmTransactionContext) { - IAnyResource fromGoldenResource = myMdmControllerHelper.getLatestGoldenResourceFromIdOrThrowException(ProviderConstants.MDM_MERGE_GR_FROM_GOLDEN_RESOURCE_ID, theFromGoldenResourceId); + public IAnyResource mergeGoldenResources(String theFromGoldenResourceId, String theToGoldenResourceId, IAnyResource theFromGoldenResource, MdmTransactionContext theMdmTransactionContext) { + boolean isOverwritingGoldenResource = (theFromGoldenResource != null); + + 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); myMdmControllerHelper.validateMergeResources(fromGoldenResource, toGoldenResource); myMdmControllerHelper.validateSameVersion(fromGoldenResource, theFromGoldenResourceId); diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmSurvivorshipSvcImpl.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmSurvivorshipSvcImpl.java index 4caa97602e5..e5dc8332abe 100644 --- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmSurvivorshipSvcImpl.java +++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmSurvivorshipSvcImpl.java @@ -64,11 +64,17 @@ public class MdmSurvivorshipSvcImpl implements IMdmSurvivorshipService { */ @Override public void applySurvivorshipRulesToGoldenResource(T theTargetResource, T theGoldenResource, MdmTransactionContext theMdmTransactionContext) { - // TerserUtil.mergeFields(myFhirContext, (IBaseResource) theTargetResource, (IBaseResource) theGoldenResource, TerserUtil.DEFAULT_EXCLUDED_FIELDS); - if (MdmTransactionContext.OperationType.MERGE_GOLDEN_RESOURCES == theMdmTransactionContext.getRestOperation()) { - TerserUtil.mergeFieldsExceptIdAndMeta(myFhirContext, (IBaseResource) theTargetResource, (IBaseResource) theGoldenResource); - } else { - TerserUtil.overwriteFields(myFhirContext, (IBaseResource) theTargetResource, (IBaseResource) theGoldenResource, TerserUtil.EXCLUDE_IDS_AND_META); + switch (theMdmTransactionContext.getRestOperation()) { + 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); + break; + default: + TerserUtil.overwriteFields(myFhirContext, (IBaseResource) theTargetResource, (IBaseResource) theGoldenResource, TerserUtil.EXCLUDE_IDS_AND_META); + break; } } } diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/BaseMdmR4Test.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/BaseMdmR4Test.java index 4d3eb16ea80..23ebb90370b 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/BaseMdmR4Test.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/BaseMdmR4Test.java @@ -139,7 +139,9 @@ abstract public class BaseMdmR4Test extends BaseJpaR4Test { @Nonnull protected Patient createGoldenPatient() { - return createPatient(new Patient(), true, false); + Patient patient = new Patient(); + patient.setActive(true); + return createPatient(patient, true, false); } @Nonnull diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderBatchR4Test.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderBatchR4Test.java index fd1d76f5dc2..ca168bd378b 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderBatchR4Test.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderBatchR4Test.java @@ -35,12 +35,10 @@ public class MdmProviderBatchR4Test extends BaseLinkR4Test { protected IAnyResource myGoldenMedication; protected StringType myGoldenMedicationId; - @Autowired IInterceptorService myInterceptorService; PointcutLatch afterMdmLatch = new PointcutLatch(Pointcut.MDM_AFTER_PERSISTED_RESOURCE_CHECKED); - @BeforeEach public void before() { super.before(); @@ -58,7 +56,6 @@ public class MdmProviderBatchR4Test extends BaseLinkR4Test { myGoldenMedication = getGoldenResourceFromTargetResource(myMedication); myGoldenMedicationId = new StringType(myGoldenMedication.getIdElement().getValue()); - myInterceptorService.registerAnonymousInterceptor(Pointcut.MDM_AFTER_PERSISTED_RESOURCE_CHECKED, afterMdmLatch); } diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderMergeGoldenResourcesR4Test.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderMergeGoldenResourcesR4Test.java index 36950758c44..ad7c3c20e8c 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderMergeGoldenResourcesR4Test.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderMergeGoldenResourcesR4Test.java @@ -38,19 +38,46 @@ public class MdmProviderMergeGoldenResourcesR4Test extends BaseProviderR4Test { myToGoldenPatientId = new StringType(myToGoldenPatient.getIdElement().getValue()); } + + @Test + public void testMergeWithOverride() { + myFromGoldenPatient.getName().clear(); + myFromGoldenPatient.addName().setFamily("Family").addGiven("Given"); + myFromGoldenPatient.addCommunication(); + myFromGoldenPatient.addExtension(); + + Patient mergedSourcePatient = (Patient) myMdmProvider.mergeGoldenResources(myFromGoldenPatientId, + myToGoldenPatientId, myFromGoldenPatient, myRequestDetails); + + assertEquals(myFromGoldenPatient.getName().size(), mergedSourcePatient.getName().size()); + assertEquals(myFromGoldenPatient.getName().get(0).getNameAsSingleString(), mergedSourcePatient.getName().get(0).getNameAsSingleString()); + + assertEquals(myFromGoldenPatient.getCommunication().size(), mergedSourcePatient.getCommunication().size()); + assertEquals(myFromGoldenPatient.getExtension().size(), mergedSourcePatient.getExtension().size()); + + Patient fromSourcePatient = myPatientDao.read(myFromGoldenPatient.getIdElement().toUnqualifiedVersionless()); + assertEquals(fromSourcePatient.getName().size(), mergedSourcePatient.getName().size()); + assertEquals(fromSourcePatient.getName().get(0).getNameAsSingleString(), mergedSourcePatient.getName().get(0).getNameAsSingleString()); + } + + @Test public void testMerge() { Patient mergedSourcePatient = (Patient) myMdmProvider.mergeGoldenResources(myFromGoldenPatientId, - myToGoldenPatientId, myRequestDetails); + myToGoldenPatientId, null, myRequestDetails); + + // we do not check setActive anymore - as not all types support that + assertTrue(MdmResourceUtil.isGoldenRecord(mergedSourcePatient)); + assertTrue(!MdmResourceUtil.isGoldenRecordRedirected(mergedSourcePatient)); - assertTrue(MdmResourceUtil.isGoldenRecord(myFromGoldenPatient)); assertEquals(myToGoldenPatient.getIdElement(), mergedSourcePatient.getIdElement()); assertThat(mergedSourcePatient, is(sameGoldenResourceAs(myToGoldenPatient))); assertEquals(1, getAllRedirectedGoldenPatients().size()); assertEquals(1, getAllGoldenPatients().size()); Patient fromSourcePatient = myPatientDao.read(myFromGoldenPatient.getIdElement().toUnqualifiedVersionless()); - assertThat(fromSourcePatient.getActive(), is(false)); + + assertTrue(!MdmResourceUtil.isGoldenRecord(fromSourcePatient)); assertTrue(MdmResourceUtil.isGoldenRecordRedirected(fromSourcePatient)); //TODO GGG eventually this will need to check a redirect... this is a hack which doesnt work @@ -67,12 +94,39 @@ public class MdmProviderMergeGoldenResourcesR4Test extends BaseProviderR4Test { assertEquals(link.getLinkSource(), MdmLinkSourceEnum.MANUAL); } + @Test + public void testMergeWithManualOverride() { + Patient mergedSourcePatient = (Patient) myMdmProvider.mergeGoldenResources(myFromGoldenPatientId, + myToGoldenPatientId, myFromGoldenPatient, myRequestDetails); + + assertTrue(!MdmResourceUtil.isGoldenRecord(myFromGoldenPatient)); + assertTrue(MdmResourceUtil.isGoldenRecordRedirected(myFromGoldenPatient)); + + assertEquals(myToGoldenPatient.getIdElement(), mergedSourcePatient.getIdElement()); + assertThat(mergedSourcePatient, is(sameGoldenResourceAs(myToGoldenPatient))); + assertEquals(1, getAllRedirectedGoldenPatients().size()); + assertEquals(1, getAllGoldenPatients().size()); + + Patient fromSourcePatient = myPatientDao.read(myFromGoldenPatient.getIdElement().toUnqualifiedVersionless()); + assertTrue(!MdmResourceUtil.isGoldenRecord(fromSourcePatient)); + assertTrue(MdmResourceUtil.isGoldenRecordRedirected(fromSourcePatient)); + + List links = myMdmLinkDaoSvc.findMdmLinksBySourceResource(myFromGoldenPatient); + assertThat(links, hasSize(1)); + + MdmLink link = links.get(0); + assertEquals(link.getSourcePid(), myFromGoldenPatient.getIdElement().toUnqualifiedVersionless().getIdPartAsLong()); + assertEquals(link.getGoldenResourcePid(), myToGoldenPatient.getIdElement().toUnqualifiedVersionless().getIdPartAsLong()); + assertEquals(link.getMatchResult(), MdmMatchResultEnum.REDIRECT); + assertEquals(link.getLinkSource(), MdmLinkSourceEnum.MANUAL); + } + @Test public void testUnmanagedMerge() { StringType fromGoldenResourceId = new StringType(createPatient().getIdElement().getValue()); StringType toGoldenResourceId = new StringType(createPatient().getIdElement().getValue()); try { - myMdmProvider.mergeGoldenResources(fromGoldenResourceId, toGoldenResourceId, myRequestDetails); + myMdmProvider.mergeGoldenResources(fromGoldenResourceId, toGoldenResourceId, null, myRequestDetails); fail(); } catch (InvalidRequestException e) { assertEquals("Only MDM managed resources can be merged. MDM managed resources must have the HAPI-MDM tag.", e.getMessage()); @@ -82,19 +136,19 @@ public class MdmProviderMergeGoldenResourcesR4Test extends BaseProviderR4Test { @Test public void testNullParams() { try { - myMdmProvider.mergeGoldenResources(null, null, myRequestDetails); + myMdmProvider.mergeGoldenResources(null, null, null, myRequestDetails); fail(); } catch (InvalidRequestException e) { assertEquals("fromGoldenResourceId cannot be null", e.getMessage()); } try { - myMdmProvider.mergeGoldenResources(null, myToGoldenPatientId, myRequestDetails); + myMdmProvider.mergeGoldenResources(null, myToGoldenPatientId, null, myRequestDetails); fail(); } catch (InvalidRequestException e) { assertEquals("fromGoldenResourceId cannot be null", e.getMessage()); } try { - myMdmProvider.mergeGoldenResources(myFromGoldenPatientId, null, myRequestDetails); + myMdmProvider.mergeGoldenResources(myFromGoldenPatientId, null, null, myRequestDetails); fail(); } catch (InvalidRequestException e) { assertEquals("toGoldenResourceId cannot be null", e.getMessage()); @@ -104,28 +158,49 @@ public class MdmProviderMergeGoldenResourcesR4Test extends BaseProviderR4Test { @Test public void testBadParams() { try { - myMdmProvider.mergeGoldenResources(new StringType("Patient/1"), new StringType("Patient/1"), myRequestDetails); + myMdmProvider.mergeGoldenResources(new StringType("Patient/1"), new StringType("Patient/1"), null, myRequestDetails); fail(); } catch (InvalidRequestException e) { assertEquals("fromGoldenResourceId must be different from toGoldenResourceId", e.getMessage()); } try { - myMdmProvider.mergeGoldenResources(new StringType("Patient/abc"), myToGoldenPatientId, myRequestDetails); + myMdmProvider.mergeGoldenResources(myFromGoldenPatientId, myToGoldenPatientId, new Patient(), myRequestDetails); + fail(); + } catch (InvalidRequestException e) { + assertEquals("resource.id cannot be null", e.getMessage()); + } + + try { + myMdmProvider.mergeGoldenResources(myFromGoldenPatientId, myToGoldenPatientId, myToGoldenPatient, myRequestDetails); + fail(); + } catch (InvalidRequestException e) { + assertEquals("resource must be different from the one with toGoldenResourceId", e.getMessage()); + } + + try { + myMdmProvider.mergeGoldenResources(new StringType("Patient/abc"), myToGoldenPatientId, null, myRequestDetails); fail(); } catch (ResourceNotFoundException e) { assertEquals("Resource Patient/abc is not known", e.getMessage()); } try { - myMdmProvider.mergeGoldenResources(new StringType("Organization/abc"), myToGoldenPatientId, myRequestDetails); + myMdmProvider.mergeGoldenResources(new StringType("Patient/abc"), myToGoldenPatientId, null, myRequestDetails); + fail(); + } catch (ResourceNotFoundException e) { + assertEquals("Resource Patient/abc is not known", e.getMessage()); + } + + try { + myMdmProvider.mergeGoldenResources(new StringType("Organization/abc"), myToGoldenPatientId, null, myRequestDetails); fail(); } catch (ResourceNotFoundException e) { assertEquals("Resource Organization/abc is not known", e.getMessage()); } try { - myMdmProvider.mergeGoldenResources(myFromGoldenPatientId, new StringType("Patient/abc"), myRequestDetails); + myMdmProvider.mergeGoldenResources(myFromGoldenPatientId, new StringType("Patient/abc"), null, myRequestDetails); fail(); } catch (ResourceNotFoundException e) { assertEquals("Resource Patient/abc is not known", e.getMessage()); diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmControllerSvc.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmControllerSvc.java index 78a11dbe5db..8ce3b3af77a 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmControllerSvc.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmControllerSvc.java @@ -34,7 +34,7 @@ public interface IMdmControllerSvc { void notDuplicateGoldenResource(String theGoldenResourceId, String theTargetGoldenResourceId, MdmTransactionContext theMdmTransactionContext); - IAnyResource mergeGoldenResources(String theFromGoldenResourceId, String theToGoldenResourceId, MdmTransactionContext theMdmTransactionContext); + IAnyResource mergeGoldenResources(String theFromGoldenResourceId, String theToGoldenResourceId, IAnyResource theFromGoldenResource, MdmTransactionContext theMdmTransactionContext); IAnyResource updateLink(String theGoldenResourceId, String theSourceResourceId, String theMatchResult, MdmTransactionContext theMdmTransactionContext); } diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/model/MdmTransactionContext.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/model/MdmTransactionContext.java index 2bb43f8de64..1b8e6976fa0 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/model/MdmTransactionContext.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/model/MdmTransactionContext.java @@ -44,6 +44,8 @@ public class MdmTransactionContext { private String myResourceType; + private boolean myForceResourceUpdate; + public TransactionLogMessages getTransactionLogMessages() { return myTransactionLogMessages; } @@ -88,4 +90,11 @@ public class MdmTransactionContext { this.myResourceType = myResourceType; } + public boolean isForceResourceUpdate() { + return myForceResourceUpdate; + } + + public void setForceResourceUpdate(boolean theForceResourceUpdate) { + myForceResourceUpdate = theForceResourceUpdate; + } } diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/BaseMdmProvider.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/BaseMdmProvider.java index e9bdb713959..6d386c6866a 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/BaseMdmProvider.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/BaseMdmProvider.java @@ -29,6 +29,7 @@ import ca.uhn.fhir.rest.server.TransactionLogMessages; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.provider.ProviderConstants; import ca.uhn.fhir.util.ParametersUtil; +import org.hl7.fhir.instance.model.api.IAnyResource; import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBaseParameters; import org.hl7.fhir.instance.model.api.IPrimitiveType; @@ -50,6 +51,16 @@ public abstract class BaseMdmProvider { throw new InvalidRequestException("fromGoldenResourceId must be different from toGoldenResourceId"); } } + protected void validateOptionalMergeResource(IAnyResource theFromGoldenResource, IPrimitiveType theToGoldenResourceId) { + if (theFromGoldenResource == null) { + return; + } + validateNotNull(ProviderConstants.MDM_MERGE_RESOURCE_ID, theFromGoldenResource.getIdElement()); + if (theFromGoldenResource.getIdElement().getValue().equals(theToGoldenResourceId.getValue())) { + throw new InvalidRequestException("resource must be different from the one with toGoldenResourceId"); + } + validateMergeParameters(theFromGoldenResource.getIdElement(), theToGoldenResourceId); + } private void validateNotNull(String theName, IPrimitiveType theString) { if (theString == null || theString.getValue() == null) { diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/MdmProviderDstu3Plus.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/MdmProviderDstu3Plus.java index bbbcaa43092..1a3023e5a1e 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/MdmProviderDstu3Plus.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/MdmProviderDstu3Plus.java @@ -144,14 +144,15 @@ public class MdmProviderDstu3Plus extends BaseMdmProvider { @Operation(name = ProviderConstants.MDM_MERGE_GOLDEN_RESOURCES) public IBaseResource mergeGoldenResources(@OperationParam(name = ProviderConstants.MDM_MERGE_GR_FROM_GOLDEN_RESOURCE_ID, min = 1, max = 1, typeName = "string") IPrimitiveType theFromGoldenResourceId, @OperationParam(name = ProviderConstants.MDM_MERGE_GR_TO_GOLDEN_RESOURCE_ID, min = 1, max = 1, typeName = "string") IPrimitiveType theToGoldenResourceId, - @OperationParam() + @OperationParam(name = ProviderConstants.MDM_MERGE_RESOURCE, max = 1) IAnyResource theMergedResource, RequestDetails theRequestDetails) { validateMergeParameters(theFromGoldenResourceId, theToGoldenResourceId); + validateOptionalMergeResource(theMergedResource, theToGoldenResourceId); - return myMdmControllerSvc.mergeGoldenResources(theFromGoldenResourceId.getValueAsString(), theToGoldenResourceId.getValueAsString(), - createMdmContext(theRequestDetails, MdmTransactionContext.OperationType.MERGE_GOLDEN_RESOURCES, - getResourceType(ProviderConstants.MDM_MERGE_GR_FROM_GOLDEN_RESOURCE_ID, theFromGoldenResourceId)) - ); + MdmTransactionContext txContext = createMdmContext(theRequestDetails, MdmTransactionContext.OperationType.MERGE_GOLDEN_RESOURCES, + getResourceType(ProviderConstants.MDM_MERGE_GR_FROM_GOLDEN_RESOURCE_ID, theFromGoldenResourceId)); + txContext.setForceResourceUpdate(theMergedResource != null); + return myMdmControllerSvc.mergeGoldenResources(theFromGoldenResourceId.getValueAsString(), theToGoldenResourceId.getValueAsString(), theMergedResource, txContext); } @Operation(name = ProviderConstants.MDM_UPDATE_LINK) diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/util/TerserUtil.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/util/TerserUtil.java index d019ecd7317..3bb19d3b214 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/util/TerserUtil.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/util/TerserUtil.java @@ -42,7 +42,7 @@ import static ca.uhn.fhir.mdm.util.GoldenResourceHelper.FIELD_NAME_IDENTIFIER; public final class TerserUtil { public static final Collection IDS_AND_META_EXCLUDES = - Collections.unmodifiableSet(Stream.of("id", "meta", "identifier").collect(Collectors.toSet())); + Collections.unmodifiableSet(Stream.of("id", "identifier", "meta", "active").collect(Collectors.toSet())); public static final Predicate EXCLUDE_IDS_AND_META = new Predicate() { @Override diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/provider/ProviderConstants.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/provider/ProviderConstants.java index 2899516bc90..a6258b46f95 100644 --- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/provider/ProviderConstants.java +++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/provider/ProviderConstants.java @@ -62,15 +62,15 @@ public class ProviderConstants { * EMPI Operations */ public static final String EMPI_MATCH = "$match"; - //TODO GGG MDM: implement a server-level MDM match to complement the FHIR-spec $match for /Patient public static final String MDM_MATCH = "$mdm-match"; public static final String MDM_MATCH_RESOURCE = "resource"; public static final String MDM_RESOURCE_TYPE = "resourceType"; - //TODO GGG MDM: rename all these vars public static final String MDM_MERGE_GOLDEN_RESOURCES = "$mdm-merge-golden-resources"; public static final String MDM_MERGE_GR_FROM_GOLDEN_RESOURCE_ID = "fromGoldenResourceId"; public static final String MDM_MERGE_GR_TO_GOLDEN_RESOURCE_ID = "toGoldenResourceId"; + public static final String MDM_MERGE_RESOURCE = "resource"; + public static final String MDM_MERGE_RESOURCE_ID = "resource.id"; public static final String MDM_UPDATE_LINK = "$mdm-update-link"; public static final String MDM_UPDATE_LINK_GOLDEN_RESOURCE_ID = "goldenResourceId";