mirror of
https://github.com/hapifhir/hapi-fhir.git
synced 2025-03-09 14:33:32 +00:00
5138 enhance existing historical link with mactchResultMap field (#5213)
This commit is contained in:
parent
8d1529276b
commit
fd5cff3d23
@ -209,7 +209,7 @@ public class ParametersUtil {
|
|||||||
*
|
*
|
||||||
* @param theContext The FhirContext
|
* @param theContext The FhirContext
|
||||||
* @param theParameters The Parameters resource
|
* @param theParameters The Parameters resource
|
||||||
* @param theName The parametr name
|
* @param theName The parameter name
|
||||||
* @param theValue The parameter value (can be a {@link IBaseResource resource} or a {@link IBaseDatatype datatype})
|
* @param theValue The parameter value (can be a {@link IBaseResource resource} or a {@link IBaseDatatype datatype})
|
||||||
*/
|
*/
|
||||||
public static void addParameterToParameters(
|
public static void addParameterToParameters(
|
||||||
@ -248,7 +248,7 @@ public class ParametersUtil {
|
|||||||
|
|
||||||
private static IBase createParameterRepetition(
|
private static IBase createParameterRepetition(
|
||||||
FhirContext theContext,
|
FhirContext theContext,
|
||||||
IBaseResource theTargetResource,
|
IBase theTargetResource,
|
||||||
BaseRuntimeChildDefinition paramChild,
|
BaseRuntimeChildDefinition paramChild,
|
||||||
BaseRuntimeElementCompositeDefinition<?> paramChildElem,
|
BaseRuntimeElementCompositeDefinition<?> paramChildElem,
|
||||||
String theName) {
|
String theName) {
|
||||||
@ -458,6 +458,17 @@ public class ParametersUtil {
|
|||||||
return part;
|
return part;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IBase createPart(FhirContext theContext, IBase thePart, String theName) {
|
||||||
|
BaseRuntimeElementCompositeDefinition<?> def =
|
||||||
|
(BaseRuntimeElementCompositeDefinition<?>) theContext.getElementDefinition(thePart.getClass());
|
||||||
|
BaseRuntimeChildDefinition partChild = def.getChildByName("part");
|
||||||
|
|
||||||
|
BaseRuntimeElementCompositeDefinition<?> partChildElem =
|
||||||
|
(BaseRuntimeElementCompositeDefinition<?>) partChild.getChildByName("part");
|
||||||
|
|
||||||
|
return createParameterRepetition(theContext, thePart, partChild, partChildElem, theName);
|
||||||
|
}
|
||||||
|
|
||||||
public static void addPartResource(
|
public static void addPartResource(
|
||||||
FhirContext theContext, IBase theParameter, String theName, IBaseResource theValue) {
|
FhirContext theContext, IBase theParameter, String theName, IBaseResource theValue) {
|
||||||
BaseRuntimeElementCompositeDefinition<?> def =
|
BaseRuntimeElementCompositeDefinition<?> def =
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
type: add
|
||||||
|
issue: 5138
|
||||||
|
title: "A match result map field has been added to the `$mdm-link-history` operation. This new field shows the rules that
|
||||||
|
evaluated true during matching and the corresponding initial match result when the link was created."
|
@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.mdm.svc;
|
|||||||
|
|
||||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||||
import ca.uhn.fhir.mdm.api.IMdmLink;
|
import ca.uhn.fhir.mdm.api.IMdmLink;
|
||||||
|
import ca.uhn.fhir.mdm.api.IMdmSettings;
|
||||||
import ca.uhn.fhir.mdm.api.MdmLinkWithRevision;
|
import ca.uhn.fhir.mdm.api.MdmLinkWithRevision;
|
||||||
import ca.uhn.fhir.mdm.model.mdmevents.MdmLinkJson;
|
import ca.uhn.fhir.mdm.model.mdmevents.MdmLinkJson;
|
||||||
import ca.uhn.fhir.mdm.model.mdmevents.MdmLinkWithRevisionJson;
|
import ca.uhn.fhir.mdm.model.mdmevents.MdmLinkWithRevisionJson;
|
||||||
@ -35,6 +36,9 @@ public class MdmModelConverterSvcImpl implements IMdmModelConverterSvc {
|
|||||||
@Autowired
|
@Autowired
|
||||||
IIdHelperService myIdHelperService;
|
IIdHelperService myIdHelperService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IMdmSettings myMdmSettings;
|
||||||
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
@Override
|
@Override
|
||||||
public MdmLinkJson toJson(IMdmLink theLink) {
|
public MdmLinkJson toJson(IMdmLink theLink) {
|
||||||
@ -69,6 +73,7 @@ public class MdmModelConverterSvcImpl implements IMdmModelConverterSvc {
|
|||||||
retVal.setUpdated(theLink.getUpdated());
|
retVal.setUpdated(theLink.getUpdated());
|
||||||
retVal.setVersion(theLink.getVersion());
|
retVal.setVersion(theLink.getVersion());
|
||||||
retVal.setRuleCount(theLink.getRuleCount());
|
retVal.setRuleCount(theLink.getRuleCount());
|
||||||
|
retVal.translateAndSetRule(myMdmSettings.getMdmRules(), theLink.getVector());
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -642,7 +642,7 @@ abstract public class BaseMdmR4Test extends BaseJpaR4Test {
|
|||||||
return myMdmLinkDao.save(mdmLink);
|
return myMdmLinkDao.save(mdmLink);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected MdmLink createGoldenPatientAndLinkToSourcePatient(MdmMatchResultEnum theMdmMatchResultEnum, MdmLinkSourceEnum theMdmLinkSourceEnum, String theVersion, Date theCreateTime, Date theUpdateTime, boolean theLinkCreatedNewResource) {
|
protected MdmLink createGoldenPatientAndLinkToSourcePatient(MdmMatchResultEnum theMdmMatchResultEnum, MdmLinkSourceEnum theMdmLinkSourceEnum, String theVersion, Date theCreateTime, Date theUpdateTime, boolean theLinkCreatedNewResource, Long theVector) {
|
||||||
final Patient goldenPatient = createPatient();
|
final Patient goldenPatient = createPatient();
|
||||||
final Patient sourcePatient = createPatient();
|
final Patient sourcePatient = createPatient();
|
||||||
|
|
||||||
@ -655,6 +655,7 @@ abstract public class BaseMdmR4Test extends BaseJpaR4Test {
|
|||||||
mdmLink.setGoldenResourcePersistenceId(runInTransaction(()->myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), goldenPatient)));
|
mdmLink.setGoldenResourcePersistenceId(runInTransaction(()->myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), goldenPatient)));
|
||||||
mdmLink.setSourcePersistenceId(runInTransaction(()->myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), sourcePatient)));
|
mdmLink.setSourcePersistenceId(runInTransaction(()->myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), sourcePatient)));
|
||||||
mdmLink.setHadToCreateNewGoldenResource(theLinkCreatedNewResource);
|
mdmLink.setHadToCreateNewGoldenResource(theLinkCreatedNewResource);
|
||||||
|
mdmLink.setVector(theVector);
|
||||||
|
|
||||||
return myMdmLinkDao.save(mdmLink);
|
return myMdmLinkDao.save(mdmLink);
|
||||||
}
|
}
|
||||||
|
@ -38,19 +38,20 @@ public class MdmModelConverterSvcImplTest extends BaseMdmR4Test {
|
|||||||
final Date updateTime = new Date();
|
final Date updateTime = new Date();
|
||||||
final String version = "1";
|
final String version = "1";
|
||||||
final boolean isLinkCreatedResource = false;
|
final boolean isLinkCreatedResource = false;
|
||||||
|
final long vector = 4L;
|
||||||
final double score = 0.8333333333333;
|
final double score = 0.8333333333333;
|
||||||
final double scoreRounded = BigDecimal.valueOf(score).setScale(4, RoundingMode.HALF_UP).doubleValue();
|
final double scoreRounded = BigDecimal.valueOf(score).setScale(4, RoundingMode.HALF_UP).doubleValue();
|
||||||
|
|
||||||
MdmLink mdmLink = createGoldenPatientAndLinkToSourcePatient(MdmMatchResultEnum.MATCH, MdmLinkSourceEnum.MANUAL, version, createTime, updateTime, isLinkCreatedResource);
|
final MdmLink mdmLink = createGoldenPatientAndLinkToSourcePatient(MdmMatchResultEnum.MATCH, MdmLinkSourceEnum.MANUAL, version, createTime, updateTime, isLinkCreatedResource, vector);
|
||||||
mdmLink.setScore(score);
|
mdmLink.setScore(score);
|
||||||
mdmLink.setVector(61L);
|
|
||||||
myMdmLinkDao.save(mdmLink);
|
myMdmLinkDao.save(mdmLink);
|
||||||
|
|
||||||
|
|
||||||
final MdmLinkJson actualMdmLinkJson = myMdmModelConverterSvc.toJson(mdmLink);
|
final MdmLinkJson actualMdmLinkJson = myMdmModelConverterSvc.toJson(mdmLink);
|
||||||
|
|
||||||
ourLog.info("actualMdmLinkJson: {}", actualMdmLinkJson);
|
ourLog.info("actualMdmLinkJson: {}", actualMdmLinkJson);
|
||||||
|
|
||||||
MdmLinkJson expectedMdmLinkJson = getExepctedMdmLinkJson(mdmLink.getGoldenResourcePersistenceId().getId(), mdmLink.getSourcePersistenceId().getId(), MdmMatchResultEnum.MATCH, MdmLinkSourceEnum.MANUAL, version, createTime, updateTime, isLinkCreatedResource, scoreRounded);
|
MdmLinkJson expectedMdmLinkJson = getExepctedMdmLinkJson(mdmLink.getGoldenResourcePersistenceId().getId(), mdmLink.getSourcePersistenceId().getId(), MdmMatchResultEnum.MATCH, MdmLinkSourceEnum.MANUAL, version, createTime, updateTime, isLinkCreatedResource, vector, scoreRounded);
|
||||||
assertEquals(expectedMdmLinkJson.getSourceId(), actualMdmLinkJson.getSourceId());
|
assertEquals(expectedMdmLinkJson.getSourceId(), actualMdmLinkJson.getSourceId());
|
||||||
assertEquals(expectedMdmLinkJson.getGoldenResourceId(), actualMdmLinkJson.getGoldenResourceId());
|
assertEquals(expectedMdmLinkJson.getGoldenResourceId(), actualMdmLinkJson.getGoldenResourceId());
|
||||||
assertEquals(expectedMdmLinkJson.getGoldenPid().getId(), actualMdmLinkJson.getGoldenPid().getId());
|
assertEquals(expectedMdmLinkJson.getGoldenPid().getId(), actualMdmLinkJson.getGoldenPid().getId());
|
||||||
@ -59,6 +60,7 @@ public class MdmModelConverterSvcImplTest extends BaseMdmR4Test {
|
|||||||
assertEquals(expectedMdmLinkJson.getScore(), actualMdmLinkJson.getScore());
|
assertEquals(expectedMdmLinkJson.getScore(), actualMdmLinkJson.getScore());
|
||||||
assertEquals(expectedMdmLinkJson.getMatchResult(), actualMdmLinkJson.getMatchResult());
|
assertEquals(expectedMdmLinkJson.getMatchResult(), actualMdmLinkJson.getMatchResult());
|
||||||
assertEquals(expectedMdmLinkJson.getLinkSource(), actualMdmLinkJson.getLinkSource());
|
assertEquals(expectedMdmLinkJson.getLinkSource(), actualMdmLinkJson.getLinkSource());
|
||||||
|
assertEquals(getExepctedMdmLinkJson(mdmLink.getGoldenResourcePersistenceId().getId(), mdmLink.getSourcePersistenceId().getId(), MdmMatchResultEnum.MATCH, MdmLinkSourceEnum.MANUAL, version, createTime, updateTime, isLinkCreatedResource, vector, scoreRounded), actualMdmLinkJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -72,12 +74,12 @@ public class MdmModelConverterSvcImplTest extends BaseMdmR4Test {
|
|||||||
final String version = "1";
|
final String version = "1";
|
||||||
final boolean isLinkCreatedResource = false;
|
final boolean isLinkCreatedResource = false;
|
||||||
final long revisionNumber = 2L;
|
final long revisionNumber = 2L;
|
||||||
|
final long vector = 4L;
|
||||||
final double score = 0.8333333333333;
|
final double score = 0.8333333333333;
|
||||||
final double scoreRounded = BigDecimal.valueOf(score).setScale(4, RoundingMode.HALF_UP).doubleValue();
|
final double scoreRounded = BigDecimal.valueOf(score).setScale(4, RoundingMode.HALF_UP).doubleValue();
|
||||||
|
|
||||||
MdmLink mdmLink = createGoldenPatientAndLinkToSourcePatient(MdmMatchResultEnum.MATCH, MdmLinkSourceEnum.MANUAL, version, createTime, updateTime, isLinkCreatedResource);
|
final MdmLink mdmLink = createGoldenPatientAndLinkToSourcePatient(MdmMatchResultEnum.MATCH, MdmLinkSourceEnum.MANUAL, version, createTime, updateTime, isLinkCreatedResource, vector);
|
||||||
mdmLink.setScore(score);
|
mdmLink.setScore(score);
|
||||||
mdmLink.setVector(61L);
|
|
||||||
myMdmLinkDao.save(mdmLink);
|
myMdmLinkDao.save(mdmLink);
|
||||||
|
|
||||||
final MdmLinkWithRevision<IMdmLink<? extends IResourcePersistentId<?>>> revision = new MdmLinkWithRevision<>(mdmLink, new EnversRevision(RevisionType.ADD, revisionNumber, revisionTimestamp));
|
final MdmLinkWithRevision<IMdmLink<? extends IResourcePersistentId<?>>> revision = new MdmLinkWithRevision<>(mdmLink, new EnversRevision(RevisionType.ADD, revisionNumber, revisionTimestamp));
|
||||||
@ -85,7 +87,7 @@ public class MdmModelConverterSvcImplTest extends BaseMdmR4Test {
|
|||||||
final MdmLinkWithRevisionJson actualMdmLinkWithRevisionJson = myMdmModelConverterSvc.toJson(revision);
|
final MdmLinkWithRevisionJson actualMdmLinkWithRevisionJson = myMdmModelConverterSvc.toJson(revision);
|
||||||
|
|
||||||
final MdmLinkWithRevisionJson expectedMdmLinkWithRevisionJson =
|
final MdmLinkWithRevisionJson expectedMdmLinkWithRevisionJson =
|
||||||
new MdmLinkWithRevisionJson(getExepctedMdmLinkJson(mdmLink.getGoldenResourcePersistenceId().getId(), mdmLink.getSourcePersistenceId().getId(), MdmMatchResultEnum.MATCH, MdmLinkSourceEnum.MANUAL, version, createTime, updateTime, isLinkCreatedResource, scoreRounded), revisionNumber, revisionTimestamp);
|
new MdmLinkWithRevisionJson(getExepctedMdmLinkJson(mdmLink.getGoldenResourcePersistenceId().getId(), mdmLink.getSourcePersistenceId().getId(), MdmMatchResultEnum.MATCH, MdmLinkSourceEnum.MANUAL, version, createTime, updateTime, isLinkCreatedResource, vector, scoreRounded), revisionNumber, revisionTimestamp);
|
||||||
|
|
||||||
assertMdmLinkRevisionsEqual(expectedMdmLinkWithRevisionJson, actualMdmLinkWithRevisionJson);
|
assertMdmLinkRevisionsEqual(expectedMdmLinkWithRevisionJson, actualMdmLinkWithRevisionJson);
|
||||||
}
|
}
|
||||||
@ -104,7 +106,7 @@ public class MdmModelConverterSvcImplTest extends BaseMdmR4Test {
|
|||||||
assertEquals(theExpectedMdmLinkWithRevisionJson.getRevisionTimestamp(), theActualMdmLinkWithRevisionJson.getRevisionTimestamp());
|
assertEquals(theExpectedMdmLinkWithRevisionJson.getRevisionTimestamp(), theActualMdmLinkWithRevisionJson.getRevisionTimestamp());
|
||||||
}
|
}
|
||||||
|
|
||||||
private MdmLinkJson getExepctedMdmLinkJson(Long theGoldenPatientId, Long theSourceId, MdmMatchResultEnum theMdmMatchResultEnum, MdmLinkSourceEnum theMdmLinkSourceEnum, String version, Date theCreateTime, Date theUpdateTime, boolean theLinkCreatedNewResource, double theScore) {
|
private MdmLinkJson getExepctedMdmLinkJson(Long theGoldenPatientId, Long theSourceId, MdmMatchResultEnum theMdmMatchResultEnum, MdmLinkSourceEnum theMdmLinkSourceEnum, String version, Date theCreateTime, Date theUpdateTime, boolean theLinkCreatedNewResource, Long theVector, double theScore) {
|
||||||
final MdmLinkJson mdmLinkJson = new MdmLinkJson();
|
final MdmLinkJson mdmLinkJson = new MdmLinkJson();
|
||||||
|
|
||||||
mdmLinkJson.setGoldenResourceId("Patient/" + theGoldenPatientId);
|
mdmLinkJson.setGoldenResourceId("Patient/" + theGoldenPatientId);
|
||||||
@ -121,6 +123,7 @@ public class MdmModelConverterSvcImplTest extends BaseMdmR4Test {
|
|||||||
|
|
||||||
// make sure vector is not converted
|
// make sure vector is not converted
|
||||||
mdmLinkJson.setVector(null);
|
mdmLinkJson.setVector(null);
|
||||||
|
mdmLinkJson.translateAndSetRule(myMdmSettings.getMdmRules(), theVector);
|
||||||
|
|
||||||
return mdmLinkJson;
|
return mdmLinkJson;
|
||||||
}
|
}
|
||||||
|
@ -90,4 +90,17 @@ public class MdmHistorySearchParameters {
|
|||||||
return MdmControllerUtil.extractGoldenResourceIdDtOrNull(
|
return MdmControllerUtil.extractGoldenResourceIdDtOrNull(
|
||||||
ProviderConstants.MDM_QUERY_LINKS_GOLDEN_RESOURCE_ID, theTheGoldenResourceId);
|
ProviderConstants.MDM_QUERY_LINKS_GOLDEN_RESOURCE_ID, theTheGoldenResourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum SearchOperatorEnum {
|
||||||
|
/**
|
||||||
|
* Used to indicate we should perform an OR search between all IDs provided
|
||||||
|
* ie. links only need at least 1 of the IDs provided in the search parameters
|
||||||
|
*/
|
||||||
|
OR,
|
||||||
|
/**
|
||||||
|
* Used to indicate we should perform an AND search between all IDs provided
|
||||||
|
* ie. links must contain all IDs provided in the search parameters
|
||||||
|
*/
|
||||||
|
AND
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,13 +21,17 @@ package ca.uhn.fhir.mdm.model.mdmevents;
|
|||||||
|
|
||||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||||
|
import ca.uhn.fhir.mdm.rules.json.MdmRulesJson;
|
||||||
import ca.uhn.fhir.model.api.IModelJson;
|
import ca.uhn.fhir.model.api.IModelJson;
|
||||||
import ca.uhn.fhir.rest.api.server.storage.IResourcePersistentId;
|
import ca.uhn.fhir.rest.api.server.storage.IResourcePersistentId;
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class MdmLinkJson implements IModelJson {
|
public class MdmLinkJson implements IModelJson {
|
||||||
|
|
||||||
@ -97,6 +101,14 @@ public class MdmLinkJson implements IModelJson {
|
|||||||
@JsonProperty("ruleCount")
|
@JsonProperty("ruleCount")
|
||||||
private Long myRuleCount;
|
private Long myRuleCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matched rules are the rules, as defined in the matchResultMap, that evaluated true
|
||||||
|
* for this link. This property stores the name of the rule, represented by a String,
|
||||||
|
* and the corresponding MatchResultEnum for that rule.
|
||||||
|
*/
|
||||||
|
@JsonProperty(value = "matchedRules")
|
||||||
|
private Set<Map.Entry<String, MdmMatchResultEnum>> myRule = new HashSet<>();
|
||||||
|
|
||||||
public String getGoldenResourceId() {
|
public String getGoldenResourceId() {
|
||||||
return myGoldenResourceId;
|
return myGoldenResourceId;
|
||||||
}
|
}
|
||||||
@ -204,6 +216,14 @@ public class MdmLinkJson implements IModelJson {
|
|||||||
myRuleCount = theRuleCount;
|
myRuleCount = theRuleCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Set<Map.Entry<String, MdmMatchResultEnum>> getRule() {
|
||||||
|
return myRule;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void translateAndSetRule(MdmRulesJson theRule, Long theVector) {
|
||||||
|
myRule = theRule.getMatchedRulesFromVectorMap(theVector);
|
||||||
|
}
|
||||||
|
|
||||||
public IResourcePersistentId<?> getGoldenPid() {
|
public IResourcePersistentId<?> getGoldenPid() {
|
||||||
return myGoldenPid;
|
return myGoldenPid;
|
||||||
}
|
}
|
||||||
|
@ -21,10 +21,12 @@ package ca.uhn.fhir.mdm.provider;
|
|||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.i18n.Msg;
|
import ca.uhn.fhir.i18n.Msg;
|
||||||
|
import ca.uhn.fhir.mdm.api.IMdmControllerSvc;
|
||||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||||
import ca.uhn.fhir.mdm.api.paging.MdmPageLinkBuilder;
|
import ca.uhn.fhir.mdm.api.paging.MdmPageLinkBuilder;
|
||||||
import ca.uhn.fhir.mdm.api.paging.MdmPageLinkTuple;
|
import ca.uhn.fhir.mdm.api.paging.MdmPageLinkTuple;
|
||||||
import ca.uhn.fhir.mdm.api.paging.MdmPageRequest;
|
import ca.uhn.fhir.mdm.api.paging.MdmPageRequest;
|
||||||
|
import ca.uhn.fhir.mdm.api.params.MdmHistorySearchParameters;
|
||||||
import ca.uhn.fhir.mdm.model.MdmTransactionContext;
|
import ca.uhn.fhir.mdm.model.MdmTransactionContext;
|
||||||
import ca.uhn.fhir.mdm.model.mdmevents.MdmLinkJson;
|
import ca.uhn.fhir.mdm.model.mdmevents.MdmLinkJson;
|
||||||
import ca.uhn.fhir.mdm.model.mdmevents.MdmLinkWithRevisionJson;
|
import ca.uhn.fhir.mdm.model.mdmevents.MdmLinkWithRevisionJson;
|
||||||
@ -44,16 +46,21 @@ import org.springframework.data.domain.Page;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public abstract class BaseMdmProvider {
|
public abstract class BaseMdmProvider {
|
||||||
|
|
||||||
protected final FhirContext myFhirContext;
|
protected final FhirContext myFhirContext;
|
||||||
|
protected final IMdmControllerSvc myMdmControllerSvc;
|
||||||
|
|
||||||
public BaseMdmProvider(FhirContext theFhirContext) {
|
public BaseMdmProvider(FhirContext theFhirContext, IMdmControllerSvc theMdmControllerSvc) {
|
||||||
myFhirContext = theFhirContext;
|
myFhirContext = theFhirContext;
|
||||||
|
myMdmControllerSvc = theMdmControllerSvc;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void validateMergeParameters(
|
protected void validateMergeParameters(
|
||||||
@ -214,7 +221,9 @@ public abstract class BaseMdmProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void parametersFromMdmLinkRevisions(
|
protected void parametersFromMdmLinkRevisions(
|
||||||
IBaseParameters theRetVal, List<MdmLinkWithRevisionJson> theMdmLinkRevisions) {
|
IBaseParameters theRetVal,
|
||||||
|
List<MdmLinkWithRevisionJson> theMdmLinkRevisions,
|
||||||
|
ServletRequestDetails theRequestDetails) {
|
||||||
if (theMdmLinkRevisions.isEmpty()) {
|
if (theMdmLinkRevisions.isEmpty()) {
|
||||||
final IBase resultPart = ParametersUtil.addParameterToParameters(
|
final IBase resultPart = ParametersUtil.addParameterToParameters(
|
||||||
myFhirContext, theRetVal, "historical links not found for query parameters");
|
myFhirContext, theRetVal, "historical links not found for query parameters");
|
||||||
@ -223,26 +232,72 @@ public abstract class BaseMdmProvider {
|
|||||||
myFhirContext, resultPart, "theResults", "historical links not found for query parameters");
|
myFhirContext, resultPart, "theResults", "historical links not found for query parameters");
|
||||||
}
|
}
|
||||||
|
|
||||||
theMdmLinkRevisions.forEach(mdmLinkRevision -> parametersFromMdmLinkRevision(theRetVal, mdmLinkRevision));
|
theMdmLinkRevisions.forEach(mdmLinkRevision -> parametersFromMdmLinkRevision(
|
||||||
|
theRetVal,
|
||||||
|
mdmLinkRevision,
|
||||||
|
findInitialMatchResult(theMdmLinkRevisions, mdmLinkRevision, theRequestDetails)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parametersFromMdmLinkRevision(IBaseParameters retVal, MdmLinkWithRevisionJson mdmLinkRevision) {
|
private MdmMatchResultEnum findInitialMatchResult(
|
||||||
final IBase resultPart = ParametersUtil.addParameterToParameters(myFhirContext, retVal, "historical link");
|
List<MdmLinkWithRevisionJson> theRevisionList,
|
||||||
final MdmLinkJson mdmLink = mdmLinkRevision.getMdmLink();
|
MdmLinkWithRevisionJson theToMatch,
|
||||||
|
ServletRequestDetails theRequestDetails) {
|
||||||
|
String sourceId = theToMatch.getMdmLink().getSourceId();
|
||||||
|
String goldenId = theToMatch.getMdmLink().getGoldenResourceId();
|
||||||
|
|
||||||
|
// In the REDIRECT case, both the goldenResourceId and sourceResourceId fields are actually both
|
||||||
|
// golden resources. Because of this, based on our history query, it's possible not all links
|
||||||
|
// involving that golden resource will show up in the results (eg. query for goldenResourceId = GR/1
|
||||||
|
// but sourceResourceId = GR/1 in the link history). Hence, we should re-query to find the initial
|
||||||
|
// match result.
|
||||||
|
if (theToMatch.getMdmLink().getMatchResult() == MdmMatchResultEnum.REDIRECT) {
|
||||||
|
MdmHistorySearchParameters params = new MdmHistorySearchParameters()
|
||||||
|
.setSourceIds(List.of(sourceId, goldenId))
|
||||||
|
.setGoldenResourceIds(List.of(sourceId, goldenId));
|
||||||
|
|
||||||
|
List<MdmLinkWithRevisionJson> result = myMdmControllerSvc.queryLinkHistory(params, theRequestDetails);
|
||||||
|
// If there is a POSSIBLE_DUPLICATE, a user merged two resources with *pre-existing* POSSIBLE_DUPLICATE link
|
||||||
|
// so the initial match result is POSSIBLE_DUPLICATE
|
||||||
|
// If no POSSIBLE_DUPLICATE, a user merged two *unlinked* GRs, so the initial match result is REDIRECT
|
||||||
|
return containsPossibleDuplicate(result)
|
||||||
|
? MdmMatchResultEnum.POSSIBLE_DUPLICATE
|
||||||
|
: MdmMatchResultEnum.REDIRECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get first match result with given source and golden ID
|
||||||
|
Optional<MdmLinkWithRevisionJson> theEarliestRevision = theRevisionList.stream()
|
||||||
|
.filter(revision -> revision.getMdmLink().getSourceId().equals(sourceId))
|
||||||
|
.filter(revision -> revision.getMdmLink().getGoldenResourceId().equals(goldenId))
|
||||||
|
.min(Comparator.comparing(MdmLinkWithRevisionJson::getRevisionNumber));
|
||||||
|
|
||||||
|
return theEarliestRevision.isPresent()
|
||||||
|
? theEarliestRevision.get().getMdmLink().getMatchResult()
|
||||||
|
: theToMatch.getMdmLink().getMatchResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean containsPossibleDuplicate(List<MdmLinkWithRevisionJson> result) {
|
||||||
|
return result.stream().anyMatch(t -> t.getMdmLink().getMatchResult() == MdmMatchResultEnum.POSSIBLE_DUPLICATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parametersFromMdmLinkRevision(
|
||||||
|
IBaseParameters theRetVal,
|
||||||
|
MdmLinkWithRevisionJson theMdmLinkRevision,
|
||||||
|
MdmMatchResultEnum theInitialAutoResult) {
|
||||||
|
final IBase resultPart = ParametersUtil.addParameterToParameters(myFhirContext, theRetVal, "historical link");
|
||||||
|
final MdmLinkJson mdmLink = theMdmLinkRevision.getMdmLink();
|
||||||
|
|
||||||
ParametersUtil.addPartString(myFhirContext, resultPart, "goldenResourceId", mdmLink.getGoldenResourceId());
|
ParametersUtil.addPartString(myFhirContext, resultPart, "goldenResourceId", mdmLink.getGoldenResourceId());
|
||||||
ParametersUtil.addPartString(
|
ParametersUtil.addPartString(
|
||||||
myFhirContext,
|
myFhirContext,
|
||||||
resultPart,
|
resultPart,
|
||||||
"revisionTimestamp",
|
"revisionTimestamp",
|
||||||
mdmLinkRevision.getRevisionTimestamp().toString());
|
theMdmLinkRevision.getRevisionTimestamp().toString());
|
||||||
ParametersUtil.addPartString(myFhirContext, resultPart, "sourceResourceId", mdmLink.getSourceId());
|
ParametersUtil.addPartString(myFhirContext, resultPart, "sourceResourceId", mdmLink.getSourceId());
|
||||||
ParametersUtil.addPartString(
|
ParametersUtil.addPartString(
|
||||||
myFhirContext,
|
myFhirContext,
|
||||||
resultPart,
|
resultPart,
|
||||||
"matchResult",
|
"matchResult",
|
||||||
mdmLink.getMatchResult().name());
|
mdmLink.getMatchResult().name());
|
||||||
ParametersUtil.addPartDecimal(myFhirContext, resultPart, "score", mdmLink.getScore());
|
|
||||||
ParametersUtil.addPartString(
|
ParametersUtil.addPartString(
|
||||||
myFhirContext, resultPart, "linkSource", mdmLink.getLinkSource().name());
|
myFhirContext, resultPart, "linkSource", mdmLink.getLinkSource().name());
|
||||||
ParametersUtil.addPartBoolean(myFhirContext, resultPart, "eidMatch", mdmLink.getEidMatch());
|
ParametersUtil.addPartBoolean(myFhirContext, resultPart, "eidMatch", mdmLink.getEidMatch());
|
||||||
@ -253,6 +308,16 @@ public abstract class BaseMdmProvider {
|
|||||||
mdmLink.getCreated().getTime());
|
mdmLink.getCreated().getTime());
|
||||||
ParametersUtil.addPartDecimal(myFhirContext, resultPart, "linkUpdated", (double)
|
ParametersUtil.addPartDecimal(myFhirContext, resultPart, "linkUpdated", (double)
|
||||||
mdmLink.getUpdated().getTime());
|
mdmLink.getUpdated().getTime());
|
||||||
|
|
||||||
|
IBase matchResultMapSubpart = ParametersUtil.createPart(myFhirContext, resultPart, "matchResultMap");
|
||||||
|
|
||||||
|
IBase matchedRulesSubpart = ParametersUtil.createPart(myFhirContext, matchResultMapSubpart, "matchedRules");
|
||||||
|
for (Map.Entry<String, MdmMatchResultEnum> entry : mdmLink.getRule()) {
|
||||||
|
ParametersUtil.addPartString(myFhirContext, matchedRulesSubpart, "rule", entry.getKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
ParametersUtil.addPartString(
|
||||||
|
myFhirContext, matchResultMapSubpart, "initialMatchResult", theInitialAutoResult.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addPagingParameters(
|
protected void addPagingParameters(
|
||||||
|
@ -48,16 +48,13 @@ import static org.slf4j.LoggerFactory.getLogger;
|
|||||||
public class MdmLinkHistoryProviderDstu3Plus extends BaseMdmProvider {
|
public class MdmLinkHistoryProviderDstu3Plus extends BaseMdmProvider {
|
||||||
private static final Logger ourLog = getLogger(MdmLinkHistoryProviderDstu3Plus.class);
|
private static final Logger ourLog = getLogger(MdmLinkHistoryProviderDstu3Plus.class);
|
||||||
|
|
||||||
private final IMdmControllerSvc myMdmControllerSvc;
|
|
||||||
|
|
||||||
private final IInterceptorBroadcaster myInterceptorBroadcaster;
|
private final IInterceptorBroadcaster myInterceptorBroadcaster;
|
||||||
|
|
||||||
public MdmLinkHistoryProviderDstu3Plus(
|
public MdmLinkHistoryProviderDstu3Plus(
|
||||||
FhirContext theFhirContext,
|
FhirContext theFhirContext,
|
||||||
IMdmControllerSvc theMdmControllerSvc,
|
IMdmControllerSvc theMdmControllerSvc,
|
||||||
IInterceptorBroadcaster theIInterceptorBroadcaster) {
|
IInterceptorBroadcaster theIInterceptorBroadcaster) {
|
||||||
super(theFhirContext);
|
super(theFhirContext, theMdmControllerSvc);
|
||||||
myMdmControllerSvc = theMdmControllerSvc;
|
|
||||||
myInterceptorBroadcaster = theIInterceptorBroadcaster;
|
myInterceptorBroadcaster = theIInterceptorBroadcaster;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,7 +90,7 @@ public class MdmLinkHistoryProviderDstu3Plus extends BaseMdmProvider {
|
|||||||
final List<MdmLinkWithRevisionJson> mdmLinkRevisionsFromSvc =
|
final List<MdmLinkWithRevisionJson> mdmLinkRevisionsFromSvc =
|
||||||
myMdmControllerSvc.queryLinkHistory(mdmHistorySearchParameters, theRequestDetails);
|
myMdmControllerSvc.queryLinkHistory(mdmHistorySearchParameters, theRequestDetails);
|
||||||
|
|
||||||
parametersFromMdmLinkRevisions(retVal, mdmLinkRevisionsFromSvc);
|
parametersFromMdmLinkRevisions(retVal, mdmLinkRevisionsFromSvc, theRequestDetails);
|
||||||
|
|
||||||
if (myInterceptorBroadcaster.hasHooks(Pointcut.MDM_POST_LINK_HISTORY)) {
|
if (myInterceptorBroadcaster.hasHooks(Pointcut.MDM_POST_LINK_HISTORY)) {
|
||||||
// MDM_POST_LINK_HISTORY hook
|
// MDM_POST_LINK_HISTORY hook
|
||||||
|
@ -74,7 +74,6 @@ public class MdmProviderDstu3Plus extends BaseMdmProvider {
|
|||||||
private static final String PATIENT_RESOURCE = "Patient";
|
private static final String PATIENT_RESOURCE = "Patient";
|
||||||
private static final String PRACTITIONER_RESOURCE = "Practitioner";
|
private static final String PRACTITIONER_RESOURCE = "Practitioner";
|
||||||
|
|
||||||
private final IMdmControllerSvc myMdmControllerSvc;
|
|
||||||
private final IMdmSubmitSvc myMdmSubmitSvc;
|
private final IMdmSubmitSvc myMdmSubmitSvc;
|
||||||
private final IMdmSettings myMdmSettings;
|
private final IMdmSettings myMdmSettings;
|
||||||
private final MdmControllerHelper myMdmControllerHelper;
|
private final MdmControllerHelper myMdmControllerHelper;
|
||||||
@ -97,8 +96,7 @@ public class MdmProviderDstu3Plus extends BaseMdmProvider {
|
|||||||
IMdmSubmitSvc theMdmSubmitSvc,
|
IMdmSubmitSvc theMdmSubmitSvc,
|
||||||
IInterceptorBroadcaster theIInterceptorBroadcaster,
|
IInterceptorBroadcaster theIInterceptorBroadcaster,
|
||||||
IMdmSettings theIMdmSettings) {
|
IMdmSettings theIMdmSettings) {
|
||||||
super(theFhirContext);
|
super(theFhirContext, theMdmControllerSvc);
|
||||||
myMdmControllerSvc = theMdmControllerSvc;
|
|
||||||
myMdmControllerHelper = theMdmHelper;
|
myMdmControllerHelper = theMdmHelper;
|
||||||
myMdmSubmitSvc = theMdmSubmitSvc;
|
myMdmSubmitSvc = theMdmSubmitSvc;
|
||||||
myInterceptorBroadcaster = theIInterceptorBroadcaster;
|
myInterceptorBroadcaster = theIInterceptorBroadcaster;
|
||||||
|
@ -33,6 +33,8 @@ import java.util.Collections;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static ca.uhn.fhir.mdm.api.MdmConstants.ALL_RESOURCE_SEARCH_PARAM_TYPE;
|
import static ca.uhn.fhir.mdm.api.MdmConstants.ALL_RESOURCE_SEARCH_PARAM_TYPE;
|
||||||
|
|
||||||
@ -207,6 +209,13 @@ public class MdmRulesJson implements IModelJson {
|
|||||||
return myVectorMatchResultMap.getFieldMatchNames(theVector);
|
return myVectorMatchResultMap.getFieldMatchNames(theVector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Set<Map.Entry<String, MdmMatchResultEnum>> getMatchedRulesFromVectorMap(Long theLong) {
|
||||||
|
Set<String> matchedRules = myVectorMatchResultMap.getMatchedRules(theLong);
|
||||||
|
return myMatchResultMap.entrySet().stream()
|
||||||
|
.filter(e -> matchedRules.contains(e.getKey()))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
public String getDetailedFieldMatchResultWithSuccessInformation(long theVector) {
|
public String getDetailedFieldMatchResultWithSuccessInformation(long theVector) {
|
||||||
List<String> fieldMatchResult = new ArrayList<>();
|
List<String> fieldMatchResult = new ArrayList<>();
|
||||||
for (int i = 0; i < myMatchFieldJsonList.size(); ++i) {
|
for (int i = 0; i < myMatchFieldJsonList.size(); ++i) {
|
||||||
|
@ -28,6 +28,7 @@ import java.util.HashMap;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class VectorMatchResultMap {
|
public class VectorMatchResultMap {
|
||||||
private final MdmRulesJson myMdmRulesJson;
|
private final MdmRulesJson myMdmRulesJson;
|
||||||
@ -64,6 +65,16 @@ public class VectorMatchResultMap {
|
|||||||
return MdmMatchResultEnum.NO_MATCH;
|
return MdmMatchResultEnum.NO_MATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Set<String> getMatchedRules(Long theVector) {
|
||||||
|
if (theVector == null) {
|
||||||
|
return new HashSet<>();
|
||||||
|
}
|
||||||
|
return myVectorToFieldMatchNamesMap.entrySet().stream()
|
||||||
|
.filter(e -> ((e.getKey() & theVector) == e.getKey()))
|
||||||
|
.map(Map.Entry::getValue)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
private void put(String theFieldMatchNames, MdmMatchResultEnum theMatchResult) {
|
private void put(String theFieldMatchNames, MdmMatchResultEnum theMatchResult) {
|
||||||
long vector = getVector(theFieldMatchNames);
|
long vector = getVector(theFieldMatchNames);
|
||||||
myVectorToFieldMatchNamesMap.put(vector, theFieldMatchNames);
|
myVectorToFieldMatchNamesMap.put(vector, theFieldMatchNames);
|
||||||
@ -104,4 +115,10 @@ public class VectorMatchResultMap {
|
|||||||
public String getFieldMatchNames(long theVector) {
|
public String getFieldMatchNames(long theVector) {
|
||||||
return myVectorToFieldMatchNamesMap.get(theVector);
|
return myVectorToFieldMatchNamesMap.get(theVector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Set<String> getAllFieldMatchNames() {
|
||||||
|
return myVectorToFieldMatchNamesMap.keySet().stream()
|
||||||
|
.map(key -> myVectorToFieldMatchNamesMap.get(key))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user