From a2aa2ca1c37ec9f171285c0ef8d3502448c8b37e Mon Sep 17 00:00:00 2001
From: Nick Goupinets
Date: Thu, 29 Jul 2021 15:52:09 -0400
Subject: [PATCH 01/13] 2849 Added new parameter to MDM processing
---
.../ca/uhn/fhir/interceptor/api/Pointcut.java | 6 +-
.../jpa/mdm/broker/MdmMessageHandler.java | 18 ++++--
.../fhir/jpa/mdm/svc/MdmEidUpdateService.java | 2 +
.../uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvc.java | 5 ++
.../fhir/jpa/mdm/helper/BaseMdmHelper.java | 3 +
.../interceptor/MdmStorageInterceptorIT.java | 26 +++++++++
.../uhn/fhir/mdm/api/MdmLinkChangeEvent.java | 55 +++++++++++++++++++
.../fhir/mdm/model/MdmTransactionContext.java | 11 ++++
8 files changed, 119 insertions(+), 7 deletions(-)
create mode 100644 hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkChangeEvent.java
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java
index db6dff8b7a1..d8f0f33ae9f 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java
@@ -1986,13 +1986,17 @@ public enum Pointcut implements IPointcut {
*
* - ca.uhn.fhir.rest.server.messaging.ResourceOperationMessage - This parameter should not be modified as processing is complete when this hook is invoked.
* - ca.uhn.fhir.rest.server.TransactionLogMessages - This parameter is for informational messages provided by the MDM module during MDM processing.
+ * - ca.uhn.fhir.mdm.api.MdmLinkChangeEvent - Contains information about the change event, including target and golden resource IDs and the operation type.
*
*
*
* Hooks should return void
.
*
*/
- MDM_AFTER_PERSISTED_RESOURCE_CHECKED(void.class, "ca.uhn.fhir.rest.server.messaging.ResourceOperationMessage", "ca.uhn.fhir.rest.server.TransactionLogMessages"),
+ MDM_AFTER_PERSISTED_RESOURCE_CHECKED(void.class,
+ "ca.uhn.fhir.rest.server.messaging.ResourceOperationMessage",
+ "ca.uhn.fhir.rest.server.TransactionLogMessages",
+ "ca.uhn.fhir.mdm.api.MdmLinkChangeEvent"),
/**
* Performance Tracing Hook:
diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/broker/MdmMessageHandler.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/broker/MdmMessageHandler.java
index 3a84eebb083..b80d2caafc7 100644
--- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/broker/MdmMessageHandler.java
+++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/broker/MdmMessageHandler.java
@@ -30,12 +30,15 @@ import ca.uhn.fhir.jpa.mdm.svc.candidate.TooManyCandidatesException;
import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedJsonMessage;
import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
import ca.uhn.fhir.mdm.api.IMdmSettings;
+import ca.uhn.fhir.mdm.api.MdmLinkChangeEvent;
import ca.uhn.fhir.mdm.log.Logs;
import ca.uhn.fhir.mdm.model.MdmTransactionContext;
import ca.uhn.fhir.rest.server.TransactionLogMessages;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.messaging.ResourceOperationMessage;
import org.hl7.fhir.instance.model.api.IAnyResource;
+import org.hl7.fhir.instance.model.api.IBaseResource;
+import org.hl7.fhir.instance.model.api.IIdType;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
@@ -89,11 +92,11 @@ public class MdmMessageHandler implements MessageHandler {
try {
switch (theMsg.getOperationType()) {
case CREATE:
- handleCreatePatientOrPractitioner(theMsg, mdmContext);
+ handleCreateResource(theMsg, mdmContext);
break;
case UPDATE:
case MANUALLY_TRIGGERED:
- handleUpdatePatientOrPractitioner(theMsg, mdmContext);
+ handleUpdateResource(theMsg, mdmContext);
break;
case DELETE:
default:
@@ -105,12 +108,15 @@ public class MdmMessageHandler implements MessageHandler {
} finally {
// Interceptor call: MDM_AFTER_PERSISTED_RESOURCE_CHECKED
- ResourceOperationMessage outgoingMsg = new ResourceOperationMessage(myFhirContext, theMsg.getPayload(myFhirContext), theMsg.getOperationType());
+ IBaseResource targetResource = theMsg.getPayload(myFhirContext);
+ ResourceOperationMessage outgoingMsg = new ResourceOperationMessage(myFhirContext, targetResource, theMsg.getOperationType());
outgoingMsg.setTransactionId(theMsg.getTransactionId());
HookParams params = new HookParams()
.add(ResourceOperationMessage.class, outgoingMsg)
- .add(TransactionLogMessages.class, mdmContext.getTransactionLogMessages());
+ .add(TransactionLogMessages.class, mdmContext.getTransactionLogMessages())
+ .add(MdmLinkChangeEvent.class, mdmContext.getMdmLinkChangeEvent());
+
myInterceptorBroadcaster.callHooks(Pointcut.MDM_AFTER_PERSISTED_RESOURCE_CHECKED, params);
}
}
@@ -142,7 +148,7 @@ public class MdmMessageHandler implements MessageHandler {
}
}
- private void handleCreatePatientOrPractitioner(ResourceModifiedMessage theMsg, MdmTransactionContext theMdmTransactionContext) {
+ private void handleCreateResource(ResourceModifiedMessage theMsg, MdmTransactionContext theMdmTransactionContext) {
myMdmMatchLinkSvc.updateMdmLinksForMdmSource(getResourceFromPayload(theMsg), theMdmTransactionContext);
}
@@ -150,7 +156,7 @@ public class MdmMessageHandler implements MessageHandler {
return (IAnyResource) theMsg.getNewPayload(myFhirContext);
}
- private void handleUpdatePatientOrPractitioner(ResourceModifiedMessage theMsg, MdmTransactionContext theMdmTransactionContext) {
+ private void handleUpdateResource(ResourceModifiedMessage theMsg, MdmTransactionContext theMdmTransactionContext) {
myMdmMatchLinkSvc.updateMdmLinksForMdmSource(getResourceFromPayload(theMsg), theMdmTransactionContext);
}
diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmEidUpdateService.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmEidUpdateService.java
index 94db6849073..d23c27db9f1 100644
--- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmEidUpdateService.java
+++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmEidUpdateService.java
@@ -85,6 +85,8 @@ public class MdmEidUpdateService {
myMdmSurvivorshipService.applySurvivorshipRulesToGoldenResource(theTargetResource, updateContext.getMatchedGoldenResource(), theMdmTransactionContext);
myMdmResourceDaoSvc.upsertGoldenResource(updateContext.getMatchedGoldenResource(), theMdmTransactionContext.getResourceType());
}
+
+ theMdmTransactionContext.getMdmLinkChangeEvent().setGoldenResourceId(updateContext.getExistingGoldenResource());
}
private void handleNoEidsInCommon(IAnyResource theResource, MatchedGoldenResourceCandidate theMatchedGoldenResourceCandidate, MdmTransactionContext theMdmTransactionContext, MdmUpdateContext theUpdateContext) {
diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvc.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvc.java
index fdd04914646..90020ffc259 100644
--- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvc.java
+++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvc.java
@@ -112,11 +112,14 @@ public class MdmMatchLinkSvc {
//Set all GoldenResources as POSSIBLE_DUPLICATE of the last GoldenResource.
IAnyResource firstGoldenResource = goldenResources.get(0);
+ theMdmTransactionContext.getMdmLinkChangeEvent().setGoldenResourceId(firstGoldenResource);
+
goldenResources.subList(1, goldenResources.size())
.forEach(possibleDuplicateGoldenResource -> {
MdmMatchOutcome outcome = MdmMatchOutcome.POSSIBLE_DUPLICATE;
outcome.setEidMatch(theCandidateList.isEidMatch());
myMdmLinkSvc.updateLink(firstGoldenResource, possibleDuplicateGoldenResource, outcome, MdmLinkSourceEnum.AUTO, theMdmTransactionContext);
+ theMdmTransactionContext.getMdmLinkChangeEvent().addDuplicateGoldenResourceId(possibleDuplicateGoldenResource);
});
}
}
@@ -129,6 +132,8 @@ public class MdmMatchLinkSvc {
// 2. Create source resource for the MDM source
// 3. UPDATE MDM LINK TABLE
myMdmLinkSvc.updateLink(newGoldenResource, theResource, MdmMatchOutcome.NEW_GOLDEN_RESOURCE_MATCH, MdmLinkSourceEnum.AUTO, theMdmTransactionContext);
+
+ theMdmTransactionContext.getMdmLinkChangeEvent().setGoldenResourceId(newGoldenResource);
}
private void handleMdmCreate(IAnyResource theTargetResource, MatchedGoldenResourceCandidate theGoldenResourceCandidate, MdmTransactionContext theMdmTransactionContext) {
diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/helper/BaseMdmHelper.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/helper/BaseMdmHelper.java
index 1389c4c5ea1..601b3ce2920 100644
--- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/helper/BaseMdmHelper.java
+++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/helper/BaseMdmHelper.java
@@ -106,5 +106,8 @@ public abstract class BaseMdmHelper implements BeforeEachCallback, AfterEachCall
return channel.getQueueSizeForUnitTest();
}
+ public PointcutLatch getAfterMdmLatch() {
+ return myAfterMdmLatch;
+ }
}
diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmStorageInterceptorIT.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmStorageInterceptorIT.java
index c722b23dab2..7d24395852d 100644
--- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmStorageInterceptorIT.java
+++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmStorageInterceptorIT.java
@@ -7,13 +7,16 @@ import ca.uhn.fhir.jpa.mdm.BaseMdmR4Test;
import ca.uhn.fhir.jpa.mdm.helper.MdmHelperConfig;
import ca.uhn.fhir.jpa.mdm.helper.MdmHelperR4;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
+import ca.uhn.fhir.mdm.api.MdmLinkChangeEvent;
import ca.uhn.fhir.mdm.model.CanonicalEID;
import ca.uhn.fhir.mdm.rules.config.MdmSettings;
+import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
import ca.uhn.fhir.rest.param.ReferenceParam;
import ca.uhn.fhir.rest.server.TransactionLogMessages;
import ca.uhn.fhir.rest.server.exceptions.ForbiddenOperationException;
+import ca.uhn.fhir.rest.server.messaging.ResourceOperationMessage;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
@@ -21,16 +24,21 @@ import org.hl7.fhir.r4.model.Enumerations;
import org.hl7.fhir.r4.model.Medication;
import org.hl7.fhir.r4.model.Organization;
import org.hl7.fhir.r4.model.Patient;
+import org.hl7.fhir.r4.model.Practitioner;
import org.hl7.fhir.r4.model.SearchParameter;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Example;
+import org.springframework.data.domain.ExampleMatcher;
+import org.springframework.data.domain.Pageable;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import java.util.Date;
import java.util.List;
+import java.util.Optional;
import static ca.uhn.fhir.mdm.api.MdmConstants.CODE_GOLDEN_RECORD;
import static ca.uhn.fhir.mdm.api.MdmConstants.CODE_GOLDEN_RECORD_REDIRECTED;
@@ -67,6 +75,24 @@ public class MdmStorageInterceptorIT extends BaseMdmR4Test {
assertLinkCount(1);
}
+ @Test
+ public void testCreateLinkChangeEvent() throws InterruptedException {
+ Practitioner pr = buildPractitionerWithNameAndId("Young", "AC-DC");
+ myMdmHelper.createWithLatch(pr);
+
+ ResourceOperationMessage resourceOperationMessage = myMdmHelper.getAfterMdmLatch().getLatchInvocationParameterOfType(ResourceOperationMessage.class);
+ assertNotNull(resourceOperationMessage);
+ assertEquals(pr.getId(), resourceOperationMessage.getId());
+
+ MdmLink example = new MdmLink();
+ example.setSourcePid(pr.getIdElement().getIdPartAsLong());
+ MdmLink link = myMdmLinkDao.findAll(Example.of(example)).get(0);
+
+ MdmLinkChangeEvent linkChangeEvent = myMdmHelper.getAfterMdmLatch().getLatchInvocationParameterOfType(MdmLinkChangeEvent.class);
+ assertNotNull(linkChangeEvent);
+ assertEquals(link.getGoldenResourcePid(), new IdDt(linkChangeEvent.getGoldenResourceId()).getIdPartAsLong());
+ }
+
@Test
public void testSearchExpandingInterceptorWorks() {
SearchParameterMap subject = new SearchParameterMap("subject", new ReferenceParam("Patient/123").setMdmExpand(true)).setLoadSynchronous(true);
diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkChangeEvent.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkChangeEvent.java
new file mode 100644
index 00000000000..374d955aba8
--- /dev/null
+++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkChangeEvent.java
@@ -0,0 +1,55 @@
+package ca.uhn.fhir.mdm.api;
+
+import org.hl7.fhir.instance.model.api.IBaseResource;
+import org.hl7.fhir.instance.model.api.IIdType;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class MdmLinkChangeEvent {
+
+ private String myGoldenResourceId;
+ private Set myDuplicateGoldenResourceIds = new HashSet<>();
+
+ public String getGoldenResourceId() {
+ return myGoldenResourceId;
+ }
+
+ public void setGoldenResourceId(IBaseResource theGoldenResourceId) {
+ setGoldenResourceId(getIdAsString(theGoldenResourceId));
+ }
+
+ public void setGoldenResourceId(String theGoldenResourceId) {
+ myGoldenResourceId = theGoldenResourceId;
+ }
+
+ private String getIdAsString(IBaseResource theResource) {
+ if (theResource == null) {
+ return null;
+ }
+ IIdType idElement = theResource.getIdElement();
+ if (idElement == null) {
+ return null;
+ }
+ return idElement.getValueAsString();
+ }
+
+ public Set getDuplicateGoldenResourceIds() {
+ return myDuplicateGoldenResourceIds;
+ }
+
+ public void setDuplicateGoldenResourceIds(Set theDuplicateGoldenResourceIds) {
+ myDuplicateGoldenResourceIds = theDuplicateGoldenResourceIds;
+ }
+
+ public MdmLinkChangeEvent addDuplicateGoldenResourceId(IBaseResource theDuplicateGoldenResourceId) {
+ String id = getIdAsString(theDuplicateGoldenResourceId);
+ if (id != null) {
+ getDuplicateGoldenResourceIds().add(id);
+ }
+ return this;
+ }
+
+}
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 a2fb07fe200..db699fd602b 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
@@ -20,6 +20,7 @@ package ca.uhn.fhir.mdm.model;
* #L%
*/
+import ca.uhn.fhir.mdm.api.MdmLinkChangeEvent;
import ca.uhn.fhir.rest.server.TransactionLogMessages;
public class MdmTransactionContext {
@@ -45,6 +46,8 @@ public class MdmTransactionContext {
private String myResourceType;
+ private MdmLinkChangeEvent myMdmLinkChangeEvent = new MdmLinkChangeEvent();
+
public TransactionLogMessages getTransactionLogMessages() {
return myTransactionLogMessages;
}
@@ -92,4 +95,12 @@ public class MdmTransactionContext {
public void setResourceType(String myResourceType) {
this.myResourceType = myResourceType;
}
+
+ public MdmLinkChangeEvent getMdmLinkChangeEvent() {
+ return myMdmLinkChangeEvent;
+ }
+
+ public void setMdmLinkChangeEvent(MdmLinkChangeEvent theMdmLinkChangeEvent) {
+ myMdmLinkChangeEvent = theMdmLinkChangeEvent;
+ }
}
From 0d34fe61c81da55d5d641a496cef957de1c5fd4b Mon Sep 17 00:00:00 2001
From: Nick Goupinets
Date: Fri, 30 Jul 2021 11:17:56 -0400
Subject: [PATCH 02/13] Adding tests
---
.../jpa/mdm/broker/MdmMessageHandler.java | 1 +
.../interceptor/MdmStorageInterceptorIT.java | 36 +++++++++++++++++++
.../uhn/fhir/mdm/api/MdmLinkChangeEvent.java | 16 +++++++--
3 files changed, 51 insertions(+), 2 deletions(-)
diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/broker/MdmMessageHandler.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/broker/MdmMessageHandler.java
index b80d2caafc7..967349c0823 100644
--- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/broker/MdmMessageHandler.java
+++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/broker/MdmMessageHandler.java
@@ -111,6 +111,7 @@ public class MdmMessageHandler implements MessageHandler {
IBaseResource targetResource = theMsg.getPayload(myFhirContext);
ResourceOperationMessage outgoingMsg = new ResourceOperationMessage(myFhirContext, targetResource, theMsg.getOperationType());
outgoingMsg.setTransactionId(theMsg.getTransactionId());
+ mdmContext.getMdmLinkChangeEvent().setTargetResourceId(targetResource);
HookParams params = new HookParams()
.add(ResourceOperationMessage.class, outgoingMsg)
diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmStorageInterceptorIT.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmStorageInterceptorIT.java
index 7d24395852d..919911a3e25 100644
--- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmStorageInterceptorIT.java
+++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmStorageInterceptorIT.java
@@ -91,6 +91,42 @@ public class MdmStorageInterceptorIT extends BaseMdmR4Test {
MdmLinkChangeEvent linkChangeEvent = myMdmHelper.getAfterMdmLatch().getLatchInvocationParameterOfType(MdmLinkChangeEvent.class);
assertNotNull(linkChangeEvent);
assertEquals(link.getGoldenResourcePid(), new IdDt(linkChangeEvent.getGoldenResourceId()).getIdPartAsLong());
+ assertEquals(link.getSourcePid(), new IdDt(linkChangeEvent.getTargetResourceId()).getIdPartAsLong());
+ }
+
+ @Test
+ public void testUpdateLinkChangeEvent() throws InterruptedException {
+ Patient patient1 = addExternalEID(buildJanePatient(), "eid-1");
+ patient1 = createPatientAndUpdateLinks(patient1);
+
+ Patient patient2 = addExternalEID(buildJanePatient(), "eid-2");
+ patient2 = createPatientAndUpdateLinks(patient2);
+
+ MdmLinkChangeEvent linkChangeEvent = myMdmHelper.getAfterMdmLatch().getLatchInvocationParameterOfType(MdmLinkChangeEvent.class);
+ assertNotNull(linkChangeEvent);
+// assertEquals(link.getGoldenResourcePid(), new IdDt(linkChangeEvent.getGoldenResourceId()).getIdPartAsLong());
+// assertEquals(link.getSourcePid(), new IdDt(linkChangeEvent.getTargetResourceId()).getIdPartAsLong());
+ }
+
+ @Test
+ public void testDuplicateLinkChangeEvent() throws InterruptedException {
+ fail();
+
+ Practitioner pr = buildPractitionerWithNameAndId("Young", "AC-DC");
+ myMdmHelper.createWithLatch(pr);
+
+ ResourceOperationMessage resourceOperationMessage = myMdmHelper.getAfterMdmLatch().getLatchInvocationParameterOfType(ResourceOperationMessage.class);
+ assertNotNull(resourceOperationMessage);
+ assertEquals(pr.getId(), resourceOperationMessage.getId());
+
+ MdmLink example = new MdmLink();
+ example.setSourcePid(pr.getIdElement().getIdPartAsLong());
+ MdmLink link = myMdmLinkDao.findAll(Example.of(example)).get(0);
+
+ MdmLinkChangeEvent linkChangeEvent = myMdmHelper.getAfterMdmLatch().getLatchInvocationParameterOfType(MdmLinkChangeEvent.class);
+ assertNotNull(linkChangeEvent);
+ assertEquals(link.getGoldenResourcePid(), new IdDt(linkChangeEvent.getGoldenResourceId()).getIdPartAsLong());
+ assertEquals(link.getSourcePid(), new IdDt(linkChangeEvent.getTargetResourceId()).getIdPartAsLong());
}
@Test
diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkChangeEvent.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkChangeEvent.java
index 374d955aba8..c0593b2929d 100644
--- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkChangeEvent.java
+++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkChangeEvent.java
@@ -1,15 +1,15 @@
package ca.uhn.fhir.mdm.api;
+import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
-import java.util.ArrayList;
import java.util.HashSet;
-import java.util.List;
import java.util.Set;
public class MdmLinkChangeEvent {
+ private String myTargetResourceId;
private String myGoldenResourceId;
private Set myDuplicateGoldenResourceIds = new HashSet<>();
@@ -36,6 +36,18 @@ public class MdmLinkChangeEvent {
return idElement.getValueAsString();
}
+ public String getTargetResourceId() {
+ return myTargetResourceId;
+ }
+
+ public void setTargetResourceId(IBaseResource theTargetResource) {
+ setTargetResourceId(getIdAsString(theTargetResource));
+ }
+
+ public void setTargetResourceId(String theTargetResourceId) {
+ myTargetResourceId = theTargetResourceId;
+ }
+
public Set getDuplicateGoldenResourceIds() {
return myDuplicateGoldenResourceIds;
}
From 891a6304d0e021021c540282e8ebf8b7adf6c0f4 Mon Sep 17 00:00:00 2001
From: Nick Goupinets
Date: Wed, 4 Aug 2021 11:06:14 -0400
Subject: [PATCH 03/13] WIP
---
.../dao/r4/FhirResourceDaoCodeSystemR4.java | 2 +-
.../jpa/mdm/broker/MdmMessageHandler.java | 1 -
.../uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvc.java | 6 +++
.../interceptor/MdmStorageInterceptorIT.java | 54 ++++++++-----------
.../uhn/fhir/mdm/api/MdmLinkChangeEvent.java | 36 ++++++++++++-
.../fhir/mdm/model/MdmTransactionContext.java | 1 +
6 files changed, 65 insertions(+), 35 deletions(-)
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoCodeSystemR4.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoCodeSystemR4.java
index 2ff1ee51c70..335cef64375 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoCodeSystemR4.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoCodeSystemR4.java
@@ -139,7 +139,7 @@ public class FhirResourceDaoCodeSystemR4 extends BaseHapiFhirResourceDao myDuplicateGoldenResourceIds = new HashSet<>();
public String getGoldenResourceId() {
@@ -64,4 +88,12 @@ public class MdmLinkChangeEvent {
return this;
}
+ @Override
+ public String toString() {
+ return "MdmLinkChangeEvent{" +
+ "myTargetResourceId='" + myTargetResourceId + '\'' +
+ ", myGoldenResourceId='" + myGoldenResourceId + '\'' +
+ ", myDuplicateGoldenResourceIds=" + myDuplicateGoldenResourceIds +
+ '}';
+ }
}
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 db699fd602b..ce35ea3f150 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
@@ -103,4 +103,5 @@ public class MdmTransactionContext {
public void setMdmLinkChangeEvent(MdmLinkChangeEvent theMdmLinkChangeEvent) {
myMdmLinkChangeEvent = theMdmLinkChangeEvent;
}
+
}
From 4be3334f6ff29f13629d65e67957475547de0c46 Mon Sep 17 00:00:00 2001
From: Nick Goupinets
Date: Wed, 4 Aug 2021 16:33:59 -0400
Subject: [PATCH 04/13] WIP after persistence checked
---
.../dao/r4/FhirResourceDaoCodeSystemR4.java | 2 +-
.../jpa/mdm/broker/MdmMessageHandler.java | 30 ++++++++++++++++---
2 files changed, 27 insertions(+), 5 deletions(-)
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoCodeSystemR4.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoCodeSystemR4.java
index 6a01ab94c70..5f2aa32a2ec 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoCodeSystemR4.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoCodeSystemR4.java
@@ -138,7 +138,7 @@ public class FhirResourceDaoCodeSystemR4 extends BaseHapiFhirResourceDao mdmLinkBySource = myMdmLinkDaoSvc.findMdmLinkBySource(targetResource);
+ if (!mdmLinkBySource.isPresent()) {
+ ourLog.warn("Unable to find link by source for {}", targetResource.getIdElement());
+ }
+
+ mdmLinkBySource.ifPresent(link -> {
+ linkChangeEvent.setMdmMatchResult(link.getMatchResult());
+ linkChangeEvent.setMdmLinkSource(link.getLinkSource());
+ linkChangeEvent.setEidMatch(link.isEidMatchPresent());
+ linkChangeEvent.setNewGoldenResource(link.getHadToCreateNewGoldenResource());
+ linkChangeEvent.setScore(link.getScore());
+ linkChangeEvent.setRuleCount(link.getRuleCount());
+ });
+
HookParams params = new HookParams()
.add(ResourceOperationMessage.class, outgoingMsg)
.add(TransactionLogMessages.class, mdmContext.getTransactionLogMessages())
From 8670f107b5118c274b00c92327478f26f55bc9ad Mon Sep 17 00:00:00 2001
From: Nick Goupinets
Date: Tue, 17 Aug 2021 13:17:44 -0400
Subject: [PATCH 05/13] Updated link expansion
---
.../ca/uhn/fhir/jpa/dao/data/IMdmLinkDao.java | 9 +++
.../fhir/jpa/dao/mdm/MdmLinkExpandSvc.java | 22 +++++-
.../fhir/jpa/mdm/dao/MdmLinkDaoSvcTest.java | 9 +++
.../uhn/fhir/mdm/api/MdmLinkChangeEvent.java | 72 ++++++++++++++++++-
4 files changed, 106 insertions(+), 6 deletions(-)
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IMdmLinkDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IMdmLinkDao.java
index 16834facbe2..be0a6289a4e 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IMdmLinkDao.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IMdmLinkDao.java
@@ -67,4 +67,13 @@ public interface IMdmLinkDao extends JpaRepository {
"AND ml.myMatchResult=:matchResult")
List expandPidsBySourcePidAndMatchResult(@Param("sourcePid") Long theSourcePid, @Param("matchResult") MdmMatchResultEnum theMdmMatchResultEnum);
+ @Query("SELECT DISTINCT ml.myGoldenResourcePid as goldenPid, ml.mySourcePid as sourcePid " +
+ "FROM MdmLink ml " +
+ "INNER JOIN MdmLink ml2 " +
+ "ON ml.myGoldenResourcePid = ml2.myGoldenResourcePid " +
+ "WHERE (ml2.mySourcePid = :sourceOrGoldenPid OR ml2.myGoldenResourcePid = :sourceOrGoldenPid) " +
+ "AND ml2.myMatchResult=:matchResult " +
+ "AND ml.myMatchResult=:matchResult")
+ List expandPidsBySourceOrGoldenResourcePidAndMatchResult(@Param("sourceOrGoldenPid") Long theSourceOrGoldenPid, @Param("matchResult") MdmMatchResultEnum theMdmMatchResultEnum);
+
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/mdm/MdmLinkExpandSvc.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/mdm/MdmLinkExpandSvc.java
index 66af7f5a706..b03e22d04b8 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/mdm/MdmLinkExpandSvc.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/mdm/MdmLinkExpandSvc.java
@@ -72,6 +72,19 @@ public class MdmLinkExpandSvc {
return expandMdmBySourceResourcePid(pidOrThrowException);
}
+ /**
+ * Given a resource ID of a source resource or golden resource, perform MDM expansion and return all the resource
+ * IDs of all resources that are MDM-Matched to this resource.
+ *
+ * @param theId The Resource ID of the resource to MDM-Expand
+ * @return A set of strings representing the FHIR ids of the expanded resources.
+ */
+ public Set expandMdmBySourceOrGoldenResourceId(IIdType theId) {
+ ourLog.debug("About to expand source resource with resource id {}", theId);
+ Long pidOrThrowException = myIdHelperService.getPidOrThrowException(theId);
+ return flatten(myMdmLinkDao.expandPidsBySourceOrGoldenResourcePidAndMatchResult(pidOrThrowException, MdmMatchResultEnum.MATCH));
+ }
+
/**
* Given a PID of a source resource, perform MDM expansion and return all the resource IDs of all resources that are
* MDM-Matched to this resource.
@@ -81,14 +94,17 @@ public class MdmLinkExpandSvc {
*/
public Set expandMdmBySourceResourcePid(Long theSourceResourcePid) {
ourLog.debug("About to expand source resource with PID {}", theSourceResourcePid);
- List goldenPidSourcePidTuples = myMdmLinkDao.expandPidsBySourcePidAndMatchResult(theSourceResourcePid, MdmMatchResultEnum.MATCH);
+ return flatten(myMdmLinkDao.expandPidsBySourcePidAndMatchResult(theSourceResourcePid, MdmMatchResultEnum.MATCH));
+ }
+
+ protected Set flatten(List thePidTuples) {
Set flattenedPids = new HashSet<>();
- goldenPidSourcePidTuples.forEach(tuple -> {
+ thePidTuples.forEach(tuple -> {
flattenedPids.add(tuple.getSourcePid());
flattenedPids.add(tuple.getGoldenPid());
});
Set resourceIds = myIdHelperService.translatePidsToFhirResourceIds(flattenedPids);
- ourLog.debug("Pid {} has been expanded to [{}]", theSourceResourcePid, String.join(",", resourceIds));
+ ourLog.debug("Expanded pids are [{}]", String.join(",", resourceIds));
return resourceIds;
}
diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/dao/MdmLinkDaoSvcTest.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/dao/MdmLinkDaoSvcTest.java
index ae034af6fa7..b5deb25f0c6 100644
--- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/dao/MdmLinkDaoSvcTest.java
+++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/dao/MdmLinkDaoSvcTest.java
@@ -83,6 +83,15 @@ public class MdmLinkDaoSvcTest extends BaseMdmR4Test {
assertThat(lists, hasSize(10));
+ lists.stream()
+ .forEach(tuple -> {
+ assertThat(tuple.getGoldenPid(), is(equalTo(golden.getIdElement().getIdPartAsLong())));
+ assertThat(tuple.getSourcePid(), is(in(expectedExpandedPids)));
+ });
+
+ lists = myMdmLinkDao.expandPidsBySourceOrGoldenResourcePidAndMatchResult(mdmLinks.get(0).getGoldenResourcePid(), MdmMatchResultEnum.MATCH);
+ assertThat(lists, hasSize(10));
+
lists.stream()
.forEach(tuple -> {
assertThat(tuple.getGoldenPid(), is(equalTo(golden.getIdElement().getIdPartAsLong())));
diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkChangeEvent.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkChangeEvent.java
index e2d6b199812..8e306c16e6e 100644
--- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkChangeEvent.java
+++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkChangeEvent.java
@@ -30,9 +30,21 @@ import java.util.Set;
public class MdmLinkChangeEvent implements IModelJson {
- @JsonProperty(value = "targetResourceId")
+ @JsonProperty(value = "matchResult")
+ private MdmMatchResultEnum myMdmMatchResult;
+ @JsonProperty(value = "linkSource")
+ private MdmLinkSourceEnum myMdmLinkSource;
+ @JsonProperty(value = "eidMatch")
+ private Boolean myEidMatch;
+ @JsonProperty(value = "newGoldenResource")
+ private Boolean myNewGoldenResource;
+ @JsonProperty(value = "score")
+ private Double myScore;
+ @JsonProperty(value = "ruleCount")
+ private Long myRuleCount;
+ @JsonProperty(value = "targetResourceId", required = true)
private String myTargetResourceId;
- @JsonProperty(value = "goldenResourceId")
+ @JsonProperty(value = "goldenResourceId", required = true)
private String myGoldenResourceId;
@JsonProperty(value = "duplicateResourceIds")
private Set myDuplicateGoldenResourceIds = new HashSet<>();
@@ -88,10 +100,64 @@ public class MdmLinkChangeEvent implements IModelJson {
return this;
}
+ public MdmMatchResultEnum getMdmMatchResult() {
+ return myMdmMatchResult;
+ }
+
+ public void setMdmMatchResult(MdmMatchResultEnum theMdmMatchResult) {
+ myMdmMatchResult = theMdmMatchResult;
+ }
+
+ public MdmLinkSourceEnum getMdmLinkSource() {
+ return myMdmLinkSource;
+ }
+
+ public void setMdmLinkSource(MdmLinkSourceEnum theMdmLinkSource) {
+ myMdmLinkSource = theMdmLinkSource;
+ }
+
+ public Boolean getEidMatch() {
+ return myEidMatch;
+ }
+
+ public void setEidMatch(Boolean theEidMatch) {
+ myEidMatch = theEidMatch;
+ }
+
+ public Boolean getNewGoldenResource() {
+ return myNewGoldenResource;
+ }
+
+ public void setNewGoldenResource(Boolean theNewGoldenResource) {
+ myNewGoldenResource = theNewGoldenResource;
+ }
+
+ public Double getScore() {
+ return myScore;
+ }
+
+ public void setScore(Double theScore) {
+ myScore = theScore;
+ }
+
+ public Long getRuleCount() {
+ return myRuleCount;
+ }
+
+ public void setRuleCount(Long theRuleCount) {
+ myRuleCount = theRuleCount;
+ }
+
@Override
public String toString() {
return "MdmLinkChangeEvent{" +
- "myTargetResourceId='" + myTargetResourceId + '\'' +
+ "myMdmMatchResult=" + myMdmMatchResult +
+ ", myMdmLinkSource=" + myMdmLinkSource +
+ ", myEidMatch=" + myEidMatch +
+ ", myNewGoldenResource=" + myNewGoldenResource +
+ ", myScore=" + myScore +
+ ", myRuleCount=" + myRuleCount +
+ ", myTargetResourceId='" + myTargetResourceId + '\'' +
", myGoldenResourceId='" + myGoldenResourceId + '\'' +
", myDuplicateGoldenResourceIds=" + myDuplicateGoldenResourceIds +
'}';
From 1e41621eca369ceb8e3a116db4002d1b334cc33f Mon Sep 17 00:00:00 2001
From: Nick Goupinets
Date: Thu, 19 Aug 2021 16:43:51 -0400
Subject: [PATCH 06/13] Rolled back changes
---
.../ca/uhn/fhir/jpa/dao/data/IMdmLinkDao.java | 9 --------
.../fhir/jpa/dao/mdm/MdmLinkExpandSvc.java | 22 +++----------------
.../fhir/jpa/mdm/dao/MdmLinkDaoSvcTest.java | 9 --------
3 files changed, 3 insertions(+), 37 deletions(-)
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IMdmLinkDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IMdmLinkDao.java
index be0a6289a4e..16834facbe2 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IMdmLinkDao.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IMdmLinkDao.java
@@ -67,13 +67,4 @@ public interface IMdmLinkDao extends JpaRepository {
"AND ml.myMatchResult=:matchResult")
List expandPidsBySourcePidAndMatchResult(@Param("sourcePid") Long theSourcePid, @Param("matchResult") MdmMatchResultEnum theMdmMatchResultEnum);
- @Query("SELECT DISTINCT ml.myGoldenResourcePid as goldenPid, ml.mySourcePid as sourcePid " +
- "FROM MdmLink ml " +
- "INNER JOIN MdmLink ml2 " +
- "ON ml.myGoldenResourcePid = ml2.myGoldenResourcePid " +
- "WHERE (ml2.mySourcePid = :sourceOrGoldenPid OR ml2.myGoldenResourcePid = :sourceOrGoldenPid) " +
- "AND ml2.myMatchResult=:matchResult " +
- "AND ml.myMatchResult=:matchResult")
- List expandPidsBySourceOrGoldenResourcePidAndMatchResult(@Param("sourceOrGoldenPid") Long theSourceOrGoldenPid, @Param("matchResult") MdmMatchResultEnum theMdmMatchResultEnum);
-
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/mdm/MdmLinkExpandSvc.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/mdm/MdmLinkExpandSvc.java
index b03e22d04b8..66af7f5a706 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/mdm/MdmLinkExpandSvc.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/mdm/MdmLinkExpandSvc.java
@@ -72,19 +72,6 @@ public class MdmLinkExpandSvc {
return expandMdmBySourceResourcePid(pidOrThrowException);
}
- /**
- * Given a resource ID of a source resource or golden resource, perform MDM expansion and return all the resource
- * IDs of all resources that are MDM-Matched to this resource.
- *
- * @param theId The Resource ID of the resource to MDM-Expand
- * @return A set of strings representing the FHIR ids of the expanded resources.
- */
- public Set expandMdmBySourceOrGoldenResourceId(IIdType theId) {
- ourLog.debug("About to expand source resource with resource id {}", theId);
- Long pidOrThrowException = myIdHelperService.getPidOrThrowException(theId);
- return flatten(myMdmLinkDao.expandPidsBySourceOrGoldenResourcePidAndMatchResult(pidOrThrowException, MdmMatchResultEnum.MATCH));
- }
-
/**
* Given a PID of a source resource, perform MDM expansion and return all the resource IDs of all resources that are
* MDM-Matched to this resource.
@@ -94,17 +81,14 @@ public class MdmLinkExpandSvc {
*/
public Set expandMdmBySourceResourcePid(Long theSourceResourcePid) {
ourLog.debug("About to expand source resource with PID {}", theSourceResourcePid);
- return flatten(myMdmLinkDao.expandPidsBySourcePidAndMatchResult(theSourceResourcePid, MdmMatchResultEnum.MATCH));
- }
-
- protected Set flatten(List thePidTuples) {
+ List goldenPidSourcePidTuples = myMdmLinkDao.expandPidsBySourcePidAndMatchResult(theSourceResourcePid, MdmMatchResultEnum.MATCH);
Set flattenedPids = new HashSet<>();
- thePidTuples.forEach(tuple -> {
+ goldenPidSourcePidTuples.forEach(tuple -> {
flattenedPids.add(tuple.getSourcePid());
flattenedPids.add(tuple.getGoldenPid());
});
Set resourceIds = myIdHelperService.translatePidsToFhirResourceIds(flattenedPids);
- ourLog.debug("Expanded pids are [{}]", String.join(",", resourceIds));
+ ourLog.debug("Pid {} has been expanded to [{}]", theSourceResourcePid, String.join(",", resourceIds));
return resourceIds;
}
diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/dao/MdmLinkDaoSvcTest.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/dao/MdmLinkDaoSvcTest.java
index b5deb25f0c6..ae034af6fa7 100644
--- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/dao/MdmLinkDaoSvcTest.java
+++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/dao/MdmLinkDaoSvcTest.java
@@ -83,15 +83,6 @@ public class MdmLinkDaoSvcTest extends BaseMdmR4Test {
assertThat(lists, hasSize(10));
- lists.stream()
- .forEach(tuple -> {
- assertThat(tuple.getGoldenPid(), is(equalTo(golden.getIdElement().getIdPartAsLong())));
- assertThat(tuple.getSourcePid(), is(in(expectedExpandedPids)));
- });
-
- lists = myMdmLinkDao.expandPidsBySourceOrGoldenResourcePidAndMatchResult(mdmLinks.get(0).getGoldenResourcePid(), MdmMatchResultEnum.MATCH);
- assertThat(lists, hasSize(10));
-
lists.stream()
.forEach(tuple -> {
assertThat(tuple.getGoldenPid(), is(equalTo(golden.getIdElement().getIdPartAsLong())));
From 6ea58f74d1e3317683242a8fd0f94ac8bb2b881d Mon Sep 17 00:00:00 2001
From: Nick Goupinets
Date: Mon, 23 Aug 2021 10:55:09 -0400
Subject: [PATCH 07/13] Code review
---
.../jpa/mdm/broker/MdmMessageHandler.java | 22 +++-----
.../jpa/mdm/config/MdmConsumerConfig.java | 11 +++-
.../jpa/mdm/svc/IMdmModelConverterSvc.java | 39 ++++++++++++++
...cImpl.java => MdmLinkQuerySvcImplSvc.java} | 32 ++++--------
.../jpa/mdm/svc/MdmModelConverterSvcImpl.java | 52 +++++++++++++++++++
.../interceptor/MdmStorageInterceptorIT.java | 7 +--
...LinkChangeEvent.java => MdmLinkEvent.java} | 21 +++++++-
.../java/ca/uhn/fhir/mdm/api/MdmLinkJson.java | 19 ++++++-
.../fhir/mdm/model/MdmTransactionContext.java | 12 ++---
9 files changed, 160 insertions(+), 55 deletions(-)
create mode 100644 hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/IMdmModelConverterSvc.java
rename hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/{MdmLinkQuerySvcImpl.java => MdmLinkQuerySvcImplSvc.java} (73%)
create mode 100644 hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmModelConverterSvcImpl.java
rename hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/{MdmLinkChangeEvent.java => MdmLinkEvent.java} (86%)
diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/broker/MdmMessageHandler.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/broker/MdmMessageHandler.java
index 5f103311abb..701f00b034b 100644
--- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/broker/MdmMessageHandler.java
+++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/broker/MdmMessageHandler.java
@@ -26,15 +26,14 @@ import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
import ca.uhn.fhir.interceptor.api.Pointcut;
import ca.uhn.fhir.jpa.entity.MdmLink;
import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
-import ca.uhn.fhir.jpa.mdm.svc.MdmLinkSvcImpl;
+import ca.uhn.fhir.jpa.mdm.svc.IMdmModelConverterSvc;
import ca.uhn.fhir.jpa.mdm.svc.MdmMatchLinkSvc;
import ca.uhn.fhir.jpa.mdm.svc.MdmResourceFilteringSvc;
import ca.uhn.fhir.jpa.mdm.svc.candidate.TooManyCandidatesException;
import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedJsonMessage;
import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
-import ca.uhn.fhir.mdm.api.IMdmLinkSvc;
import ca.uhn.fhir.mdm.api.IMdmSettings;
-import ca.uhn.fhir.mdm.api.MdmLinkChangeEvent;
+import ca.uhn.fhir.mdm.api.MdmLinkEvent;
import ca.uhn.fhir.mdm.log.Logs;
import ca.uhn.fhir.mdm.model.MdmTransactionContext;
import ca.uhn.fhir.rest.server.TransactionLogMessages;
@@ -42,7 +41,6 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.messaging.ResourceOperationMessage;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IBaseResource;
-import org.hl7.fhir.instance.model.api.IIdType;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
@@ -69,6 +67,8 @@ public class MdmMessageHandler implements MessageHandler {
private MdmResourceFilteringSvc myMdmResourceFilteringSvc;
@Autowired
private IMdmSettings myMdmSettings;
+ @Autowired
+ private IMdmModelConverterSvc myModelConverter;
@Override
public void handleMessage(Message> theMessage) throws MessagingException {
@@ -119,25 +119,17 @@ public class MdmMessageHandler implements MessageHandler {
ResourceOperationMessage outgoingMsg = new ResourceOperationMessage(myFhirContext, targetResource, theMsg.getOperationType());
outgoingMsg.setTransactionId(theMsg.getTransactionId());
- MdmLinkChangeEvent linkChangeEvent = mdmContext.getMdmLinkChangeEvent();
+ MdmLinkEvent linkChangeEvent = mdmContext.getMdmLinkChangeEvent();
Optional mdmLinkBySource = myMdmLinkDaoSvc.findMdmLinkBySource(targetResource);
if (!mdmLinkBySource.isPresent()) {
ourLog.warn("Unable to find link by source for {}", targetResource.getIdElement());
}
- mdmLinkBySource.ifPresent(link -> {
- linkChangeEvent.setMdmMatchResult(link.getMatchResult());
- linkChangeEvent.setMdmLinkSource(link.getLinkSource());
- linkChangeEvent.setEidMatch(link.isEidMatchPresent());
- linkChangeEvent.setNewGoldenResource(link.getHadToCreateNewGoldenResource());
- linkChangeEvent.setScore(link.getScore());
- linkChangeEvent.setRuleCount(link.getRuleCount());
- });
-
+ mdmLinkBySource.ifPresent(link -> linkChangeEvent.setFromLink(myModelConverter.toJson(link)));
HookParams params = new HookParams()
.add(ResourceOperationMessage.class, outgoingMsg)
.add(TransactionLogMessages.class, mdmContext.getTransactionLogMessages())
- .add(MdmLinkChangeEvent.class, mdmContext.getMdmLinkChangeEvent());
+ .add(MdmLinkEvent.class, mdmContext.getMdmLinkChangeEvent());
myInterceptorBroadcaster.callHooks(Pointcut.MDM_AFTER_PERSISTED_RESOURCE_CHECKED, params);
}
diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/config/MdmConsumerConfig.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/config/MdmConsumerConfig.java
index 51981cdecaa..56f81f8b87a 100644
--- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/config/MdmConsumerConfig.java
+++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/config/MdmConsumerConfig.java
@@ -31,15 +31,17 @@ import ca.uhn.fhir.jpa.mdm.dao.MdmLinkFactory;
import ca.uhn.fhir.jpa.mdm.interceptor.IMdmStorageInterceptor;
import ca.uhn.fhir.jpa.mdm.interceptor.MdmStorageInterceptor;
import ca.uhn.fhir.jpa.mdm.svc.GoldenResourceMergerSvcImpl;
+import ca.uhn.fhir.jpa.mdm.svc.IMdmModelConverterSvc;
import ca.uhn.fhir.jpa.mdm.svc.MdmClearSvcImpl;
import ca.uhn.fhir.jpa.mdm.svc.MdmControllerSvcImpl;
import ca.uhn.fhir.jpa.mdm.svc.MdmEidUpdateService;
import ca.uhn.fhir.jpa.mdm.svc.MdmGoldenResourceDeletingSvc;
-import ca.uhn.fhir.jpa.mdm.svc.MdmLinkQuerySvcImpl;
+import ca.uhn.fhir.jpa.mdm.svc.MdmLinkQuerySvcImplSvc;
import ca.uhn.fhir.jpa.mdm.svc.MdmLinkSvcImpl;
import ca.uhn.fhir.jpa.mdm.svc.MdmLinkUpdaterSvcImpl;
import ca.uhn.fhir.jpa.mdm.svc.MdmMatchFinderSvcImpl;
import ca.uhn.fhir.jpa.mdm.svc.MdmMatchLinkSvc;
+import ca.uhn.fhir.jpa.mdm.svc.MdmModelConverterSvcImpl;
import ca.uhn.fhir.jpa.mdm.svc.MdmResourceDaoSvc;
import ca.uhn.fhir.jpa.mdm.svc.MdmResourceFilteringSvc;
import ca.uhn.fhir.jpa.mdm.svc.MdmSearchParamSvc;
@@ -179,7 +181,12 @@ public class MdmConsumerConfig {
@Bean
IMdmLinkQuerySvc mdmLinkQuerySvc() {
- return new MdmLinkQuerySvcImpl();
+ return new MdmLinkQuerySvcImplSvc();
+ }
+
+ @Bean
+ IMdmModelConverterSvc mdmModelConverterSvc() {
+ return new MdmModelConverterSvcImpl();
}
@Bean
diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/IMdmModelConverterSvc.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/IMdmModelConverterSvc.java
new file mode 100644
index 00000000000..67c534a9489
--- /dev/null
+++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/IMdmModelConverterSvc.java
@@ -0,0 +1,39 @@
+package ca.uhn.fhir.jpa.mdm.svc;
+
+/*-
+ * #%L
+ * HAPI FHIR JPA Server - Master Data Management
+ * %%
+ * 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%
+ */
+
+import ca.uhn.fhir.jpa.entity.MdmLink;
+import ca.uhn.fhir.mdm.api.MdmLinkJson;
+
+/**
+ * Contract for decoupling API dependency from the base / JPA modules.
+ */
+public interface IMdmModelConverterSvc {
+
+ /**
+ * Creates JSON representation of the provided MDM link
+ *
+ * @param theLink Link to convert
+ * @return Returns the converted link
+ */
+ public MdmLinkJson toJson(MdmLink theLink);
+
+}
diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmLinkQuerySvcImpl.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmLinkQuerySvcImplSvc.java
similarity index 73%
rename from hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmLinkQuerySvcImpl.java
rename to hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmLinkQuerySvcImplSvc.java
index ea00e81ec4d..996dbe8e5cc 100644
--- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmLinkQuerySvcImpl.java
+++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmLinkQuerySvcImplSvc.java
@@ -36,20 +36,24 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
-public class MdmLinkQuerySvcImpl implements IMdmLinkQuerySvc {
+public class MdmLinkQuerySvcImplSvc implements IMdmLinkQuerySvc {
- private static final Logger ourLog = LoggerFactory.getLogger(MdmLinkQuerySvcImpl.class);
+ private static final Logger ourLog = LoggerFactory.getLogger(MdmLinkQuerySvcImplSvc.class);
+
+ @Autowired
+ MdmLinkDaoSvc myMdmLinkDaoSvc;
@Autowired
IdHelperService myIdHelperService;
+
@Autowired
- MdmLinkDaoSvc myMdmLinkDaoSvc;
+ IMdmModelConverterSvc myMdmModelConverterSvc;
@Override
public Page queryLinks(IIdType theGoldenResourceId, IIdType theSourceResourceId, MdmMatchResultEnum theMatchResult, MdmLinkSourceEnum theLinkSource, MdmTransactionContext theMdmContext, MdmPageRequest thePageRequest) {
Example exampleLink = exampleLinkFromParameters(theGoldenResourceId, theSourceResourceId, theMatchResult, theLinkSource);
Page mdmLinkByExample = myMdmLinkDaoSvc.findMdmLinkByExample(exampleLink, thePageRequest);
- Page map = mdmLinkByExample.map(this::toJson);
+ Page map = mdmLinkByExample.map(myMdmModelConverterSvc::toJson);
return map;
}
@@ -57,28 +61,10 @@ public class MdmLinkQuerySvcImpl implements IMdmLinkQuerySvc {
public Page getDuplicateGoldenResources(MdmTransactionContext theMdmContext, MdmPageRequest thePageRequest) {
Example exampleLink = exampleLinkFromParameters(null, null, MdmMatchResultEnum.POSSIBLE_DUPLICATE, null);
Page mdmLinkPage = myMdmLinkDaoSvc.findMdmLinkByExample(exampleLink, thePageRequest);
- Page map = mdmLinkPage.map(this::toJson);
+ Page map = mdmLinkPage.map(myMdmModelConverterSvc::toJson);
return map;
}
- private MdmLinkJson toJson(MdmLink theLink) {
- MdmLinkJson retval = new MdmLinkJson();
- String sourceId = myIdHelperService.resourceIdFromPidOrThrowException(theLink.getSourcePid()).toVersionless().getValue();
- retval.setSourceId(sourceId);
- String goldenResourceId = myIdHelperService.resourceIdFromPidOrThrowException(theLink.getGoldenResourcePid()).toVersionless().getValue();
- retval.setGoldenResourceId(goldenResourceId);
- retval.setCreated(theLink.getCreated());
- retval.setEidMatch(theLink.getEidMatch());
- retval.setLinkSource(theLink.getLinkSource());
- retval.setMatchResult(theLink.getMatchResult());
- retval.setLinkCreatedNewResource(theLink.getHadToCreateNewGoldenResource());
- retval.setScore(theLink.getScore());
- retval.setUpdated(theLink.getUpdated());
- retval.setVector(theLink.getVector());
- retval.setVersion(theLink.getVersion());
- return retval;
- }
-
private Example exampleLinkFromParameters(IIdType theGoldenResourceId, IIdType theSourceId, MdmMatchResultEnum theMatchResult, MdmLinkSourceEnum theLinkSource) {
MdmLink mdmLink = myMdmLinkDaoSvc.newMdmLink();
if (theGoldenResourceId != null) {
diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmModelConverterSvcImpl.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmModelConverterSvcImpl.java
new file mode 100644
index 00000000000..195ac388e68
--- /dev/null
+++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmModelConverterSvcImpl.java
@@ -0,0 +1,52 @@
+package ca.uhn.fhir.jpa.mdm.svc;
+
+/*-
+ * #%L
+ * HAPI FHIR JPA Server - Master Data Management
+ * %%
+ * 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%
+ */
+
+import ca.uhn.fhir.jpa.dao.index.IdHelperService;
+import ca.uhn.fhir.jpa.entity.MdmLink;
+import ca.uhn.fhir.mdm.api.MdmLinkJson;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class MdmModelConverterSvcImpl implements IMdmModelConverterSvc {
+
+ @Autowired
+ IdHelperService myIdHelperService;
+
+ public MdmLinkJson toJson(MdmLink theLink) {
+ MdmLinkJson retval = new MdmLinkJson();
+ String sourceId = myIdHelperService.resourceIdFromPidOrThrowException(theLink.getSourcePid()).toVersionless().getValue();
+ retval.setSourceId(sourceId);
+ String goldenResourceId = myIdHelperService.resourceIdFromPidOrThrowException(theLink.getGoldenResourcePid()).toVersionless().getValue();
+ retval.setGoldenResourceId(goldenResourceId);
+ retval.setCreated(theLink.getCreated());
+ retval.setEidMatch(theLink.getEidMatch());
+ retval.setLinkSource(theLink.getLinkSource());
+ retval.setMatchResult(theLink.getMatchResult());
+ retval.setLinkCreatedNewResource(theLink.getHadToCreateNewGoldenResource());
+ retval.setScore(theLink.getScore());
+ retval.setUpdated(theLink.getUpdated());
+ retval.setVector(theLink.getVector());
+ retval.setVersion(theLink.getVersion());
+ retval.setRuleCount(theLink.getRuleCount());
+ return retval;
+ }
+
+}
diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmStorageInterceptorIT.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmStorageInterceptorIT.java
index 4d729730f7c..cd1518cbc59 100644
--- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmStorageInterceptorIT.java
+++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmStorageInterceptorIT.java
@@ -7,7 +7,7 @@ import ca.uhn.fhir.jpa.mdm.BaseMdmR4Test;
import ca.uhn.fhir.jpa.mdm.helper.MdmHelperConfig;
import ca.uhn.fhir.jpa.mdm.helper.MdmHelperR4;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
-import ca.uhn.fhir.mdm.api.MdmLinkChangeEvent;
+import ca.uhn.fhir.mdm.api.MdmLinkEvent;
import ca.uhn.fhir.mdm.model.CanonicalEID;
import ca.uhn.fhir.mdm.model.MdmTransactionContext;
import ca.uhn.fhir.mdm.rules.config.MdmSettings;
@@ -32,14 +32,11 @@ import org.junit.jupiter.api.extension.RegisterExtension;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
-import org.springframework.data.domain.ExampleMatcher;
-import org.springframework.data.domain.Pageable;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import java.util.Date;
import java.util.List;
-import java.util.Optional;
import static ca.uhn.fhir.mdm.api.MdmConstants.CODE_GOLDEN_RECORD;
import static ca.uhn.fhir.mdm.api.MdmConstants.CODE_GOLDEN_RECORD_REDIRECTED;
@@ -89,7 +86,7 @@ public class MdmStorageInterceptorIT extends BaseMdmR4Test {
MdmLink link = getLinkByTargetId(pr);
- MdmLinkChangeEvent linkChangeEvent = myMdmHelper.getAfterMdmLatch().getLatchInvocationParameterOfType(MdmLinkChangeEvent.class);
+ MdmLinkEvent linkChangeEvent = myMdmHelper.getAfterMdmLatch().getLatchInvocationParameterOfType(MdmLinkEvent.class);
assertNotNull(linkChangeEvent);
assertEquals(link.getGoldenResourcePid(), new IdDt(linkChangeEvent.getGoldenResourceId()).getIdPartAsLong());
assertEquals(link.getSourcePid(), new IdDt(linkChangeEvent.getTargetResourceId()).getIdPartAsLong());
diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkChangeEvent.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkEvent.java
similarity index 86%
rename from hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkChangeEvent.java
rename to hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkEvent.java
index 8e306c16e6e..7eda6f328d8 100644
--- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkChangeEvent.java
+++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkEvent.java
@@ -28,7 +28,7 @@ import org.hl7.fhir.instance.model.api.IIdType;
import java.util.HashSet;
import java.util.Set;
-public class MdmLinkChangeEvent implements IModelJson {
+public class MdmLinkEvent implements IModelJson {
@JsonProperty(value = "matchResult")
private MdmMatchResultEnum myMdmMatchResult;
@@ -92,7 +92,7 @@ public class MdmLinkChangeEvent implements IModelJson {
myDuplicateGoldenResourceIds = theDuplicateGoldenResourceIds;
}
- public MdmLinkChangeEvent addDuplicateGoldenResourceId(IBaseResource theDuplicateGoldenResourceId) {
+ public MdmLinkEvent addDuplicateGoldenResourceId(IBaseResource theDuplicateGoldenResourceId) {
String id = getIdAsString(theDuplicateGoldenResourceId);
if (id != null) {
getDuplicateGoldenResourceIds().add(id);
@@ -121,6 +121,10 @@ public class MdmLinkChangeEvent implements IModelJson {
}
public void setEidMatch(Boolean theEidMatch) {
+ if (theEidMatch == null) {
+ myEidMatch = Boolean.FALSE;
+ return;
+ }
myEidMatch = theEidMatch;
}
@@ -129,6 +133,10 @@ public class MdmLinkChangeEvent implements IModelJson {
}
public void setNewGoldenResource(Boolean theNewGoldenResource) {
+ if (theNewGoldenResource == null) {
+ myNewGoldenResource = Boolean.FALSE;
+ return;
+ }
myNewGoldenResource = theNewGoldenResource;
}
@@ -148,6 +156,15 @@ public class MdmLinkChangeEvent implements IModelJson {
myRuleCount = theRuleCount;
}
+ public void setFromLink(MdmLinkJson theMdmLinkJson) {
+ setMdmMatchResult(theMdmLinkJson.getMatchResult());
+ setMdmLinkSource(theMdmLinkJson.getLinkSource());
+ setEidMatch(theMdmLinkJson.getEidMatch());
+ setNewGoldenResource(theMdmLinkJson.getLinkCreatedNewResource());
+ setScore(theMdmLinkJson.getScore());
+ setRuleCount(theMdmLinkJson.getRuleCount());
+ }
+
@Override
public String toString() {
return "MdmLinkChangeEvent{" +
diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkJson.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkJson.java
index 744aa384823..424298418b4 100644
--- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkJson.java
+++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkJson.java
@@ -48,11 +48,15 @@ public class MdmLinkJson implements IModelJson {
@JsonProperty("version")
private String myVersion;
- /** This link was created as a result of an eid match **/
+ /**
+ * This link was created as a result of an eid match
+ **/
@JsonProperty("eidMatch")
private Boolean myEidMatch;
- /** This link created a new golden resource **/
+ /**
+ * This link created a new golden resource
+ **/
@JsonProperty("linkCreatedNewGoldenResource")
private Boolean myLinkCreatedNewResource;
@@ -62,6 +66,9 @@ public class MdmLinkJson implements IModelJson {
@JsonProperty("score")
private Double myScore;
+ @JsonProperty("ruleCount")
+ private Long myRuleCount;
+
public String getGoldenResourceId() {
return myGoldenResourceId;
}
@@ -160,4 +167,12 @@ public class MdmLinkJson implements IModelJson {
myScore = theScore;
return this;
}
+
+ public Long getRuleCount() {
+ return myRuleCount;
+ }
+
+ public void setRuleCount(Long theRuleCount) {
+ myRuleCount = theRuleCount;
+ }
}
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 ce35ea3f150..9853918a9d7 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
@@ -20,7 +20,7 @@ package ca.uhn.fhir.mdm.model;
* #L%
*/
-import ca.uhn.fhir.mdm.api.MdmLinkChangeEvent;
+import ca.uhn.fhir.mdm.api.MdmLinkEvent;
import ca.uhn.fhir.rest.server.TransactionLogMessages;
public class MdmTransactionContext {
@@ -46,7 +46,7 @@ public class MdmTransactionContext {
private String myResourceType;
- private MdmLinkChangeEvent myMdmLinkChangeEvent = new MdmLinkChangeEvent();
+ private MdmLinkEvent myMdmLinkEvent = new MdmLinkEvent();
public TransactionLogMessages getTransactionLogMessages() {
return myTransactionLogMessages;
@@ -96,12 +96,12 @@ public class MdmTransactionContext {
this.myResourceType = myResourceType;
}
- public MdmLinkChangeEvent getMdmLinkChangeEvent() {
- return myMdmLinkChangeEvent;
+ public MdmLinkEvent getMdmLinkChangeEvent() {
+ return myMdmLinkEvent;
}
- public void setMdmLinkChangeEvent(MdmLinkChangeEvent theMdmLinkChangeEvent) {
- myMdmLinkChangeEvent = theMdmLinkChangeEvent;
+ public void setMdmLinkChangeEvent(MdmLinkEvent theMdmLinkEvent) {
+ myMdmLinkEvent = theMdmLinkEvent;
}
}
From 3a5e391c77690c0cc57975cd6dd9cf478fe174a0 Mon Sep 17 00:00:00 2001
From: Nick Goupinets
Date: Mon, 23 Aug 2021 11:00:04 -0400
Subject: [PATCH 08/13] Fixed pointcut def
---
.../src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java
index d8f0f33ae9f..30f81b90889 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java
@@ -1996,7 +1996,7 @@ public enum Pointcut implements IPointcut {
MDM_AFTER_PERSISTED_RESOURCE_CHECKED(void.class,
"ca.uhn.fhir.rest.server.messaging.ResourceOperationMessage",
"ca.uhn.fhir.rest.server.TransactionLogMessages",
- "ca.uhn.fhir.mdm.api.MdmLinkChangeEvent"),
+ "ca.uhn.fhir.mdm.api.MdmLinkEvent"),
/**
* Performance Tracing Hook:
From 91a961f9fd6ec0b4cfc61746891a1b086cb30799 Mon Sep 17 00:00:00 2001
From: Nick Goupinets
Date: Fri, 27 Aug 2021 10:48:19 -0400
Subject: [PATCH 09/13] Added changelog
---
.../hapi/fhir/changelog/5_6_0/2850-updated-mdm-pointcut.yaml | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/5_6_0/2850-updated-mdm-pointcut.yaml
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/5_6_0/2850-updated-mdm-pointcut.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/5_6_0/2850-updated-mdm-pointcut.yaml
new file mode 100644
index 00000000000..712e336d130
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/5_6_0/2850-updated-mdm-pointcut.yaml
@@ -0,0 +1,4 @@
+---
+type: add
+issue: 2850
+title: "Updated handling of MDM_AFTER_PERSISTED_RESOURCE_CHECKED pointcut to include additional MDM related info."
From 4e012236c21e3614bc2615ffed7bfe67c9c5ea01 Mon Sep 17 00:00:00 2001
From: Nick Goupinets
Date: Fri, 27 Aug 2021 16:31:23 -0400
Subject: [PATCH 10/13] Updated comments and added misc refactorings
---
.../fhir/jpa/mdm/broker/MdmMessageHandler.java | 4 ++--
.../fhir/jpa/mdm/svc/MdmEidUpdateService.java | 2 +-
.../uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvc.java | 12 ++++++------
.../candidate/FindCandidateByExampleSvc.java | 10 +++++-----
.../ca/uhn/fhir/jpa/mdm/BaseMdmR4Test.java | 4 ++--
.../interceptor/MdmStorageInterceptorIT.java | 18 ++++++++++++------
.../fhir/mdm/model/MdmTransactionContext.java | 2 +-
7 files changed, 29 insertions(+), 23 deletions(-)
diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/broker/MdmMessageHandler.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/broker/MdmMessageHandler.java
index 701f00b034b..6589d6b41e9 100644
--- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/broker/MdmMessageHandler.java
+++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/broker/MdmMessageHandler.java
@@ -119,7 +119,7 @@ public class MdmMessageHandler implements MessageHandler {
ResourceOperationMessage outgoingMsg = new ResourceOperationMessage(myFhirContext, targetResource, theMsg.getOperationType());
outgoingMsg.setTransactionId(theMsg.getTransactionId());
- MdmLinkEvent linkChangeEvent = mdmContext.getMdmLinkChangeEvent();
+ MdmLinkEvent linkChangeEvent = mdmContext.getMdmLinkEvent();
Optional mdmLinkBySource = myMdmLinkDaoSvc.findMdmLinkBySource(targetResource);
if (!mdmLinkBySource.isPresent()) {
ourLog.warn("Unable to find link by source for {}", targetResource.getIdElement());
@@ -129,7 +129,7 @@ public class MdmMessageHandler implements MessageHandler {
HookParams params = new HookParams()
.add(ResourceOperationMessage.class, outgoingMsg)
.add(TransactionLogMessages.class, mdmContext.getTransactionLogMessages())
- .add(MdmLinkEvent.class, mdmContext.getMdmLinkChangeEvent());
+ .add(MdmLinkEvent.class, mdmContext.getMdmLinkEvent());
myInterceptorBroadcaster.callHooks(Pointcut.MDM_AFTER_PERSISTED_RESOURCE_CHECKED, params);
}
diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmEidUpdateService.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmEidUpdateService.java
index d23c27db9f1..2e035615200 100644
--- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmEidUpdateService.java
+++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmEidUpdateService.java
@@ -86,7 +86,7 @@ public class MdmEidUpdateService {
myMdmResourceDaoSvc.upsertGoldenResource(updateContext.getMatchedGoldenResource(), theMdmTransactionContext.getResourceType());
}
- theMdmTransactionContext.getMdmLinkChangeEvent().setGoldenResourceId(updateContext.getExistingGoldenResource());
+ theMdmTransactionContext.getMdmLinkEvent().setGoldenResourceId(updateContext.getExistingGoldenResource());
}
private void handleNoEidsInCommon(IAnyResource theResource, MatchedGoldenResourceCandidate theMatchedGoldenResourceCandidate, MdmTransactionContext theMdmTransactionContext, MdmUpdateContext theUpdateContext) {
diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvc.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvc.java
index e0f6b932557..ce285b58bac 100644
--- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvc.java
+++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvc.java
@@ -78,7 +78,7 @@ public class MdmMatchLinkSvc {
private MdmTransactionContext doMdmUpdate(IAnyResource theResource, MdmTransactionContext theMdmTransactionContext) {
CandidateList candidateList = myMdmGoldenResourceFindingSvc.findGoldenResourceCandidates(theResource);
- theMdmTransactionContext.getMdmLinkChangeEvent().setTargetResourceId(theResource);
+ theMdmTransactionContext.getMdmLinkEvent().setTargetResourceId(theResource);
if (candidateList.isEmpty()) {
handleMdmWithNoCandidates(theResource, theMdmTransactionContext);
@@ -114,14 +114,14 @@ public class MdmMatchLinkSvc {
//Set all GoldenResources as POSSIBLE_DUPLICATE of the last GoldenResource.
IAnyResource firstGoldenResource = goldenResources.get(0);
- theMdmTransactionContext.getMdmLinkChangeEvent().setGoldenResourceId(firstGoldenResource);
+ theMdmTransactionContext.getMdmLinkEvent().setGoldenResourceId(firstGoldenResource);
goldenResources.subList(1, goldenResources.size())
.forEach(possibleDuplicateGoldenResource -> {
MdmMatchOutcome outcome = MdmMatchOutcome.POSSIBLE_DUPLICATE;
outcome.setEidMatch(theCandidateList.isEidMatch());
myMdmLinkSvc.updateLink(firstGoldenResource, possibleDuplicateGoldenResource, outcome, MdmLinkSourceEnum.AUTO, theMdmTransactionContext);
- theMdmTransactionContext.getMdmLinkChangeEvent().addDuplicateGoldenResourceId(possibleDuplicateGoldenResource);
+ theMdmTransactionContext.getMdmLinkEvent().addDuplicateGoldenResourceId(possibleDuplicateGoldenResource);
});
}
}
@@ -135,7 +135,7 @@ public class MdmMatchLinkSvc {
// 3. UPDATE MDM LINK TABLE
myMdmLinkSvc.updateLink(newGoldenResource, theResource, MdmMatchOutcome.NEW_GOLDEN_RESOURCE_MATCH, MdmLinkSourceEnum.AUTO, theMdmTransactionContext);
- theMdmTransactionContext.getMdmLinkChangeEvent().setGoldenResourceId(newGoldenResource);
+ theMdmTransactionContext.getMdmLinkEvent().setGoldenResourceId(newGoldenResource);
}
private void handleMdmCreate(IAnyResource theTargetResource, MatchedGoldenResourceCandidate theGoldenResourceCandidate, MdmTransactionContext theMdmTransactionContext) {
@@ -145,7 +145,7 @@ public class MdmMatchLinkSvc {
if (myGoldenResourceHelper.isPotentialDuplicate(goldenResource, theTargetResource)) {
log(theMdmTransactionContext, "Duplicate detected based on the fact that both resources have different external EIDs.");
IAnyResource newGoldenResource = myGoldenResourceHelper.createGoldenResourceFromMdmSourceResource(theTargetResource, theMdmTransactionContext);
- theMdmTransactionContext.getMdmLinkChangeEvent().setGoldenResourceId(newGoldenResource);
+ theMdmTransactionContext.getMdmLinkEvent().setGoldenResourceId(newGoldenResource);
myMdmLinkSvc.updateLink(newGoldenResource, theTargetResource, MdmMatchOutcome.NEW_GOLDEN_RESOURCE_MATCH, MdmLinkSourceEnum.AUTO, theMdmTransactionContext);
myMdmLinkSvc.updateLink(newGoldenResource, goldenResource, MdmMatchOutcome.POSSIBLE_DUPLICATE, MdmLinkSourceEnum.AUTO, theMdmTransactionContext);
@@ -155,7 +155,7 @@ public class MdmMatchLinkSvc {
myEidUpdateService.applySurvivorshipRulesAndSaveGoldenResource(theTargetResource, goldenResource, theMdmTransactionContext);
}
- theMdmTransactionContext.getMdmLinkChangeEvent().setGoldenResourceId(goldenResource);
+ theMdmTransactionContext.getMdmLinkEvent().setGoldenResourceId(goldenResource);
myMdmLinkSvc.updateLink(goldenResource, theTargetResource, theGoldenResourceCandidate.getMatchResult(), MdmLinkSourceEnum.AUTO, theMdmTransactionContext);
}
}
diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/candidate/FindCandidateByExampleSvc.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/candidate/FindCandidateByExampleSvc.java
index 43606a95818..5533c82667b 100644
--- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/candidate/FindCandidateByExampleSvc.java
+++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/candidate/FindCandidateByExampleSvc.java
@@ -54,9 +54,9 @@ public class FindCandidateByExampleSvc extends BaseCandidateFinder {
private IMdmMatchFinderSvc myMdmMatchFinderSvc;
/**
- * Attempt to find matching Golden Resources by resolving them from similar Matching target resources, where target resource
- * can be either Patient or Practitioner. Runs MDM logic over the existing target resources, then finds their
- * entries in the MdmLink table, and returns all the matches found therein.
+ * Attempt to find matching Golden Resources by resolving them from similar Matching target resources. Runs MDM logic
+ * over the existing target resources, then finds their entries in the MdmLink table, and returns all the matches
+ * found therein.
*
* @param theTarget the {@link IBaseResource} which we want to find candidate Golden Resources for.
* @return an Optional list of {@link MatchedGoldenResourceCandidate} indicating matches.
@@ -69,8 +69,8 @@ public class FindCandidateByExampleSvc extends BaseCandidateFinder {
List matchedCandidates = myMdmMatchFinderSvc.getMatchedTargets(myFhirContext.getResourceType(theTarget), theTarget);
- //Convert all possible match targets to their equivalent Golden Resources by looking up in the MdmLink table,
- //while ensuring that the matches aren't in our NO_MATCH list.
+ // Convert all possible match targets to their equivalent Golden Resources by looking up in the MdmLink table,
+ // while ensuring that the matches aren't in our NO_MATCH list.
// The data flow is as follows ->
// MatchedTargetCandidate -> Golden Resource -> MdmLink -> MatchedGoldenResourceCandidate
matchedCandidates = matchedCandidates.stream().filter(mc -> mc.isMatch() || mc.isPossibleMatch()).collect(Collectors.toList());
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 96115a95bf2..60936356c54 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
@@ -326,14 +326,14 @@ abstract public class BaseMdmR4Test extends BaseJpaR4Test {
assertEquals(theExpectedCount, myMdmLinkDao.count());
}
- protected IAnyResource getGoldenResourceFromTargetResource(IAnyResource theBaseResource) {
+ protected T getGoldenResourceFromTargetResource(T theBaseResource) {
String resourceType = theBaseResource.getIdElement().getResourceType();
IFhirResourceDao relevantDao = myDaoRegistry.getResourceDao(resourceType);
Optional matchedLinkForTargetPid = myMdmLinkDaoSvc.getMatchedLinkForSourcePid(myIdHelperService.getPidOrNull(theBaseResource));
if (matchedLinkForTargetPid.isPresent()) {
Long goldenResourcePid = matchedLinkForTargetPid.get().getGoldenResourcePid();
- return (IAnyResource) relevantDao.readByPid(new ResourcePersistentId(goldenResourcePid));
+ return (T) relevantDao.readByPid(new ResourcePersistentId(goldenResourcePid));
} else {
return null;
}
diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmStorageInterceptorIT.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmStorageInterceptorIT.java
index cd1518cbc59..330e1380bef 100644
--- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmStorageInterceptorIT.java
+++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmStorageInterceptorIT.java
@@ -6,8 +6,12 @@ import ca.uhn.fhir.jpa.entity.MdmLink;
import ca.uhn.fhir.jpa.mdm.BaseMdmR4Test;
import ca.uhn.fhir.jpa.mdm.helper.MdmHelperConfig;
import ca.uhn.fhir.jpa.mdm.helper.MdmHelperR4;
+import ca.uhn.fhir.jpa.mdm.svc.MdmLinkSvcImpl;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
+import ca.uhn.fhir.mdm.api.IMdmLinkSvc;
import ca.uhn.fhir.mdm.api.MdmLinkEvent;
+import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
+import ca.uhn.fhir.mdm.api.MdmMatchOutcome;
import ca.uhn.fhir.mdm.model.CanonicalEID;
import ca.uhn.fhir.mdm.model.MdmTransactionContext;
import ca.uhn.fhir.mdm.rules.config.MdmSettings;
@@ -68,6 +72,8 @@ public class MdmStorageInterceptorIT extends BaseMdmR4Test {
public MdmHelperR4 myMdmHelper;
@Autowired
private IdHelperService myIdHelperService;
+ @Autowired
+ private IMdmLinkSvc myMdmLinkSvc;
@Test
public void testCreatePractitioner() throws InterruptedException {
@@ -105,17 +111,17 @@ public class MdmStorageInterceptorIT extends BaseMdmR4Test {
MdmTransactionContext ctx = createContextForCreate("Patient");
myMdmMatchLinkSvc.updateMdmLinksForMdmSource(patient1, ctx);
- ourLog.info(ctx.getMdmLinkChangeEvent().toString());
- assertEquals(patient1.getIdElement().getValue(), ctx.getMdmLinkChangeEvent().getTargetResourceId());
- assertEquals(getLinkByTargetId(patient1).getGoldenResourcePid(), new IdDt(ctx.getMdmLinkChangeEvent().getGoldenResourceId()).getIdPartAsLong());
+ ourLog.info(ctx.getMdmLinkEvent().toString());
+ assertEquals(patient1.getIdElement().getValue(), ctx.getMdmLinkEvent().getTargetResourceId());
+ assertEquals(getLinkByTargetId(patient1).getGoldenResourcePid(), new IdDt(ctx.getMdmLinkEvent().getGoldenResourceId()).getIdPartAsLong());
Patient patient2 = addExternalEID(buildJanePatient(), "eid-2");
myMdmHelper.createWithLatch(patient2);
ctx = createContextForCreate("Patient");
myMdmMatchLinkSvc.updateMdmLinksForMdmSource(patient2, ctx);
- ourLog.info(ctx.getMdmLinkChangeEvent().toString());
- assertEquals(patient2.getIdElement().getValue(), ctx.getMdmLinkChangeEvent().getTargetResourceId());
- assertEquals(getLinkByTargetId(patient2).getGoldenResourcePid(), new IdDt(ctx.getMdmLinkChangeEvent().getGoldenResourceId()).getIdPartAsLong());
+ ourLog.info(ctx.getMdmLinkEvent().toString());
+ assertEquals(patient2.getIdElement().getValue(), ctx.getMdmLinkEvent().getTargetResourceId());
+ assertEquals(getLinkByTargetId(patient2).getGoldenResourcePid(), new IdDt(ctx.getMdmLinkEvent().getGoldenResourceId()).getIdPartAsLong());
}
@Test
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 9853918a9d7..4f13e7ac706 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
@@ -96,7 +96,7 @@ public class MdmTransactionContext {
this.myResourceType = myResourceType;
}
- public MdmLinkEvent getMdmLinkChangeEvent() {
+ public MdmLinkEvent getMdmLinkEvent() {
return myMdmLinkEvent;
}
From 2a60e91713ae20cd983365cdd8bdb51e3f097ecf Mon Sep 17 00:00:00 2001
From: Nick Goupinets
Date: Thu, 2 Sep 2021 17:41:57 -0400
Subject: [PATCH 11/13] WIP Dup Test
---
.../uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvc.java | 1 +
.../fhir/jpa/mdm/interceptor/MdmEventIT.java | 190 ++++++++++++++++++
.../interceptor/MdmStorageInterceptorIT.java | 32 +--
3 files changed, 193 insertions(+), 30 deletions(-)
create mode 100644 hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmEventIT.java
diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvc.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvc.java
index ce285b58bac..2c2eba5342e 100644
--- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvc.java
+++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvc.java
@@ -101,6 +101,7 @@ public class MdmMatchLinkSvc {
handleMdmWithSingleCandidate(theResource, firstMatch, theMdmTransactionContext);
} else {
log(theMdmTransactionContext, "MDM received multiple match candidates, that were linked to different Golden Resources. Setting POSSIBLE_DUPLICATES and POSSIBLE_MATCHES.");
+
//Set them all as POSSIBLE_MATCH
List goldenResources = new ArrayList<>();
for (MatchedGoldenResourceCandidate matchedGoldenResourceCandidate : theCandidateList.getCandidates()) {
diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmEventIT.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmEventIT.java
new file mode 100644
index 00000000000..1bfdd0c1cb2
--- /dev/null
+++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmEventIT.java
@@ -0,0 +1,190 @@
+package ca.uhn.fhir.jpa.mdm.interceptor;
+
+import ca.uhn.fhir.jpa.dao.index.IdHelperService;
+import ca.uhn.fhir.jpa.entity.MdmLink;
+import ca.uhn.fhir.jpa.mdm.BaseMdmR4Test;
+import ca.uhn.fhir.jpa.mdm.helper.MdmHelperConfig;
+import ca.uhn.fhir.jpa.mdm.helper.MdmHelperR4;
+import ca.uhn.fhir.jpa.search.HapiLuceneAnalysisConfigurer;
+import ca.uhn.fhir.mdm.api.MdmLinkEvent;
+import ca.uhn.fhir.mdm.model.MdmTransactionContext;
+import ca.uhn.fhir.model.primitive.IdDt;
+import ca.uhn.fhir.rest.server.messaging.ResourceOperationMessage;
+import org.hibernate.dialect.H2Dialect;
+import org.hibernate.search.backend.lucene.cfg.LuceneBackendSettings;
+import org.hibernate.search.backend.lucene.cfg.LuceneIndexSettings;
+import org.hibernate.search.engine.cfg.BackendSettings;
+import org.hibernate.search.mapper.orm.cfg.HibernateOrmMapperSettings;
+import org.hl7.fhir.instance.model.api.IBaseResource;
+import org.hl7.fhir.r4.model.Patient;
+import org.hl7.fhir.r4.model.Practitioner;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Primary;
+import org.springframework.data.domain.Example;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
+
+import java.util.Properties;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+@TestPropertySource(properties = {
+ "mdm.prevent_multiple_eids=false"
+})
+@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
+@ContextConfiguration(classes = {MdmHelperConfig.class})
+public class MdmEventIT extends BaseMdmR4Test {
+
+ private static final Logger ourLog = getLogger(MdmEventIT.class);
+
+ @RegisterExtension
+ @Autowired
+ public MdmHelperR4 myMdmHelper;
+ @Autowired
+ private IdHelperService myIdHelperService;
+
+ @Bean
+ @Primary
+ public Properties jpaProperties() {
+ Properties extraProperties = new Properties();
+ extraProperties.put("hibernate.format_sql", "true");
+ extraProperties.put("hibernate.show_sql", "true");
+ extraProperties.put("hibernate.hbm2ddl.auto", "update");
+ extraProperties.put("hibernate.dialect", H2Dialect.class.getName());
+
+ extraProperties.put(BackendSettings.backendKey(BackendSettings.TYPE), "lucene");
+ extraProperties.put(BackendSettings.backendKey(LuceneBackendSettings.ANALYSIS_CONFIGURER), HapiLuceneAnalysisConfigurer.class.getName());
+ extraProperties.put(BackendSettings.backendKey(LuceneIndexSettings.DIRECTORY_TYPE), "local-heap");
+ extraProperties.put(BackendSettings.backendKey(LuceneBackendSettings.LUCENE_VERSION), "LUCENE_CURRENT");
+ extraProperties.put(HibernateOrmMapperSettings.ENABLED, "true");
+
+ return extraProperties;
+ }
+
+
+ @Test
+ public void testDuplicateLinkChangeEvent() throws InterruptedException {
+ Patient patient1 = buildJanePatient();
+ addExternalEID(patient1, "eid-1");
+ addExternalEID(patient1, "eid-11");
+ patient1 = createPatientAndUpdateLinks(patient1);
+
+ Patient patient2 = buildPaulPatient();
+ addExternalEID(patient2, "eid-2");
+ addExternalEID(patient2, "eid-22");
+ patient2 = createPatientAndUpdateLinks(patient2);
+
+ Patient patient3 = buildPaulPatient();
+ addExternalEID(patient3, "eid-22");
+ patient3 = createPatientAndUpdateLinks(patient3);
+
+ patient2.getIdentifier().clear();
+ addExternalEID(patient2, "eid-11");
+ addExternalEID(patient2, "eid-22");
+
+ patient2 = (Patient) myPatientDao.update(patient2).getResource();
+ MdmTransactionContext ctx = myMdmMatchLinkSvc.updateMdmLinksForMdmSource(patient2, createContextForUpdate(patient2.getIdElement().getResourceType()));
+
+ MdmLinkEvent mdmLinkEvent = ctx.getMdmLinkEvent();
+ assertFalse(mdmLinkEvent.getDuplicateGoldenResourceIds().isEmpty());
+ }
+
+ // @Test
+ public void testCreateLinkChangeEvent() throws InterruptedException {
+ Practitioner pr = buildPractitionerWithNameAndId("Young", "AC-DC");
+ myMdmHelper.createWithLatch(pr);
+
+ ResourceOperationMessage resourceOperationMessage = myMdmHelper.getAfterMdmLatch().getLatchInvocationParameterOfType(ResourceOperationMessage.class);
+ assertNotNull(resourceOperationMessage);
+ assertEquals(pr.getId(), resourceOperationMessage.getId());
+
+ MdmLink link = getLinkByTargetId(pr);
+
+ MdmLinkEvent linkChangeEvent = myMdmHelper.getAfterMdmLatch().getLatchInvocationParameterOfType(MdmLinkEvent.class);
+ assertNotNull(linkChangeEvent);
+ assertEquals(link.getGoldenResourcePid(), new IdDt(linkChangeEvent.getGoldenResourceId()).getIdPartAsLong());
+ assertEquals(link.getSourcePid(), new IdDt(linkChangeEvent.getTargetResourceId()).getIdPartAsLong());
+ }
+
+ /*
+ @Test
+ public void testDuplicateLinkChangeEvent() throws InterruptedException {
+ logAllLinks();
+ for (IBaseResource r : myPatientDao.search(new SearchParameterMap()).getAllResources()) {
+ ourLog.info("Found {}", r);
+ }
+
+ Patient myPatient = createPatientAndUpdateLinks(buildPaulPatient());
+ StringType myPatientId = new StringType(myPatient.getIdElement().getValue());
+
+ Patient mySourcePatient = getGoldenResourceFromTargetResource(myPatient);
+ StringType mySourcePatientId = new StringType(mySourcePatient.getIdElement().getValue());
+ StringType myVersionlessGodlenResourceId = new StringType(mySourcePatient.getIdElement().toVersionless().getValue());
+
+ MdmLink myLink = myMdmLinkDaoSvc.findMdmLinkBySource(myPatient).get();
+ // Tests require our initial link to be a POSSIBLE_MATCH
+ myLink.setMatchResult(MdmMatchResultEnum.POSSIBLE_MATCH);
+ saveLink(myLink);
+ assertEquals(MdmLinkSourceEnum.AUTO, myLink.getLinkSource());
+// myDaoConfig.setExpungeEnabled(true);
+
+ // Add a second patient
+ createPatientAndUpdateLinks(buildJanePatient());
+
+ // Add a possible duplicate
+ StringType myLinkSource = new StringType(MdmLinkSourceEnum.AUTO.name());
+ Patient sourcePatient1 = createGoldenPatient();
+ StringType myGoldenResource1Id = new StringType(sourcePatient1.getIdElement().toVersionless().getValue());
+ Long sourcePatient1Pid = myIdHelperService.getPidOrNull(sourcePatient1);
+ Patient sourcePatient2 = createGoldenPatient();
+ StringType myGoldenResource2Id = new StringType(sourcePatient2.getIdElement().toVersionless().getValue());
+ Long sourcePatient2Pid = myIdHelperService.getPidOrNull(sourcePatient2);
+
+
+ MdmLink possibleDuplicateMdmLink = myMdmLinkDaoSvc.newMdmLink().setGoldenResourcePid(sourcePatient1Pid).setSourcePid(sourcePatient2Pid).setMatchResult(MdmMatchResultEnum.POSSIBLE_DUPLICATE).setLinkSource(MdmLinkSourceEnum.AUTO);
+ saveLink(possibleDuplicateMdmLink);
+
+ logAllLinks();
+
+ ResourceOperationMessage resourceOperationMessage = myMdmHelper.getAfterMdmLatch().getLatchInvocationParameterOfType(ResourceOperationMessage.class);
+ assertNotNull(resourceOperationMessage);
+ assertEquals(sourcePatient2.getId(), resourceOperationMessage.getId());
+ }
+ */
+
+ private MdmLink getLinkByTargetId(IBaseResource theResource) {
+ MdmLink example = new MdmLink();
+ example.setSourcePid(theResource.getIdElement().getIdPartAsLong());
+ return myMdmLinkDao.findAll(Example.of(example)).get(0);
+ }
+
+ @Test
+ public void testUpdateLinkChangeEvent() throws InterruptedException {
+ Patient patient1 = addExternalEID(buildJanePatient(), "eid-1");
+ myMdmHelper.createWithLatch(patient1);
+
+ MdmTransactionContext ctx = createContextForCreate("Patient");
+ myMdmMatchLinkSvc.updateMdmLinksForMdmSource(patient1, ctx);
+ ourLog.info(ctx.getMdmLinkEvent().toString());
+ assertEquals(patient1.getIdElement().getValue(), ctx.getMdmLinkEvent().getTargetResourceId());
+ assertEquals(getLinkByTargetId(patient1).getGoldenResourcePid(), new IdDt(ctx.getMdmLinkEvent().getGoldenResourceId()).getIdPartAsLong());
+
+ Patient patient2 = addExternalEID(buildJanePatient(), "eid-2");
+ myMdmHelper.createWithLatch(patient2);
+ ctx = createContextForCreate("Patient");
+ myMdmMatchLinkSvc.updateMdmLinksForMdmSource(patient2, ctx);
+ ourLog.info(ctx.getMdmLinkEvent().toString());
+ assertEquals(patient2.getIdElement().getValue(), ctx.getMdmLinkEvent().getTargetResourceId());
+ assertEquals(getLinkByTargetId(patient2).getGoldenResourcePid(), new IdDt(ctx.getMdmLinkEvent().getGoldenResourceId()).getIdPartAsLong());
+ }
+
+
+}
diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmStorageInterceptorIT.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmStorageInterceptorIT.java
index 330e1380bef..30281f7fd90 100644
--- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmStorageInterceptorIT.java
+++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmStorageInterceptorIT.java
@@ -6,12 +6,7 @@ import ca.uhn.fhir.jpa.entity.MdmLink;
import ca.uhn.fhir.jpa.mdm.BaseMdmR4Test;
import ca.uhn.fhir.jpa.mdm.helper.MdmHelperConfig;
import ca.uhn.fhir.jpa.mdm.helper.MdmHelperR4;
-import ca.uhn.fhir.jpa.mdm.svc.MdmLinkSvcImpl;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
-import ca.uhn.fhir.mdm.api.IMdmLinkSvc;
-import ca.uhn.fhir.mdm.api.MdmLinkEvent;
-import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
-import ca.uhn.fhir.mdm.api.MdmMatchOutcome;
import ca.uhn.fhir.mdm.model.CanonicalEID;
import ca.uhn.fhir.mdm.model.MdmTransactionContext;
import ca.uhn.fhir.mdm.rules.config.MdmSettings;
@@ -21,7 +16,6 @@ import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
import ca.uhn.fhir.rest.param.ReferenceParam;
import ca.uhn.fhir.rest.server.TransactionLogMessages;
import ca.uhn.fhir.rest.server.exceptions.ForbiddenOperationException;
-import ca.uhn.fhir.rest.server.messaging.ResourceOperationMessage;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
@@ -29,7 +23,6 @@ import org.hl7.fhir.r4.model.Enumerations;
import org.hl7.fhir.r4.model.Medication;
import org.hl7.fhir.r4.model.Organization;
import org.hl7.fhir.r4.model.Patient;
-import org.hl7.fhir.r4.model.Practitioner;
import org.hl7.fhir.r4.model.SearchParameter;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
@@ -55,9 +48,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import static org.slf4j.LoggerFactory.getLogger;
@@ -72,8 +63,6 @@ public class MdmStorageInterceptorIT extends BaseMdmR4Test {
public MdmHelperR4 myMdmHelper;
@Autowired
private IdHelperService myIdHelperService;
- @Autowired
- private IMdmLinkSvc myMdmLinkSvc;
@Test
public void testCreatePractitioner() throws InterruptedException {
@@ -81,23 +70,6 @@ public class MdmStorageInterceptorIT extends BaseMdmR4Test {
assertLinkCount(1);
}
- @Test
- public void testCreateLinkChangeEvent() throws InterruptedException {
- Practitioner pr = buildPractitionerWithNameAndId("Young", "AC-DC");
- myMdmHelper.createWithLatch(pr);
-
- ResourceOperationMessage resourceOperationMessage = myMdmHelper.getAfterMdmLatch().getLatchInvocationParameterOfType(ResourceOperationMessage.class);
- assertNotNull(resourceOperationMessage);
- assertEquals(pr.getId(), resourceOperationMessage.getId());
-
- MdmLink link = getLinkByTargetId(pr);
-
- MdmLinkEvent linkChangeEvent = myMdmHelper.getAfterMdmLatch().getLatchInvocationParameterOfType(MdmLinkEvent.class);
- assertNotNull(linkChangeEvent);
- assertEquals(link.getGoldenResourcePid(), new IdDt(linkChangeEvent.getGoldenResourceId()).getIdPartAsLong());
- assertEquals(link.getSourcePid(), new IdDt(linkChangeEvent.getTargetResourceId()).getIdPartAsLong());
- }
-
private MdmLink getLinkByTargetId(IBaseResource theResource) {
MdmLink example = new MdmLink();
example.setSourcePid(theResource.getIdElement().getIdPartAsLong());
@@ -113,7 +85,7 @@ public class MdmStorageInterceptorIT extends BaseMdmR4Test {
myMdmMatchLinkSvc.updateMdmLinksForMdmSource(patient1, ctx);
ourLog.info(ctx.getMdmLinkEvent().toString());
assertEquals(patient1.getIdElement().getValue(), ctx.getMdmLinkEvent().getTargetResourceId());
- assertEquals(getLinkByTargetId(patient1).getGoldenResourcePid(), new IdDt(ctx.getMdmLinkEvent().getGoldenResourceId()).getIdPartAsLong());
+ assertEquals(getLinkByTargetId(patient1).getGoldenResourcePid(), new IdDt(ctx.getMdmLinkEvent().getGoldenResourceId()).getIdPartAsLong());
Patient patient2 = addExternalEID(buildJanePatient(), "eid-2");
myMdmHelper.createWithLatch(patient2);
@@ -121,7 +93,7 @@ public class MdmStorageInterceptorIT extends BaseMdmR4Test {
myMdmMatchLinkSvc.updateMdmLinksForMdmSource(patient2, ctx);
ourLog.info(ctx.getMdmLinkEvent().toString());
assertEquals(patient2.getIdElement().getValue(), ctx.getMdmLinkEvent().getTargetResourceId());
- assertEquals(getLinkByTargetId(patient2).getGoldenResourcePid(), new IdDt(ctx.getMdmLinkEvent().getGoldenResourceId()).getIdPartAsLong());
+ assertEquals(getLinkByTargetId(patient2).getGoldenResourcePid(), new IdDt(ctx.getMdmLinkEvent().getGoldenResourceId()).getIdPartAsLong());
}
@Test
From c63a5038419e7ce6e549c28711b0f1e4b36ebcbd Mon Sep 17 00:00:00 2001
From: Nick Goupinets
Date: Fri, 3 Sep 2021 16:29:26 -0400
Subject: [PATCH 12/13] Updated link processing for MDM events
---
.../java/ca/uhn/fhir/jpa/entity/MdmLink.java | 3 +-
.../jpa/mdm/broker/MdmMessageHandler.java | 14 +-
.../fhir/jpa/mdm/svc/MdmEidUpdateService.java | 2 -
.../uhn/fhir/jpa/mdm/svc/MdmLinkSvcImpl.java | 10 +-
.../uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvc.java | 8 -
.../jpa/mdm/svc/MdmModelConverterSvcImpl.java | 28 ++--
.../fhir/jpa/mdm/interceptor/MdmEventIT.java | 115 ++++----------
.../interceptor/MdmStorageInterceptorIT.java | 20 ---
.../java/ca/uhn/fhir/mdm/api/IMdmLink.java | 24 +++
.../ca/uhn/fhir/mdm/api/MdmLinkEvent.java | 148 ++----------------
.../fhir/mdm/model/MdmTransactionContext.java | 18 ++-
11 files changed, 106 insertions(+), 284 deletions(-)
create mode 100644 hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmLink.java
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/MdmLink.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/MdmLink.java
index cd8cbff422d..4892ed8c1f9 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/MdmLink.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/MdmLink.java
@@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.entity;
* #L%
*/
+import ca.uhn.fhir.mdm.api.IMdmLink;
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
@@ -47,7 +48,7 @@ import java.util.Date;
@Table(name = "MPI_LINK", uniqueConstraints = {
@UniqueConstraint(name = "IDX_EMPI_PERSON_TGT", columnNames = {"PERSON_PID", "TARGET_PID"}),
})
-public class MdmLink {
+public class MdmLink implements IMdmLink {
public static final int VERSION_LENGTH = 16;
private static final int MATCH_RESULT_LENGTH = 16;
private static final int LINK_SOURCE_LENGTH = 16;
diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/broker/MdmMessageHandler.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/broker/MdmMessageHandler.java
index 6589d6b41e9..7695be8f448 100644
--- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/broker/MdmMessageHandler.java
+++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/broker/MdmMessageHandler.java
@@ -119,17 +119,17 @@ public class MdmMessageHandler implements MessageHandler {
ResourceOperationMessage outgoingMsg = new ResourceOperationMessage(myFhirContext, targetResource, theMsg.getOperationType());
outgoingMsg.setTransactionId(theMsg.getTransactionId());
- MdmLinkEvent linkChangeEvent = mdmContext.getMdmLinkEvent();
- Optional mdmLinkBySource = myMdmLinkDaoSvc.findMdmLinkBySource(targetResource);
- if (!mdmLinkBySource.isPresent()) {
- ourLog.warn("Unable to find link by source for {}", targetResource.getIdElement());
- }
+ MdmLinkEvent linkChangeEvent = new MdmLinkEvent();
+ mdmContext.getMdmLinks()
+ .stream()
+ .forEach(l -> {
+ linkChangeEvent.addMdmLink(myModelConverter.toJson((MdmLink) l));
+ });
- mdmLinkBySource.ifPresent(link -> linkChangeEvent.setFromLink(myModelConverter.toJson(link)));
HookParams params = new HookParams()
.add(ResourceOperationMessage.class, outgoingMsg)
.add(TransactionLogMessages.class, mdmContext.getTransactionLogMessages())
- .add(MdmLinkEvent.class, mdmContext.getMdmLinkEvent());
+ .add(MdmLinkEvent.class, linkChangeEvent);
myInterceptorBroadcaster.callHooks(Pointcut.MDM_AFTER_PERSISTED_RESOURCE_CHECKED, params);
}
diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmEidUpdateService.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmEidUpdateService.java
index 2e035615200..94db6849073 100644
--- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmEidUpdateService.java
+++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmEidUpdateService.java
@@ -85,8 +85,6 @@ public class MdmEidUpdateService {
myMdmSurvivorshipService.applySurvivorshipRulesToGoldenResource(theTargetResource, updateContext.getMatchedGoldenResource(), theMdmTransactionContext);
myMdmResourceDaoSvc.upsertGoldenResource(updateContext.getMatchedGoldenResource(), theMdmTransactionContext.getResourceType());
}
-
- theMdmTransactionContext.getMdmLinkEvent().setGoldenResourceId(updateContext.getExistingGoldenResource());
}
private void handleNoEidsInCommon(IAnyResource theResource, MatchedGoldenResourceCandidate theMatchedGoldenResourceCandidate, MdmTransactionContext theMdmTransactionContext, MdmUpdateContext theUpdateContext) {
diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmLinkSvcImpl.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmLinkSvcImpl.java
index 3d744f43d11..7e4b95dad0c 100644
--- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmLinkSvcImpl.java
+++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmLinkSvcImpl.java
@@ -53,6 +53,8 @@ public class MdmLinkSvcImpl implements IMdmLinkSvc {
private MdmLinkDaoSvc myMdmLinkDaoSvc;
@Autowired
private IdHelperService myIdHelperService;
+ @Autowired
+ private IMdmModelConverterSvc myMdmModelConverterSvc;
@Override
@Transactional
@@ -69,7 +71,8 @@ public class MdmLinkSvcImpl implements IMdmLinkSvc {
validateRequestIsLegal(theGoldenResource, theSourceResource, matchResultEnum, theLinkSource);
myMdmResourceDaoSvc.upsertGoldenResource(theGoldenResource, theMdmTransactionContext.getResourceType());
- createOrUpdateLinkEntity(theGoldenResource, theSourceResource, theMatchOutcome, theLinkSource, theMdmTransactionContext);
+ MdmLink link = createOrUpdateLinkEntity(theGoldenResource, theSourceResource, theMatchOutcome, theLinkSource, theMdmTransactionContext);
+ theMdmTransactionContext.addMdmLink(link);
}
private boolean goldenResourceLinkedAsNoMatch(IAnyResource theGoldenResource, IAnyResource theSourceResource) {
@@ -87,6 +90,7 @@ public class MdmLinkSvcImpl implements IMdmLinkSvc {
MdmLink mdmLink = optionalMdmLink.get();
log(theMdmTransactionContext, "Deleting MdmLink [" + theGoldenResource.getIdElement().toVersionless() + " -> " + theSourceResource.getIdElement().toVersionless() + "] with result: " + mdmLink.getMatchResult());
myMdmLinkDaoSvc.deleteLink(mdmLink);
+ theMdmTransactionContext.addMdmLink(mdmLink);
}
}
@@ -129,8 +133,8 @@ public class MdmLinkSvcImpl implements IMdmLinkSvc {
}
}
- private void createOrUpdateLinkEntity(IBaseResource theGoldenResource, IBaseResource theSourceResource, MdmMatchOutcome theMatchOutcome, MdmLinkSourceEnum theLinkSource, MdmTransactionContext theMdmTransactionContext) {
- myMdmLinkDaoSvc.createOrUpdateLinkEntity(theGoldenResource, theSourceResource, theMatchOutcome, theLinkSource, theMdmTransactionContext);
+ private MdmLink createOrUpdateLinkEntity(IBaseResource theGoldenResource, IBaseResource theSourceResource, MdmMatchOutcome theMatchOutcome, MdmLinkSourceEnum theLinkSource, MdmTransactionContext theMdmTransactionContext) {
+ return myMdmLinkDaoSvc.createOrUpdateLinkEntity(theGoldenResource, theSourceResource, theMatchOutcome, theLinkSource, theMdmTransactionContext);
}
private void log(MdmTransactionContext theMdmTransactionContext, String theMessage) {
diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvc.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvc.java
index 2c2eba5342e..8eda5742dd2 100644
--- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvc.java
+++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvc.java
@@ -78,8 +78,6 @@ public class MdmMatchLinkSvc {
private MdmTransactionContext doMdmUpdate(IAnyResource theResource, MdmTransactionContext theMdmTransactionContext) {
CandidateList candidateList = myMdmGoldenResourceFindingSvc.findGoldenResourceCandidates(theResource);
- theMdmTransactionContext.getMdmLinkEvent().setTargetResourceId(theResource);
-
if (candidateList.isEmpty()) {
handleMdmWithNoCandidates(theResource, theMdmTransactionContext);
} else if (candidateList.exactlyOneMatch()) {
@@ -115,14 +113,12 @@ public class MdmMatchLinkSvc {
//Set all GoldenResources as POSSIBLE_DUPLICATE of the last GoldenResource.
IAnyResource firstGoldenResource = goldenResources.get(0);
- theMdmTransactionContext.getMdmLinkEvent().setGoldenResourceId(firstGoldenResource);
goldenResources.subList(1, goldenResources.size())
.forEach(possibleDuplicateGoldenResource -> {
MdmMatchOutcome outcome = MdmMatchOutcome.POSSIBLE_DUPLICATE;
outcome.setEidMatch(theCandidateList.isEidMatch());
myMdmLinkSvc.updateLink(firstGoldenResource, possibleDuplicateGoldenResource, outcome, MdmLinkSourceEnum.AUTO, theMdmTransactionContext);
- theMdmTransactionContext.getMdmLinkEvent().addDuplicateGoldenResourceId(possibleDuplicateGoldenResource);
});
}
}
@@ -135,8 +131,6 @@ public class MdmMatchLinkSvc {
// 2. Create source resource for the MDM source
// 3. UPDATE MDM LINK TABLE
myMdmLinkSvc.updateLink(newGoldenResource, theResource, MdmMatchOutcome.NEW_GOLDEN_RESOURCE_MATCH, MdmLinkSourceEnum.AUTO, theMdmTransactionContext);
-
- theMdmTransactionContext.getMdmLinkEvent().setGoldenResourceId(newGoldenResource);
}
private void handleMdmCreate(IAnyResource theTargetResource, MatchedGoldenResourceCandidate theGoldenResourceCandidate, MdmTransactionContext theMdmTransactionContext) {
@@ -146,7 +140,6 @@ public class MdmMatchLinkSvc {
if (myGoldenResourceHelper.isPotentialDuplicate(goldenResource, theTargetResource)) {
log(theMdmTransactionContext, "Duplicate detected based on the fact that both resources have different external EIDs.");
IAnyResource newGoldenResource = myGoldenResourceHelper.createGoldenResourceFromMdmSourceResource(theTargetResource, theMdmTransactionContext);
- theMdmTransactionContext.getMdmLinkEvent().setGoldenResourceId(newGoldenResource);
myMdmLinkSvc.updateLink(newGoldenResource, theTargetResource, MdmMatchOutcome.NEW_GOLDEN_RESOURCE_MATCH, MdmLinkSourceEnum.AUTO, theMdmTransactionContext);
myMdmLinkSvc.updateLink(newGoldenResource, goldenResource, MdmMatchOutcome.POSSIBLE_DUPLICATE, MdmLinkSourceEnum.AUTO, theMdmTransactionContext);
@@ -156,7 +149,6 @@ public class MdmMatchLinkSvc {
myEidUpdateService.applySurvivorshipRulesAndSaveGoldenResource(theTargetResource, goldenResource, theMdmTransactionContext);
}
- theMdmTransactionContext.getMdmLinkEvent().setGoldenResourceId(goldenResource);
myMdmLinkSvc.updateLink(goldenResource, theTargetResource, theGoldenResourceCandidate.getMatchResult(), MdmLinkSourceEnum.AUTO, theMdmTransactionContext);
}
}
diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmModelConverterSvcImpl.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmModelConverterSvcImpl.java
index 195ac388e68..89a8ae5c34e 100644
--- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmModelConverterSvcImpl.java
+++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmModelConverterSvcImpl.java
@@ -31,22 +31,22 @@ public class MdmModelConverterSvcImpl implements IMdmModelConverterSvc {
IdHelperService myIdHelperService;
public MdmLinkJson toJson(MdmLink theLink) {
- MdmLinkJson retval = new MdmLinkJson();
+ MdmLinkJson retVal = new MdmLinkJson();
String sourceId = myIdHelperService.resourceIdFromPidOrThrowException(theLink.getSourcePid()).toVersionless().getValue();
- retval.setSourceId(sourceId);
+ retVal.setSourceId(sourceId);
String goldenResourceId = myIdHelperService.resourceIdFromPidOrThrowException(theLink.getGoldenResourcePid()).toVersionless().getValue();
- retval.setGoldenResourceId(goldenResourceId);
- retval.setCreated(theLink.getCreated());
- retval.setEidMatch(theLink.getEidMatch());
- retval.setLinkSource(theLink.getLinkSource());
- retval.setMatchResult(theLink.getMatchResult());
- retval.setLinkCreatedNewResource(theLink.getHadToCreateNewGoldenResource());
- retval.setScore(theLink.getScore());
- retval.setUpdated(theLink.getUpdated());
- retval.setVector(theLink.getVector());
- retval.setVersion(theLink.getVersion());
- retval.setRuleCount(theLink.getRuleCount());
- return retval;
+ retVal.setGoldenResourceId(goldenResourceId);
+ retVal.setCreated(theLink.getCreated());
+ retVal.setEidMatch(theLink.getEidMatch());
+ retVal.setLinkSource(theLink.getLinkSource());
+ retVal.setMatchResult(theLink.getMatchResult());
+ retVal.setLinkCreatedNewResource(theLink.getHadToCreateNewGoldenResource());
+ retVal.setScore(theLink.getScore());
+ retVal.setUpdated(theLink.getUpdated());
+ retVal.setVector(theLink.getVector());
+ retVal.setVersion(theLink.getVersion());
+ retVal.setRuleCount(theLink.getRuleCount());
+ return retVal;
}
}
diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmEventIT.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmEventIT.java
index 1bfdd0c1cb2..39ec89b4c7d 100644
--- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmEventIT.java
+++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmEventIT.java
@@ -6,7 +6,10 @@ import ca.uhn.fhir.jpa.mdm.BaseMdmR4Test;
import ca.uhn.fhir.jpa.mdm.helper.MdmHelperConfig;
import ca.uhn.fhir.jpa.mdm.helper.MdmHelperR4;
import ca.uhn.fhir.jpa.search.HapiLuceneAnalysisConfigurer;
+import ca.uhn.fhir.mdm.api.IMdmLink;
import ca.uhn.fhir.mdm.api.MdmLinkEvent;
+import ca.uhn.fhir.mdm.api.MdmLinkJson;
+import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
import ca.uhn.fhir.mdm.model.MdmTransactionContext;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.server.messaging.ResourceOperationMessage;
@@ -29,6 +32,7 @@ import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
+import java.util.List;
import java.util.Properties;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -51,53 +55,38 @@ public class MdmEventIT extends BaseMdmR4Test {
@Autowired
private IdHelperService myIdHelperService;
- @Bean
- @Primary
- public Properties jpaProperties() {
- Properties extraProperties = new Properties();
- extraProperties.put("hibernate.format_sql", "true");
- extraProperties.put("hibernate.show_sql", "true");
- extraProperties.put("hibernate.hbm2ddl.auto", "update");
- extraProperties.put("hibernate.dialect", H2Dialect.class.getName());
-
- extraProperties.put(BackendSettings.backendKey(BackendSettings.TYPE), "lucene");
- extraProperties.put(BackendSettings.backendKey(LuceneBackendSettings.ANALYSIS_CONFIGURER), HapiLuceneAnalysisConfigurer.class.getName());
- extraProperties.put(BackendSettings.backendKey(LuceneIndexSettings.DIRECTORY_TYPE), "local-heap");
- extraProperties.put(BackendSettings.backendKey(LuceneBackendSettings.LUCENE_VERSION), "LUCENE_CURRENT");
- extraProperties.put(HibernateOrmMapperSettings.ENABLED, "true");
-
- return extraProperties;
- }
-
-
@Test
public void testDuplicateLinkChangeEvent() throws InterruptedException {
Patient patient1 = buildJanePatient();
addExternalEID(patient1, "eid-1");
addExternalEID(patient1, "eid-11");
- patient1 = createPatientAndUpdateLinks(patient1);
+ myMdmHelper.createWithLatch(patient1);
Patient patient2 = buildPaulPatient();
addExternalEID(patient2, "eid-2");
addExternalEID(patient2, "eid-22");
- patient2 = createPatientAndUpdateLinks(patient2);
+ myMdmHelper.createWithLatch(patient2);
Patient patient3 = buildPaulPatient();
addExternalEID(patient3, "eid-22");
- patient3 = createPatientAndUpdateLinks(patient3);
+ myMdmHelper.createWithLatch(patient3);
patient2.getIdentifier().clear();
addExternalEID(patient2, "eid-11");
addExternalEID(patient2, "eid-22");
- patient2 = (Patient) myPatientDao.update(patient2).getResource();
- MdmTransactionContext ctx = myMdmMatchLinkSvc.updateMdmLinksForMdmSource(patient2, createContextForUpdate(patient2.getIdElement().getResourceType()));
+ myMdmHelper.updateWithLatch(patient2);
- MdmLinkEvent mdmLinkEvent = ctx.getMdmLinkEvent();
- assertFalse(mdmLinkEvent.getDuplicateGoldenResourceIds().isEmpty());
+ MdmLinkEvent linkChangeEvent = myMdmHelper.getAfterMdmLatch().getLatchInvocationParameterOfType(MdmLinkEvent.class);
+ assertNotNull(linkChangeEvent);
+
+ // MdmTransactionContext ctx = myMdmMatchLinkSvc.updateMdmLinksForMdmSource(patient2, createContextForUpdate(patient2.getIdElement().getResourceType()));
+
+ List mdmLinkEvent = linkChangeEvent.getMdmLinks();
+ assertEquals(3, mdmLinkEvent.size());
}
- // @Test
+ @Test
public void testCreateLinkChangeEvent() throws InterruptedException {
Practitioner pr = buildPractitionerWithNameAndId("Young", "AC-DC");
myMdmHelper.createWithLatch(pr);
@@ -110,56 +99,13 @@ public class MdmEventIT extends BaseMdmR4Test {
MdmLinkEvent linkChangeEvent = myMdmHelper.getAfterMdmLatch().getLatchInvocationParameterOfType(MdmLinkEvent.class);
assertNotNull(linkChangeEvent);
- assertEquals(link.getGoldenResourcePid(), new IdDt(linkChangeEvent.getGoldenResourceId()).getIdPartAsLong());
- assertEquals(link.getSourcePid(), new IdDt(linkChangeEvent.getTargetResourceId()).getIdPartAsLong());
+
+ assertEquals(1, linkChangeEvent.getMdmLinks().size());
+ MdmLinkJson l = linkChangeEvent.getMdmLinks().get(0);
+ assertEquals(link.getGoldenResourcePid(), new IdDt(l.getGoldenResourceId()).getIdPartAsLong());
+ assertEquals(link.getSourcePid(), new IdDt(l.getSourceId()).getIdPartAsLong());
}
- /*
- @Test
- public void testDuplicateLinkChangeEvent() throws InterruptedException {
- logAllLinks();
- for (IBaseResource r : myPatientDao.search(new SearchParameterMap()).getAllResources()) {
- ourLog.info("Found {}", r);
- }
-
- Patient myPatient = createPatientAndUpdateLinks(buildPaulPatient());
- StringType myPatientId = new StringType(myPatient.getIdElement().getValue());
-
- Patient mySourcePatient = getGoldenResourceFromTargetResource(myPatient);
- StringType mySourcePatientId = new StringType(mySourcePatient.getIdElement().getValue());
- StringType myVersionlessGodlenResourceId = new StringType(mySourcePatient.getIdElement().toVersionless().getValue());
-
- MdmLink myLink = myMdmLinkDaoSvc.findMdmLinkBySource(myPatient).get();
- // Tests require our initial link to be a POSSIBLE_MATCH
- myLink.setMatchResult(MdmMatchResultEnum.POSSIBLE_MATCH);
- saveLink(myLink);
- assertEquals(MdmLinkSourceEnum.AUTO, myLink.getLinkSource());
-// myDaoConfig.setExpungeEnabled(true);
-
- // Add a second patient
- createPatientAndUpdateLinks(buildJanePatient());
-
- // Add a possible duplicate
- StringType myLinkSource = new StringType(MdmLinkSourceEnum.AUTO.name());
- Patient sourcePatient1 = createGoldenPatient();
- StringType myGoldenResource1Id = new StringType(sourcePatient1.getIdElement().toVersionless().getValue());
- Long sourcePatient1Pid = myIdHelperService.getPidOrNull(sourcePatient1);
- Patient sourcePatient2 = createGoldenPatient();
- StringType myGoldenResource2Id = new StringType(sourcePatient2.getIdElement().toVersionless().getValue());
- Long sourcePatient2Pid = myIdHelperService.getPidOrNull(sourcePatient2);
-
-
- MdmLink possibleDuplicateMdmLink = myMdmLinkDaoSvc.newMdmLink().setGoldenResourcePid(sourcePatient1Pid).setSourcePid(sourcePatient2Pid).setMatchResult(MdmMatchResultEnum.POSSIBLE_DUPLICATE).setLinkSource(MdmLinkSourceEnum.AUTO);
- saveLink(possibleDuplicateMdmLink);
-
- logAllLinks();
-
- ResourceOperationMessage resourceOperationMessage = myMdmHelper.getAfterMdmLatch().getLatchInvocationParameterOfType(ResourceOperationMessage.class);
- assertNotNull(resourceOperationMessage);
- assertEquals(sourcePatient2.getId(), resourceOperationMessage.getId());
- }
- */
-
private MdmLink getLinkByTargetId(IBaseResource theResource) {
MdmLink example = new MdmLink();
example.setSourcePid(theResource.getIdElement().getIdPartAsLong());
@@ -171,19 +117,14 @@ public class MdmEventIT extends BaseMdmR4Test {
Patient patient1 = addExternalEID(buildJanePatient(), "eid-1");
myMdmHelper.createWithLatch(patient1);
- MdmTransactionContext ctx = createContextForCreate("Patient");
- myMdmMatchLinkSvc.updateMdmLinksForMdmSource(patient1, ctx);
- ourLog.info(ctx.getMdmLinkEvent().toString());
- assertEquals(patient1.getIdElement().getValue(), ctx.getMdmLinkEvent().getTargetResourceId());
- assertEquals(getLinkByTargetId(patient1).getGoldenResourcePid(), new IdDt(ctx.getMdmLinkEvent().getGoldenResourceId()).getIdPartAsLong());
+ MdmLinkEvent linkChangeEvent = myMdmHelper.getAfterMdmLatch().getLatchInvocationParameterOfType(MdmLinkEvent.class);
+ assertNotNull(linkChangeEvent);
+ assertEquals(1, linkChangeEvent.getMdmLinks().size());
- Patient patient2 = addExternalEID(buildJanePatient(), "eid-2");
- myMdmHelper.createWithLatch(patient2);
- ctx = createContextForCreate("Patient");
- myMdmMatchLinkSvc.updateMdmLinksForMdmSource(patient2, ctx);
- ourLog.info(ctx.getMdmLinkEvent().toString());
- assertEquals(patient2.getIdElement().getValue(), ctx.getMdmLinkEvent().getTargetResourceId());
- assertEquals(getLinkByTargetId(patient2).getGoldenResourcePid(), new IdDt(ctx.getMdmLinkEvent().getGoldenResourceId()).getIdPartAsLong());
+ MdmLinkJson link = linkChangeEvent.getMdmLinks().get(0);
+ assertEquals(patient1.getResourceType() + "/" + patient1.getIdElement().getIdPart(), link.getSourceId());
+ assertEquals(getLinkByTargetId(patient1).getGoldenResourcePid(), new IdDt(link.getGoldenResourceId()).getIdPartAsLong());
+ assertEquals(MdmMatchResultEnum.MATCH, link.getMatchResult());
}
diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmStorageInterceptorIT.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmStorageInterceptorIT.java
index 30281f7fd90..4509b9052da 100644
--- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmStorageInterceptorIT.java
+++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmStorageInterceptorIT.java
@@ -76,26 +76,6 @@ public class MdmStorageInterceptorIT extends BaseMdmR4Test {
return myMdmLinkDao.findAll(Example.of(example)).get(0);
}
- @Test
- public void testUpdateLinkChangeEvent() throws InterruptedException {
- Patient patient1 = addExternalEID(buildJanePatient(), "eid-1");
- myMdmHelper.createWithLatch(patient1);
-
- MdmTransactionContext ctx = createContextForCreate("Patient");
- myMdmMatchLinkSvc.updateMdmLinksForMdmSource(patient1, ctx);
- ourLog.info(ctx.getMdmLinkEvent().toString());
- assertEquals(patient1.getIdElement().getValue(), ctx.getMdmLinkEvent().getTargetResourceId());
- assertEquals(getLinkByTargetId(patient1).getGoldenResourcePid(), new IdDt(ctx.getMdmLinkEvent().getGoldenResourceId()).getIdPartAsLong());
-
- Patient patient2 = addExternalEID(buildJanePatient(), "eid-2");
- myMdmHelper.createWithLatch(patient2);
- ctx = createContextForCreate("Patient");
- myMdmMatchLinkSvc.updateMdmLinksForMdmSource(patient2, ctx);
- ourLog.info(ctx.getMdmLinkEvent().toString());
- assertEquals(patient2.getIdElement().getValue(), ctx.getMdmLinkEvent().getTargetResourceId());
- assertEquals(getLinkByTargetId(patient2).getGoldenResourcePid(), new IdDt(ctx.getMdmLinkEvent().getGoldenResourceId()).getIdPartAsLong());
- }
-
@Test
public void testSearchExpandingInterceptorWorks() {
SearchParameterMap subject = new SearchParameterMap("subject", new ReferenceParam("Patient/123").setMdmExpand(true)).setLoadSynchronous(true);
diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmLink.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmLink.java
new file mode 100644
index 00000000000..bf87929d9bd
--- /dev/null
+++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmLink.java
@@ -0,0 +1,24 @@
+package ca.uhn.fhir.mdm.api;
+
+/*-
+ * #%L
+ * HAPI FHIR - Master Data Management
+ * %%
+ * 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%
+ */
+
+public interface IMdmLink {
+}
diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkEvent.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkEvent.java
index 7eda6f328d8..c65ee1c9e2d 100644
--- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkEvent.java
+++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkEvent.java
@@ -25,158 +25,32 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
+import java.util.ArrayList;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
public class MdmLinkEvent implements IModelJson {
- @JsonProperty(value = "matchResult")
- private MdmMatchResultEnum myMdmMatchResult;
- @JsonProperty(value = "linkSource")
- private MdmLinkSourceEnum myMdmLinkSource;
- @JsonProperty(value = "eidMatch")
- private Boolean myEidMatch;
- @JsonProperty(value = "newGoldenResource")
- private Boolean myNewGoldenResource;
- @JsonProperty(value = "score")
- private Double myScore;
- @JsonProperty(value = "ruleCount")
- private Long myRuleCount;
- @JsonProperty(value = "targetResourceId", required = true)
- private String myTargetResourceId;
- @JsonProperty(value = "goldenResourceId", required = true)
- private String myGoldenResourceId;
- @JsonProperty(value = "duplicateResourceIds")
- private Set myDuplicateGoldenResourceIds = new HashSet<>();
+ private List myMdmLinks = new ArrayList<>();
- public String getGoldenResourceId() {
- return myGoldenResourceId;
+ public List getMdmLinks() {
+ return myMdmLinks;
}
- public void setGoldenResourceId(IBaseResource theGoldenResourceId) {
- setGoldenResourceId(getIdAsString(theGoldenResourceId));
+ public void setMdmLinks(List theMdmLinks) {
+ myMdmLinks = theMdmLinks;
}
- public void setGoldenResourceId(String theGoldenResourceId) {
- myGoldenResourceId = theGoldenResourceId;
- }
-
- private String getIdAsString(IBaseResource theResource) {
- if (theResource == null) {
- return null;
- }
- IIdType idElement = theResource.getIdElement();
- if (idElement == null) {
- return null;
- }
- return idElement.getValueAsString();
- }
-
- public String getTargetResourceId() {
- return myTargetResourceId;
- }
-
- public void setTargetResourceId(IBaseResource theTargetResource) {
- setTargetResourceId(getIdAsString(theTargetResource));
- }
-
- public void setTargetResourceId(String theTargetResourceId) {
- myTargetResourceId = theTargetResourceId;
- }
-
- public Set getDuplicateGoldenResourceIds() {
- return myDuplicateGoldenResourceIds;
- }
-
- public void setDuplicateGoldenResourceIds(Set theDuplicateGoldenResourceIds) {
- myDuplicateGoldenResourceIds = theDuplicateGoldenResourceIds;
- }
-
- public MdmLinkEvent addDuplicateGoldenResourceId(IBaseResource theDuplicateGoldenResourceId) {
- String id = getIdAsString(theDuplicateGoldenResourceId);
- if (id != null) {
- getDuplicateGoldenResourceIds().add(id);
- }
+ public MdmLinkEvent addMdmLink(MdmLinkJson theMdmLink) {
+ getMdmLinks().add(theMdmLink);
return this;
}
- public MdmMatchResultEnum getMdmMatchResult() {
- return myMdmMatchResult;
- }
-
- public void setMdmMatchResult(MdmMatchResultEnum theMdmMatchResult) {
- myMdmMatchResult = theMdmMatchResult;
- }
-
- public MdmLinkSourceEnum getMdmLinkSource() {
- return myMdmLinkSource;
- }
-
- public void setMdmLinkSource(MdmLinkSourceEnum theMdmLinkSource) {
- myMdmLinkSource = theMdmLinkSource;
- }
-
- public Boolean getEidMatch() {
- return myEidMatch;
- }
-
- public void setEidMatch(Boolean theEidMatch) {
- if (theEidMatch == null) {
- myEidMatch = Boolean.FALSE;
- return;
- }
- myEidMatch = theEidMatch;
- }
-
- public Boolean getNewGoldenResource() {
- return myNewGoldenResource;
- }
-
- public void setNewGoldenResource(Boolean theNewGoldenResource) {
- if (theNewGoldenResource == null) {
- myNewGoldenResource = Boolean.FALSE;
- return;
- }
- myNewGoldenResource = theNewGoldenResource;
- }
-
- public Double getScore() {
- return myScore;
- }
-
- public void setScore(Double theScore) {
- myScore = theScore;
- }
-
- public Long getRuleCount() {
- return myRuleCount;
- }
-
- public void setRuleCount(Long theRuleCount) {
- myRuleCount = theRuleCount;
- }
-
- public void setFromLink(MdmLinkJson theMdmLinkJson) {
- setMdmMatchResult(theMdmLinkJson.getMatchResult());
- setMdmLinkSource(theMdmLinkJson.getLinkSource());
- setEidMatch(theMdmLinkJson.getEidMatch());
- setNewGoldenResource(theMdmLinkJson.getLinkCreatedNewResource());
- setScore(theMdmLinkJson.getScore());
- setRuleCount(theMdmLinkJson.getRuleCount());
- }
-
@Override
public String toString() {
- return "MdmLinkChangeEvent{" +
- "myMdmMatchResult=" + myMdmMatchResult +
- ", myMdmLinkSource=" + myMdmLinkSource +
- ", myEidMatch=" + myEidMatch +
- ", myNewGoldenResource=" + myNewGoldenResource +
- ", myScore=" + myScore +
- ", myRuleCount=" + myRuleCount +
- ", myTargetResourceId='" + myTargetResourceId + '\'' +
- ", myGoldenResourceId='" + myGoldenResourceId + '\'' +
- ", myDuplicateGoldenResourceIds=" + myDuplicateGoldenResourceIds +
+ return "MdmLinkEvent{" +
+ "myMdmLinks=" + myMdmLinks +
'}';
}
}
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 4f13e7ac706..9047462d50f 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
@@ -20,9 +20,13 @@ package ca.uhn.fhir.mdm.model;
* #L%
*/
+import ca.uhn.fhir.mdm.api.IMdmLink;
import ca.uhn.fhir.mdm.api.MdmLinkEvent;
import ca.uhn.fhir.rest.server.TransactionLogMessages;
+import java.util.ArrayList;
+import java.util.List;
+
public class MdmTransactionContext {
public enum OperationType {
@@ -46,7 +50,7 @@ public class MdmTransactionContext {
private String myResourceType;
- private MdmLinkEvent myMdmLinkEvent = new MdmLinkEvent();
+ private List myMdmLinkEvents = new ArrayList<>();
public TransactionLogMessages getTransactionLogMessages() {
return myTransactionLogMessages;
@@ -96,12 +100,16 @@ public class MdmTransactionContext {
this.myResourceType = myResourceType;
}
- public MdmLinkEvent getMdmLinkEvent() {
- return myMdmLinkEvent;
+ public List getMdmLinks() {
+ return myMdmLinkEvents;
}
- public void setMdmLinkChangeEvent(MdmLinkEvent theMdmLinkEvent) {
- myMdmLinkEvent = theMdmLinkEvent;
+ public MdmTransactionContext addMdmLink(IMdmLink theMdmLinkEvent) {
+ getMdmLinks().add(theMdmLinkEvent);
+ return this;
}
+ public void setMdmLinks(List theMdmLinkEvents) {
+ myMdmLinkEvents = theMdmLinkEvents;
+ }
}
From 010628fa86094000f3bda8b166d212bbd29ef31b Mon Sep 17 00:00:00 2001
From: Nick Goupinets
Date: Tue, 7 Sep 2021 11:24:37 -0400
Subject: [PATCH 13/13] Added asserts
---
.../fhir/jpa/mdm/interceptor/MdmEventIT.java | 17 ++++++++++++++---
.../java/ca/uhn/fhir/mdm/api/MdmLinkJson.java | 18 ++++++++++++++++++
2 files changed, 32 insertions(+), 3 deletions(-)
diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmEventIT.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmEventIT.java
index 39ec89b4c7d..cafbdebbff2 100644
--- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmEventIT.java
+++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmEventIT.java
@@ -80,7 +80,19 @@ public class MdmEventIT extends BaseMdmR4Test {
MdmLinkEvent linkChangeEvent = myMdmHelper.getAfterMdmLatch().getLatchInvocationParameterOfType(MdmLinkEvent.class);
assertNotNull(linkChangeEvent);
- // MdmTransactionContext ctx = myMdmMatchLinkSvc.updateMdmLinksForMdmSource(patient2, createContextForUpdate(patient2.getIdElement().getResourceType()));
+ ourLog.info("Got event: {}", linkChangeEvent);
+
+ long expectTwoPossibleMatchesForPatientTwo = linkChangeEvent.getMdmLinks()
+ .stream()
+ .filter(l -> l.getSourceId().equals(patient2.getIdElement().toVersionless().getValueAsString()) && l.getMatchResult() == MdmMatchResultEnum.POSSIBLE_MATCH)
+ .count();
+ assertEquals(2, expectTwoPossibleMatchesForPatientTwo);
+
+ long expectOnePossibleDuplicate = linkChangeEvent.getMdmLinks()
+ .stream()
+ .filter(l -> l.getMatchResult() == MdmMatchResultEnum.POSSIBLE_DUPLICATE)
+ .count();
+ assertEquals(1, expectOnePossibleDuplicate);
List mdmLinkEvent = linkChangeEvent.getMdmLinks();
assertEquals(3, mdmLinkEvent.size());
@@ -122,10 +134,9 @@ public class MdmEventIT extends BaseMdmR4Test {
assertEquals(1, linkChangeEvent.getMdmLinks().size());
MdmLinkJson link = linkChangeEvent.getMdmLinks().get(0);
- assertEquals(patient1.getResourceType() + "/" + patient1.getIdElement().getIdPart(), link.getSourceId());
+ assertEquals(patient1.getIdElement().toVersionless().getValueAsString(), link.getSourceId());
assertEquals(getLinkByTargetId(patient1).getGoldenResourcePid(), new IdDt(link.getGoldenResourceId()).getIdPartAsLong());
assertEquals(MdmMatchResultEnum.MATCH, link.getMatchResult());
}
-
}
diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkJson.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkJson.java
index 424298418b4..d21f8deada6 100644
--- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkJson.java
+++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/MdmLinkJson.java
@@ -175,4 +175,22 @@ public class MdmLinkJson implements IModelJson {
public void setRuleCount(Long theRuleCount) {
myRuleCount = theRuleCount;
}
+
+ @Override
+ public String toString() {
+ return "MdmLinkJson{" +
+ "myGoldenResourceId='" + myGoldenResourceId + '\'' +
+ ", mySourceId='" + mySourceId + '\'' +
+ ", myMatchResult=" + myMatchResult +
+ ", myLinkSource=" + myLinkSource +
+ ", myCreated=" + myCreated +
+ ", myUpdated=" + myUpdated +
+ ", myVersion='" + myVersion + '\'' +
+ ", myEidMatch=" + myEidMatch +
+ ", myLinkCreatedNewResource=" + myLinkCreatedNewResource +
+ ", myVector=" + myVector +
+ ", myScore=" + myScore +
+ ", myRuleCount=" + myRuleCount +
+ '}';
+ }
}