Removed person refs
This commit is contained in:
parent
417ae55cb4
commit
ffee7a894f
|
@ -53,7 +53,6 @@ public class MdmLink {
|
|||
private static final int LINK_SOURCE_LENGTH = 16;
|
||||
public static final int TARGET_TYPE_LENGTH = 40;
|
||||
|
||||
|
||||
@SequenceGenerator(name = "SEQ_EMPI_LINK_ID", sequenceName = "SEQ_EMPI_LINK_ID")
|
||||
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_EMPI_LINK_ID")
|
||||
@Id
|
||||
|
|
|
@ -44,6 +44,7 @@ import org.springframework.stereotype.Service;
|
|||
|
||||
@Service
|
||||
public class MdmMessageHandler implements MessageHandler {
|
||||
|
||||
private static final Logger ourLog = Logs.getMdmTroubleshootingLog();
|
||||
|
||||
@Autowired
|
||||
|
@ -76,7 +77,8 @@ public class MdmMessageHandler implements MessageHandler {
|
|||
throw e;
|
||||
}
|
||||
}
|
||||
public void matchMdmAndUpdateLinks(ResourceModifiedMessage theMsg) {
|
||||
|
||||
private void matchMdmAndUpdateLinks(ResourceModifiedMessage theMsg) {
|
||||
String resourceType = theMsg.getId(myFhirContext).getResourceType();
|
||||
validateResourceType(resourceType);
|
||||
MdmTransactionContext mdmContext = createMdmContext(theMsg, resourceType);
|
||||
|
|
|
@ -128,7 +128,7 @@ public class MdmConsumerConfig {
|
|||
}
|
||||
|
||||
@Bean
|
||||
MdmGoldenResourceFindingSvc mdmPersonFindingSvc() {
|
||||
MdmGoldenResourceFindingSvc mdmGoldenResourceFindingSvc() {
|
||||
return new MdmGoldenResourceFindingSvc();
|
||||
}
|
||||
|
||||
|
@ -163,7 +163,7 @@ public class MdmConsumerConfig {
|
|||
}
|
||||
|
||||
@Bean
|
||||
IGoldenResourceMergerSvc mdmPersonMergerSvc() {
|
||||
IGoldenResourceMergerSvc mdmGoldenResourceMergerSvc() {
|
||||
return new GoldenResourceMergerSvcImpl();
|
||||
}
|
||||
|
||||
|
|
|
@ -33,32 +33,34 @@ import org.springframework.stereotype.Service;
|
|||
|
||||
@Service
|
||||
public class MdmSearchParameterLoader {
|
||||
|
||||
public static final String MDM_PERSON_ASSURANCE_SEARCH_PARAMETER_ID = "person-assurance";
|
||||
public static final String MDM_PERSON_ACTIVE_SEARCH_PARAMETER_ID = "person-active";
|
||||
|
||||
@Autowired
|
||||
public FhirContext myFhirContext;
|
||||
@Autowired
|
||||
public DaoRegistry myDaoRegistry;
|
||||
|
||||
synchronized public void daoUpdateMdmSearchParameters() {
|
||||
IBaseResource personAssurance;
|
||||
IBaseResource personActive;
|
||||
IBaseResource goldenResourceAssurance;
|
||||
IBaseResource goldenResourceActive;
|
||||
switch (myFhirContext.getVersion().getVersion()) {
|
||||
case DSTU3:
|
||||
personAssurance = buildAssuranceMdmSearchParameterDstu3();
|
||||
personActive = buildActiveMdmSearchParameterDstu3();
|
||||
goldenResourceAssurance = buildAssuranceMdmSearchParameterDstu3();
|
||||
goldenResourceActive = buildActiveMdmSearchParameterDstu3();
|
||||
break;
|
||||
case R4:
|
||||
personAssurance = buildAssuranceMdmSearchParameterR4();
|
||||
personActive = buildActiveMdmSearchParameterR4();
|
||||
goldenResourceAssurance = buildAssuranceMdmSearchParameterR4();
|
||||
goldenResourceActive = buildActiveMdmSearchParameterR4();
|
||||
break;
|
||||
default:
|
||||
throw new ConfigurationException("MDM not supported for FHIR version " + myFhirContext.getVersion().getVersion());
|
||||
}
|
||||
|
||||
IFhirResourceDao<IBaseResource> searchParameterDao = myDaoRegistry.getResourceDao("SearchParameter");
|
||||
searchParameterDao.update(personAssurance);
|
||||
searchParameterDao.update(personActive);
|
||||
searchParameterDao.update(goldenResourceAssurance);
|
||||
searchParameterDao.update(goldenResourceActive);
|
||||
}
|
||||
|
||||
private org.hl7.fhir.dstu3.model.SearchParameter buildAssuranceMdmSearchParameterDstu3() {
|
||||
|
|
|
@ -21,14 +21,14 @@ package ca.uhn.fhir.jpa.mdm.dao;
|
|||
*/
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.dao.data.IMdmLinkDao;
|
||||
import ca.uhn.fhir.jpa.dao.index.IdHelperService;
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchOutcome;
|
||||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||
import ca.uhn.fhir.mdm.log.Logs;
|
||||
import ca.uhn.fhir.mdm.model.MdmTransactionContext;
|
||||
import ca.uhn.fhir.jpa.dao.data.IMdmLinkDao;
|
||||
import ca.uhn.fhir.jpa.dao.index.IdHelperService;
|
||||
import ca.uhn.fhir.jpa.entity.MdmLink;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.slf4j.Logger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -92,7 +92,6 @@ public class MdmLinkDaoSvc {
|
|||
} else {
|
||||
MdmLink newLink = myMdmLinkFactory.newMdmLink();
|
||||
newLink.setGoldenResourcePid(theGoldenResourcePid);
|
||||
newLink.setPersonPid(theGoldenResourcePid);
|
||||
newLink.setTargetPid(theTargetResourcePid);
|
||||
return newLink;
|
||||
}
|
||||
|
@ -160,16 +159,16 @@ public class MdmLinkDaoSvc {
|
|||
}
|
||||
|
||||
/**
|
||||
* Given a person a target and a match result, return the matching {@link MdmLink}, if it exists.
|
||||
* Given a golden resource a target and a match result, return the matching {@link MdmLink}, if it exists.
|
||||
*
|
||||
* @param thePersonPid The Pid of the Person in the relationship
|
||||
* @param theGoldenResourcePid The Pid of the Golden Resource in the relationship
|
||||
* @param theTargetPid The Pid of the target in the relationship
|
||||
* @param theMatchResult The MatchResult you are looking for.
|
||||
* @return an Optional {@link MdmLink} containing the matched link if it exists.
|
||||
*/
|
||||
public Optional<MdmLink> getMdmLinksByPersonPidTargetPidAndMatchResult(Long thePersonPid, Long theTargetPid, MdmMatchResultEnum theMatchResult) {
|
||||
public Optional<MdmLink> getMdmLinksByGoldenResourcePidTargetPidAndMatchResult(Long theGoldenResourcePid, Long theTargetPid, MdmMatchResultEnum theMatchResult) {
|
||||
MdmLink exampleLink = myMdmLinkFactory.newMdmLink();
|
||||
exampleLink.setGoldenResourcePid(thePersonPid);
|
||||
exampleLink.setGoldenResourcePid(theGoldenResourcePid);
|
||||
exampleLink.setTargetPid(theTargetPid);
|
||||
exampleLink.setMatchResult(theMatchResult);
|
||||
Example<MdmLink> example = Example.of(exampleLink);
|
||||
|
@ -179,7 +178,7 @@ public class MdmLinkDaoSvc {
|
|||
/**
|
||||
* Get all {@link MdmLink} which have {@link MdmMatchResultEnum#POSSIBLE_DUPLICATE} as their match result.
|
||||
*
|
||||
* @return A list of {@link MdmLink} that hold potential duplicate persons.
|
||||
* @return A list of {@link MdmLink} that hold potential duplicate golden resources.
|
||||
*/
|
||||
public List<MdmLink> getPossibleDuplicates() {
|
||||
MdmLink exampleLink = myMdmLinkFactory.newMdmLink();
|
||||
|
@ -210,10 +209,10 @@ public class MdmLinkDaoSvc {
|
|||
}
|
||||
|
||||
/**
|
||||
* Given a Golden Resource , return all links in which they are the source Person of the {@link MdmLink}
|
||||
* Given a Golden Resource, return all links in which they are the source Golden Resource of the {@link MdmLink}
|
||||
*
|
||||
* @param theGoldenResource The {@link IBaseResource} Person who's links you would like to retrieve.
|
||||
* @return A list of all {@link MdmLink} entities in which theGoldenResource is the source Person.
|
||||
* @param theGoldenResource The {@link IBaseResource} Golden Resource who's links you would like to retrieve.
|
||||
* @return A list of all {@link MdmLink} entities in which theGoldenResource is the source Golden Resource
|
||||
*/
|
||||
public List<MdmLink> findMdmLinksByGoldenResource(IBaseResource theGoldenResource) {
|
||||
Long pid = myIdHelperService.getPidOrNull(theGoldenResource);
|
||||
|
@ -228,7 +227,7 @@ public class MdmLinkDaoSvc {
|
|||
/**
|
||||
* Delete all {@link MdmLink} entities, and return all resource PIDs from the source of the relationship.
|
||||
*
|
||||
* @return A list of Long representing the related Person Pids.
|
||||
* @return A list of Long representing the related Golden Resource Pids.
|
||||
*/
|
||||
@Transactional
|
||||
public List<Long> deleteAllMdmLinksAndReturnGoldenResourcePids() {
|
||||
|
@ -237,26 +236,26 @@ public class MdmLinkDaoSvc {
|
|||
}
|
||||
|
||||
private List<Long> deleteMdmLinksAndReturnGoldenResourcePids(List<MdmLink> theLinks) {
|
||||
Set<Long> persons = theLinks.stream().map(MdmLink::getGoldenResourcePid).collect(Collectors.toSet());
|
||||
Set<Long> goldenResources = theLinks.stream().map(MdmLink::getGoldenResourcePid).collect(Collectors.toSet());
|
||||
//TODO GGG this is probably invalid... we are essentially looking for GOLDEN -> GOLDEN links, which are either POSSIBLE_DUPLICATE
|
||||
//and REDIRECT
|
||||
//persons.addAll(theLinks.stream().filter(link -> "Person".equals(link.getEmpiTargetType())).map(EmpiLink::getTargetPid).collect(Collectors.toSet()));
|
||||
persons.addAll(theLinks.stream()
|
||||
//goldenResources.addAll(theLinks.stream().filter(link -> "Person".equals(link.getEmpiTargetType())).map(EmpiLink::getTargetPid).collect(Collectors.toSet()));
|
||||
goldenResources.addAll(theLinks.stream()
|
||||
.filter(link -> link.getMatchResult().equals(MdmMatchResultEnum.REDIRECT)
|
||||
|| link.getMatchResult().equals(MdmMatchResultEnum.POSSIBLE_DUPLICATE))
|
||||
.map(MdmLink::getTargetPid).collect(Collectors.toSet()));
|
||||
ourLog.info("Deleting {} MDM link records...", theLinks.size());
|
||||
myMdmLinkDao.deleteAll(theLinks);
|
||||
ourLog.info("{} MDM link records deleted", theLinks.size());
|
||||
return new ArrayList<>(persons);
|
||||
return new ArrayList<>(goldenResources);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a valid {@link String}, delete all {@link MdmLink} entities for that type, and get the Pids
|
||||
* for the Person resources which were the sources of the links.
|
||||
* for the Golden Resources which were the sources of the links.
|
||||
*
|
||||
* @param theTargetType the type of relationship you would like to delete.
|
||||
* @return A list of longs representing the Pids of the Person resources used as the sources of the relationships that were deleted.
|
||||
* @return A list of longs representing the Pids of the Golden Resources resources used as the sources of the relationships that were deleted.
|
||||
*/
|
||||
public List<Long> deleteAllMdmLinksOfTypeAndReturnGoldenResourcePids(String theTargetType) {
|
||||
MdmLink link = new MdmLink();
|
||||
|
|
|
@ -78,8 +78,7 @@ public class MdmStorageInterceptor implements IMdmStorageInterceptor {
|
|||
}
|
||||
|
||||
@Hook(Pointcut.STORAGE_PRESTORAGE_RESOURCE_UPDATED)
|
||||
public void blockManualPersonManipulationOnUpdate(IBaseResource theOldResource, IBaseResource theUpdatedResource, RequestDetails theRequestDetails, ServletRequestDetails theServletRequestDetails) {
|
||||
|
||||
public void blockManualGoldenResourceManipulationOnUpdate(IBaseResource theOldResource, IBaseResource theUpdatedResource, RequestDetails theRequestDetails, ServletRequestDetails theServletRequestDetails) {
|
||||
//If running in single EID mode, forbid multiple eids.
|
||||
if (myMdmSettings.isPreventMultipleEids()) {
|
||||
forbidIfHasMultipleEids(theUpdatedResource);
|
||||
|
@ -87,7 +86,7 @@ public class MdmStorageInterceptor implements IMdmStorageInterceptor {
|
|||
|
||||
//TODO GGG MDM: Check if this is actually handled already in mdm update code or not.
|
||||
if (myGoldenResourceHelper.isDeactivated(theUpdatedResource)) {
|
||||
ourLog.debug("Deleting MDM links to deactivated Person {}", theUpdatedResource.getIdElement().toUnqualifiedVersionless());
|
||||
ourLog.debug("Deleting MDM links to deactivated Golden resource {}", theUpdatedResource.getIdElement().toUnqualifiedVersionless());
|
||||
int deleted = myMdmLinkDeleteSvc.deleteNonRedirectWithWithAnyReferenceTo(theUpdatedResource);
|
||||
if (deleted > 0) {
|
||||
ourLog.debug("Deleted {} MDM links", deleted);
|
||||
|
|
|
@ -34,8 +34,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This class is responsible for clearing out existing MDM links, as well as deleting all persons related to those MDM Links.
|
||||
*
|
||||
* This class is responsible for clearing out existing MDM links, as well as deleting all Golden Resources related to those MDM Links.
|
||||
*/
|
||||
public class MdmClearSvcImpl implements IMdmExpungeSvc {
|
||||
private static final Logger ourLog = Logs.getMdmTroubleshootingLog();
|
||||
|
@ -55,10 +54,10 @@ public class MdmClearSvcImpl implements IMdmExpungeSvc {
|
|||
public long expungeAllMdmLinksOfTargetType(String theResourceType, ServletRequestDetails theRequestDetails) {
|
||||
throwExceptionIfInvalidTargetType(theResourceType);
|
||||
ourLog.info("Clearing all MDM Links for resource type {}...", theResourceType);
|
||||
List<Long> personPids = myMdmLinkDaoSvc.deleteAllMdmLinksOfTypeAndReturnGoldenResourcePids(theResourceType);
|
||||
DeleteMethodOutcome deleteOutcome = myMdmGoldenResourceDeletingSvcImpl.expungeGoldenResourcePids(personPids, theRequestDetails);
|
||||
ourLog.info("MDM clear operation complete. Removed {} MDM links and {} Person resources.", personPids.size(), deleteOutcome.getExpungedResourcesCount());
|
||||
return personPids.size();
|
||||
List<Long> goldenResourcePids = myMdmLinkDaoSvc.deleteAllMdmLinksOfTypeAndReturnGoldenResourcePids(theResourceType);
|
||||
DeleteMethodOutcome deleteOutcome = myMdmGoldenResourceDeletingSvcImpl.expungeGoldenResourcePids(goldenResourcePids, theResourceType, theRequestDetails);
|
||||
ourLog.info("MDM clear operation complete. Removed {} MDM links and {} Golden Resources.", goldenResourcePids.size(), deleteOutcome.getExpungedResourcesCount());
|
||||
return goldenResourcePids.size();
|
||||
}
|
||||
|
||||
private void throwExceptionIfInvalidTargetType(String theResourceType) {
|
||||
|
@ -70,10 +69,16 @@ public class MdmClearSvcImpl implements IMdmExpungeSvc {
|
|||
@Override
|
||||
public long expungeAllMdmLinks(ServletRequestDetails theRequestDetails) {
|
||||
ourLog.info("Clearing all MDM Links...");
|
||||
long retVal = 0;
|
||||
|
||||
for(String mdmType : myMdmSettings.getMdmRules().getMdmTypes()) {
|
||||
List<Long> goldenResourcePids = myMdmLinkDaoSvc.deleteAllMdmLinksAndReturnGoldenResourcePids();
|
||||
DeleteMethodOutcome deleteOutcome = myMdmGoldenResourceDeletingSvcImpl.expungeGoldenResourcePids(goldenResourcePids, theRequestDetails);
|
||||
ourLog.info("MDM clear operation complete. Removed {} MDM links and expunged {} Golden resources.", goldenResourcePids.size(), deleteOutcome.getExpungedResourcesCount());
|
||||
return goldenResourcePids.size();
|
||||
DeleteMethodOutcome deleteOutcome = myMdmGoldenResourceDeletingSvcImpl.expungeGoldenResourcePids(goldenResourcePids, null, theRequestDetails);
|
||||
ourLog.info("MDM clear operation on type {} complete. Removed {} MDM links and expunged {} Golden resources.", mdmType, goldenResourcePids.size(), deleteOutcome.getExpungedResourcesCount());
|
||||
retVal += goldenResourcePids.size();
|
||||
}
|
||||
ourLog.info("MDM clear complete expunged a total of golden resources.", retVal);
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -54,47 +54,47 @@ public class MdmControllerSvcImpl implements IMdmControllerSvc {
|
|||
IMdmLinkUpdaterSvc myIMdmLinkUpdaterSvc;
|
||||
|
||||
@Override
|
||||
public IAnyResource mergeGoldenResources(String theFromPersonId, String theToPersonId, MdmTransactionContext theMdmTransactionContext) {
|
||||
IAnyResource fromPerson = myMdmControllerHelper.getLatestGoldenResourceFromIdOrThrowException(ProviderConstants.MDM_MERGE_GR_FROM_GOLDEN_RESOURCE_ID, theFromPersonId);
|
||||
IAnyResource toPerson = myMdmControllerHelper.getLatestGoldenResourceFromIdOrThrowException(ProviderConstants.MDM_MERGE_GR_TO_GOLDEN_RESOURCE_ID, theToPersonId);
|
||||
myMdmControllerHelper.validateMergeResources(fromPerson, toPerson);
|
||||
myMdmControllerHelper.validateSameVersion(fromPerson, theFromPersonId);
|
||||
myMdmControllerHelper.validateSameVersion(toPerson, theToPersonId);
|
||||
public IAnyResource mergeGoldenResources(String theFromGoldenResourceId, String theToGoldenResourceId, MdmTransactionContext theMdmTransactionContext) {
|
||||
IAnyResource fromGoldenResource = myMdmControllerHelper.getLatestGoldenResourceFromIdOrThrowException(ProviderConstants.MDM_MERGE_GR_FROM_GOLDEN_RESOURCE_ID, theFromGoldenResourceId);
|
||||
IAnyResource toGoldenResource = myMdmControllerHelper.getLatestGoldenResourceFromIdOrThrowException(ProviderConstants.MDM_MERGE_GR_TO_GOLDEN_RESOURCE_ID, theToGoldenResourceId);
|
||||
myMdmControllerHelper.validateMergeResources(fromGoldenResource, toGoldenResource);
|
||||
myMdmControllerHelper.validateSameVersion(fromGoldenResource, theFromGoldenResourceId);
|
||||
myMdmControllerHelper.validateSameVersion(toGoldenResource, theToGoldenResourceId);
|
||||
|
||||
return myGoldenResourceMergerSvc.mergeGoldenResources(fromPerson, toPerson, theMdmTransactionContext);
|
||||
return myGoldenResourceMergerSvc.mergeGoldenResources(fromGoldenResource, toGoldenResource, theMdmTransactionContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<MdmLinkJson> queryLinks(@Nullable String thePersonId, @Nullable String theTargetId, @Nullable String theMatchResult, @Nullable String theLinkSource, MdmTransactionContext theMdmTransactionContext) {
|
||||
IIdType personId = MdmControllerUtil.extractPersonIdDtOrNull(ProviderConstants.MDM_QUERY_LINKS_GOLDEN_RESOURCE_ID, thePersonId);
|
||||
public Stream<MdmLinkJson> queryLinks(@Nullable String theGoldenResourceId, @Nullable String theTargetId, @Nullable String theMatchResult, @Nullable String theLinkSource, MdmTransactionContext theMdmTransactionContext) {
|
||||
IIdType goldenResourceId = MdmControllerUtil.extractGoldenResourceIdDtOrNull(ProviderConstants.MDM_QUERY_LINKS_GOLDEN_RESOURCE_ID, theGoldenResourceId);
|
||||
IIdType targetId = MdmControllerUtil.extractTargetIdDtOrNull(ProviderConstants.MDM_QUERY_LINKS_RESOURCE_ID, theTargetId);
|
||||
MdmMatchResultEnum matchResult = MdmControllerUtil.extractMatchResultOrNull(theMatchResult);
|
||||
MdmLinkSourceEnum linkSource = MdmControllerUtil.extractLinkSourceOrNull(theLinkSource);
|
||||
|
||||
return myMdmLinkQuerySvc.queryLinks(personId, targetId, matchResult, linkSource, theMdmTransactionContext);
|
||||
return myMdmLinkQuerySvc.queryLinks(goldenResourceId, targetId, matchResult, linkSource, theMdmTransactionContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<MdmLinkJson> getDuplicateGoldenResources(MdmTransactionContext theMdmTransactionContext) {
|
||||
return myMdmLinkQuerySvc.getDuplicatePersons(theMdmTransactionContext);
|
||||
return myMdmLinkQuerySvc.getDuplicateGoldenResources(theMdmTransactionContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAnyResource updateLink(String theGoldenResourceId, String theTargetId, String theMatchResult, MdmTransactionContext theMdmTransactionContext) {
|
||||
MdmMatchResultEnum matchResult = MdmControllerUtil.extractMatchResultOrNull(theMatchResult);
|
||||
IAnyResource person = myMdmControllerHelper.getLatestGoldenResourceFromIdOrThrowException(ProviderConstants.MDM_UPDATE_LINK_GOLDEN_RESOURCE_ID, theGoldenResourceId);
|
||||
IAnyResource goldenResource = myMdmControllerHelper.getLatestGoldenResourceFromIdOrThrowException(ProviderConstants.MDM_UPDATE_LINK_GOLDEN_RESOURCE_ID, theGoldenResourceId);
|
||||
IAnyResource target = myMdmControllerHelper.getLatestTargetFromIdOrThrowException(ProviderConstants.MDM_UPDATE_LINK_RESOURCE_ID, theTargetId);
|
||||
myMdmControllerHelper.validateSameVersion(person, theGoldenResourceId);
|
||||
myMdmControllerHelper.validateSameVersion(goldenResource, theGoldenResourceId);
|
||||
myMdmControllerHelper.validateSameVersion(target, theTargetId);
|
||||
|
||||
return myIMdmLinkUpdaterSvc.updateLink(person, target, matchResult, theMdmTransactionContext);
|
||||
return myIMdmLinkUpdaterSvc.updateLink(goldenResource, target, matchResult, theMdmTransactionContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notDuplicateGoldenResource(String thePersonId, String theTargetPersonId, MdmTransactionContext theMdmTransactionContext) {
|
||||
IAnyResource person = myMdmControllerHelper.getLatestGoldenResourceFromIdOrThrowException(ProviderConstants.MDM_UPDATE_LINK_GOLDEN_RESOURCE_ID, thePersonId);
|
||||
IAnyResource target = myMdmControllerHelper.getLatestGoldenResourceFromIdOrThrowException(ProviderConstants.MDM_UPDATE_LINK_RESOURCE_ID, theTargetPersonId);
|
||||
public void notDuplicateGoldenResource(String theGoldenResourceId, String theTargetGoldenResourceId, MdmTransactionContext theMdmTransactionContext) {
|
||||
IAnyResource goldenResource = myMdmControllerHelper.getLatestGoldenResourceFromIdOrThrowException(ProviderConstants.MDM_UPDATE_LINK_GOLDEN_RESOURCE_ID, theGoldenResourceId);
|
||||
IAnyResource target = myMdmControllerHelper.getLatestGoldenResourceFromIdOrThrowException(ProviderConstants.MDM_UPDATE_LINK_RESOURCE_ID, theTargetGoldenResourceId);
|
||||
|
||||
myIMdmLinkUpdaterSvc.notDuplicatePerson(person, target, theMdmTransactionContext);
|
||||
myIMdmLinkUpdaterSvc.notDuplicateGoldenResource(goldenResource, target, theMdmTransactionContext);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ public class MdmEidUpdateService {
|
|||
|
||||
void handleMdmUpdate(IAnyResource theResource, MatchedGoldenResourceCandidate theMatchedGoldenResourceCandidate, MdmTransactionContext theMdmTransactionContext) {
|
||||
MdmUpdateContext updateContext = new MdmUpdateContext(theMatchedGoldenResourceCandidate, theResource);
|
||||
if (updateContext.isRemainsMatchedToSamePerson()) {
|
||||
if (updateContext.isRemainsMatchedToSameGoldenResource()) {
|
||||
// Copy over any new external EIDs which don't already exist.
|
||||
// TODO NG - Eventually this call will use terser to clone data in, once the surviorship rules for copying data will be confirmed
|
||||
// myPersonHelper.updatePersonFromUpdatedEmpiTarget(updateContext.getMatchedPerson(), theResource, theEmpiTransactionContext);
|
||||
|
@ -75,20 +75,20 @@ public class MdmEidUpdateService {
|
|||
handleNoEidsInCommon(theResource, theMatchedGoldenResourceCandidate, theMdmTransactionContext, updateContext);
|
||||
}
|
||||
} else {
|
||||
//This is a new linking scenario. we have to break the existing link and link to the new person. For now, we create duplicate.
|
||||
//updated patient has an EID that matches to a new candidate. Link them, and set the persons possible duplicates
|
||||
linkToNewPersonAndFlagAsDuplicate(theResource, updateContext.getExistingPerson(), updateContext.getMatchedGoldenResource(), theMdmTransactionContext);
|
||||
//This is a new linking scenario. we have to break the existing link and link to the new Golden Resource. For now, we create duplicate.
|
||||
//updated patient has an EID that matches to a new candidate. Link them, and set the Golden Resources possible duplicates
|
||||
linkToNewGoldenResourceAndFlagAsDuplicate(theResource, updateContext.getExistingGoldenResource(), updateContext.getMatchedGoldenResource(), theMdmTransactionContext);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleNoEidsInCommon(IAnyResource theResource, MatchedGoldenResourceCandidate theMatchedGoldenResourceCandidate, MdmTransactionContext theMdmTransactionContext, MdmUpdateContext theUpdateContext) {
|
||||
// the user is simply updating their EID. We propagate this change to the Person.
|
||||
//overwrite. No EIDS in common, but still same person.
|
||||
// the user is simply updating their EID. We propagate this change to the GoldenResource.
|
||||
//overwrite. No EIDS in common, but still same GoldenResource.
|
||||
if (myMdmSettings.isPreventMultipleEids()) {
|
||||
if (myMdmLinkDaoSvc.findMdmMatchLinksBySource(theUpdateContext.getMatchedGoldenResource()).size() <= 1) { // If there is only 0/1 link on the person, we can safely overwrite the EID.
|
||||
if (myMdmLinkDaoSvc.findMdmMatchLinksBySource(theUpdateContext.getMatchedGoldenResource()).size() <= 1) { // If there is only 0/1 link on the GoldenResource, we can safely overwrite the EID.
|
||||
handleExternalEidOverwrite(theUpdateContext.getMatchedGoldenResource(), theResource, theMdmTransactionContext);
|
||||
} else { // If the person has multiple patients tied to it, we can't just overwrite the EID, so we split the person.
|
||||
createNewPersonAndFlagAsDuplicate(theResource, theMdmTransactionContext, theUpdateContext.getExistingPerson());
|
||||
} else { // If the GoldenResource has multiple targets tied to it, we can't just overwrite the EID, so we split the GoldenResource.
|
||||
createNewGoldenResourceAndFlagAsDuplicate(theResource, theMdmTransactionContext, theUpdateContext.getExistingGoldenResource());
|
||||
}
|
||||
} else {
|
||||
myGoldenResourceHelper.handleExternalEidAddition(theUpdateContext.getMatchedGoldenResource(), theResource, theMdmTransactionContext);
|
||||
|
@ -96,31 +96,31 @@ public class MdmEidUpdateService {
|
|||
myMdmLinkSvc.updateLink(theUpdateContext.getMatchedGoldenResource(), theResource, theMatchedGoldenResourceCandidate.getMatchResult(), MdmLinkSourceEnum.AUTO, theMdmTransactionContext);
|
||||
}
|
||||
|
||||
private void handleExternalEidOverwrite(IAnyResource thePerson, IAnyResource theResource, MdmTransactionContext theMdmTransactionContext) {
|
||||
private void handleExternalEidOverwrite(IAnyResource theGoldenResource, IAnyResource theResource, MdmTransactionContext theMdmTransactionContext) {
|
||||
List<CanonicalEID> eidFromResource = myEIDHelper.getExternalEid(theResource);
|
||||
if (!eidFromResource.isEmpty()) {
|
||||
myGoldenResourceHelper.overwriteExternalEids(thePerson, eidFromResource);
|
||||
myGoldenResourceHelper.overwriteExternalEids(theGoldenResource, eidFromResource);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean candidateIsSameAsMdmLinkPerson(MdmLink theExistingMatchLink, MatchedGoldenResourceCandidate thePersonCandidate) {
|
||||
return theExistingMatchLink.getGoldenResourcePid().equals(thePersonCandidate.getCandidatePersonPid().getIdAsLong());
|
||||
private boolean candidateIsSameAsMdmLinkGoldenResource(MdmLink theExistingMatchLink, MatchedGoldenResourceCandidate theGoldenResourceCandidate) {
|
||||
return theExistingMatchLink.getGoldenResourcePid().equals(theGoldenResourceCandidate.getCandidateGoldenResourcePid().getIdAsLong());
|
||||
}
|
||||
|
||||
private void createNewPersonAndFlagAsDuplicate(IAnyResource theResource, MdmTransactionContext theMdmTransactionContext, IAnyResource theOldPerson) {
|
||||
private void createNewGoldenResourceAndFlagAsDuplicate(IAnyResource theResource, MdmTransactionContext theMdmTransactionContext, IAnyResource theOldGoldenResource) {
|
||||
log(theMdmTransactionContext, "Duplicate detected based on the fact that both resources have different external EIDs.");
|
||||
IAnyResource newPerson = myGoldenResourceHelper.createGoldenResourceFromMdmTarget(theResource);
|
||||
IAnyResource newGoldenResource = myGoldenResourceHelper.createGoldenResourceFromMdmTarget(theResource);
|
||||
|
||||
myMdmLinkSvc.updateLink(newPerson, theResource, MdmMatchOutcome.NEW_PERSON_MATCH, MdmLinkSourceEnum.AUTO, theMdmTransactionContext);
|
||||
myMdmLinkSvc.updateLink(newPerson, theOldPerson, MdmMatchOutcome.POSSIBLE_DUPLICATE, MdmLinkSourceEnum.AUTO, theMdmTransactionContext);
|
||||
myMdmLinkSvc.updateLink(newGoldenResource, theResource, MdmMatchOutcome.NEW_GOLDEN_RESOURCE_MATCH, MdmLinkSourceEnum.AUTO, theMdmTransactionContext);
|
||||
myMdmLinkSvc.updateLink(newGoldenResource, theOldGoldenResource, MdmMatchOutcome.POSSIBLE_DUPLICATE, MdmLinkSourceEnum.AUTO, theMdmTransactionContext);
|
||||
}
|
||||
|
||||
private void linkToNewPersonAndFlagAsDuplicate(IAnyResource theResource, IAnyResource theOldPerson, IAnyResource theNewPerson, MdmTransactionContext theMdmTransactionContext) {
|
||||
private void linkToNewGoldenResourceAndFlagAsDuplicate(IAnyResource theResource, IAnyResource theOldGoldenResource, IAnyResource theNewGoldenResource, MdmTransactionContext theMdmTransactionContext) {
|
||||
log(theMdmTransactionContext, "Changing a match link!");
|
||||
myMdmLinkSvc.deleteLink(theOldPerson, theResource, theMdmTransactionContext);
|
||||
myMdmLinkSvc.updateLink(theNewPerson, theResource, MdmMatchOutcome.NEW_PERSON_MATCH, MdmLinkSourceEnum.AUTO, theMdmTransactionContext);
|
||||
myMdmLinkSvc.deleteLink(theOldGoldenResource, theResource, theMdmTransactionContext);
|
||||
myMdmLinkSvc.updateLink(theNewGoldenResource, theResource, MdmMatchOutcome.NEW_GOLDEN_RESOURCE_MATCH, MdmLinkSourceEnum.AUTO, theMdmTransactionContext);
|
||||
log(theMdmTransactionContext, "Duplicate detected based on the fact that both resources have different external EIDs.");
|
||||
myMdmLinkSvc.updateLink(theNewPerson, theOldPerson, MdmMatchOutcome.POSSIBLE_DUPLICATE, MdmLinkSourceEnum.AUTO, theMdmTransactionContext);
|
||||
myMdmLinkSvc.updateLink(theNewGoldenResource, theOldGoldenResource, MdmMatchOutcome.POSSIBLE_DUPLICATE, MdmLinkSourceEnum.AUTO, theMdmTransactionContext);
|
||||
}
|
||||
|
||||
private void log(MdmTransactionContext theMdmTransactionContext, String theMessage) {
|
||||
|
@ -132,10 +132,11 @@ public class MdmEidUpdateService {
|
|||
* Data class to hold context surrounding an update operation for an MDM target.
|
||||
*/
|
||||
class MdmUpdateContext {
|
||||
|
||||
private final boolean myHasEidsInCommon;
|
||||
private final boolean myIncomingResourceHasAnEid;
|
||||
private IAnyResource myExistingPerson;
|
||||
private boolean myRemainsMatchedToSamePerson;
|
||||
private IAnyResource myExistingGoldenResource;
|
||||
private boolean myRemainsMatchedToSameGoldenResource;
|
||||
private final IAnyResource myMatchedGoldenResource;
|
||||
|
||||
public IAnyResource getMatchedGoldenResource() {
|
||||
|
@ -150,15 +151,15 @@ public class MdmEidUpdateService {
|
|||
myIncomingResourceHasAnEid = !myEIDHelper.getExternalEid(theResource).isEmpty();
|
||||
|
||||
Optional<MdmLink> theExistingMatchLink = myMdmLinkDaoSvc.getMatchedLinkForTarget(theResource);
|
||||
myExistingPerson = null;
|
||||
myExistingGoldenResource = null;
|
||||
|
||||
if (theExistingMatchLink.isPresent()) {
|
||||
MdmLink mdmLink = theExistingMatchLink.get();
|
||||
Long existingPersonPid = mdmLink.getGoldenResourcePid();
|
||||
myExistingPerson = myMdmResourceDaoSvc.readGoldenResourceByPid(new ResourcePersistentId(existingPersonPid), resourceType);
|
||||
myRemainsMatchedToSamePerson = candidateIsSameAsMdmLinkPerson(mdmLink, theMatchedGoldenResourceCandidate);
|
||||
Long existingGoldenResourcePid = mdmLink.getGoldenResourcePid();
|
||||
myExistingGoldenResource = myMdmResourceDaoSvc.readGoldenResourceByPid(new ResourcePersistentId(existingGoldenResourcePid), resourceType);
|
||||
myRemainsMatchedToSameGoldenResource = candidateIsSameAsMdmLinkGoldenResource(mdmLink, theMatchedGoldenResourceCandidate);
|
||||
} else {
|
||||
myRemainsMatchedToSamePerson = false;
|
||||
myRemainsMatchedToSameGoldenResource = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -170,12 +171,12 @@ public class MdmEidUpdateService {
|
|||
return myIncomingResourceHasAnEid;
|
||||
}
|
||||
|
||||
public IAnyResource getExistingPerson() {
|
||||
return myExistingPerson;
|
||||
public IAnyResource getExistingGoldenResource() {
|
||||
return myExistingGoldenResource;
|
||||
}
|
||||
|
||||
public boolean isRemainsMatchedToSamePerson() {
|
||||
return myRemainsMatchedToSamePerson;
|
||||
public boolean isRemainsMatchedToSameGoldenResource() {
|
||||
return myRemainsMatchedToSameGoldenResource;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ import java.util.List;
|
|||
|
||||
@Service
|
||||
public class MdmGoldenResourceDeletingSvc {
|
||||
|
||||
private static final Logger ourLog = Logs.getMdmTroubleshootingLog();
|
||||
|
||||
/**
|
||||
|
@ -50,7 +51,7 @@ public class MdmGoldenResourceDeletingSvc {
|
|||
@Autowired
|
||||
DeleteExpungeService myDeleteExpungeService;
|
||||
|
||||
public DeleteMethodOutcome expungeGoldenResourcePids(List<Long> thePersonPids, ServletRequestDetails theRequestDetails) {
|
||||
return myDeleteExpungeService.expungeByResourcePids(ProviderConstants.MDM_CLEAR, "Person", new SliceImpl<>(thePersonPids), theRequestDetails);
|
||||
public DeleteMethodOutcome expungeGoldenResourcePids(List<Long> theGoldenResourcePids, String theResourceType, ServletRequestDetails theRequestDetails) {
|
||||
return myDeleteExpungeService.expungeByResourcePids(ProviderConstants.MDM_CLEAR, theResourceType, new SliceImpl<>(theGoldenResourcePids), theRequestDetails);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ public class MdmLinkQuerySvcImpl implements IMdmLinkQuerySvc {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Stream<MdmLinkJson> getDuplicatePersons(MdmTransactionContext theMdmContext) {
|
||||
public Stream<MdmLinkJson> getDuplicateGoldenResources(MdmTransactionContext theMdmContext) {
|
||||
Example<MdmLink> exampleLink = exampleLinkFromParameters(null, null, MdmMatchResultEnum.POSSIBLE_DUPLICATE, null);
|
||||
return myMdmLinkDaoSvc.findMdmLinkByExample(exampleLink).stream().map(this::toJson);
|
||||
}
|
||||
|
@ -76,10 +76,10 @@ public class MdmLinkQuerySvcImpl implements IMdmLinkQuerySvc {
|
|||
return retval;
|
||||
}
|
||||
|
||||
private Example<MdmLink> exampleLinkFromParameters(IIdType thePersonId, IIdType theTargetId, MdmMatchResultEnum theMatchResult, MdmLinkSourceEnum theLinkSource) {
|
||||
private Example<MdmLink> exampleLinkFromParameters(IIdType theGoldenResourceId, IIdType theTargetId, MdmMatchResultEnum theMatchResult, MdmLinkSourceEnum theLinkSource) {
|
||||
MdmLink mdmLink = myMdmLinkDaoSvc.newMdmLink();
|
||||
if (thePersonId != null) {
|
||||
mdmLink.setGoldenResourcePid(myIdHelperService.getPidOrThrowException(thePersonId));
|
||||
if (theGoldenResourceId != null) {
|
||||
mdmLink.setGoldenResourcePid(myIdHelperService.getPidOrThrowException(theGoldenResourceId));
|
||||
}
|
||||
if (theTargetId != null) {
|
||||
mdmLink.setTargetPid(myIdHelperService.getPidOrThrowException(theTargetId));
|
||||
|
|
|
@ -29,7 +29,6 @@ import ca.uhn.fhir.mdm.api.MdmMatchOutcome;
|
|||
import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
||||
import ca.uhn.fhir.mdm.log.Logs;
|
||||
import ca.uhn.fhir.mdm.model.MdmTransactionContext;
|
||||
import ca.uhn.fhir.mdm.util.GoldenResourceHelper;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
@ -45,6 +44,7 @@ import java.util.Optional;
|
|||
*/
|
||||
@Service
|
||||
public class MdmLinkSvcImpl implements IMdmLinkSvc {
|
||||
|
||||
private static final Logger ourLog = Logs.getMdmTroubleshootingLog();
|
||||
|
||||
@Autowired
|
||||
|
@ -52,15 +52,13 @@ public class MdmLinkSvcImpl implements IMdmLinkSvc {
|
|||
@Autowired
|
||||
private MdmLinkDaoSvc myMdmLinkDaoSvc;
|
||||
@Autowired
|
||||
private GoldenResourceHelper myGoldenResourceHelper;
|
||||
@Autowired
|
||||
private IdHelperService myIdHelperService;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void updateLink(IAnyResource thePerson, IAnyResource theTarget, MdmMatchOutcome theMatchOutcome, MdmLinkSourceEnum theLinkSource, MdmTransactionContext theMdmTransactionContext) {
|
||||
if (theMatchOutcome.isPossibleDuplicate() && personsLinkedAsNoMatch(thePerson, theTarget)) {
|
||||
log(theMdmTransactionContext, thePerson.getIdElement().toUnqualifiedVersionless() +
|
||||
public void updateLink(IAnyResource theGoldenResource, IAnyResource theTarget, MdmMatchOutcome theMatchOutcome, MdmLinkSourceEnum theLinkSource, MdmTransactionContext theMdmTransactionContext) {
|
||||
if (theMatchOutcome.isPossibleDuplicate() && goldenResourceLinkedAsNoMatch(theGoldenResource, theTarget)) {
|
||||
log(theMdmTransactionContext, theGoldenResource.getIdElement().toUnqualifiedVersionless() +
|
||||
" is linked as NO_MATCH with " +
|
||||
theTarget.getIdElement().toUnqualifiedVersionless() +
|
||||
" not linking as POSSIBLE_DUPLICATE.");
|
||||
|
@ -68,18 +66,18 @@ public class MdmLinkSvcImpl implements IMdmLinkSvc {
|
|||
}
|
||||
|
||||
MdmMatchResultEnum matchResultEnum = theMatchOutcome.getMatchResultEnum();
|
||||
validateRequestIsLegal(thePerson, theTarget, matchResultEnum, theLinkSource);
|
||||
validateRequestIsLegal(theGoldenResource, theTarget, matchResultEnum, theLinkSource);
|
||||
|
||||
myMdmResourceDaoSvc.upsertGoldenResource(thePerson, theMdmTransactionContext.getResourceType());
|
||||
createOrUpdateLinkEntity(thePerson, theTarget, theMatchOutcome, theLinkSource, theMdmTransactionContext);
|
||||
myMdmResourceDaoSvc.upsertGoldenResource(theGoldenResource, theMdmTransactionContext.getResourceType());
|
||||
createOrUpdateLinkEntity(theGoldenResource, theTarget, theMatchOutcome, theLinkSource, theMdmTransactionContext);
|
||||
}
|
||||
|
||||
private boolean personsLinkedAsNoMatch(IAnyResource thePerson, IAnyResource theTarget) {
|
||||
Long personId = myIdHelperService.getPidOrThrowException(thePerson);
|
||||
private boolean goldenResourceLinkedAsNoMatch(IAnyResource theGoldenResource, IAnyResource theTarget) {
|
||||
Long goldenResourceId = myIdHelperService.getPidOrThrowException(theGoldenResource);
|
||||
Long targetId = myIdHelperService.getPidOrThrowException(theTarget);
|
||||
// TODO perf collapse into one query
|
||||
return myMdmLinkDaoSvc.getMdmLinksByPersonPidTargetPidAndMatchResult(personId, targetId, MdmMatchResultEnum.NO_MATCH).isPresent() ||
|
||||
myMdmLinkDaoSvc.getMdmLinksByPersonPidTargetPidAndMatchResult(targetId, personId, MdmMatchResultEnum.NO_MATCH).isPresent();
|
||||
return myMdmLinkDaoSvc.getMdmLinksByGoldenResourcePidTargetPidAndMatchResult(goldenResourceId, targetId, MdmMatchResultEnum.NO_MATCH).isPresent() ||
|
||||
myMdmLinkDaoSvc.getMdmLinksByGoldenResourcePidTargetPidAndMatchResult(targetId, goldenResourceId, MdmMatchResultEnum.NO_MATCH).isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -120,12 +118,12 @@ public class MdmLinkSvcImpl implements IMdmLinkSvc {
|
|||
return theIncomingSource == MdmLinkSourceEnum.AUTO && theExistingSource.isManual();
|
||||
}
|
||||
|
||||
private Optional<MdmLink> getMdmLinkForGoldenResourceTargetPair(IAnyResource thePerson, IAnyResource theCandidate) {
|
||||
if (thePerson.getIdElement().getIdPart() == null || theCandidate.getIdElement().getIdPart() == null) {
|
||||
private Optional<MdmLink> getMdmLinkForGoldenResourceTargetPair(IAnyResource theGoldenResource, IAnyResource theCandidate) {
|
||||
if (theGoldenResource.getIdElement().getIdPart() == null || theCandidate.getIdElement().getIdPart() == null) {
|
||||
return Optional.empty();
|
||||
} else {
|
||||
return myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndTargetResourcePid(
|
||||
myIdHelperService.getPidOrNull(thePerson),
|
||||
myIdHelperService.getPidOrNull(theGoldenResource),
|
||||
myIdHelperService.getPidOrNull(theCandidate)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ public class MdmLinkUpdaterSvcImpl implements IMdmLinkUpdaterSvc {
|
|||
myMdmLinkDaoSvc.save(mdmLink);
|
||||
myMdmResourceDaoSvc.upsertGoldenResource(theGoldenResource, theMdmContext.getResourceType());
|
||||
if (theMatchResult == MdmMatchResultEnum.NO_MATCH) {
|
||||
// Need to find a new Person to link this target to
|
||||
// Need to find a new Golden Resource to link this target to
|
||||
myMdmMatchLinkSvc.updateMdmLinksForMdmTarget(theTarget, theMdmContext);
|
||||
}
|
||||
return theGoldenResource;
|
||||
|
@ -128,20 +128,20 @@ public class MdmLinkUpdaterSvcImpl implements IMdmLinkUpdaterSvc {
|
|||
|
||||
@Transactional
|
||||
@Override
|
||||
public void notDuplicatePerson(IAnyResource thePerson, IAnyResource theTarget, MdmTransactionContext theMdmContext) {
|
||||
validateNotDuplicatePersonRequest(thePerson, theTarget);
|
||||
public void notDuplicateGoldenResource(IAnyResource theGoldenResource, IAnyResource theTarget, MdmTransactionContext theMdmContext) {
|
||||
validateNotDuplicateGoldenResourceRequest(theGoldenResource, theTarget);
|
||||
|
||||
Long personId = myIdHelperService.getPidOrThrowException(thePerson);
|
||||
Long goldenResourceId = myIdHelperService.getPidOrThrowException(theGoldenResource);
|
||||
Long targetId = myIdHelperService.getPidOrThrowException(theTarget);
|
||||
|
||||
Optional<MdmLink> oMdmLink = myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndTargetResourcePid(personId, targetId);
|
||||
Optional<MdmLink> oMdmLink = myMdmLinkDaoSvc.getLinkByGoldenResourcePidAndTargetResourcePid(goldenResourceId, targetId);
|
||||
if (!oMdmLink.isPresent()) {
|
||||
throw new InvalidRequestException("No link exists between " + thePerson.getIdElement().toVersionless() + " and " + theTarget.getIdElement().toVersionless());
|
||||
throw new InvalidRequestException("No link exists between " + theGoldenResource.getIdElement().toVersionless() + " and " + theTarget.getIdElement().toVersionless());
|
||||
}
|
||||
|
||||
MdmLink mdmLink = oMdmLink.get();
|
||||
if (!mdmLink.isPossibleDuplicate()) {
|
||||
throw new InvalidRequestException(thePerson.getIdElement().toVersionless() + " and " + theTarget.getIdElement().toVersionless() + " are not linked as POSSIBLE_DUPLICATE.");
|
||||
throw new InvalidRequestException(theGoldenResource.getIdElement().toVersionless() + " and " + theTarget.getIdElement().toVersionless() + " are not linked as POSSIBLE_DUPLICATE.");
|
||||
}
|
||||
mdmLink.setMatchResult(MdmMatchResultEnum.NO_MATCH);
|
||||
mdmLink.setLinkSource(MdmLinkSourceEnum.MANUAL);
|
||||
|
@ -151,7 +151,7 @@ public class MdmLinkUpdaterSvcImpl implements IMdmLinkUpdaterSvc {
|
|||
/**
|
||||
* Ensure that the two resources are of the same type and both are managed by HAPI-MDM
|
||||
*/
|
||||
private void validateNotDuplicatePersonRequest(IAnyResource theGoldenResource, IAnyResource theTarget) {
|
||||
private void validateNotDuplicateGoldenResourceRequest(IAnyResource theGoldenResource, IAnyResource theTarget) {
|
||||
String goldenResourceType = myFhirContext.getResourceType(theGoldenResource);
|
||||
String targetType = myFhirContext.getResourceType(theTarget);
|
||||
if (!goldenResourceType.equalsIgnoreCase(targetType)) {
|
||||
|
@ -159,7 +159,7 @@ public class MdmLinkUpdaterSvcImpl implements IMdmLinkUpdaterSvc {
|
|||
}
|
||||
|
||||
if (!MdmUtil.isMdmManaged(theGoldenResource) || !MdmUtil.isMdmManaged(theTarget)) {
|
||||
throw new InvalidRequestException("Only MDM Managed Golden Resources may be updated via this operation. The resource provided is not tagged as managed by hapi-mdm");
|
||||
throw new InvalidRequestException("Only MDM Managed Golden Resources may be updated via this operation. The resource provided is not tagged as managed by HAPI-MDM");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,8 +41,8 @@ import java.util.List;
|
|||
|
||||
/**
|
||||
* MdmMatchLinkSvc is the entrypoint for HAPI's MDM system. An incoming resource can call
|
||||
* updateMdmLinksForMdmTarget and the underlying MDM system will take care of matching it to a person, or creating a
|
||||
* new Person if a suitable one was not found.
|
||||
* updateMdmLinksForMdmTarget and the underlying MDM system will take care of matching it to a GoldenResource, or creating a
|
||||
* new GoldenResource if a suitable one was not found.
|
||||
*/
|
||||
@Service
|
||||
public class MdmMatchLinkSvc {
|
||||
|
@ -58,7 +58,7 @@ public class MdmMatchLinkSvc {
|
|||
private MdmEidUpdateService myEidUpdateService;
|
||||
|
||||
/**
|
||||
* Given an MDM Target (consisting of either a Patient or a Practitioner), find a suitable Person candidate for them,
|
||||
* Given an MDM Target (consisting of either a Patient or a Practitioner), find a suitable Golden Resource candidate for them,
|
||||
* or create one if one does not exist. Performs matching based on rules defined in mdm-rules.json.
|
||||
* Does nothing if resource is determined to be not managed by MDM.
|
||||
*
|
||||
|
@ -89,33 +89,33 @@ public class MdmMatchLinkSvc {
|
|||
|
||||
private void handleMdmWithMultipleCandidates(IAnyResource theResource, CandidateList theCandidateList, MdmTransactionContext theMdmTransactionContext) {
|
||||
MatchedGoldenResourceCandidate firstMatch = theCandidateList.getFirstMatch();
|
||||
Long samplePersonPid = firstMatch.getCandidatePersonPid().getIdAsLong();
|
||||
boolean allSamePerson = theCandidateList.stream()
|
||||
.allMatch(candidate -> candidate.getCandidatePersonPid().getIdAsLong().equals(samplePersonPid));
|
||||
Long sampleGoldenResourcePid = firstMatch.getCandidateGoldenResourcePid().getIdAsLong();
|
||||
boolean allSameGoldenResource = theCandidateList.stream()
|
||||
.allMatch(candidate -> candidate.getCandidateGoldenResourcePid().getIdAsLong().equals(sampleGoldenResourcePid));
|
||||
|
||||
if (allSamePerson) {
|
||||
log(theMdmTransactionContext, "MDM received multiple match candidates, but they are all linked to the same person.");
|
||||
if (allSameGoldenResource) {
|
||||
log(theMdmTransactionContext, "MDM received multiple match candidates, but they are all linked to the same Golden Resource.");
|
||||
handleMdmWithSingleCandidate(theResource, firstMatch, theMdmTransactionContext);
|
||||
} else {
|
||||
log(theMdmTransactionContext, "MDM received multiple match candidates, that were linked to different Persons. Setting POSSIBLE_DUPLICATES and POSSIBLE_MATCHES.");
|
||||
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<IAnyResource> persons = new ArrayList<>();
|
||||
List<IAnyResource> goldenResources = new ArrayList<>();
|
||||
for (MatchedGoldenResourceCandidate matchedGoldenResourceCandidate : theCandidateList.getCandidates()) {
|
||||
IAnyResource person = myMdmGoldenResourceFindingSvc
|
||||
IAnyResource goldenResource = myMdmGoldenResourceFindingSvc
|
||||
.getGoldenResourceFromMatchedGoldenResourceCandidate(matchedGoldenResourceCandidate, theMdmTransactionContext.getResourceType());
|
||||
MdmMatchOutcome outcome = MdmMatchOutcome.POSSIBLE_MATCH;
|
||||
outcome.setEidMatch(theCandidateList.isEidMatch());
|
||||
myMdmLinkSvc.updateLink(person, theResource, outcome, MdmLinkSourceEnum.AUTO, theMdmTransactionContext);
|
||||
persons.add(person);
|
||||
myMdmLinkSvc.updateLink(goldenResource, theResource, outcome, MdmLinkSourceEnum.AUTO, theMdmTransactionContext);
|
||||
goldenResources.add(goldenResource);
|
||||
}
|
||||
|
||||
//Set all Persons as POSSIBLE_DUPLICATE of the last person.
|
||||
IAnyResource firstPerson = persons.get(0);
|
||||
persons.subList(1, persons.size())
|
||||
.forEach(possibleDuplicatePerson -> {
|
||||
//Set all GoldenResources as POSSIBLE_DUPLICATE of the last GoldenResource.
|
||||
IAnyResource firstGoldenResource = goldenResources.get(0);
|
||||
goldenResources.subList(1, goldenResources.size())
|
||||
.forEach(possibleDuplicateGoldenResource -> {
|
||||
MdmMatchOutcome outcome = MdmMatchOutcome.POSSIBLE_DUPLICATE;
|
||||
outcome.setEidMatch(theCandidateList.isEidMatch());
|
||||
myMdmLinkSvc.updateLink(firstPerson, possibleDuplicatePerson, outcome, MdmLinkSourceEnum.AUTO, theMdmTransactionContext);
|
||||
myMdmLinkSvc.updateLink(firstGoldenResource, possibleDuplicateGoldenResource, outcome, MdmLinkSourceEnum.AUTO, theMdmTransactionContext);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -128,33 +128,33 @@ public class MdmMatchLinkSvc {
|
|||
// 2. Create source resoruce for the MDM target
|
||||
// 3. UPDATE MDM LINK TABLE
|
||||
|
||||
myMdmLinkSvc.updateLink(newGoldenResource, theResource, MdmMatchOutcome.NEW_PERSON_MATCH, MdmLinkSourceEnum.AUTO, theMdmTransactionContext);
|
||||
myMdmLinkSvc.updateLink(newGoldenResource, theResource, MdmMatchOutcome.NEW_GOLDEN_RESOURCE_MATCH, MdmLinkSourceEnum.AUTO, theMdmTransactionContext);
|
||||
}
|
||||
|
||||
private void handleMdmCreate(IAnyResource theTargetResource, MatchedGoldenResourceCandidate thePersonCandidate, MdmTransactionContext theMdmTransactionContext) {
|
||||
private void handleMdmCreate(IAnyResource theTargetResource, MatchedGoldenResourceCandidate theGoldenResourceCandidate, MdmTransactionContext theMdmTransactionContext) {
|
||||
log(theMdmTransactionContext, "MDM has narrowed down to one candidate for matching.");
|
||||
IAnyResource golenResource = myMdmGoldenResourceFindingSvc.getGoldenResourceFromMatchedGoldenResourceCandidate(thePersonCandidate, theMdmTransactionContext.getResourceType());
|
||||
IAnyResource golenResource = myMdmGoldenResourceFindingSvc.getGoldenResourceFromMatchedGoldenResourceCandidate(theGoldenResourceCandidate, theMdmTransactionContext.getResourceType());
|
||||
|
||||
if (myGoldenResourceHelper.isPotentialDuplicate(golenResource, theTargetResource)) {
|
||||
log(theMdmTransactionContext, "Duplicate detected based on the fact that both resources have different external EIDs.");
|
||||
IAnyResource newGoldenResource = myGoldenResourceHelper.createGoldenResourceFromMdmTarget(theTargetResource);
|
||||
myMdmLinkSvc.updateLink(newGoldenResource, theTargetResource, MdmMatchOutcome.NEW_PERSON_MATCH, MdmLinkSourceEnum.AUTO, theMdmTransactionContext);
|
||||
myMdmLinkSvc.updateLink(newGoldenResource, theTargetResource, MdmMatchOutcome.NEW_GOLDEN_RESOURCE_MATCH, MdmLinkSourceEnum.AUTO, theMdmTransactionContext);
|
||||
myMdmLinkSvc.updateLink(newGoldenResource, golenResource, MdmMatchOutcome.POSSIBLE_DUPLICATE, MdmLinkSourceEnum.AUTO, theMdmTransactionContext);
|
||||
} else {
|
||||
if (thePersonCandidate.isMatch()) {
|
||||
if (theGoldenResourceCandidate.isMatch()) {
|
||||
myGoldenResourceHelper.handleExternalEidAddition(golenResource, theTargetResource, theMdmTransactionContext);
|
||||
//TODO MDM GGG/NG: eventually we need to add survivorship rules of attributes here. Currently no data is copied over except EIDs.
|
||||
}
|
||||
myMdmLinkSvc.updateLink(golenResource, theTargetResource, thePersonCandidate.getMatchResult(), MdmLinkSourceEnum.AUTO, theMdmTransactionContext);
|
||||
myMdmLinkSvc.updateLink(golenResource, theTargetResource, theGoldenResourceCandidate.getMatchResult(), MdmLinkSourceEnum.AUTO, theMdmTransactionContext);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleMdmWithSingleCandidate(IAnyResource theResource, MatchedGoldenResourceCandidate thePersonCandidate, MdmTransactionContext theMdmTransactionContext) {
|
||||
private void handleMdmWithSingleCandidate(IAnyResource theResource, MatchedGoldenResourceCandidate theGoldenResourceCandidate, MdmTransactionContext theMdmTransactionContext) {
|
||||
log(theMdmTransactionContext, "MDM has narrowed down to one candidate for matching.");
|
||||
if (theMdmTransactionContext.getRestOperation().equals(MdmTransactionContext.OperationType.UPDATE_RESOURCE)) {
|
||||
myEidUpdateService.handleMdmUpdate(theResource, thePersonCandidate, theMdmTransactionContext);
|
||||
myEidUpdateService.handleMdmUpdate(theResource, theGoldenResourceCandidate, theMdmTransactionContext);
|
||||
} else {
|
||||
handleMdmCreate(theResource, thePersonCandidate, theMdmTransactionContext);
|
||||
handleMdmCreate(theResource, theGoldenResourceCandidate, theMdmTransactionContext);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ import java.util.Optional;
|
|||
@Service
|
||||
public class MdmResourceDaoSvc {
|
||||
|
||||
private static final int MAX_MATCHING_PERSONS = 1000;
|
||||
private static final int MAX_MATCHING_GOLDEN_RESOURCES = 1000;
|
||||
|
||||
@Autowired
|
||||
DaoRegistry myDaoRegistry;
|
||||
|
@ -80,14 +80,14 @@ public class MdmResourceDaoSvc {
|
|||
|
||||
IFhirResourceDao resourceDao = myDaoRegistry.getResourceDao(theResourceType);
|
||||
IBundleProvider search = resourceDao.search(map);
|
||||
List<IBaseResource> resources = search.getResources(0, MAX_MATCHING_PERSONS);
|
||||
List<IBaseResource> resources = search.getResources(0, MAX_MATCHING_GOLDEN_RESOURCES);
|
||||
|
||||
if (resources.isEmpty()) {
|
||||
return Optional.empty();
|
||||
} else if (resources.size() > 1) {
|
||||
throw new InternalErrorException("Found more than one active " +
|
||||
MdmConstants.CODE_HAPI_MDM_MANAGED +
|
||||
" Person with EID " +
|
||||
" Golden Resource with EID " +
|
||||
theEid +
|
||||
": " +
|
||||
resources.get(0).getIdElement().getValue() +
|
||||
|
|
|
@ -51,12 +51,12 @@ public class FindCandidateByEidSvc extends BaseCandidateFinder {
|
|||
List<CanonicalEID> eidFromResource = myEIDHelper.getExternalEid(theBaseResource);
|
||||
if (!eidFromResource.isEmpty()) {
|
||||
for (CanonicalEID eid : eidFromResource) {
|
||||
Optional<IAnyResource> oFoundPerson = myMdmResourceDaoSvc.searchGoldenResourceByEID(eid.getValue(), theBaseResource.getIdElement().getResourceType());
|
||||
if (oFoundPerson.isPresent()) {
|
||||
IAnyResource foundPerson = oFoundPerson.get();
|
||||
Long pidOrNull = myIdHelperService.getPidOrNull(foundPerson);
|
||||
Optional<IAnyResource> oFoundGoldenResource = myMdmResourceDaoSvc.searchGoldenResourceByEID(eid.getValue(), theBaseResource.getIdElement().getResourceType());
|
||||
if (oFoundGoldenResource.isPresent()) {
|
||||
IAnyResource foundGoldenResource = oFoundGoldenResource.get();
|
||||
Long pidOrNull = myIdHelperService.getPidOrNull(foundGoldenResource);
|
||||
MatchedGoldenResourceCandidate mpc = new MatchedGoldenResourceCandidate(new ResourcePersistentId(pidOrNull), MdmMatchOutcome.EID_MATCH);
|
||||
ourLog.debug("Matched {} by EID {}", foundPerson.getIdElement(), eid);
|
||||
ourLog.debug("Matched {} by EID {}", foundGoldenResource.getIdElement(), eid);
|
||||
retval.add(mpc);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,9 +36,9 @@ public class FindCandidateByLinkSvc extends BaseCandidateFinder {
|
|||
private static final Logger ourLog = Logs.getMdmTroubleshootingLog();
|
||||
|
||||
/**
|
||||
* Attempt to find a currently matching Person, based on the presence of an {@link MdmLink} entity.
|
||||
* Attempt to find a currently matching Golden Resource, based on the presence of an {@link MdmLink} entity.
|
||||
*
|
||||
* @param theTarget the {@link IAnyResource} that we want to find candidate Persons for.
|
||||
* @param theTarget the {@link IAnyResource} that we want to find candidate Golden Resources for.
|
||||
* @return an Optional list of {@link MatchedGoldenResourceCandidate} indicating matches.
|
||||
*/
|
||||
@Override
|
||||
|
@ -49,9 +49,9 @@ public class FindCandidateByLinkSvc extends BaseCandidateFinder {
|
|||
if (targetPid != null) {
|
||||
Optional<MdmLink> oLink = myMdmLinkDaoSvc.getMatchedLinkForTargetPid(targetPid);
|
||||
if (oLink.isPresent()) {
|
||||
ResourcePersistentId personPid = new ResourcePersistentId(oLink.get().getGoldenResourcePid());
|
||||
ResourcePersistentId goldenResourcePid = new ResourcePersistentId(oLink.get().getGoldenResourcePid());
|
||||
ourLog.debug("Resource previously linked. Using existing link.");
|
||||
retval.add(new MatchedGoldenResourceCandidate(personPid, oLink.get()));
|
||||
retval.add(new MatchedGoldenResourceCandidate(goldenResourcePid, oLink.get()));
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
|
|
|
@ -54,25 +54,25 @@ public class FindCandidateByScoreSvc extends BaseCandidateFinder {
|
|||
private IMdmMatchFinderSvc myMdmMatchFinderSvc;
|
||||
|
||||
/**
|
||||
* Attempt to find matching Persons by resolving them from similar Matching target resources, where target resource
|
||||
* can be either Patient or Practitioner. Runs MDM logic over the existing Patient/Practitioners, then finds their
|
||||
* 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.
|
||||
*
|
||||
* @param theTarget the {@link IBaseResource} which we want to find candidate Persons for.
|
||||
* @param theTarget the {@link IBaseResource} which we want to find candidate Golden Resources for.
|
||||
* @return an Optional list of {@link MatchedGoldenResourceCandidate} indicating matches.
|
||||
*/
|
||||
@Override
|
||||
protected List<MatchedGoldenResourceCandidate> findMatchGoldenResourceCandidates(IAnyResource theTarget) {
|
||||
List<MatchedGoldenResourceCandidate> retval = new ArrayList<>();
|
||||
|
||||
List<Long> personPidsToExclude = getNoMatchPersonPids(theTarget);
|
||||
List<Long> goldenResourcePidsToExclude = getNoMatchGoldenResourcePids(theTarget);
|
||||
|
||||
List<MatchedTarget> matchedCandidates = myMdmMatchFinderSvc.getMatchedTargets(myFhirContext.getResourceType(theTarget), theTarget);
|
||||
|
||||
//Convert all possible match targets to their equivalent Persons by looking up in the MdmLink table,
|
||||
//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 -> Person -> MdmLink -> MatchedPersonCandidate
|
||||
// MatchedTargetCandidate -> Golden Resource -> MdmLink -> MatchedGoldenResourceCandidate
|
||||
matchedCandidates = matchedCandidates.stream().filter(mc -> mc.isMatch() || mc.isPossibleMatch()).collect(Collectors.toList());
|
||||
for (MatchedTarget match : matchedCandidates) {
|
||||
Optional<MdmLink> optionalMdmLink = myMdmLinkDaoSvc.getMatchedLinkForTargetPid(myIdHelperService.getPidOrNull(match.getTarget()));
|
||||
|
@ -81,8 +81,8 @@ public class FindCandidateByScoreSvc extends BaseCandidateFinder {
|
|||
}
|
||||
|
||||
MdmLink matchMdmLink = optionalMdmLink.get();
|
||||
if (personPidsToExclude.contains(matchMdmLink.getGoldenResourcePid())) {
|
||||
ourLog.info("Skipping MDM on candidate person with PID {} due to manual NO_MATCH", matchMdmLink.getGoldenResourcePid());
|
||||
if (goldenResourcePidsToExclude.contains(matchMdmLink.getGoldenResourcePid())) {
|
||||
ourLog.info("Skipping MDM on candidate Golden Resource with PID {} due to manual NO_MATCH", matchMdmLink.getGoldenResourcePid());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,7 @@ public class FindCandidateByScoreSvc extends BaseCandidateFinder {
|
|||
return retval;
|
||||
}
|
||||
|
||||
private List<Long> getNoMatchPersonPids(IBaseResource theBaseResource) {
|
||||
private List<Long> getNoMatchGoldenResourcePids(IBaseResource theBaseResource) {
|
||||
Long targetPid = myIdHelperService.getPidOrNull(theBaseResource);
|
||||
return myMdmLinkDaoSvc.getMdmLinksByTargetPidAndMatchResult(targetPid, MdmMatchResultEnum.NO_MATCH)
|
||||
.stream()
|
||||
|
@ -100,8 +100,8 @@ public class FindCandidateByScoreSvc extends BaseCandidateFinder {
|
|||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private ResourcePersistentId getResourcePersistentId(Long thePersonPid) {
|
||||
return new ResourcePersistentId(thePersonPid);
|
||||
private ResourcePersistentId getResourcePersistentId(Long theGoldenResourcePid) {
|
||||
return new ResourcePersistentId(theGoldenResourcePid);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -34,12 +34,12 @@ public class MatchedGoldenResourceCandidate {
|
|||
myMdmMatchOutcome = theMdmMatchOutcome;
|
||||
}
|
||||
|
||||
public MatchedGoldenResourceCandidate(ResourcePersistentId thePersonPid, MdmLink theMdmLink) {
|
||||
myCandidateGoldenResourcePid = thePersonPid;
|
||||
public MatchedGoldenResourceCandidate(ResourcePersistentId theGoldenResourcePid, MdmLink theMdmLink) {
|
||||
myCandidateGoldenResourcePid = theGoldenResourcePid;
|
||||
myMdmMatchOutcome = new MdmMatchOutcome(theMdmLink.getVector(), theMdmLink.getScore()).setMatchResultEnum(theMdmLink.getMatchResult());
|
||||
}
|
||||
|
||||
public ResourcePersistentId getCandidatePersonPid() {
|
||||
public ResourcePersistentId getCandidateGoldenResourcePid() {
|
||||
return myCandidateGoldenResourcePid;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ import java.util.stream.Collectors;
|
|||
|
||||
@Service
|
||||
public class MdmCandidateSearchCriteriaBuilderSvc {
|
||||
|
||||
@Autowired
|
||||
private MdmSearchParamSvc myMdmSearchParamSvc;
|
||||
|
||||
|
@ -52,7 +53,7 @@ public class MdmCandidateSearchCriteriaBuilderSvc {
|
|||
// If there are candidate search params, then make use of them, otherwise, search with only the filters.
|
||||
if (resourceSearchParam != null) {
|
||||
resourceSearchParam.iterator().forEachRemaining(searchParam -> {
|
||||
//to compare it to all known PERSON objects, using the overlapping search parameters that they have.
|
||||
//to compare it to all known GOLDEN_RESOURCE objects, using the overlapping search parameters that they have.
|
||||
List<String> valuesFromResourceForSearchParam = myMdmSearchParamSvc.getValueFromResourceForSearchParam(theResource, searchParam);
|
||||
if (!valuesFromResourceForSearchParam.isEmpty()) {
|
||||
criteria.add(buildResourceMatchQuery(searchParam, valuesFromResourceForSearchParam));
|
||||
|
|
|
@ -47,18 +47,18 @@ public class MdmGoldenResourceFindingSvc {
|
|||
private FindCandidateByScoreSvc myFindCandidateByScoreSvc;
|
||||
|
||||
/**
|
||||
* Given an incoming IBaseResource, limited to Patient/Practitioner, return a list of {@link MatchedGoldenResourceCandidate}
|
||||
* indicating possible candidates for a matching Person. Uses several separate methods for finding candidates:
|
||||
* Given an incoming IBaseResource, limited to the supported MDM type, return a list of {@link MatchedGoldenResourceCandidate}
|
||||
* indicating possible candidates for a matching Golden Resource. Uses several separate methods for finding candidates:
|
||||
* <p>
|
||||
* 0. First, check the incoming Resource for an EID. If it is present, and we can find a Person with this EID, it automatically matches.
|
||||
* 1. First, check link table for any entries where this baseresource is the target of a person. If found, return.
|
||||
* 2. If none are found, attempt to find Person Resources which link to this theResource.
|
||||
* 3. If none are found, attempt to find Person Resources similar to our incoming resource based on the MDM rules and field matchers.
|
||||
* 4. If none are found, attempt to find Persons that are linked to Patients/Practitioners that are similar to our incoming resource based on the MDM rules and
|
||||
* 0. First, check the incoming Resource for an EID. If it is present, and we can find a Golden Resource with this EID, it automatically matches.
|
||||
* 1. First, check link table for any entries where this baseresource is the target of a Golden Resource. If found, return.
|
||||
* 2. If none are found, attempt to find Golden Resources which link to this theResource.
|
||||
* 3. If none are found, attempt to find Golden Resources similar to our incoming resource based on the MDM rules and field matchers.
|
||||
* 4. If none are found, attempt to find Golden Resources that are linked to targets that are similar to our incoming resource based on the MDM rules and
|
||||
* field matchers.
|
||||
*
|
||||
* @param theResource the {@link IBaseResource} we are attempting to find matching candidate Persons for.
|
||||
* @return A list of {@link MatchedGoldenResourceCandidate} indicating all potential Person matches.
|
||||
* @param theResource the {@link IBaseResource} we are attempting to find matching candidate Golden Resources for.
|
||||
* @return A list of {@link MatchedGoldenResourceCandidate} indicating all potential Golden Resource matches.
|
||||
*/
|
||||
public CandidateList findGoldenResourceCandidates(IAnyResource theResource) {
|
||||
CandidateList matchedGoldenResourceCandidates = myFindCandidateByEidSvc.findCandidates(theResource);
|
||||
|
@ -77,7 +77,7 @@ public class MdmGoldenResourceFindingSvc {
|
|||
}
|
||||
|
||||
public IAnyResource getGoldenResourceFromMatchedGoldenResourceCandidate(MatchedGoldenResourceCandidate theMatchedGoldenResourceCandidate, String theResourceType) {
|
||||
ResourcePersistentId personPid = theMatchedGoldenResourceCandidate.getCandidatePersonPid();
|
||||
return myMdmResourceDaoSvc.readGoldenResourceByPid(personPid, theResourceType);
|
||||
ResourcePersistentId goldenResourcePid = theMatchedGoldenResourceCandidate.getCandidateGoldenResourcePid();
|
||||
return myMdmResourceDaoSvc.readGoldenResourceByPid(goldenResourcePid, theResourceType);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ import ca.uhn.fhir.jpa.mdm.config.MdmSubmitterConfig;
|
|||
import ca.uhn.fhir.jpa.mdm.config.TestMdmConfigR4;
|
||||
import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc;
|
||||
import ca.uhn.fhir.jpa.mdm.matcher.IsLinkedTo;
|
||||
import ca.uhn.fhir.jpa.mdm.matcher.IsMatchedToAPerson;
|
||||
import ca.uhn.fhir.jpa.mdm.matcher.IsMatchedToAGoldenResource;
|
||||
import ca.uhn.fhir.jpa.mdm.matcher.IsPossibleDuplicateOf;
|
||||
import ca.uhn.fhir.jpa.mdm.matcher.IsPossibleLinkedTo;
|
||||
import ca.uhn.fhir.jpa.mdm.matcher.IsPossibleMatchWith;
|
||||
|
@ -414,7 +414,7 @@ abstract public class BaseMdmR4Test extends BaseJpaR4Test {
|
|||
}
|
||||
|
||||
protected Matcher<IAnyResource> matchedToAGoldenResource() {
|
||||
return IsMatchedToAPerson.matchedToAGoldenResource(myIdHelperService, myMdmLinkDaoSvc);
|
||||
return IsMatchedToAGoldenResource.matchedToAGoldenResource(myIdHelperService, myMdmLinkDaoSvc);
|
||||
}
|
||||
|
||||
protected Patient getOnlyGoldenPatient() {
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
package ca.uhn.fhir.jpa.mdm.interceptor;
|
||||
|
||||
import ca.uhn.fhir.mdm.model.CanonicalEID;
|
||||
import ca.uhn.fhir.mdm.rules.config.MdmSettings;
|
||||
import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome;
|
||||
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.entity.MdmLink;
|
||||
import ca.uhn.fhir.mdm.model.CanonicalEID;
|
||||
import ca.uhn.fhir.mdm.rules.config.MdmSettings;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import ca.uhn.fhir.rest.server.TransactionLogMessages;
|
||||
|
@ -19,7 +19,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.Person;
|
||||
import org.hl7.fhir.r4.model.SearchParameter;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -73,7 +72,7 @@ public class MdmStorageInterceptorIT extends BaseMdmR4Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testDeletePersonDeletesLinks() throws InterruptedException {
|
||||
public void testDeleteGoldenResourceDeletesLinks() throws InterruptedException {
|
||||
myMdmHelper.createWithLatch(buildPaulPatient());
|
||||
assertLinkCount(1);
|
||||
Patient sourcePatient = getOnlyGoldenPatient();
|
||||
|
@ -83,7 +82,7 @@ public class MdmStorageInterceptorIT extends BaseMdmR4Test {
|
|||
|
||||
@Test
|
||||
public void testCreatePatientWithMdmTagForbidden() throws InterruptedException {
|
||||
//Creating a person with the MDM-MANAGED tag should fail
|
||||
//Creating a golden resource with the MDM-MANAGED tag should fail
|
||||
Patient patient = new Patient();
|
||||
patient.getMeta().addTag(SYSTEM_MDM_MANAGED, CODE_HAPI_MDM_MANAGED, "User is managed by MDM");
|
||||
try {
|
||||
|
@ -119,7 +118,7 @@ public class MdmStorageInterceptorIT extends BaseMdmR4Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testCreatingPersonWithInsufficentMDMAttributesIsNotMDMProcessed() throws InterruptedException {
|
||||
public void testCreatingGoldenResourceWithInsufficentMDMAttributesIsNotMDMProcessed() throws InterruptedException {
|
||||
myMdmHelper.doCreateResource(new Patient(), true);
|
||||
assertLinkCount(0);
|
||||
}
|
||||
|
@ -158,7 +157,7 @@ public class MdmStorageInterceptorIT extends BaseMdmR4Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testPersonRecordsManagedByMdmAllShareSameTag() throws InterruptedException {
|
||||
public void testGoldenResourceRecordsManagedByMdmAllShareSameTag() throws InterruptedException {
|
||||
myMdmHelper.createWithLatch(buildJanePatient());
|
||||
myMdmHelper.createWithLatch(buildPaulPatient());
|
||||
|
||||
|
@ -166,22 +165,22 @@ public class MdmStorageInterceptorIT extends BaseMdmR4Test {
|
|||
IBundleProvider search = myPatientDao.search(buildGoldenResourceSearchParameterMap());
|
||||
List<IBaseResource> resources = search.getResources(0, search.size());
|
||||
|
||||
for (IBaseResource person : resources) {
|
||||
assertThat(person.getMeta().getTag(SYSTEM_MDM_MANAGED, CODE_HAPI_MDM_MANAGED), is(notNullValue()));
|
||||
for (IBaseResource r : resources) {
|
||||
assertThat(r.getMeta().getTag(SYSTEM_MDM_MANAGED, CODE_HAPI_MDM_MANAGED), is(notNullValue()));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonMdmManagedPersonCannotHaveMdmManagedTagAddedToThem() {
|
||||
//Person created manually.
|
||||
Person person = new Person();
|
||||
DaoMethodOutcome daoMethodOutcome = myMdmHelper.doCreateResource(person, true);
|
||||
public void testNonMdmManagedGoldenResourceCannotHaveMdmManagedTagAddedToThem() {
|
||||
// GoldenResource created manually.
|
||||
Patient patient = new Patient();
|
||||
DaoMethodOutcome daoMethodOutcome = myMdmHelper.doCreateResource(patient, true);
|
||||
assertNotNull(daoMethodOutcome.getId());
|
||||
|
||||
//Updating that person to set them as MDM managed is not allowed.
|
||||
person.getMeta().addTag(SYSTEM_MDM_MANAGED, CODE_HAPI_MDM_MANAGED, "User is managed by MDM");
|
||||
//Updating that patient to set them as MDM managed is not allowed.
|
||||
patient.getMeta().addTag(SYSTEM_MDM_MANAGED, CODE_HAPI_MDM_MANAGED, "User is managed by MDM");
|
||||
try {
|
||||
myMdmHelper.doUpdateResource(person, true);
|
||||
myMdmHelper.doUpdateResource(patient, true);
|
||||
fail();
|
||||
} catch (ForbiddenOperationException e) {
|
||||
assertEquals("The HAPI-MDM tag on a resource may not be changed once created.", e.getMessage());
|
||||
|
@ -189,8 +188,8 @@ public class MdmStorageInterceptorIT extends BaseMdmR4Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testMdmManagedPersonCannotBeModifiedByPersonUpdateRequest() throws InterruptedException {
|
||||
// When MDM is enabled, only the MDM system is allowed to modify Person links of Persons with the MDM-MANAGED tag.
|
||||
public void testMdmManagedGoldenResourceCannotBeModifiedByGoldenResourceUpdateRequest() throws InterruptedException {
|
||||
// When MDM is enabled, only the MDM system is allowed to modify GoldenResource links of GoldenResources with the MDM-MANAGED tag.
|
||||
Patient patient = new Patient();
|
||||
IIdType patientId = myMdmHelper.createWithLatch(buildPaulPatient()).getDaoMethodOutcome().getId().toUnqualifiedVersionless();
|
||||
|
||||
|
@ -223,7 +222,7 @@ public class MdmStorageInterceptorIT extends BaseMdmR4Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testWhenASingularPatientUpdatesExternalEidThatPersonEidIsUpdated() throws InterruptedException {
|
||||
public void testWhenASingularPatientUpdatesExternalEidThatGoldenResourceEidIsUpdated() throws InterruptedException {
|
||||
Patient jane = addExternalEID(buildJanePatient(), "some_eid");
|
||||
MdmHelperR4.OutcomeAndLogMessageWrapper latch = myMdmHelper.createWithLatch(jane);
|
||||
jane.setId(latch.getDaoMethodOutcome().getId());
|
||||
|
@ -231,8 +230,8 @@ public class MdmStorageInterceptorIT extends BaseMdmR4Test {
|
|||
jane = addExternalEID(jane, "some_new_eid");
|
||||
|
||||
MdmHelperR4.OutcomeAndLogMessageWrapper outcomeWrapper = myMdmHelper.updateWithLatch(jane);
|
||||
IAnyResource person = getGoldenResourceFromTargetResource(jane);
|
||||
List<CanonicalEID> externalEids = myEIDHelper.getExternalEid(person);
|
||||
IAnyResource patient = getGoldenResourceFromTargetResource(jane);
|
||||
List<CanonicalEID> externalEids = myEIDHelper.getExternalEid(patient);
|
||||
assertThat(externalEids, hasSize(1));
|
||||
assertThat("some_new_eid", is(equalTo(externalEids.get(0).getValue())));
|
||||
}
|
||||
|
|
|
@ -11,13 +11,13 @@ import java.util.stream.Collectors;
|
|||
|
||||
/**
|
||||
* A Matcher which allows us to check that a target patient/practitioner at a given link level.
|
||||
* is linked to a set of patients/practitioners via a person.
|
||||
* is linked to a set of patients/practitioners via a golden resource.
|
||||
*
|
||||
*/
|
||||
public class IsLinkedTo extends BaseGoldenResourceMatcher {
|
||||
|
||||
private List<Long> baseResourcePersonPids;
|
||||
private Long incomingResourcePersonPid;
|
||||
private List<Long> baseResourceGoldenResourcePids;
|
||||
private Long incomingResourceGoldenResourcePid;
|
||||
|
||||
protected IsLinkedTo(IdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theBaseResource) {
|
||||
super(theIdHelperService, theMdmLinkDaoSvc, theBaseResource);
|
||||
|
@ -26,16 +26,16 @@ public class IsLinkedTo extends BaseGoldenResourceMatcher {
|
|||
|
||||
@Override
|
||||
protected boolean matchesSafely(IAnyResource theIncomingResource) {
|
||||
incomingResourcePersonPid = getMatchedResourcePidFromResource(theIncomingResource);
|
||||
incomingResourceGoldenResourcePid = getMatchedResourcePidFromResource(theIncomingResource);
|
||||
|
||||
//OK, lets grab all the person pids of the resources passed in via the constructor.
|
||||
baseResourcePersonPids = myBaseResources.stream()
|
||||
//OK, lets grab all the golden resource pids of the resources passed in via the constructor.
|
||||
baseResourceGoldenResourcePids = myBaseResources.stream()
|
||||
.map(this::getMatchedResourcePidFromResource)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
//The resources are linked if all person pids match the incoming person pid.
|
||||
return baseResourcePersonPids.stream()
|
||||
.allMatch(pid -> pid.equals(incomingResourcePersonPid));
|
||||
//The resources are linked if all golden resource pids match the incoming golden resource pid.
|
||||
return baseResourceGoldenResourcePids.stream()
|
||||
.allMatch(pid -> pid.equals(incomingResourceGoldenResourcePid));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -10,12 +10,12 @@ import org.hl7.fhir.instance.model.api.IAnyResource;
|
|||
|
||||
import java.util.Optional;
|
||||
|
||||
public class IsMatchedToAPerson extends TypeSafeMatcher<IAnyResource> {
|
||||
public class IsMatchedToAGoldenResource extends TypeSafeMatcher<IAnyResource> {
|
||||
|
||||
private final IdHelperService myIdHelperService;
|
||||
private final MdmLinkDaoSvc myMdmLinkDaoSvc;
|
||||
|
||||
public IsMatchedToAPerson(IdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc) {
|
||||
public IsMatchedToAGoldenResource(IdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc) {
|
||||
myIdHelperService = theIdHelperService;
|
||||
myMdmLinkDaoSvc = theMdmLinkDaoSvc;
|
||||
}
|
||||
|
@ -28,10 +28,10 @@ public class IsMatchedToAPerson extends TypeSafeMatcher<IAnyResource> {
|
|||
|
||||
@Override
|
||||
public void describeTo(Description theDescription) {
|
||||
theDescription.appendText("patient/practitioner was not linked to a Person.");
|
||||
theDescription.appendText("target was not linked to a Golden Resource.");
|
||||
}
|
||||
|
||||
public static Matcher<IAnyResource> matchedToAGoldenResource(IdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc) {
|
||||
return new IsMatchedToAPerson(theIdHelperService, theMdmLinkDaoSvc);
|
||||
return new IsMatchedToAGoldenResource(theIdHelperService, theMdmLinkDaoSvc);
|
||||
}
|
||||
}
|
|
@ -13,11 +13,12 @@ import java.util.Optional;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
public class IsPossibleDuplicateOf extends BaseGoldenResourceMatcher {
|
||||
|
||||
/**
|
||||
* Matcher with tells us if there is an MdmLink with between these two resources that are considered POSSIBLE DUPLICATE.
|
||||
* For use only on persons.
|
||||
* For use only on GoldenResource.
|
||||
*/
|
||||
private Long incomingPersonPid;
|
||||
private Long incomingGoldenResourcePid;
|
||||
|
||||
protected IsPossibleDuplicateOf(IdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theBaseResource) {
|
||||
super(theIdHelperService, theMdmLinkDaoSvc, theBaseResource);
|
||||
|
@ -25,20 +26,19 @@ public class IsPossibleDuplicateOf extends BaseGoldenResourceMatcher {
|
|||
|
||||
@Override
|
||||
protected boolean matchesSafely(IAnyResource theIncomingResource) {
|
||||
incomingGoldenResourcePid = getMatchedResourcePidFromResource(theIncomingResource);
|
||||
|
||||
incomingPersonPid = getMatchedResourcePidFromResource(theIncomingResource);
|
||||
|
||||
List<Long> personPidsToMatch = myBaseResources.stream()
|
||||
List<Long> goldenResourcePidsToMatch = myBaseResources.stream()
|
||||
.map(this::getMatchedResourcePidFromResource)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
|
||||
//Returns true if there is a POSSIBLE_DUPLICATE between the incoming resource, and all of the resources passed in via the constructor.
|
||||
return personPidsToMatch.stream()
|
||||
return goldenResourcePidsToMatch.stream()
|
||||
.map(baseResourcePid -> {
|
||||
Optional<MdmLink> duplicateLink = myMdmLinkDaoSvc.getMdmLinksByPersonPidTargetPidAndMatchResult(baseResourcePid, incomingPersonPid, MdmMatchResultEnum.POSSIBLE_DUPLICATE);
|
||||
Optional<MdmLink> duplicateLink = myMdmLinkDaoSvc.getMdmLinksByGoldenResourcePidTargetPidAndMatchResult(baseResourcePid, incomingGoldenResourcePid, MdmMatchResultEnum.POSSIBLE_DUPLICATE);
|
||||
if (!duplicateLink.isPresent()) {
|
||||
duplicateLink = myMdmLinkDaoSvc.getMdmLinksByPersonPidTargetPidAndMatchResult(incomingPersonPid, baseResourcePid, MdmMatchResultEnum.POSSIBLE_DUPLICATE);
|
||||
duplicateLink = myMdmLinkDaoSvc.getMdmLinksByGoldenResourcePidTargetPidAndMatchResult(incomingGoldenResourcePid, baseResourcePid, MdmMatchResultEnum.POSSIBLE_DUPLICATE);
|
||||
}
|
||||
return duplicateLink;
|
||||
}).allMatch(Optional::isPresent);
|
||||
|
@ -46,7 +46,7 @@ public class IsPossibleDuplicateOf extends BaseGoldenResourceMatcher {
|
|||
|
||||
@Override
|
||||
public void describeTo(Description theDescription) {
|
||||
theDescription.appendText("Resource was not duplicate of Resource/" + incomingPersonPid);
|
||||
theDescription.appendText("Resource was not duplicate of Resource/" + incomingGoldenResourcePid);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -10,14 +10,13 @@ import java.util.List;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* A Matcher which allows us to check that a target patient/practitioner at a given link level.
|
||||
* is linked to a set of patients/practitioners via a person.
|
||||
*
|
||||
* A Matcher which allows us to check that a target resource at a given link level
|
||||
* is linked to a set of target resources via a golden resource.
|
||||
*/
|
||||
public class IsPossibleLinkedTo extends BaseGoldenResourceMatcher {
|
||||
|
||||
private List<Long> baseResourcePersonPids;
|
||||
private Long incomingResourcePersonPid;
|
||||
private List<Long> baseResourceGoldenResourcePids;
|
||||
private Long incomingResourceGoldenResourcePid;
|
||||
|
||||
protected IsPossibleLinkedTo(IdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theTargetResources) {
|
||||
super(theIdHelperService, theMdmLinkDaoSvc, theTargetResources);
|
||||
|
@ -25,16 +24,16 @@ public class IsPossibleLinkedTo extends BaseGoldenResourceMatcher {
|
|||
|
||||
@Override
|
||||
protected boolean matchesSafely(IAnyResource theGoldenResource) {
|
||||
incomingResourcePersonPid = myIdHelperService.getPidOrNull(theGoldenResource);
|
||||
incomingResourceGoldenResourcePid = myIdHelperService.getPidOrNull(theGoldenResource);
|
||||
|
||||
//OK, lets grab all the person pids of the resources passed in via the constructor.
|
||||
baseResourcePersonPids = myBaseResources.stream()
|
||||
//OK, lets grab all the golden resource pids of the resources passed in via the constructor.
|
||||
baseResourceGoldenResourcePids = myBaseResources.stream()
|
||||
.flatMap(iBaseResource -> getPossibleMatchedGoldenResourcePidsFromTarget(iBaseResource).stream())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
//The resources are linked if all person pids match the incoming person pid.
|
||||
return baseResourcePersonPids.stream()
|
||||
.allMatch(pid -> pid.equals(incomingResourcePersonPid));
|
||||
//The resources are linked if all golden resource pids match the incoming golden resource pid.
|
||||
return baseResourceGoldenResourcePids.stream()
|
||||
.allMatch(pid -> pid.equals(incomingResourceGoldenResourcePid));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -25,13 +25,13 @@ public class IsPossibleMatchWith extends BaseGoldenResourceMatcher {
|
|||
protected boolean matchesSafely(IAnyResource theIncomingResource) {
|
||||
List<MdmLink> mdmLinks = getMdmLinksForTarget(theIncomingResource, MdmMatchResultEnum.POSSIBLE_MATCH);
|
||||
|
||||
List<Long> personPidsToMatch = myBaseResources.stream()
|
||||
List<Long> goldenResourcePidsToMatch = myBaseResources.stream()
|
||||
.map(this::getMatchedResourcePidFromResource)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (personPidsToMatch.isEmpty()) {
|
||||
personPidsToMatch = myBaseResources.stream()
|
||||
if (goldenResourcePidsToMatch.isEmpty()) {
|
||||
goldenResourcePidsToMatch = myBaseResources.stream()
|
||||
.flatMap(iBaseResource -> getPossibleMatchedGoldenResourcePidsFromTarget(iBaseResource).stream())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ public class IsPossibleMatchWith extends BaseGoldenResourceMatcher {
|
|||
.stream().map(MdmLink::getGoldenResourcePid)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return mdmLinkGoldenResourcePids.containsAll(personPidsToMatch);
|
||||
return mdmLinkGoldenResourcePids.containsAll(goldenResourcePidsToMatch);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -30,6 +30,7 @@ import static org.hamcrest.Matchers.nullValue;
|
|||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
public class MdmProviderClearLinkR4Test extends BaseLinkR4Test {
|
||||
|
||||
protected Practitioner myPractitioner;
|
||||
protected StringType myPractitionerId;
|
||||
protected IAnyResource myPractitionerGoldenResource;
|
||||
|
@ -78,29 +79,29 @@ public class MdmProviderClearLinkR4Test extends BaseLinkR4Test {
|
|||
|
||||
}
|
||||
@Test
|
||||
public void testPersonsWithMultipleHistoricalVersionsCanBeDeleted() {
|
||||
public void testGoldenResourceWithMultipleHistoricalVersionsCanBeDeleted() {
|
||||
createPatientAndUpdateLinks(buildJanePatient());
|
||||
createPatientAndUpdateLinks(buildJanePatient());
|
||||
createPatientAndUpdateLinks(buildJanePatient());
|
||||
createPatientAndUpdateLinks(buildJanePatient());
|
||||
Patient patientAndUpdateLinks = createPatientAndUpdateLinks(buildJanePatient());
|
||||
IAnyResource person = getGoldenResourceFromTargetResource(patientAndUpdateLinks);
|
||||
assertThat(person, is(notNullValue()));
|
||||
IAnyResource goldenResource = getGoldenResourceFromTargetResource(patientAndUpdateLinks);
|
||||
assertThat(goldenResource, is(notNullValue()));
|
||||
myMdmProviderR4.clearMdmLinks(null, myRequestDetails);
|
||||
assertNoPatientLinksExist();
|
||||
person = getGoldenResourceFromTargetResource(patientAndUpdateLinks);
|
||||
assertThat(person, is(nullValue()));
|
||||
goldenResource = getGoldenResourceFromTargetResource(patientAndUpdateLinks);
|
||||
assertThat(goldenResource, is(nullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPersonWithLinksToOtherPersonsCanBeDeleted() {
|
||||
public void testGoldenResourceWithLinksToOtherGoldenResourcesCanBeDeleted() {
|
||||
createPatientAndUpdateLinks(buildJanePatient());
|
||||
Patient patientAndUpdateLinks1 = createPatientAndUpdateLinks(buildJanePatient());
|
||||
Patient patientAndUpdateLinks = createPatientAndUpdateLinks(buildPaulPatient());
|
||||
|
||||
IAnyResource personFromTarget = getGoldenResourceFromTargetResource(patientAndUpdateLinks);
|
||||
IAnyResource personFromTarget2 = getGoldenResourceFromTargetResource(patientAndUpdateLinks1);
|
||||
linkPersons(personFromTarget, personFromTarget2);
|
||||
IAnyResource goldenResourceFromTarget = getGoldenResourceFromTargetResource(patientAndUpdateLinks);
|
||||
IAnyResource goldenResourceFromTarget2 = getGoldenResourceFromTargetResource(patientAndUpdateLinks1);
|
||||
linkGoldenResources(goldenResourceFromTarget, goldenResourceFromTarget2);
|
||||
|
||||
//SUT
|
||||
myMdmProviderR4.clearMdmLinks(null, myRequestDetails);
|
||||
|
@ -119,19 +120,19 @@ public class MdmProviderClearLinkR4Test extends BaseLinkR4Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testPersonsWithCircularReferenceCanBeCleared() {
|
||||
public void testGoldenResourceWithCircularReferenceCanBeCleared() {
|
||||
Patient patientAndUpdateLinks = createPatientAndUpdateLinks(buildPaulPatient());
|
||||
Patient patientAndUpdateLinks1 = createPatientAndUpdateLinks(buildJanePatient());
|
||||
Patient patientAndUpdateLinks2 = createPatientAndUpdateLinks(buildFrankPatient());
|
||||
|
||||
IAnyResource personFromTarget = getGoldenResourceFromTargetResource(patientAndUpdateLinks);
|
||||
IAnyResource personFromTarget1 = getGoldenResourceFromTargetResource(patientAndUpdateLinks1);
|
||||
IAnyResource personFromTarget2 = getGoldenResourceFromTargetResource(patientAndUpdateLinks2);
|
||||
IAnyResource goldenResourceFromTarget = getGoldenResourceFromTargetResource(patientAndUpdateLinks);
|
||||
IAnyResource goldenResourceFromTarget1 = getGoldenResourceFromTargetResource(patientAndUpdateLinks1);
|
||||
IAnyResource goldenResourceFromTarget2 = getGoldenResourceFromTargetResource(patientAndUpdateLinks2);
|
||||
|
||||
// A -> B -> C -> A linkages.
|
||||
linkPersons(personFromTarget, personFromTarget1);
|
||||
linkPersons(personFromTarget1, personFromTarget2);
|
||||
linkPersons(personFromTarget2, personFromTarget);
|
||||
linkGoldenResources(goldenResourceFromTarget, goldenResourceFromTarget1);
|
||||
linkGoldenResources(goldenResourceFromTarget1, goldenResourceFromTarget2);
|
||||
linkGoldenResources(goldenResourceFromTarget2, goldenResourceFromTarget);
|
||||
|
||||
//SUT
|
||||
Parameters parameters = myMdmProviderR4.clearMdmLinks(null, myRequestDetails);
|
||||
|
@ -145,7 +146,7 @@ public class MdmProviderClearLinkR4Test extends BaseLinkR4Test {
|
|||
}
|
||||
|
||||
//TODO GGG unclear if we actually need to reimplement this.
|
||||
private void linkPersons(IAnyResource theGoldenResource, IAnyResource theTargetResource) {
|
||||
private void linkGoldenResources(IAnyResource theGoldenResource, IAnyResource theTargetResource) {
|
||||
// TODO NG - Should be ok to leave this - not really
|
||||
// throw new UnsupportedOperationException("We need to fix this!");
|
||||
myMdmLinkDaoSvc.createOrUpdateLinkEntity(theGoldenResource, theTargetResource, POSSIBLE_MATCH, MdmLinkSourceEnum.AUTO, createContextForCreate("Patient"));
|
||||
|
|
|
@ -20,7 +20,7 @@ import static org.junit.Assert.assertTrue;
|
|||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
public class MdmProviderMergePersonsR4Test extends BaseProviderR4Test {
|
||||
public class MdmProviderMergeGoldenResourcesR4Test extends BaseProviderR4Test {
|
||||
|
||||
private Patient myFromGoldenPatient;
|
||||
private StringType myFromGoldenPatientId;
|
||||
|
@ -70,10 +70,10 @@ public class MdmProviderMergePersonsR4Test extends BaseProviderR4Test {
|
|||
|
||||
@Test
|
||||
public void testUnmanagedMerge() {
|
||||
StringType fromPersonId = new StringType(createPatient().getIdElement().getValue());
|
||||
StringType toPersonId = new StringType(createPatient().getIdElement().getValue());
|
||||
StringType fromGoldenResourceId = new StringType(createPatient().getIdElement().getValue());
|
||||
StringType toGoldenResourceId = new StringType(createPatient().getIdElement().getValue());
|
||||
try {
|
||||
myMdmProviderR4.mergeGoldenResources(fromPersonId, toPersonId, myRequestDetails);
|
||||
myMdmProviderR4.mergeGoldenResources(fromGoldenResourceId, toGoldenResourceId, myRequestDetails);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("Only MDM managed resources can be merged. MDM managed resources must have the HAPI-MDM tag.", e.getMessage());
|
||||
|
@ -105,24 +105,31 @@ public class MdmProviderMergePersonsR4Test extends BaseProviderR4Test {
|
|||
@Test
|
||||
public void testBadParams() {
|
||||
try {
|
||||
myMdmProviderR4.mergeGoldenResources(new StringType("Person/1"), new StringType("Person/1"), myRequestDetails);
|
||||
myMdmProviderR4.mergeGoldenResources(new StringType("Patient/1"), new StringType("Patient/1"), myRequestDetails);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("fromPersonId must be different from toPersonId", e.getMessage());
|
||||
assertEquals("fromGoldenResourceId must be different from toGoldenResourceId", e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
myMdmProviderR4.mergeGoldenResources(new StringType("Person/abc"), myToGoldenPatientId, myRequestDetails);
|
||||
myMdmProviderR4.mergeGoldenResources(new StringType("Patient/abc"), myToGoldenPatientId, myRequestDetails);
|
||||
fail();
|
||||
} catch (ResourceNotFoundException e) {
|
||||
assertEquals("Resource Person/abc is not known", e.getMessage());
|
||||
assertEquals("Resource Patient/abc is not known", e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
myMdmProviderR4.mergeGoldenResources(myFromGoldenPatientId, new StringType("Person/abc"), myRequestDetails);
|
||||
myMdmProviderR4.mergeGoldenResources(new StringType("Organization/abc"), myToGoldenPatientId, myRequestDetails);
|
||||
fail();
|
||||
} catch (ResourceNotFoundException e) {
|
||||
assertEquals("Resource Person/abc is not known", e.getMessage());
|
||||
assertEquals("Resource Organization/abc is not known", e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
myMdmProviderR4.mergeGoldenResources(myFromGoldenPatientId, new StringType("Patient/abc"), myRequestDetails);
|
||||
fail();
|
||||
} catch (ResourceNotFoundException e) {
|
||||
assertEquals("Resource Patient/abc is not known", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -29,8 +29,8 @@ import static org.junit.jupiter.api.Assertions.fail;
|
|||
public class MdmProviderQueryLinkR4Test extends BaseLinkR4Test {
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(MdmProviderQueryLinkR4Test.class);
|
||||
private StringType myLinkSource;
|
||||
private StringType myPerson1Id;
|
||||
private StringType myPerson2Id;
|
||||
private StringType myGoldenResource1Id;
|
||||
private StringType myGoldenResource2Id;
|
||||
|
||||
@Override
|
||||
@BeforeEach
|
||||
|
@ -43,10 +43,10 @@ public class MdmProviderQueryLinkR4Test extends BaseLinkR4Test {
|
|||
// Add a possible duplicate
|
||||
myLinkSource = new StringType(MdmLinkSourceEnum.AUTO.name());
|
||||
Patient sourcePatient1 = createGoldenPatient();
|
||||
myPerson1Id = new StringType(sourcePatient1.getIdElement().toVersionless().getValue());
|
||||
myGoldenResource1Id = new StringType(sourcePatient1.getIdElement().toVersionless().getValue());
|
||||
Long sourcePatient1Pid = myIdHelperService.getPidOrNull(sourcePatient1);
|
||||
Patient sourcePatient2 = createGoldenPatient();
|
||||
myPerson2Id = new StringType(sourcePatient2.getIdElement().toVersionless().getValue());
|
||||
myGoldenResource2Id = new StringType(sourcePatient2.getIdElement().toVersionless().getValue());
|
||||
Long sourcePatient2Pid = myIdHelperService.getPidOrNull(sourcePatient2);
|
||||
|
||||
MdmLink possibleDuplicateMdmLink = myMdmLinkDaoSvc.newMdmLink().setGoldenResourcePid(sourcePatient1Pid).setTargetPid(sourcePatient2Pid).setMatchResult(MdmMatchResultEnum.POSSIBLE_DUPLICATE).setLinkSource(MdmLinkSourceEnum.AUTO);
|
||||
|
@ -69,15 +69,15 @@ public class MdmProviderQueryLinkR4Test extends BaseLinkR4Test {
|
|||
// Add a third patient
|
||||
Patient patient = createPatientAndUpdateLinks(buildJanePatient());
|
||||
IdType patientId = patient.getIdElement().toVersionless();
|
||||
IAnyResource person = getGoldenResourceFromTargetResource(patient);
|
||||
IIdType personId = person.getIdElement().toVersionless();
|
||||
IAnyResource goldenResource = getGoldenResourceFromTargetResource(patient);
|
||||
IIdType goldenResourceId = goldenResource.getIdElement().toVersionless();
|
||||
|
||||
Parameters result = myMdmProviderR4.queryLinks(null, null, null, myLinkSource, myRequestDetails);
|
||||
ourLog.info(myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(result));
|
||||
List<Parameters.ParametersParameterComponent> list = result.getParameter();
|
||||
assertThat(list, hasSize(3));
|
||||
List<Parameters.ParametersParameterComponent> part = list.get(2).getPart();
|
||||
assertMdmLink(7, part, personId.getValue(), patientId.getValue(), MdmMatchResultEnum.MATCH, "false", "false", "2");
|
||||
assertMdmLink(7, part, goldenResourceId.getValue(), patientId.getValue(), MdmMatchResultEnum.MATCH, "false", "false", "2");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -87,7 +87,7 @@ public class MdmProviderQueryLinkR4Test extends BaseLinkR4Test {
|
|||
List<Parameters.ParametersParameterComponent> list = result.getParameter();
|
||||
assertThat(list, hasSize(1));
|
||||
List<Parameters.ParametersParameterComponent> part = list.get(0).getPart();
|
||||
assertMdmLink(2, part, myPerson1Id.getValue(), myPerson2Id.getValue(), MdmMatchResultEnum.POSSIBLE_DUPLICATE, "false", "false", null);
|
||||
assertMdmLink(2, part, myGoldenResource1Id.getValue(), myGoldenResource2Id.getValue(), MdmMatchResultEnum.POSSIBLE_DUPLICATE, "false", "false", null);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -98,7 +98,7 @@ public class MdmProviderQueryLinkR4Test extends BaseLinkR4Test {
|
|||
assertThat(list, hasSize(1));
|
||||
}
|
||||
{
|
||||
Parameters result = myMdmProviderR4.notDuplicate(myPerson1Id, myPerson2Id, myRequestDetails);
|
||||
Parameters result = myMdmProviderR4.notDuplicate(myGoldenResource1Id, myGoldenResource2Id, myRequestDetails);
|
||||
ourLog.info(myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(result));
|
||||
assertEquals("success", result.getParameterFirstRep().getName());
|
||||
assertTrue(((BooleanType) (result.getParameterFirstRep().getValue())).booleanValue());
|
||||
|
@ -111,17 +111,17 @@ public class MdmProviderQueryLinkR4Test extends BaseLinkR4Test {
|
|||
@Test
|
||||
public void testNotDuplicateBadId() {
|
||||
try {
|
||||
myMdmProviderR4.notDuplicate(myPerson1Id, new StringType("Person/notAnId123"), myRequestDetails);
|
||||
myMdmProviderR4.notDuplicate(myGoldenResource1Id, new StringType("Patient/notAnId123"), myRequestDetails);
|
||||
fail();
|
||||
} catch (ResourceNotFoundException e) {
|
||||
assertEquals("Resource Person/notAnId123 is not known", e.getMessage());
|
||||
assertEquals("Resource Patient/notAnId123 is not known", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void assertMdmLink(int theExpectedSize, List<Parameters.ParametersParameterComponent> thePart, String thePersonId, String theTargetId, MdmMatchResultEnum theMatchResult, String theEidMatch, String theNewPerson, String theScore) {
|
||||
private void assertMdmLink(int theExpectedSize, List<Parameters.ParametersParameterComponent> thePart, String theGoldenResourceId, String theTargetId, MdmMatchResultEnum theMatchResult, String theEidMatch, String theNewGoldenResource, String theScore) {
|
||||
assertThat(thePart, hasSize(theExpectedSize));
|
||||
assertThat(thePart.get(0).getName(), is("goldenResourceId"));
|
||||
assertThat(thePart.get(0).getValue().toString(), is(removeVersion(thePersonId)));
|
||||
assertThat(thePart.get(0).getValue().toString(), is(removeVersion(theGoldenResourceId)));
|
||||
assertThat(thePart.get(1).getName(), is("targetResourceId"));
|
||||
assertThat(thePart.get(1).getValue().toString(), is(removeVersion(theTargetId)));
|
||||
if (theExpectedSize > 2) {
|
||||
|
@ -134,7 +134,7 @@ public class MdmProviderQueryLinkR4Test extends BaseLinkR4Test {
|
|||
assertThat(thePart.get(4).getValue().primitiveValue(), is(theEidMatch));
|
||||
|
||||
assertThat(thePart.get(5).getName(), is("hadToCreateNewResource"));
|
||||
assertThat(thePart.get(5).getValue().primitiveValue(), is(theNewPerson));
|
||||
assertThat(thePart.get(5).getValue().primitiveValue(), is(theNewGoldenResource));
|
||||
|
||||
assertThat(thePart.get(6).getName(), is("score"));
|
||||
assertThat(thePart.get(6).getValue().primitiveValue(), is(theScore));
|
||||
|
|
|
@ -140,10 +140,10 @@ public class MdmProviderUpdateLinkR4Test extends BaseLinkR4Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateStrangePerson() {
|
||||
Patient person = createPatient();
|
||||
public void testUpdateStrangePatient() {
|
||||
Patient patient = createPatient();
|
||||
try {
|
||||
myMdmProviderR4.updateLink(new StringType(person.getIdElement().getValue()), myPatientId, NO_MATCH_RESULT, myRequestDetails);
|
||||
myMdmProviderR4.updateLink(new StringType(patient.getIdElement().getValue()), myPatientId, NO_MATCH_RESULT, myRequestDetails);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
String expectedMessage = myMessageHelper.getMessageForUnmanagedResource();
|
||||
|
@ -152,7 +152,7 @@ public class MdmProviderUpdateLinkR4Test extends BaseLinkR4Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testExcludedPerson() {
|
||||
public void testExcludedGoldenResource() {
|
||||
Patient patient = new Patient();
|
||||
patient.getMeta().addTag().setSystem(MdmConstants.SYSTEM_MDM_MANAGED).setCode(MdmConstants.CODE_NO_MDM_MANAGED);
|
||||
createPatient(patient);
|
||||
|
|
|
@ -37,7 +37,8 @@ import static org.hamcrest.Matchers.is;
|
|||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
public class MdmPersonMergerSvcTest extends BaseMdmR4Test {
|
||||
public class MdmGoldenResourceMergerSvcTest extends BaseMdmR4Test {
|
||||
|
||||
public static final String GIVEN_NAME = "Jenn";
|
||||
public static final String FAMILY_NAME = "Chan";
|
||||
public static final String POSTAL_CODE = "M6G 1B4";
|
||||
|
@ -114,7 +115,7 @@ public class MdmPersonMergerSvcTest extends BaseMdmR4Test {
|
|||
}
|
||||
|
||||
private MdmTransactionContext createMdmContext() {
|
||||
MdmTransactionContext mdmTransactionContext = new MdmTransactionContext(TransactionLogMessages.createFromTransactionGuid(UUID.randomUUID().toString()), MdmTransactionContext.OperationType.MERGE_PERSONS);
|
||||
MdmTransactionContext mdmTransactionContext = new MdmTransactionContext(TransactionLogMessages.createFromTransactionGuid(UUID.randomUUID().toString()), MdmTransactionContext.OperationType.MERGE_GOLDEN_RESOURCES);
|
||||
mdmTransactionContext.setResourceType("Patient");
|
||||
return mdmTransactionContext;
|
||||
}
|
||||
|
@ -149,7 +150,7 @@ public class MdmPersonMergerSvcTest extends BaseMdmR4Test {
|
|||
|
||||
@Test
|
||||
public void fullFromEmptyTo() {
|
||||
populatePerson(myFromGoldenPatient);
|
||||
populatePatient(myFromGoldenPatient);
|
||||
|
||||
Patient mergedSourcePatient = mergeGoldenPatients();
|
||||
// TODO NG - Revisit when rules are ready
|
||||
|
@ -162,7 +163,7 @@ public class MdmPersonMergerSvcTest extends BaseMdmR4Test {
|
|||
@Test
|
||||
public void emptyFromFullTo() {
|
||||
myFromGoldenPatient.getName().add(new HumanName().addGiven(BAD_GIVEN_NAME));
|
||||
populatePerson(myToGoldenPatient);
|
||||
populatePatient(myToGoldenPatient);
|
||||
|
||||
Patient mergedSourcePatient = mergeGoldenPatients();
|
||||
HumanName returnedName = mergedSourcePatient.getNameFirstRep();
|
||||
|
@ -176,7 +177,7 @@ public class MdmPersonMergerSvcTest extends BaseMdmR4Test {
|
|||
createMdmLink(myFromGoldenPatient, myTargetPatient1);
|
||||
|
||||
Patient mergedGoldenPatient = mergeGoldenPatients();
|
||||
List<MdmLink> links = getNonRedirectLinksByPerson(mergedGoldenPatient);
|
||||
List<MdmLink> links = getNonRedirectLinksByGoldenResource(mergedGoldenPatient);
|
||||
assertEquals(1, links.size());
|
||||
assertThat(mergedGoldenPatient, is(possibleLinkedTo(myTargetPatient1)));
|
||||
}
|
||||
|
@ -186,7 +187,7 @@ public class MdmPersonMergerSvcTest extends BaseMdmR4Test {
|
|||
createMdmLink(myToGoldenPatient, myTargetPatient1);
|
||||
|
||||
Patient mergedSourcePatient = mergeGoldenPatients();
|
||||
List<MdmLink> links = getNonRedirectLinksByPerson(mergedSourcePatient);
|
||||
List<MdmLink> links = getNonRedirectLinksByGoldenResource(mergedSourcePatient);
|
||||
assertEquals(1, links.size());
|
||||
assertThat(mergedSourcePatient, is(possibleLinkedTo(myTargetPatient1)));
|
||||
}
|
||||
|
@ -201,12 +202,12 @@ public class MdmPersonMergerSvcTest extends BaseMdmR4Test {
|
|||
createMdmLink(myToGoldenPatient, myTargetPatient1);
|
||||
|
||||
mergeGoldenPatients();
|
||||
List<MdmLink> links = getNonRedirectLinksByPerson(myToGoldenPatient);
|
||||
List<MdmLink> links = getNonRedirectLinksByGoldenResource(myToGoldenPatient);
|
||||
assertEquals(1, links.size());
|
||||
assertEquals(MdmLinkSourceEnum.MANUAL, links.get(0).getLinkSource());
|
||||
}
|
||||
|
||||
private List<MdmLink> getNonRedirectLinksByPerson(Patient theGoldenPatient) {
|
||||
private List<MdmLink> getNonRedirectLinksByGoldenResource(Patient theGoldenPatient) {
|
||||
return myMdmLinkDaoSvc.findMdmLinksByGoldenResource(theGoldenPatient).stream()
|
||||
.filter(link -> !link.isRedirect())
|
||||
.collect(Collectors.toList());
|
||||
|
@ -223,7 +224,7 @@ public class MdmPersonMergerSvcTest extends BaseMdmR4Test {
|
|||
createMdmLink(myToGoldenPatient, myTargetPatient1);
|
||||
|
||||
mergeGoldenPatients();
|
||||
List<MdmLink> links = getNonRedirectLinksByPerson(myToGoldenPatient);
|
||||
List<MdmLink> links = getNonRedirectLinksByGoldenResource(myToGoldenPatient);
|
||||
assertEquals(1, links.size());
|
||||
assertEquals(MdmLinkSourceEnum.MANUAL, links.get(0).getLinkSource());
|
||||
assertEquals(MdmMatchResultEnum.NO_MATCH, links.get(0).getMatchResult());
|
||||
|
@ -239,7 +240,7 @@ public class MdmPersonMergerSvcTest extends BaseMdmR4Test {
|
|||
saveLink(toLink);
|
||||
|
||||
mergeGoldenPatients();
|
||||
List<MdmLink> links = getNonRedirectLinksByPerson(myToGoldenPatient);
|
||||
List<MdmLink> links = getNonRedirectLinksByGoldenResource(myToGoldenPatient);
|
||||
assertEquals(1, links.size());
|
||||
assertEquals(MdmLinkSourceEnum.MANUAL, links.get(0).getLinkSource());
|
||||
assertEquals(MdmMatchResultEnum.NO_MATCH, links.get(0).getMatchResult());
|
||||
|
@ -434,7 +435,7 @@ public class MdmPersonMergerSvcTest extends BaseMdmR4Test {
|
|||
return myMdmLinkDaoSvc.createOrUpdateLinkEntity(theSourcePatient, theTargetPatient, POSSIBLE_MATCH, MdmLinkSourceEnum.AUTO, createContextForCreate("Patient"));
|
||||
}
|
||||
|
||||
private void populatePerson(Patient theSourcePatient) {
|
||||
private void populatePatient(Patient theSourcePatient) {
|
||||
theSourcePatient.addName(new HumanName().addGiven(GIVEN_NAME).setFamily(FAMILY_NAME));
|
||||
theSourcePatient.setGender(Enumerations.AdministrativeGender.FEMALE);
|
||||
theSourcePatient.setBirthDateElement(new DateType("1981-01-01"));
|
|
@ -95,8 +95,8 @@ public class MdmLinkSvcTest extends BaseMdmR4Test {
|
|||
|
||||
saveNoMatchLink(goldenPatient1Pid, goldenPatient2Pid);
|
||||
|
||||
myMdmLinkSvc.updateLink(goldenPatient1, goldenPatient2, MdmMatchOutcome.POSSIBLE_DUPLICATE, MdmLinkSourceEnum.AUTO, createContextForCreate("Person"));
|
||||
assertFalse(myMdmLinkDaoSvc.getMdmLinksByPersonPidTargetPidAndMatchResult(goldenPatient1Pid, goldenPatient2Pid, MdmMatchResultEnum.POSSIBLE_DUPLICATE).isPresent());
|
||||
myMdmLinkSvc.updateLink(goldenPatient1, goldenPatient2, MdmMatchOutcome.POSSIBLE_DUPLICATE, MdmLinkSourceEnum.AUTO, createContextForCreate("Patient"));
|
||||
assertFalse(myMdmLinkDaoSvc.getMdmLinksByGoldenResourcePidTargetPidAndMatchResult(goldenPatient1Pid, goldenPatient2Pid, MdmMatchResultEnum.POSSIBLE_DUPLICATE).isPresent());
|
||||
assertLinkCount(1);
|
||||
}
|
||||
|
||||
|
@ -113,8 +113,8 @@ public class MdmLinkSvcTest extends BaseMdmR4Test {
|
|||
|
||||
saveNoMatchLink(goldenPatient2Pid, goldenPatient1Pid);
|
||||
|
||||
myMdmLinkSvc.updateLink(goldenPatient1, goldenPatient2, MdmMatchOutcome.POSSIBLE_DUPLICATE, MdmLinkSourceEnum.AUTO, createContextForCreate("Person"));
|
||||
assertFalse(myMdmLinkDaoSvc.getMdmLinksByPersonPidTargetPidAndMatchResult(goldenPatient1Pid, goldenPatient2Pid, MdmMatchResultEnum.POSSIBLE_DUPLICATE).isPresent());
|
||||
myMdmLinkSvc.updateLink(goldenPatient1, goldenPatient2, MdmMatchOutcome.POSSIBLE_DUPLICATE, MdmLinkSourceEnum.AUTO, createContextForCreate("Patient"));
|
||||
assertFalse(myMdmLinkDaoSvc.getMdmLinksByGoldenResourcePidTargetPidAndMatchResult(goldenPatient1Pid, goldenPatient2Pid, MdmMatchResultEnum.POSSIBLE_DUPLICATE).isPresent());
|
||||
assertLinkCount(1);
|
||||
}
|
||||
|
||||
|
@ -135,7 +135,7 @@ public class MdmLinkSvcTest extends BaseMdmR4Test {
|
|||
|
||||
myMdmLinkSvc.updateLink(goldenPatient, patient, MdmMatchOutcome.NO_MATCH, MdmLinkSourceEnum.MANUAL, createContextForCreate("Patient"));
|
||||
try {
|
||||
myMdmLinkSvc.updateLink(goldenPatient, patient, MdmMatchOutcome.NEW_PERSON_MATCH, MdmLinkSourceEnum.AUTO, null);
|
||||
myMdmLinkSvc.updateLink(goldenPatient, patient, MdmMatchOutcome.NEW_GOLDEN_RESOURCE_MATCH, MdmLinkSourceEnum.AUTO, null);
|
||||
fail();
|
||||
} catch (InternalErrorException e) {
|
||||
assertThat(e.getMessage(), is(equalTo("MDM system is not allowed to modify links on manually created links")));
|
||||
|
@ -165,7 +165,7 @@ public class MdmLinkSvcTest extends BaseMdmR4Test {
|
|||
Patient patient2 = createPatient(buildJanePatient());
|
||||
assertEquals(0, myMdmLinkDao.count());
|
||||
|
||||
myMdmLinkDaoSvc.createOrUpdateLinkEntity(goldenPatient, patient1, MdmMatchOutcome.NEW_PERSON_MATCH, MdmLinkSourceEnum.MANUAL, createContextForCreate("Patient"));
|
||||
myMdmLinkDaoSvc.createOrUpdateLinkEntity(goldenPatient, patient1, MdmMatchOutcome.NEW_GOLDEN_RESOURCE_MATCH, MdmLinkSourceEnum.MANUAL, createContextForCreate("Patient"));
|
||||
myMdmLinkDaoSvc.createOrUpdateLinkEntity(goldenPatient, patient2, MdmMatchOutcome.NO_MATCH, MdmLinkSourceEnum.MANUAL, createContextForCreate("Patient"));
|
||||
|
||||
List<MdmLink> targets = myMdmLinkDaoSvc.findMdmLinksByGoldenResource(goldenPatient);
|
||||
|
|
|
@ -43,15 +43,16 @@ public class MdmMatchLinkSvcMultipleEidModeTest extends BaseMdmR4Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testIncomingPatientWithEIDThatMatchesPersonWithHapiEidAddsExternalEidsToPerson() {
|
||||
// Existing Person with system-assigned EID found linked from matched Patient. incoming Patient has EID. Replace Person system-assigned EID with Patient EID.
|
||||
public void testIncomingPatientWithEIDThatMatchesGoldenResourceWithHapiEidAddsExternalEidsToGoldenResource() {
|
||||
// Existing GoldenResource with system-assigned EID found linked from matched Patient. incoming Patient has EID.
|
||||
// Replace GoldenResource system-assigned EID with Patient EID.
|
||||
Patient patient = createPatientAndUpdateLinks(buildJanePatient());
|
||||
assertLinksMatchResult(MATCH);
|
||||
assertLinksCreatedNewResource(true);
|
||||
assertLinksMatchedByEid(false);
|
||||
|
||||
IAnyResource janePerson = getGoldenResourceFromTargetResource(patient);
|
||||
List<CanonicalEID> hapiEid = myEidHelper.getHapiEid(janePerson);
|
||||
IAnyResource janeGoldenResource = getGoldenResourceFromTargetResource(patient);
|
||||
List<CanonicalEID> hapiEid = myEidHelper.getHapiEid(janeGoldenResource);
|
||||
String foundHapiEid = hapiEid.get(0).getValue();
|
||||
|
||||
Patient janePatient = buildJanePatient();
|
||||
|
@ -62,7 +63,7 @@ public class MdmMatchLinkSvcMultipleEidModeTest extends BaseMdmR4Test {
|
|||
assertLinksCreatedNewResource(true, false);
|
||||
assertLinksMatchedByEid(false, false);
|
||||
|
||||
//We want to make sure the patients were linked to the same person.
|
||||
//We want to make sure the patients were linked to the same GoldenResource.
|
||||
assertThat(patient, is(sameGoldenResourceAs(janePatient)));
|
||||
|
||||
Patient sourcePatient = (Patient) getGoldenResourceFromTargetResource(patient);
|
||||
|
@ -111,9 +112,9 @@ public class MdmMatchLinkSvcMultipleEidModeTest extends BaseMdmR4Test {
|
|||
clearExternalEIDs(patient2);
|
||||
addExternalEID(patient2, "id_6");
|
||||
|
||||
//At this point, there should be 5 EIDs on the person
|
||||
Patient personFromTarget = (Patient) getGoldenResourceFromTargetResource(patient2);
|
||||
assertThat(personFromTarget.getIdentifier(), hasSize(5));
|
||||
//At this point, there should be 5 EIDs on the GoldenResource
|
||||
Patient patientFromTarget = (Patient) getGoldenResourceFromTargetResource(patient2);
|
||||
assertThat(patientFromTarget.getIdentifier(), hasSize(5));
|
||||
|
||||
updatePatientAndUpdateLinks(patient2);
|
||||
assertLinksMatchResult(MATCH, MATCH);
|
||||
|
@ -122,13 +123,12 @@ public class MdmMatchLinkSvcMultipleEidModeTest extends BaseMdmR4Test {
|
|||
|
||||
assertThat(patient1, is(sameGoldenResourceAs(patient2)));
|
||||
|
||||
personFromTarget = (Patient) getGoldenResourceFromTargetResource(patient2);
|
||||
assertThat(personFromTarget.getIdentifier(), hasSize(6));
|
||||
patientFromTarget = (Patient) getGoldenResourceFromTargetResource(patient2);
|
||||
assertThat(patientFromTarget.getIdentifier(), hasSize(6));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDuplicatePersonLinkIsCreatedWhenAnIncomingPatientArrivesWithEIDThatMatchesAnotherEIDPatient() {
|
||||
|
||||
public void testDuplicateGoldenResourceLinkIsCreatedWhenAnIncomingPatientArrivesWithEIDThatMatchesAnotherEIDPatient() {
|
||||
Patient patient1 = buildJanePatient();
|
||||
addExternalEID(patient1, "eid-1");
|
||||
addExternalEID(patient1, "eid-11");
|
||||
|
@ -153,7 +153,7 @@ public class MdmMatchLinkSvcMultipleEidModeTest extends BaseMdmR4Test {
|
|||
.map(myIdHelperService::getPidOrNull)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
//The two Persons related to the patients should both show up in the only existing POSSIBLE_DUPLICATE MdmLink.
|
||||
//The two GoldenResources related to the patients should both show up in the only existing POSSIBLE_DUPLICATE MdmLink.
|
||||
MdmLink mdmLink = possibleDuplicates.get(0);
|
||||
assertThat(mdmLink.getGoldenResourcePid(), is(in(duplicatePids)));
|
||||
assertThat(mdmLink.getTargetPid(), is(in(duplicatePids)));
|
||||
|
@ -161,7 +161,7 @@ public class MdmMatchLinkSvcMultipleEidModeTest extends BaseMdmR4Test {
|
|||
|
||||
@Test
|
||||
// Test Case #5
|
||||
public void testWhenPatientEidUpdateWouldCauseALinkChangeThatDuplicatePersonIsCreatedInstead() {
|
||||
public void testWhenPatientEidUpdateWouldCauseALinkChangeThatDuplicateGoldenResourceIsCreatedInstead() {
|
||||
Patient patient1 = buildJanePatient();
|
||||
addExternalEID(patient1, "eid-1");
|
||||
addExternalEID(patient1, "eid-11");
|
||||
|
@ -185,12 +185,12 @@ public class MdmMatchLinkSvcMultipleEidModeTest extends BaseMdmR4Test {
|
|||
assertLinksCreatedNewResource(true, true, false);
|
||||
assertLinksMatchedByEid(false, false, true);
|
||||
|
||||
//Now, Patient 2 and 3 are linked, and the person has 2 eids.
|
||||
//Now, Patient 2 and 3 are linked, and the GoldenResource has 2 eids.
|
||||
assertThat(patient2, is(sameGoldenResourceAs(patient3)));
|
||||
|
||||
//Now lets change one of the EIDs on the second patient to one that matches our original patient.
|
||||
//This should create a situation in which the incoming EIDs are matched to _two_ different persons. In this case, we want to
|
||||
//set them all to possible_match, and set the two persons as possible duplicates.
|
||||
//This should create a situation in which the incoming EIDs are matched to _two_ different GoldenResources. In this case, we want to
|
||||
//set them all to possible_match, and set the two GoldenResources as possible duplicates.
|
||||
patient2.getIdentifier().clear();
|
||||
addExternalEID(patient2, "eid-11");
|
||||
addExternalEID(patient2, "eid-22");
|
||||
|
|
|
@ -63,7 +63,7 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testAddPatientLinksToNewPersonIfNoneFound() {
|
||||
public void testAddPatientLinksToNewGoldenResourceIfNoneFound() {
|
||||
createPatientAndUpdateLinks(buildJanePatient());
|
||||
assertLinkCount(1);
|
||||
assertLinksMatchResult(MATCH);
|
||||
|
@ -97,7 +97,7 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testAddPatientLinksToExistingPersonIfMatch() {
|
||||
public void testAddPatientLinksToExistingGoldenResourceIfMatch() {
|
||||
Patient patient1 = createPatientAndUpdateLinks(buildJanePatient());
|
||||
assertLinkCount(1);
|
||||
|
||||
|
@ -111,18 +111,18 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testWhenMatchOccursOnPersonThatHasBeenManuallyNOMATCHedThatItIsBlocked() {
|
||||
public void testWhenMatchOccursOnGoldenResourceThatHasBeenManuallyNOMATCHedThatItIsBlocked() {
|
||||
Patient originalJane = createPatientAndUpdateLinks(buildJanePatient());
|
||||
IAnyResource janePerson = getGoldenResourceFromTargetResource(originalJane);
|
||||
IAnyResource janeGoldenResource = getGoldenResourceFromTargetResource(originalJane);
|
||||
|
||||
//Create a manual NO_MATCH between janePerson and unmatchedJane.
|
||||
//Create a manual NO_MATCH between janeGoldenResource and unmatchedJane.
|
||||
Patient unmatchedJane = createPatient(buildJanePatient());
|
||||
myMdmLinkSvc.updateLink(janePerson, unmatchedJane, MdmMatchOutcome.NO_MATCH, MdmLinkSourceEnum.MANUAL, createContextForCreate("Patient"));
|
||||
myMdmLinkSvc.updateLink(janeGoldenResource, unmatchedJane, MdmMatchOutcome.NO_MATCH, MdmLinkSourceEnum.MANUAL, createContextForCreate("Patient"));
|
||||
|
||||
//rerun MDM rules against unmatchedJane.
|
||||
myMdmMatchLinkSvc.updateMdmLinksForMdmTarget(unmatchedJane, createContextForCreate("Patient"));
|
||||
|
||||
assertThat(unmatchedJane, is(not(sameGoldenResourceAs(janePerson))));
|
||||
assertThat(unmatchedJane, is(not(sameGoldenResourceAs(janeGoldenResource))));
|
||||
assertThat(unmatchedJane, is(not(linkedTo(originalJane))));
|
||||
|
||||
assertLinksMatchResult(MATCH, NO_MATCH, MATCH);
|
||||
|
@ -131,23 +131,23 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testWhenPOSSIBLE_MATCHOccursOnPersonThatHasBeenManuallyNOMATCHedThatItIsBlocked() {
|
||||
public void testWhenPOSSIBLE_MATCHOccursOnGoldenResourceThatHasBeenManuallyNOMATCHedThatItIsBlocked() {
|
||||
Patient originalJane = createPatientAndUpdateLinks(buildJanePatient());
|
||||
|
||||
IBundleProvider search = myPatientDao.search(buildGoldenRecordSearchParameterMap());
|
||||
IAnyResource janePerson = (IAnyResource) search.getResources(0, 1).get(0);
|
||||
IAnyResource janeGoldenResource = (IAnyResource) search.getResources(0, 1).get(0);
|
||||
|
||||
Patient unmatchedPatient = createPatient(buildJanePatient());
|
||||
|
||||
// This simulates an admin specifically saying that unmatchedPatient does NOT match janePerson.
|
||||
myMdmLinkSvc.updateLink(janePerson, unmatchedPatient, MdmMatchOutcome.NO_MATCH, MdmLinkSourceEnum.MANUAL, createContextForCreate("Patient"));
|
||||
// This simulates an admin specifically saying that unmatchedPatient does NOT match janeGoldenResource.
|
||||
myMdmLinkSvc.updateLink(janeGoldenResource, unmatchedPatient, MdmMatchOutcome.NO_MATCH, MdmLinkSourceEnum.MANUAL, createContextForCreate("Patient"));
|
||||
// TODO change this so that it will only partially match.
|
||||
|
||||
//Now normally, when we run update links, it should link to janePerson. However, this manual NO_MATCH link
|
||||
//should cause a whole new Person to be created.
|
||||
//Now normally, when we run update links, it should link to janeGoldenResource. However, this manual NO_MATCH link
|
||||
//should cause a whole new GoldenResource to be created.
|
||||
myMdmMatchLinkSvc.updateMdmLinksForMdmTarget(unmatchedPatient, createContextForCreate("Patient"));
|
||||
|
||||
assertThat(unmatchedPatient, is(not(sameGoldenResourceAs(janePerson))));
|
||||
assertThat(unmatchedPatient, is(not(sameGoldenResourceAs(janeGoldenResource))));
|
||||
assertThat(unmatchedPatient, is(not(linkedTo(originalJane))));
|
||||
|
||||
assertLinksMatchResult(MATCH, NO_MATCH, MATCH);
|
||||
|
@ -156,7 +156,7 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testWhenPatientIsCreatedWithEIDThatItPropagatesToNewPerson() {
|
||||
public void testWhenPatientIsCreatedWithEIDThatItPropagatesToNewGoldenResource() {
|
||||
String sampleEID = "sample-eid";
|
||||
Patient janePatient = addExternalEID(buildJanePatient(), sampleEID);
|
||||
janePatient = createPatientAndUpdateLinks(janePatient);
|
||||
|
@ -172,7 +172,7 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testWhenPatientIsCreatedWithoutAnEIDThePersonGetsAutomaticallyAssignedOne() {
|
||||
public void testWhenPatientIsCreatedWithoutAnEIDTheGoldenResourceGetsAutomaticallyAssignedOne() {
|
||||
Patient patient = createPatientAndUpdateLinks(buildJanePatient());
|
||||
MdmLink mdmLink = myMdmLinkDaoSvc.getMatchedLinkForTargetPid(patient.getIdElement().getIdPartAsLong()).get();
|
||||
|
||||
|
@ -183,7 +183,7 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testPatientAttributesAreCopiedOverWhenPersonIsCreatedFromPatient() {
|
||||
public void testPatientAttributesAreCopiedOverWhenGoldenResourceIsCreatedFromPatient() {
|
||||
Patient patient = createPatientAndUpdateLinks(buildPatientWithNameIdAndBirthday("Gary", "GARY_ID", new Date()));
|
||||
|
||||
Optional<MdmLink> mdmLink = myMdmLinkDaoSvc.getMatchedLinkForTargetPid(patient.getIdElement().getIdPartAsLong());
|
||||
|
@ -199,25 +199,26 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testPatientMatchingAnotherPatientLinksToSamePerson() {
|
||||
public void testPatientMatchingAnotherPatientLinksToSameGoldenResource() {
|
||||
Patient janePatient = createPatientAndUpdateLinks(buildJanePatient());
|
||||
Patient sameJanePatient = createPatientAndUpdateLinks(buildJanePatient());
|
||||
assertThat(janePatient, is(sameGoldenResourceAs(sameJanePatient)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIncomingPatientWithEIDThatMatchesPersonWithHapiEidAddsExternalEidToPerson() {
|
||||
// Existing Person with system-assigned EID found linked from matched Patient. incoming Patient has EID. Replace Person system-assigned EID with Patient EID.
|
||||
public void testIncomingPatientWithEIDThatMatchesGoldenResourceWithHapiEidAddsExternalEidToGoldenResource() {
|
||||
// Existing GoldenResource with system-assigned EID found linked from matched Patient. incoming Patient has EID.
|
||||
// Replace GoldenResource system-assigned EID with Patient EID.
|
||||
Patient patient = createPatientAndUpdateLinks(buildJanePatient());
|
||||
|
||||
IAnyResource janePerson = getGoldenResourceFromTargetResource(patient);
|
||||
List<CanonicalEID> hapiEid = myEidHelper.getHapiEid(janePerson);
|
||||
IAnyResource janeGoldenResource = getGoldenResourceFromTargetResource(patient);
|
||||
List<CanonicalEID> hapiEid = myEidHelper.getHapiEid(janeGoldenResource);
|
||||
String foundHapiEid = hapiEid.get(0).getValue();
|
||||
|
||||
Patient janePatient = addExternalEID(buildJanePatient(), "12345");
|
||||
createPatientAndUpdateLinks(janePatient);
|
||||
|
||||
//We want to make sure the patients were linked to the same person.
|
||||
//We want to make sure the patients were linked to the same Golden Resource.
|
||||
assertThat(patient, is(sameGoldenResourceAs(janePatient)));
|
||||
|
||||
Patient sourcePatient = (Patient) getGoldenResourceFromTargetResource(patient);
|
||||
|
@ -267,7 +268,7 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testDuplicatePersonLinkIsCreatedWhenAnIncomingPatientArrivesWithEIDThatMatchesAnotherEIDPatient() {
|
||||
public void testDuplicateGoldenResourceLinkIsCreatedWhenAnIncomingPatientArrivesWithEIDThatMatchesAnotherEIDPatient() {
|
||||
|
||||
Patient patient1 = addExternalEID(buildJanePatient(), "eid-1");
|
||||
patient1 = createPatientAndUpdateLinks(patient1);
|
||||
|
@ -284,7 +285,7 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test {
|
|||
.map(myIdHelperService::getPidOrNull)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
//The two Persons related to the patients should both show up in the only existing POSSIBLE_DUPLICATE MdmLink.
|
||||
//The two GoldenResources related to the patients should both show up in the only existing POSSIBLE_DUPLICATE MdmLink.
|
||||
MdmLink mdmLink = possibleDuplicates.get(0);
|
||||
assertThat(mdmLink.getGoldenResourcePid(), is(in(duplicatePids)));
|
||||
assertThat(mdmLink.getTargetPid(), is(in(duplicatePids)));
|
||||
|
@ -318,9 +319,9 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testWhenThereAreNoMATCHOrPOSSIBLE_MATCHOutcomesThatANewPersonIsCreated() {
|
||||
public void testWhenThereAreNoMATCHOrPOSSIBLE_MATCHOutcomesThatANewGoldenResourceIsCreated() {
|
||||
/**
|
||||
* CASE 1: No MATCHED and no PROBABLE_MATCHED outcomes -> a new Person resource
|
||||
* CASE 1: No MATCHED and no PROBABLE_MATCHED outcomes -> a new GoldenResource resource
|
||||
* is created and linked to that Pat/Prac.
|
||||
*/
|
||||
assertLinkCount(0);
|
||||
|
@ -330,10 +331,10 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testWhenAllMATCHResultsAreToSamePersonThatTheyAreLinked() {
|
||||
public void testWhenAllMATCHResultsAreToSameGoldenResourceThatTheyAreLinked() {
|
||||
/**
|
||||
* CASE 2: All of the MATCHED Pat/Prac resources are already linked to the same Person ->
|
||||
* a new Link is created between the new Pat/Prac and that Person and is set to MATCHED.
|
||||
* CASE 2: All of the MATCHED Pat/Prac resources are already linked to the same GoldenResource ->
|
||||
* a new Link is created between the new Pat/Prac and that GoldenResource and is set to MATCHED.
|
||||
*/
|
||||
Patient janePatient = createPatientAndUpdateLinks(buildJanePatient());
|
||||
Patient janePatient2 = createPatientAndUpdateLinks(buildJanePatient());
|
||||
|
@ -347,27 +348,27 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testMATCHResultWithMultipleCandidatesCreatesPOSSIBLE_DUPLICATELinksAndNoPersonIsCreated() {
|
||||
public void testMATCHResultWithMultipleCandidatesCreatesPOSSIBLE_DUPLICATELinksAndNoGoldenResourceIsCreated() {
|
||||
/**
|
||||
* CASE 3: The MATCHED Pat/Prac resources link to more than one Person -> Mark all links as POSSIBLE_MATCH.
|
||||
* All other Person resources are marked as POSSIBLE_DUPLICATE of this first Person.
|
||||
* CASE 3: The MATCHED Pat/Prac resources link to more than one GoldenResource -> Mark all links as POSSIBLE_MATCH.
|
||||
* All other GoldenResource resources are marked as POSSIBLE_DUPLICATE of this first GoldenResource.
|
||||
*/
|
||||
Patient janePatient = createPatientAndUpdateLinks(buildJanePatient());
|
||||
Patient janePatient2 = createPatient(buildJanePatient());
|
||||
|
||||
//In a normal situation, janePatient2 would just match to jane patient, but here we need to hack it so they are their
|
||||
//own individual Persons for the purpose of this test.
|
||||
IAnyResource person = myGoldenResourceHelper.createGoldenResourceFromMdmTarget(janePatient2);
|
||||
myMdmLinkSvc.updateLink(person, janePatient2, MdmMatchOutcome.NEW_PERSON_MATCH, MdmLinkSourceEnum.AUTO, createContextForCreate("Patient"));
|
||||
//own individual GoldenResource for the purpose of this test.
|
||||
IAnyResource goldenResource = myGoldenResourceHelper.createGoldenResourceFromMdmTarget(janePatient2);
|
||||
myMdmLinkSvc.updateLink(goldenResource, janePatient2, MdmMatchOutcome.NEW_GOLDEN_RESOURCE_MATCH, MdmLinkSourceEnum.AUTO, createContextForCreate("Patient"));
|
||||
assertThat(janePatient, is(not(sameGoldenResourceAs(janePatient2))));
|
||||
|
||||
//In theory, this will match both Persons!
|
||||
//In theory, this will match both GoldenResources!
|
||||
Patient incomingJanePatient = createPatientAndUpdateLinks(buildJanePatient());
|
||||
|
||||
//There should now be a single POSSIBLE_DUPLICATE link with
|
||||
assertThat(janePatient, is(possibleDuplicateOf(janePatient2)));
|
||||
|
||||
//There should now be 2 POSSIBLE_MATCH links with this person.
|
||||
//There should now be 2 POSSIBLE_MATCH links with this goldenResource.
|
||||
assertThat(incomingJanePatient, is(possibleMatchWith(janePatient, janePatient2)));
|
||||
|
||||
//Ensure there is no successful MATCH links for incomingJanePatient
|
||||
|
@ -384,7 +385,7 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test {
|
|||
public void testWhenAllMatchResultsArePOSSIBLE_MATCHThattheyAreLinkedAndNoGoldenResourceIsCreated() {
|
||||
/**
|
||||
* CASE 4: Only POSSIBLE_MATCH outcomes -> In this case, mdm-link records are created with POSSIBLE_MATCH
|
||||
* outcome and await manual assignment to either NO_MATCH or MATCHED. Person link is added.
|
||||
* outcome and await manual assignment to either NO_MATCH or MATCHED. GoldenResource link is added.
|
||||
*/
|
||||
Patient patient = buildJanePatient();
|
||||
patient.getNameFirstRep().setFamily("familyone");
|
||||
|
@ -469,7 +470,7 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test {
|
|||
|
||||
//Case #1
|
||||
@Test
|
||||
public void testPatientUpdateOverwritesPersonDataOnChanges() {
|
||||
public void testPatientUpdateOverwritesGoldenResourceDataOnChanges() {
|
||||
Patient janePatient = createPatientAndUpdateLinks(buildJanePatient());
|
||||
Patient janeSourcePatient = (Patient) getGoldenResourceFromTargetResource(janePatient);
|
||||
|
||||
|
@ -480,7 +481,7 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test {
|
|||
|
||||
assertThat(janeSourcePatient, is(sameGoldenResourceAs(janePaulPatient)));
|
||||
|
||||
//Ensure the related person was updated with new info.
|
||||
//Ensure the related GoldenResource was updated with new info.
|
||||
Patient sourcePatientFromTarget = (Patient) getGoldenResourceFromTargetResource(janePaulPatient);
|
||||
HumanName nameFirstRep = sourcePatientFromTarget.getNameFirstRep();
|
||||
|
||||
|
@ -489,7 +490,7 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testPatientCreateDoesNotOverwritePersonAttributesThatAreInvolvedInLinking() {
|
||||
public void testPatientCreateDoesNotOverwriteGoldenResourceAttributesThatAreInvolvedInLinking() {
|
||||
Patient paul = buildPaulPatient();
|
||||
paul.setGender(Enumerations.AdministrativeGender.MALE);
|
||||
paul = createPatientAndUpdateLinks(paul);
|
||||
|
@ -505,14 +506,15 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test {
|
|||
|
||||
assertThat(paul2, is(sameGoldenResourceAs(paul)));
|
||||
|
||||
//Newly matched patients aren't allowed to overwrite Person Attributes unless they are empty, so gender should still be set to male.
|
||||
Patient paul2Person = (Patient) getGoldenResourceFromTargetResource(paul2);
|
||||
// assertThat(paul2Person.getGender(), is(equalTo(Enumerations.AdministrativeGender.MALE)));
|
||||
//Newly matched patients aren't allowed to overwrite GoldenResource Attributes unless they are empty,
|
||||
// so gender should still be set to male.
|
||||
Patient paul2GoldenResource = (Patient) getGoldenResourceFromTargetResource(paul2);
|
||||
// assertThat(paul2GoldenResource.getGender(), is(equalTo(Enumerations.AdministrativeGender.MALE)));
|
||||
}
|
||||
|
||||
@Test
|
||||
//Test Case #1
|
||||
public void testPatientUpdatesOverwritePersonData() {
|
||||
public void testPatientUpdatesOverwriteGoldenResourceData() {
|
||||
Patient paul = buildPaulPatient();
|
||||
String incorrectBirthdate = "1980-06-27";
|
||||
paul.getBirthDateElement().setValueAsString(incorrectBirthdate);
|
||||
|
@ -554,7 +556,7 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testSinglyLinkedPersonThatGetsAnUpdatedEidSimplyUpdatesEID() {
|
||||
public void testSinglyLinkedGoldenResourceThatGetsAnUpdatedEidSimplyUpdatesEID() {
|
||||
//Use Case # 2
|
||||
String EID_1 = "123";
|
||||
String EID_2 = "456";
|
||||
|
@ -597,18 +599,18 @@ public class MdmMatchLinkSvcTest extends BaseMdmR4Test {
|
|||
addExternalEID(patient3, "eid-2");
|
||||
patient3 = createPatientAndUpdateLinks(patient3);
|
||||
|
||||
//Now, Patient 2 and 3 are linked, and the person has 2 eids.
|
||||
//Now, Patient 2 and 3 are linked, and the GoldenResource has 2 eids.
|
||||
assertThat(patient2, is(sameGoldenResourceAs(patient3)));
|
||||
assertNoDuplicates();
|
||||
// Person A -> {P1}
|
||||
// Person B -> {P2, P3}
|
||||
// GoldenResource A -> {P1}
|
||||
// GoldenResource B -> {P2, P3}
|
||||
|
||||
patient2.getIdentifier().clear();
|
||||
addExternalEID(patient2, "eid-1");
|
||||
patient2 = updatePatientAndUpdateLinks(patient2);
|
||||
|
||||
// Person A -> {P1, P2}
|
||||
// Person B -> {P3}
|
||||
// GoldenResource A -> {P1, P2}
|
||||
// GoldenResource B -> {P3}
|
||||
// Possible duplicates A<->B
|
||||
|
||||
assertThat(patient2, is(sameGoldenResourceAs(patient1)));
|
||||
|
|
|
@ -35,13 +35,13 @@ public class MdmResourceDaoSvcTest extends BaseMdmR4Test {
|
|||
MdmUtil.setGoldenResourceRedirected(badSourcePatient);
|
||||
myPatientDao.update(badSourcePatient);
|
||||
|
||||
Optional<IAnyResource> foundPerson = myResourceDaoSvc.searchGoldenResourceByEID(TEST_EID, "Patient");
|
||||
assertTrue(foundPerson.isPresent());
|
||||
assertThat(foundPerson.get().getIdElement().toUnqualifiedVersionless().getValue(), is(goodSourcePatient.getIdElement().toUnqualifiedVersionless().getValue()));
|
||||
Optional<IAnyResource> foundGoldenResource = myResourceDaoSvc.searchGoldenResourceByEID(TEST_EID, "Patient");
|
||||
assertTrue(foundGoldenResource.isPresent());
|
||||
assertThat(foundGoldenResource.get().getIdElement().toUnqualifiedVersionless().getValue(), is(goodSourcePatient.getIdElement().toUnqualifiedVersionless().getValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchPersonByEidExcludesNonMdmManaged() {
|
||||
public void testSearcGoldenResourceByEidExcludesNonMdmManaged() {
|
||||
Patient goodSourcePatient = addExternalEID(createGoldenPatient(), TEST_EID);
|
||||
myPatientDao.update(goodSourcePatient);
|
||||
|
||||
|
|
|
@ -25,10 +25,11 @@ import org.hl7.fhir.instance.model.api.IAnyResource;
|
|||
|
||||
public interface IGoldenResourceMergerSvc {
|
||||
/**
|
||||
* Move all links from the theFromGoldenResource to theToGoldenResource and then set active=false on theFromGoldenResource. Merge all Person
|
||||
* fields.
|
||||
* @param theFromGoldenResource the person we are merging from
|
||||
* @param theToGoldenResource the person we are merging to
|
||||
* Move all links from the theFromGoldenResource to theToGoldenResource and then set active=false on theFromGoldenResource.
|
||||
* Merge all Golden Resource fields subject to survivorship rules.
|
||||
*
|
||||
* @param theFromGoldenResource the golden resource we are merging from
|
||||
* @param theToGoldenResource the golden resource we are merging to
|
||||
* @return updated theToGoldenResource with the merged fields and links.
|
||||
*/
|
||||
IAnyResource mergeGoldenResources(IAnyResource theFromGoldenResource, IAnyResource theToGoldenResource, MdmTransactionContext theMdmTransactionContext);
|
||||
|
|
|
@ -28,13 +28,13 @@ import java.util.stream.Stream;
|
|||
|
||||
public interface IMdmControllerSvc {
|
||||
|
||||
Stream<MdmLinkJson> queryLinks(@Nullable String thePersonId, @Nullable String theTargetId, @Nullable String theMatchResult, @Nullable String theLinkSource, MdmTransactionContext theMdmTransactionContext);
|
||||
Stream<MdmLinkJson> queryLinks(@Nullable String theGoldenResourceId, @Nullable String theTargetId, @Nullable String theMatchResult, @Nullable String theLinkSource, MdmTransactionContext theMdmTransactionContext);
|
||||
|
||||
Stream<MdmLinkJson> getDuplicateGoldenResources(MdmTransactionContext theMdmTransactionContext);
|
||||
|
||||
void notDuplicateGoldenResource(String thePersonId, String theTargetPersonId, MdmTransactionContext theMdmTransactionContext);
|
||||
void notDuplicateGoldenResource(String theGoldenResourceId, String theTargetGoldenResourceId, MdmTransactionContext theMdmTransactionContext);
|
||||
|
||||
IAnyResource mergeGoldenResources(String theFromPersonId, String theToPersonId, MdmTransactionContext theMdmTransactionContext);
|
||||
IAnyResource mergeGoldenResources(String theFromGoldenResourceId, String theToGoldenResourceId, MdmTransactionContext theMdmTransactionContext);
|
||||
|
||||
IAnyResource updateLink(String thePersonId, String theTargetId, String theMatchResult, MdmTransactionContext theMdmTransactionContext);
|
||||
IAnyResource updateLink(String theGoldenResourceId, String theTargetId, String theMatchResult, MdmTransactionContext theMdmTransactionContext);
|
||||
}
|
||||
|
|
|
@ -25,18 +25,16 @@ import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
|||
public interface IMdmExpungeSvc {
|
||||
|
||||
/**
|
||||
* Given a resource type, delete the underlying MDM links, and their related person objects.
|
||||
* Given a resource type, delete the underlying MDM links, and their related golden resource objects.
|
||||
*
|
||||
* @param theResourceType The type of resources
|
||||
*
|
||||
* @param theRequestDetails
|
||||
* @return the count of deleted MDM links
|
||||
*/
|
||||
long expungeAllMdmLinksOfTargetType(String theResourceType, ServletRequestDetails theRequestDetails);
|
||||
|
||||
/**
|
||||
* Delete all MDM links, and their related Person objects.
|
||||
*
|
||||
* Delete all MDM links, and their related golden resource objects.
|
||||
*
|
||||
* @return the count of deleted MDM links
|
||||
* @param theRequestDetails
|
||||
|
|
|
@ -30,5 +30,5 @@ import java.util.stream.Stream;
|
|||
*/
|
||||
public interface IMdmLinkQuerySvc {
|
||||
Stream<MdmLinkJson> queryLinks(IIdType theGoldenResourceId, IIdType theTargetId, MdmMatchResultEnum theMatchResult, MdmLinkSourceEnum theLinkSource, MdmTransactionContext theMdmContext);
|
||||
Stream<MdmLinkJson> getDuplicatePersons(MdmTransactionContext theMdmContext);
|
||||
Stream<MdmLinkJson> getDuplicateGoldenResources(MdmTransactionContext theMdmContext);
|
||||
}
|
||||
|
|
|
@ -26,20 +26,22 @@ import org.hl7.fhir.instance.model.api.IAnyResource;
|
|||
public interface IMdmLinkSvc {
|
||||
|
||||
/**
|
||||
* Update a link between a Person record and its target Patient/Practitioner record. If a link does not exist between
|
||||
* Update a link between a Golden Resource record and its target record. If a link does not exist between
|
||||
* these two records, create it.
|
||||
* @param thePerson the Person to link the target resource to.
|
||||
* @param theTargetResource the target resource, which is a Patient or Practitioner
|
||||
*
|
||||
* @param theGoldenResource the Golden Resource to link the target resource to.
|
||||
* @param theTargetResource the target resource, which can be of the MDM supported types
|
||||
* @param theMatchResult the current status of the match to set the link to.
|
||||
* @param theLinkSource MANUAL or AUTO: what caused the link.
|
||||
* @param theMdmTransactionContext
|
||||
*/
|
||||
void updateLink(IAnyResource thePerson, IAnyResource theTargetResource, MdmMatchOutcome theMatchResult, MdmLinkSourceEnum theLinkSource, MdmTransactionContext theMdmTransactionContext);
|
||||
void updateLink(IAnyResource theGoldenResource, IAnyResource theTargetResource, MdmMatchOutcome theMatchResult, MdmLinkSourceEnum theLinkSource, MdmTransactionContext theMdmTransactionContext);
|
||||
|
||||
/**
|
||||
* Delete a link between given Person and target patient/practitioner
|
||||
* @param theExistingPerson
|
||||
* Delete a link between given Golden Resource and the corresponing target
|
||||
*
|
||||
* @param theExistingGoldenResource
|
||||
* @param theResource
|
||||
*/
|
||||
void deleteLink(IAnyResource theExistingPerson, IAnyResource theResource, MdmTransactionContext theMdmTransactionContext);
|
||||
void deleteLink(IAnyResource theExistingGoldenResource, IAnyResource theResource, MdmTransactionContext theMdmTransactionContext);
|
||||
}
|
||||
|
|
|
@ -25,5 +25,5 @@ import org.hl7.fhir.instance.model.api.IAnyResource;
|
|||
|
||||
public interface IMdmLinkUpdaterSvc {
|
||||
IAnyResource updateLink(IAnyResource theGoldenResource, IAnyResource theTarget, MdmMatchResultEnum theMatchResult, MdmTransactionContext theMdmContext);
|
||||
void notDuplicatePerson(IAnyResource theGoldenResource, IAnyResource theTarget, MdmTransactionContext theMdmContext);
|
||||
void notDuplicateGoldenResource(IAnyResource theGoldenResource, IAnyResource theTarget, MdmTransactionContext theMdmContext);
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ import java.util.List;
|
|||
|
||||
public interface IMdmMatchFinderSvc {
|
||||
/**
|
||||
* Retrieve a list of possible Patient/Practitioner candidates for matching, based on the given {@link IAnyResource}
|
||||
* Retrieve a list of possible target candidates for matching, based on the given {@link IAnyResource}
|
||||
* Internally, performs all MDM matching rules on the type of the resource.
|
||||
*
|
||||
* @param theResourceType the type of the resource.
|
||||
|
|
|
@ -22,12 +22,12 @@ package ca.uhn.fhir.mdm.api;
|
|||
|
||||
public class MdmConstants {
|
||||
/**
|
||||
* TAG system for Person resources which are managed by HAPI MDM.
|
||||
* TAG system for Golden Resources which are managed by HAPI MDM.
|
||||
*/
|
||||
|
||||
public static final String SYSTEM_MDM_MANAGED = "https://hapifhir.org/NamingSystem/managing-mdm-system";
|
||||
public static final String CODE_HAPI_MDM_MANAGED = "HAPI-MDM";
|
||||
public static final String DISPLAY_HAPI_MDM_MANAGED = "This Person can only be modified by Smile CDR's MDM system.";
|
||||
public static final String DISPLAY_HAPI_MDM_MANAGED = "This Golden Resource can only be modified by Smile CDR's MDM system.";
|
||||
public static final String CODE_NO_MDM_MANAGED = "NO-MDM";
|
||||
public static final String HAPI_ENTERPRISE_IDENTIFIER_SYSTEM = "http://hapifhir.io/fhir/NamingSystem/mdm-golden-resource-enterprise-id";
|
||||
public static final String ALL_RESOURCE_SEARCH_PARAM_TYPE = "*";
|
||||
|
|
|
@ -26,6 +26,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
|||
import java.util.Date;
|
||||
|
||||
public class MdmLinkJson implements IModelJson {
|
||||
|
||||
@JsonProperty("goldenResourceId")
|
||||
private String myGoldenResourceId;
|
||||
|
||||
|
@ -51,7 +52,7 @@ public class MdmLinkJson implements IModelJson {
|
|||
@JsonProperty("eidMatch")
|
||||
private Boolean myEidMatch;
|
||||
|
||||
/** This link created a new person **/
|
||||
/** This link created a new golden resource **/
|
||||
@JsonProperty("linkCreatedNewGoldenResource")
|
||||
private Boolean myLinkCreatedNewResource;
|
||||
|
||||
|
|
|
@ -21,16 +21,15 @@ package ca.uhn.fhir.mdm.api;
|
|||
*/
|
||||
|
||||
public enum MdmLinkSourceEnum {
|
||||
|
||||
/**
|
||||
* Link was created or last modified by an algorithm
|
||||
*/
|
||||
AUTO,
|
||||
|
||||
/**
|
||||
* Link was created or last modified by a person
|
||||
* Link was created or last modified manually by a system user
|
||||
*/
|
||||
|
||||
MANUAL
|
||||
|
||||
// Stored in database as ORDINAL. Only add new values to bottom!
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ package ca.uhn.fhir.mdm.api;
|
|||
*/
|
||||
|
||||
public class MdmMatchEvaluation {
|
||||
|
||||
public final boolean match;
|
||||
public final double score;
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ public final class MdmMatchOutcome {
|
|||
|
||||
public static final MdmMatchOutcome POSSIBLE_DUPLICATE = new MdmMatchOutcome(null, null).setMatchResultEnum(MdmMatchResultEnum.POSSIBLE_DUPLICATE);
|
||||
public static final MdmMatchOutcome NO_MATCH = new MdmMatchOutcome(null, null).setMatchResultEnum(MdmMatchResultEnum.NO_MATCH);
|
||||
public static final MdmMatchOutcome NEW_PERSON_MATCH = new MdmMatchOutcome(null, null).setMatchResultEnum(MdmMatchResultEnum.MATCH).setCreatedNewResource(true);
|
||||
public static final MdmMatchOutcome NEW_GOLDEN_RESOURCE_MATCH = new MdmMatchOutcome(null, null).setMatchResultEnum(MdmMatchResultEnum.MATCH).setCreatedNewResource(true);
|
||||
public static final MdmMatchOutcome EID_MATCH = new MdmMatchOutcome(null, null).setMatchResultEnum(MdmMatchResultEnum.MATCH).setEidMatch(true);
|
||||
public static final MdmMatchOutcome POSSIBLE_MATCH = new MdmMatchOutcome(null, null).setMatchResultEnum(MdmMatchResultEnum.POSSIBLE_MATCH);
|
||||
|
||||
|
@ -45,7 +45,7 @@ public final class MdmMatchOutcome {
|
|||
public final Double score;
|
||||
|
||||
/**
|
||||
* Did the MDM match operation result in creating a new Person resource?
|
||||
* Did the MDM match operation result in creating a new golden resource resource?
|
||||
*/
|
||||
private boolean myCreatedNewResource;
|
||||
|
||||
|
@ -95,7 +95,7 @@ public final class MdmMatchOutcome {
|
|||
return myCreatedNewResource;
|
||||
}
|
||||
|
||||
/** @param theCreatedNewResource this match is creating a new person */
|
||||
/** @param theCreatedNewResource this match is creating a new golden resource */
|
||||
public MdmMatchOutcome setCreatedNewResource(boolean theCreatedNewResource) {
|
||||
myCreatedNewResource = theCreatedNewResource;
|
||||
return this;
|
||||
|
@ -152,7 +152,7 @@ public final class MdmMatchOutcome {
|
|||
return new ToStringBuilder(this)
|
||||
.append("vector", vector)
|
||||
.append("score", score)
|
||||
.append("myNewPerson", myCreatedNewResource)
|
||||
.append("myCreatedNewResource", myCreatedNewResource)
|
||||
.append("myEidMatch", myEidMatch)
|
||||
.append("myMatchResultEnum", myMatchResultEnum)
|
||||
.toString();
|
||||
|
|
|
@ -21,6 +21,7 @@ package ca.uhn.fhir.mdm.api;
|
|||
*/
|
||||
|
||||
public enum MdmMatchResultEnum {
|
||||
|
||||
/**
|
||||
* Manually confirmed to not be a match.
|
||||
*/
|
||||
|
@ -37,21 +38,21 @@ public enum MdmMatchResultEnum {
|
|||
MATCH,
|
||||
|
||||
/**
|
||||
* Link between two Person resources indicating they may be duplicates.
|
||||
* Link between two Golden Records resources indicating they may be duplicates.
|
||||
*/
|
||||
POSSIBLE_DUPLICATE,
|
||||
|
||||
/**
|
||||
* Link between Person and Target pointing to the Golden Record for that Person
|
||||
* Link between Golden Record and Target pointing to the Golden Record for that Target
|
||||
*/
|
||||
|
||||
GOLDEN_RECORD,
|
||||
|
||||
/**
|
||||
* Link between two Person resources resulting from a merge. The Person points to the active person after the merge
|
||||
* and the Target points to the inactive person after the merge.
|
||||
* Link between two Golden Resources resulting from a merge. One golden resource is deactivated. The inactive golden
|
||||
* resource points to the active golden resource after the merge. The target resource points to the inactive golden
|
||||
* resource after the merge.
|
||||
*/
|
||||
|
||||
REDIRECT
|
||||
// Stored in database as ORDINAL. Only add new values to bottom!
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ public class MdmTransactionContext {
|
|||
UPDATE_LINK,
|
||||
DUPLICATE_GOLDEN_RESOURCES,
|
||||
NOT_DUPLICATE,
|
||||
MERGE_PERSONS
|
||||
MERGE_GOLDEN_RESOURCES
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -48,7 +48,7 @@ public abstract class BaseMdmProvider {
|
|||
validateNotNull(ProviderConstants.MDM_MERGE_GR_FROM_GOLDEN_RESOURCE_ID, theFromGoldenResourceId);
|
||||
validateNotNull(ProviderConstants.MDM_MERGE_GR_TO_GOLDEN_RESOURCE_ID, theToGoldenResourceId);
|
||||
if (theFromGoldenResourceId.getValue().equals(theToGoldenResourceId.getValue())) {
|
||||
throw new InvalidRequestException("fromPersonId must be different from toPersonId");
|
||||
throw new InvalidRequestException("fromGoldenResourceId must be different from toGoldenResourceId");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -77,9 +77,9 @@ public class MdmControllerHelper {
|
|||
return (IAnyResource) myResourceLoader.load(resourceClass, theResourceId);
|
||||
}
|
||||
|
||||
public void validateMergeResources(IAnyResource theFromPerson, IAnyResource theToPerson) {
|
||||
validateIsMdmManaged(ProviderConstants.MDM_MERGE_GR_FROM_GOLDEN_RESOURCE_ID, theFromPerson);
|
||||
validateIsMdmManaged(ProviderConstants.MDM_MERGE_GR_TO_GOLDEN_RESOURCE_ID, theToPerson);
|
||||
public void validateMergeResources(IAnyResource theFromGoldenResource, IAnyResource theToGoldenResource) {
|
||||
validateIsMdmManaged(ProviderConstants.MDM_MERGE_GR_FROM_GOLDEN_RESOURCE_ID, theFromGoldenResource);
|
||||
validateIsMdmManaged(ProviderConstants.MDM_MERGE_GR_TO_GOLDEN_RESOURCE_ID, theToGoldenResource);
|
||||
}
|
||||
|
||||
public String toJson(IAnyResource theAnyResource) {
|
||||
|
|
|
@ -41,11 +41,11 @@ public class MdmControllerUtil {
|
|||
return MdmLinkSourceEnum.valueOf(theLinkSource);
|
||||
}
|
||||
|
||||
public static IIdType extractPersonIdDtOrNull(String theName, String thePersonId) {
|
||||
if (thePersonId == null) {
|
||||
public static IIdType extractGoldenResourceIdDtOrNull(String theName, String theGoldenResourceId) {
|
||||
if (theGoldenResourceId == null) {
|
||||
return null;
|
||||
}
|
||||
return getGoldenIdDtOrThrowException(theName, thePersonId);
|
||||
return getGoldenIdDtOrThrowException(theName, theGoldenResourceId);
|
||||
}
|
||||
|
||||
public static IIdType extractTargetIdDtOrNull(String theName, String theTargetId) {
|
||||
|
|
|
@ -118,7 +118,7 @@ public class MdmProviderDstu3 extends BaseMdmProvider {
|
|||
String resourceType = getResourceType(ProviderConstants.MDM_MERGE_GR_FROM_GOLDEN_RESOURCE_ID, theFromGoldenResourceId);
|
||||
|
||||
return myMdmControllerSvc.mergeGoldenResources(theFromGoldenResourceId.getValue(), theToGoldenResourceId.getValue(),
|
||||
createMdmContext(theRequestDetails, MdmTransactionContext.OperationType.MERGE_PERSONS, resourceType));
|
||||
createMdmContext(theRequestDetails, MdmTransactionContext.OperationType.MERGE_GOLDEN_RESOURCES, resourceType));
|
||||
}
|
||||
|
||||
@Operation(name = ProviderConstants.MDM_UPDATE_LINK)
|
||||
|
|
|
@ -151,7 +151,7 @@ public class MdmProviderR4 extends BaseMdmProvider {
|
|||
validateMergeParameters(theFromGoldenResourceId, theToGoldenResourceId);
|
||||
|
||||
return myMdmControllerSvc.mergeGoldenResources(theFromGoldenResourceId.getValue(), theToGoldenResourceId.getValue(),
|
||||
createMdmContext(theRequestDetails, MdmTransactionContext.OperationType.MERGE_PERSONS,
|
||||
createMdmContext(theRequestDetails, MdmTransactionContext.OperationType.MERGE_GOLDEN_RESOURCES,
|
||||
getResourceType(ProviderConstants.MDM_MERGE_GR_FROM_GOLDEN_RESOURCE_ID, theFromGoldenResourceId))
|
||||
);
|
||||
}
|
||||
|
|
|
@ -45,8 +45,8 @@ public enum MdmMatcherEnum {
|
|||
SUBSTRING(new HapiStringMatcher(new SubstringStringMatcher())),
|
||||
|
||||
DATE(new HapiDateMatcher()),
|
||||
NAME_ANY_ORDER(new NameMatcher(MdmPersonNameMatchModeEnum.ANY_ORDER)),
|
||||
NAME_FIRST_AND_LAST(new NameMatcher(MdmPersonNameMatchModeEnum.FIRST_AND_LAST)),
|
||||
NAME_ANY_ORDER(new NameMatcher(MdmNameMatchModeEnum.ANY_ORDER)),
|
||||
NAME_FIRST_AND_LAST(new NameMatcher(MdmNameMatchModeEnum.FIRST_AND_LAST)),
|
||||
|
||||
IDENTIFIER(new IdentifierMatcher());
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ package ca.uhn.fhir.mdm.rules.matcher;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
public enum MdmPersonNameMatchModeEnum {
|
||||
public enum MdmNameMatchModeEnum {
|
||||
ANY_ORDER,
|
||||
FIRST_AND_LAST
|
||||
}
|
|
@ -34,9 +34,9 @@ import java.util.stream.Collectors;
|
|||
*/
|
||||
public class NameMatcher implements IMdmFieldMatcher {
|
||||
|
||||
private final MdmPersonNameMatchModeEnum myMatchMode;
|
||||
private final MdmNameMatchModeEnum myMatchMode;
|
||||
|
||||
public NameMatcher(MdmPersonNameMatchModeEnum theMatchMode) {
|
||||
public NameMatcher(MdmNameMatchModeEnum theMatchMode) {
|
||||
myMatchMode = theMatchMode;
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ public class NameMatcher implements IMdmFieldMatcher {
|
|||
for (String leftGivenName : leftGivenNames) {
|
||||
for (String rightGivenName : rightGivenNames) {
|
||||
match |= leftGivenName.equals(rightGivenName) && leftFamilyName.equals(rightFamilyName);
|
||||
if (myMatchMode == MdmPersonNameMatchModeEnum.ANY_ORDER) {
|
||||
if (myMatchMode == MdmNameMatchModeEnum.ANY_ORDER) {
|
||||
match |= leftGivenName.equals(rightFamilyName) && leftFamilyName.equals(rightGivenName);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
|||
|
||||
/**
|
||||
* Helper class to determine assurance level based on Link Source and Match Result.
|
||||
* This is strictly for use in populating Person links.
|
||||
* This is strictly for use in populating Golden Resource links.
|
||||
*/
|
||||
public final class AssuranceLevelUtil {
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ import java.util.stream.Collectors;
|
|||
|
||||
@Service
|
||||
public final class EIDHelper {
|
||||
|
||||
private final FhirContext myFhirContext;
|
||||
private final IMdmSettings myMdmSettings;
|
||||
|
||||
|
@ -54,7 +55,7 @@ public final class EIDHelper {
|
|||
}
|
||||
|
||||
/**
|
||||
* Given an {@link IAnyResource} representing a patient/practitioner/person, retrieve their externally-assigned EID,
|
||||
* Given an {@link IAnyResource} representing a type supported by MDM, retrieve their externally-assigned EID,
|
||||
* represented as a {@link CanonicalEID}
|
||||
*
|
||||
* @param theResource the resource to extract the EID from.
|
||||
|
@ -66,7 +67,7 @@ public final class EIDHelper {
|
|||
}
|
||||
|
||||
/**
|
||||
* Given an {@link IAnyResource} representing a patient/practitioner/person, retrieve their internally-assigned EID,
|
||||
* Given an {@link IAnyResource} representing a type supported by MDM, retrieve their internally-assigned EID,
|
||||
* represented as a {@link CanonicalEID}
|
||||
*
|
||||
* @param theResource the resource to extract the EID from.
|
||||
|
@ -96,16 +97,12 @@ public final class EIDHelper {
|
|||
}
|
||||
|
||||
/**
|
||||
* An incoming resource is a potential duplicate if it matches a Patient that has a Person with an official EID, but
|
||||
* the incoming resource also has an EID that does not match.
|
||||
*
|
||||
* @param theExistingPerson
|
||||
* @param theComparingPerson
|
||||
* @return
|
||||
* An incoming resource is a potential duplicate if it matches a target resource that has a golden resource with an
|
||||
* official EID, but the incoming resource also has an EID that does not match.
|
||||
*/
|
||||
public boolean hasEidOverlap(IAnyResource theExistingPerson, IAnyResource theComparingPerson) {
|
||||
List<CanonicalEID> firstEids = this.getExternalEid(theExistingPerson);
|
||||
List<CanonicalEID> secondEids = this.getExternalEid(theComparingPerson);
|
||||
public boolean hasEidOverlap(IAnyResource theExistingGoldenResource, IAnyResource theComparingGoldenResource) {
|
||||
List<CanonicalEID> firstEids = this.getExternalEid(theExistingGoldenResource);
|
||||
List<CanonicalEID> secondEids = this.getExternalEid(theComparingGoldenResource);
|
||||
if (firstEids.isEmpty() || secondEids.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -25,26 +25,17 @@ import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
|
|||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.fhirpath.IFhirPath;
|
||||
import ca.uhn.fhir.mdm.api.IMdmSettings;
|
||||
import ca.uhn.fhir.mdm.log.Logs;
|
||||
import ca.uhn.fhir.mdm.model.CanonicalEID;
|
||||
import ca.uhn.fhir.mdm.model.CanonicalIdentityAssuranceLevel;
|
||||
import ca.uhn.fhir.mdm.model.MdmTransactionContext;
|
||||
import ca.uhn.fhir.fhirpath.IFhirPath;
|
||||
import ca.uhn.fhir.util.FhirTerser;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBase;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBackboneElement;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.hl7.fhir.r4.model.Address;
|
||||
import org.hl7.fhir.r4.model.BooleanType;
|
||||
import org.hl7.fhir.r4.model.ContactPoint;
|
||||
import org.hl7.fhir.r4.model.HumanName;
|
||||
import org.hl7.fhir.r4.model.Identifier;
|
||||
import org.hl7.fhir.r4.model.Person;
|
||||
import org.hl7.fhir.r4.model.Reference;
|
||||
import org.slf4j.Logger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
@ -53,8 +44,6 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static ca.uhn.fhir.context.FhirVersionEnum.DSTU3;
|
||||
|
@ -216,7 +205,7 @@ public class GoldenResourceHelper {
|
|||
|
||||
/**
|
||||
* Updates EID on Golden Resource, based on the incoming target resource. If the incoming resource has an external EID, it is applied
|
||||
* to the Golden Resource, unless that person already has an external EID which does not match, in which case throw {@link IllegalArgumentException}
|
||||
* to the Golden Resource, unless that golden resource already has an external EID which does not match, in which case throw {@link IllegalArgumentException}
|
||||
* <p>
|
||||
* If running in multiple EID mode, then incoming EIDs are simply added to the Golden Resource without checking for matches.
|
||||
*
|
||||
|
@ -228,17 +217,22 @@ public class GoldenResourceHelper {
|
|||
theTargetResource, MdmTransactionContext theMdmTransactionContext) {
|
||||
//This handles overwriting an automatically assigned EID if a patient that links is coming in with an official EID.
|
||||
List<CanonicalEID> incomingTargetEid = myEIDHelper.getExternalEid(theTargetResource);
|
||||
List<CanonicalEID> personOfficialEid = myEIDHelper.getExternalEid(theGoldenResource);
|
||||
List<CanonicalEID> goldenResourceOfficialEid = myEIDHelper.getExternalEid(theGoldenResource);
|
||||
|
||||
if (!incomingTargetEid.isEmpty()) {
|
||||
if (personOfficialEid.isEmpty() || !myMdmSettings.isPreventMultipleEids()) {
|
||||
log(theMdmTransactionContext, "Incoming resource:" + theTargetResource.getIdElement().toUnqualifiedVersionless() + " + with EID " + incomingTargetEid.stream().map(CanonicalEID::toString).collect(Collectors.joining(",")) + " is applying this EIDs to its related Source Resource, as this Source Resource does not yet have an external EID");
|
||||
addCanonicalEidsToGoldenResourceIfAbsent(theGoldenResource, incomingTargetEid);
|
||||
} else if (!personOfficialEid.isEmpty() && myEIDHelper.eidMatchExists(personOfficialEid, incomingTargetEid)) {
|
||||
log(theMdmTransactionContext, "incoming resource:" + theTargetResource.getIdElement().toVersionless() + " with EIDs " + incomingTargetEid.stream().map(CanonicalEID::toString).collect(Collectors.joining(",")) + " does not need to overwrite person, as this EID is already present");
|
||||
} else {
|
||||
throw new IllegalArgumentException("This would create a duplicate person!");
|
||||
if (incomingTargetEid.isEmpty()) {
|
||||
return theGoldenResource;
|
||||
}
|
||||
|
||||
if (goldenResourceOfficialEid.isEmpty() || !myMdmSettings.isPreventMultipleEids()) {
|
||||
log(theMdmTransactionContext, "Incoming resource:" + theTargetResource.getIdElement().toUnqualifiedVersionless() + " + with EID " + incomingTargetEid.stream().map(CanonicalEID::toString).collect(Collectors.joining(","))
|
||||
+ " is applying this EIDs to its related Target Resource, as this Target Resource does not yet have an external EID");
|
||||
addCanonicalEidsToGoldenResourceIfAbsent(theGoldenResource, incomingTargetEid);
|
||||
} else if (!goldenResourceOfficialEid.isEmpty() && myEIDHelper.eidMatchExists(goldenResourceOfficialEid, incomingTargetEid)) {
|
||||
log(theMdmTransactionContext, "incoming resource:" + theTargetResource.getIdElement().toVersionless() + " with EIDs " + incomingTargetEid.stream().map(CanonicalEID::toString).collect(Collectors.joining(",")) + " does not need to overwrite Golden Resource, as this EID is already present");
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Target EIDs %s would create a duplicate golden resource, as EIDs %s already exist!",
|
||||
incomingTargetEid.toString(), goldenResourceOfficialEid.toString()));
|
||||
}
|
||||
return theGoldenResource;
|
||||
}
|
||||
|
@ -334,155 +328,30 @@ public class GoldenResourceHelper {
|
|||
throw new IllegalStateException("Unsupported FHIR version " + myFhirContext.getVersion().getVersion());
|
||||
}
|
||||
|
||||
/**
|
||||
* To avoid adding duplicate
|
||||
*
|
||||
* @param thePerson
|
||||
* @param theIdentifier
|
||||
*/
|
||||
private void addIdentifierIfAbsent(org.hl7.fhir.dstu3.model.Person thePerson, org.hl7.fhir.dstu3.model.Identifier
|
||||
theIdentifier) {
|
||||
Optional<org.hl7.fhir.dstu3.model.Identifier> first = thePerson.getIdentifier().stream().filter(identifier -> identifier.getSystem().equals(theIdentifier.getSystem())).filter(identifier -> identifier.getValue().equals(theIdentifier.getValue())).findFirst();
|
||||
if (first.isPresent()) {
|
||||
return;
|
||||
} else {
|
||||
thePerson.addIdentifier(theIdentifier);
|
||||
}
|
||||
}
|
||||
|
||||
public void mergeFields(IBaseResource theFromPerson, IBaseResource theToPerson) {
|
||||
public void mergeFields(IBaseResource theFromGoldenResource, IBaseResource theToGoldenResource) {
|
||||
// TODO NG - Revisit when merge rules are defined
|
||||
cloneCompositeField(theFromPerson, theToPerson, FIELD_NAME_IDENTIFIER);
|
||||
cloneCompositeField(theFromGoldenResource, theToGoldenResource, FIELD_NAME_IDENTIFIER);
|
||||
|
||||
// switch (myFhirContext.getVersion().getVersion()) {
|
||||
// case R4:
|
||||
// mergeR4PersonFields(theFromPerson, theToPerson);
|
||||
// mergeR4PersonFields(theFromGoldenResource, theToGoldenResource);
|
||||
// break;
|
||||
// case DSTU3:
|
||||
// mergeDstu3PersonFields(theFromPerson, theToPerson);
|
||||
// mergeDstu3PersonFields(theFromGoldenResource, theToGoldenResource);
|
||||
// break;
|
||||
// default:
|
||||
// throw new UnsupportedOperationException("Version not supported: " + myFhirContext.getVersion().getVersion());
|
||||
// }
|
||||
}
|
||||
|
||||
private void mergeR4PersonFields(IBaseResource theFromPerson, IBaseResource theToPerson) {
|
||||
Person fromPerson = (Person) theFromPerson;
|
||||
Person toPerson = (Person) theToPerson;
|
||||
|
||||
mergeElementList(fromPerson, toPerson, HumanName.class, Person::getName, HumanName::equalsDeep);
|
||||
mergeElementList(fromPerson, toPerson, Identifier.class, Person::getIdentifier, Identifier::equalsDeep);
|
||||
mergeElementList(fromPerson, toPerson, Address.class, Person::getAddress, Address::equalsDeep);
|
||||
mergeElementList(fromPerson, toPerson, ContactPoint.class, Person::getTelecom, ContactPoint::equalsDeep);
|
||||
if (!toPerson.hasBirthDate()) {
|
||||
toPerson.setBirthDate(fromPerson.getBirthDate());
|
||||
}
|
||||
if (!toPerson.hasGender()) {
|
||||
toPerson.setGender(fromPerson.getGender());
|
||||
}
|
||||
if (!toPerson.hasPhoto()) {
|
||||
toPerson.setPhoto(fromPerson.getPhoto());
|
||||
}
|
||||
}
|
||||
|
||||
private <P, T> void mergeElementList(P fromPerson, P
|
||||
toPerson, Class<T> theBase, Function<P, List<T>> theGetList, BiPredicate<T, T> theEquals) {
|
||||
List<T> fromList = theGetList.apply(fromPerson);
|
||||
List<T> toList = theGetList.apply(toPerson);
|
||||
List<T> itemsToAdd = new ArrayList<>();
|
||||
|
||||
for (T fromItem : fromList) {
|
||||
if (toList.stream().noneMatch(t -> theEquals.test(fromItem, t))) {
|
||||
itemsToAdd.add(fromItem);
|
||||
}
|
||||
}
|
||||
toList.addAll(itemsToAdd);
|
||||
}
|
||||
|
||||
private void mergeDstu3PersonFields(IBaseResource theFromPerson, IBaseResource theToPerson) {
|
||||
org.hl7.fhir.dstu3.model.Person fromPerson = (org.hl7.fhir.dstu3.model.Person) theFromPerson;
|
||||
org.hl7.fhir.dstu3.model.Person toPerson = (org.hl7.fhir.dstu3.model.Person) theToPerson;
|
||||
|
||||
mergeElementList(fromPerson, toPerson, org.hl7.fhir.dstu3.model.HumanName.class, org.hl7.fhir.dstu3.model.Person::getName, org.hl7.fhir.dstu3.model.HumanName::equalsDeep);
|
||||
mergeElementList(fromPerson, toPerson, org.hl7.fhir.dstu3.model.Identifier.class, org.hl7.fhir.dstu3.model.Person::getIdentifier, org.hl7.fhir.dstu3.model.Identifier::equalsDeep);
|
||||
mergeElementList(fromPerson, toPerson, org.hl7.fhir.dstu3.model.Address.class, org.hl7.fhir.dstu3.model.Person::getAddress, org.hl7.fhir.dstu3.model.Address::equalsDeep);
|
||||
mergeElementList(fromPerson, toPerson, org.hl7.fhir.dstu3.model.ContactPoint.class, org.hl7.fhir.dstu3.model.Person::getTelecom, org.hl7.fhir.dstu3.model.ContactPoint::equalsDeep);
|
||||
|
||||
if (!toPerson.hasBirthDate()) {
|
||||
toPerson.setBirthDate(fromPerson.getBirthDate());
|
||||
}
|
||||
if (!toPerson.hasGender()) {
|
||||
toPerson.setGender(fromPerson.getGender());
|
||||
}
|
||||
if (!toPerson.hasPhoto()) {
|
||||
toPerson.setPhoto(fromPerson.getPhoto());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An incoming resource is a potential duplicate if it matches a Patient that has a Person with an official EID, but
|
||||
* the incoming resource also has an EID that does not match.
|
||||
*
|
||||
* @param theExistingPerson
|
||||
* @param theComparingPerson
|
||||
* @return
|
||||
* An incoming resource is a potential duplicate if it matches a target that has a golden resource with an official
|
||||
* EID, but the incoming resource also has an EID that does not match.
|
||||
*/
|
||||
public boolean isPotentialDuplicate(IAnyResource theExistingPerson, IAnyResource theComparingPerson) {
|
||||
List<CanonicalEID> externalEidsPerson = myEIDHelper.getExternalEid(theExistingPerson);
|
||||
List<CanonicalEID> externalEidsResource = myEIDHelper.getExternalEid(theComparingPerson);
|
||||
return !externalEidsPerson.isEmpty() && !externalEidsResource.isEmpty() && !myEIDHelper.eidMatchExists(externalEidsResource, externalEidsPerson);
|
||||
}
|
||||
|
||||
public IBaseBackboneElement newPersonLink(IIdType theTargetId, CanonicalIdentityAssuranceLevel theAssuranceLevel) {
|
||||
switch (myFhirContext.getVersion().getVersion()) {
|
||||
case R4:
|
||||
return newR4PersonLink(theTargetId, theAssuranceLevel);
|
||||
case DSTU3:
|
||||
return newDstu3PersonLink(theTargetId, theAssuranceLevel);
|
||||
default:
|
||||
throw new UnsupportedOperationException("Version not supported: " + myFhirContext.getVersion().getVersion());
|
||||
}
|
||||
}
|
||||
|
||||
private IBaseBackboneElement newR4PersonLink(IIdType theTargetId, CanonicalIdentityAssuranceLevel
|
||||
theAssuranceLevel) {
|
||||
Person.PersonLinkComponent retval = new Person.PersonLinkComponent();
|
||||
retval.setTarget(new Reference(theTargetId));
|
||||
retval.setAssurance(theAssuranceLevel.toR4());
|
||||
return retval;
|
||||
}
|
||||
|
||||
private IBaseBackboneElement newDstu3PersonLink(IIdType theTargetId, CanonicalIdentityAssuranceLevel
|
||||
theAssuranceLevel) {
|
||||
org.hl7.fhir.dstu3.model.Person.PersonLinkComponent retval = new org.hl7.fhir.dstu3.model.Person.PersonLinkComponent();
|
||||
retval.setTarget(new org.hl7.fhir.dstu3.model.Reference(theTargetId));
|
||||
retval.setAssurance(theAssuranceLevel.toDstu3());
|
||||
return retval;
|
||||
}
|
||||
|
||||
public void setLinks(IAnyResource thePersonResource, List<IBaseBackboneElement> theNewLinks) {
|
||||
switch (myFhirContext.getVersion().getVersion()) {
|
||||
case R4:
|
||||
setLinksR4(thePersonResource, theNewLinks);
|
||||
break;
|
||||
case DSTU3:
|
||||
setLinksDstu3(thePersonResource, theNewLinks);
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Version not supported: " + myFhirContext.getVersion().getVersion());
|
||||
}
|
||||
}
|
||||
|
||||
private void setLinksDstu3(IAnyResource thePersonResource, List<IBaseBackboneElement> theLinks) {
|
||||
org.hl7.fhir.dstu3.model.Person person = (org.hl7.fhir.dstu3.model.Person) thePersonResource;
|
||||
List<org.hl7.fhir.dstu3.model.Person.PersonLinkComponent> links = (List<org.hl7.fhir.dstu3.model.Person.PersonLinkComponent>) (List<?>) theLinks;
|
||||
person.setLink(links);
|
||||
}
|
||||
|
||||
private void setLinksR4(IAnyResource thePersonResource, List<IBaseBackboneElement> theLinks) {
|
||||
Person person = (Person) thePersonResource;
|
||||
List<Person.PersonLinkComponent> links = (List<Person.PersonLinkComponent>) (List<?>) theLinks;
|
||||
person.setLink(links);
|
||||
public boolean isPotentialDuplicate(IAnyResource theExistingGoldenResource, IAnyResource theComparingGoldenResource) {
|
||||
List<CanonicalEID> externalEidsGoldenResource = myEIDHelper.getExternalEid(theExistingGoldenResource);
|
||||
List<CanonicalEID> externalEidsResource = myEIDHelper.getExternalEid(theComparingGoldenResource);
|
||||
return !externalEidsGoldenResource.isEmpty() && !externalEidsResource.isEmpty() && !myEIDHelper.eidMatchExists(externalEidsResource, externalEidsGoldenResource);
|
||||
}
|
||||
|
||||
private void log(MdmTransactionContext theMdmTransactionContext, String theMessage) {
|
||||
|
|
|
@ -20,7 +20,6 @@ package ca.uhn.fhir.mdm.util;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.mdm.api.MdmConstants;
|
||||
import org.hl7.fhir.instance.model.api.IBaseCoding;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
@ -45,7 +44,7 @@ public final class MdmUtil {
|
|||
|
||||
/**
|
||||
* Checks for the presence of the MDM-managed tag, indicating the MDM system has ownership
|
||||
* of this Person's links.
|
||||
* of this golden resource's links.
|
||||
*
|
||||
* @param theBaseResource the resource to check.
|
||||
* @return a boolean indicating whether or not MDM manages this FHIR resource.
|
||||
|
|
|
@ -44,11 +44,11 @@ public abstract class BaseR4Test {
|
|||
assertEquals(theExpectedMatchEnum, theMatchResult.getMatchResultEnum());
|
||||
}
|
||||
|
||||
protected void assertMatchResult(MdmMatchResultEnum theExpectedMatchEnum, long theExpectedVector, double theExpectedScore, boolean theExpectedNewPerson, boolean theExpectedEidMatch, MdmMatchOutcome theMatchResult) {
|
||||
protected void assertMatchResult(MdmMatchResultEnum theExpectedMatchEnum, long theExpectedVector, double theExpectedScore, boolean theExpectedNewGoldenResource, boolean theExpectedEidMatch, MdmMatchOutcome theMatchResult) {
|
||||
assertEquals(theExpectedScore, theMatchResult.score, 0.001);
|
||||
assertEquals(theExpectedVector, theMatchResult.vector);
|
||||
assertEquals(theExpectedEidMatch, theMatchResult.isEidMatch());
|
||||
assertEquals(theExpectedNewPerson, theMatchResult.isCreatedNewResource());
|
||||
assertEquals(theExpectedNewGoldenResource, theMatchResult.isCreatedNewResource());
|
||||
assertEquals(theExpectedMatchEnum, theMatchResult.getMatchResultEnum());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue