From c63a5038419e7ce6e549c28711b0f1e4b36ebcbd Mon Sep 17 00:00:00 2001 From: Nick Goupinets Date: Fri, 3 Sep 2021 16:29:26 -0400 Subject: [PATCH] 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; + } }