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 + '}';