WIP Refactoring
This commit is contained in:
parent
aba6953360
commit
71856dbd64
|
@ -77,7 +77,7 @@ public class EmpiMessageHandler implements MessageHandler {
|
|||
public void matchEmpiAndUpdateLinks(ResourceModifiedMessage theMsg) {
|
||||
String resourceType = theMsg.getId(myFhirContext).getResourceType();
|
||||
validateResourceType(resourceType);
|
||||
EmpiTransactionContext empiContext = createEmpiContext(theMsg);
|
||||
EmpiTransactionContext empiContext = createEmpiContext(theMsg, resourceType);
|
||||
try {
|
||||
switch (theMsg.getOperationType()) {
|
||||
case CREATE:
|
||||
|
@ -106,7 +106,7 @@ public class EmpiMessageHandler implements MessageHandler {
|
|||
}
|
||||
}
|
||||
|
||||
private EmpiTransactionContext createEmpiContext(ResourceModifiedMessage theMsg) {
|
||||
private EmpiTransactionContext createEmpiContext(ResourceModifiedMessage theMsg, String theResourceType) {
|
||||
TransactionLogMessages transactionLogMessages = TransactionLogMessages.createFromTransactionGuid(theMsg.getTransactionId());
|
||||
EmpiTransactionContext.OperationType empiOperation;
|
||||
switch (theMsg.getOperationType()) {
|
||||
|
@ -124,7 +124,7 @@ public class EmpiMessageHandler implements MessageHandler {
|
|||
ourLog.trace("Not creating an EmpiTransactionContext for {}", theMsg.getOperationType());
|
||||
throw new InvalidRequestException("We can't handle non-update/create operations in EMPI");
|
||||
}
|
||||
return new EmpiTransactionContext(transactionLogMessages, empiOperation);
|
||||
return new EmpiTransactionContext(transactionLogMessages, empiOperation, theResourceType);
|
||||
}
|
||||
|
||||
private void validateResourceType(String theResourceType) {
|
||||
|
|
|
@ -57,7 +57,7 @@ import ca.uhn.fhir.jpa.empi.svc.EmpiResourceDaoSvc;
|
|||
import ca.uhn.fhir.jpa.empi.svc.EmpiResourceFilteringSvc;
|
||||
import ca.uhn.fhir.jpa.empi.svc.candidate.EmpiCandidateSearchCriteriaBuilderSvc;
|
||||
import ca.uhn.fhir.jpa.empi.svc.candidate.EmpiCandidateSearchSvc;
|
||||
import ca.uhn.fhir.jpa.empi.svc.candidate.EmpiPersonFindingSvc;
|
||||
import ca.uhn.fhir.jpa.empi.svc.candidate.EmpiSourceResourceFindingSvc;
|
||||
import ca.uhn.fhir.jpa.empi.svc.candidate.FindCandidateByEidSvc;
|
||||
import ca.uhn.fhir.jpa.empi.svc.candidate.FindCandidateByLinkSvc;
|
||||
import ca.uhn.fhir.jpa.empi.svc.candidate.FindCandidateByScoreSvc;
|
||||
|
@ -122,8 +122,8 @@ public class EmpiConsumerConfig {
|
|||
}
|
||||
|
||||
@Bean
|
||||
EmpiPersonFindingSvc empiPersonFindingSvc() {
|
||||
return new EmpiPersonFindingSvc();
|
||||
EmpiSourceResourceFindingSvc empiPersonFindingSvc() {
|
||||
return new EmpiSourceResourceFindingSvc();
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
|
|
@ -59,24 +59,24 @@ public class EmpiLinkDaoSvc {
|
|||
private FhirContext myFhirContext;
|
||||
|
||||
@Transactional
|
||||
public EmpiLink createOrUpdateLinkEntity(IBaseResource thePerson, IBaseResource theTarget, EmpiMatchOutcome theMatchOutcome, EmpiLinkSourceEnum theLinkSource, @Nullable EmpiTransactionContext theEmpiTransactionContext) {
|
||||
Long personPid = myIdHelperService.getPidOrNull(thePerson);
|
||||
Long resourcePid = myIdHelperService.getPidOrNull(theTarget);
|
||||
public EmpiLink createOrUpdateLinkEntity(IBaseResource theSourceResource, IBaseResource theTargetResource, EmpiMatchOutcome theMatchOutcome, EmpiLinkSourceEnum theLinkSource, @Nullable EmpiTransactionContext theEmpiTransactionContext) {
|
||||
Long sourceResourcePid = myIdHelperService.getPidOrNull(theSourceResource);
|
||||
Long targetResourcePid = myIdHelperService.getPidOrNull(theTargetResource);
|
||||
|
||||
EmpiLink empiLink = getOrCreateEmpiLinkByPersonPidAndTargetPid(personPid, resourcePid);
|
||||
EmpiLink empiLink = getOrCreateEmpiLinkBySourceResourcePidAndTargetResourcePid(sourceResourcePid, targetResourcePid);
|
||||
empiLink.setLinkSource(theLinkSource);
|
||||
empiLink.setMatchResult(theMatchOutcome.getMatchResultEnum());
|
||||
// Preserve these flags for link updates
|
||||
empiLink.setEidMatch(theMatchOutcome.isEidMatch() | empiLink.isEidMatch());
|
||||
empiLink.setHadToCreateNewResource(theMatchOutcome.isNewPerson() | empiLink.getHadToCreateNewResource());
|
||||
empiLink.setEmpiTargetType(myFhirContext.getResourceType(theTarget));
|
||||
empiLink.setEmpiTargetType(myFhirContext.getResourceType(theTargetResource));
|
||||
if (empiLink.getScore() != null) {
|
||||
empiLink.setScore(Math.max(theMatchOutcome.score, empiLink.getScore()));
|
||||
} else {
|
||||
empiLink.setScore(theMatchOutcome.score);
|
||||
}
|
||||
|
||||
String message = String.format("Creating EmpiLink from %s to %s -> %s", thePerson.getIdElement().toUnqualifiedVersionless(), theTarget.getIdElement().toUnqualifiedVersionless(), theMatchOutcome);
|
||||
String message = String.format("Creating EmpiLink from %s to %s -> %s", theSourceResource.getIdElement().toUnqualifiedVersionless(), theTargetResource.getIdElement().toUnqualifiedVersionless(), theMatchOutcome);
|
||||
theEmpiTransactionContext.addTransactionLogMessage(message);
|
||||
ourLog.debug(message);
|
||||
save(empiLink);
|
||||
|
@ -84,27 +84,26 @@ public class EmpiLinkDaoSvc {
|
|||
}
|
||||
|
||||
@Nonnull
|
||||
public EmpiLink getOrCreateEmpiLinkByPersonPidAndTargetPid(Long thePersonPid, Long theResourcePid) {
|
||||
Optional<EmpiLink> oExisting = getLinkByPersonPidAndTargetPid(thePersonPid, theResourcePid);
|
||||
public EmpiLink getOrCreateEmpiLinkBySourceResourcePidAndTargetResourcePid(Long theSourceResourcePid, Long theTargetResourcePid) {
|
||||
Optional<EmpiLink> oExisting = getLinkBySourceResourcePidAndTargetResourcePid(theSourceResourcePid, theTargetResourcePid);
|
||||
if (oExisting.isPresent()) {
|
||||
return oExisting.get();
|
||||
} else {
|
||||
EmpiLink newLink = myEmpiLinkFactory.newEmpiLink();
|
||||
newLink.setSourceResourcePid(thePersonPid);
|
||||
newLink.setPersonPid(thePersonPid);
|
||||
newLink.setTargetPid(theResourcePid);
|
||||
newLink.setSourceResourcePid(theSourceResourcePid);
|
||||
newLink.setPersonPid(theSourceResourcePid);
|
||||
newLink.setTargetPid(theTargetResourcePid);
|
||||
return newLink;
|
||||
}
|
||||
}
|
||||
|
||||
public Optional<EmpiLink> getLinkByPersonPidAndTargetPid(Long thePersonPid, Long theTargetPid) {
|
||||
|
||||
if (theTargetPid == null || thePersonPid == null) {
|
||||
public Optional<EmpiLink> getLinkBySourceResourcePidAndTargetResourcePid(Long theSourceResourcePid, Long theTargetResourcePid) {
|
||||
if (theTargetResourcePid == null || theSourceResourcePid == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
EmpiLink link = myEmpiLinkFactory.newEmpiLink();
|
||||
link.setTargetPid(theTargetPid);
|
||||
link.setSourceResourcePid(thePersonPid);
|
||||
link.setTargetPid(theTargetResourcePid);
|
||||
link.setSourceResourcePid(theSourceResourcePid);
|
||||
Example<EmpiLink> example = Example.of(link);
|
||||
return myEmpiLinkDao.findOne(example);
|
||||
}
|
||||
|
|
|
@ -30,8 +30,8 @@ import ca.uhn.fhir.empi.model.EmpiTransactionContext;
|
|||
import ca.uhn.fhir.empi.util.EIDHelper;
|
||||
import ca.uhn.fhir.empi.util.PersonHelper;
|
||||
import ca.uhn.fhir.jpa.empi.dao.EmpiLinkDaoSvc;
|
||||
import ca.uhn.fhir.jpa.empi.svc.candidate.EmpiPersonFindingSvc;
|
||||
import ca.uhn.fhir.jpa.empi.svc.candidate.MatchedPersonCandidate;
|
||||
import ca.uhn.fhir.jpa.empi.svc.candidate.EmpiSourceResourceFindingSvc;
|
||||
import ca.uhn.fhir.jpa.empi.svc.candidate.MatchedSourceResourceCandidate;
|
||||
import ca.uhn.fhir.jpa.entity.EmpiLink;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
|
@ -51,7 +51,7 @@ public class EmpiEidUpdateService {
|
|||
@Autowired
|
||||
private IEmpiLinkSvc myEmpiLinkSvc;
|
||||
@Autowired
|
||||
private EmpiPersonFindingSvc myEmpiPersonFindingSvc;
|
||||
private EmpiSourceResourceFindingSvc myEmpiSourceResourceFindingSvc;
|
||||
@Autowired
|
||||
private PersonHelper myPersonHelper;
|
||||
@Autowired
|
||||
|
@ -61,17 +61,18 @@ public class EmpiEidUpdateService {
|
|||
@Autowired
|
||||
private IEmpiSettings myEmpiSettings;
|
||||
|
||||
void handleEmpiUpdate(IAnyResource theResource, MatchedPersonCandidate theMatchedPersonCandidate, EmpiTransactionContext theEmpiTransactionContext) {
|
||||
void handleEmpiUpdate(IAnyResource theResource, MatchedSourceResourceCandidate theMatchedSourceResourceCandidate, EmpiTransactionContext theEmpiTransactionContext) {
|
||||
|
||||
EmpiUpdateContext updateContext = new EmpiUpdateContext(theMatchedPersonCandidate, theResource);
|
||||
EmpiUpdateContext updateContext = new EmpiUpdateContext(theMatchedSourceResourceCandidate, theResource);
|
||||
|
||||
if (updateContext.isRemainsMatchedToSamePerson()) {
|
||||
myPersonHelper.updatePersonFromUpdatedEmpiTarget(updateContext.getMatchedPerson(), theResource, theEmpiTransactionContext);
|
||||
// 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);
|
||||
if (!updateContext.isIncomingResourceHasAnEid() || updateContext.isHasEidsInCommon()) {
|
||||
//update to patient that uses internal EIDs only.
|
||||
myEmpiLinkSvc.updateLink(updateContext.getMatchedPerson(), theResource, theMatchedPersonCandidate.getMatchResult(), EmpiLinkSourceEnum.AUTO, theEmpiTransactionContext);
|
||||
myEmpiLinkSvc.updateLink(updateContext.getMatchedPerson(), theResource, theMatchedSourceResourceCandidate.getMatchResult(), EmpiLinkSourceEnum.AUTO, theEmpiTransactionContext);
|
||||
} else if (!updateContext.isHasEidsInCommon()) {
|
||||
handleNoEidsInCommon(theResource, theMatchedPersonCandidate, theEmpiTransactionContext, updateContext);
|
||||
handleNoEidsInCommon(theResource, theMatchedSourceResourceCandidate, theEmpiTransactionContext, 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.
|
||||
|
@ -80,7 +81,7 @@ public class EmpiEidUpdateService {
|
|||
}
|
||||
}
|
||||
|
||||
private void handleNoEidsInCommon(IAnyResource theResource, MatchedPersonCandidate theMatchedPersonCandidate, EmpiTransactionContext theEmpiTransactionContext, EmpiUpdateContext theUpdateContext) {
|
||||
private void handleNoEidsInCommon(IAnyResource theResource, MatchedSourceResourceCandidate theMatchedSourceResourceCandidate, EmpiTransactionContext theEmpiTransactionContext, EmpiUpdateContext theUpdateContext) {
|
||||
// the user is simply updating their EID. We propagate this change to the Person.
|
||||
//overwrite. No EIDS in common, but still same person.
|
||||
if (myEmpiSettings.isPreventMultipleEids()) {
|
||||
|
@ -92,7 +93,7 @@ public class EmpiEidUpdateService {
|
|||
} else {
|
||||
myPersonHelper.handleExternalEidAddition(theUpdateContext.getMatchedPerson(), theResource, theEmpiTransactionContext);
|
||||
}
|
||||
myEmpiLinkSvc.updateLink(theUpdateContext.getMatchedPerson(), theResource, theMatchedPersonCandidate.getMatchResult(), EmpiLinkSourceEnum.AUTO, theEmpiTransactionContext);
|
||||
myEmpiLinkSvc.updateLink(theUpdateContext.getMatchedPerson(), theResource, theMatchedSourceResourceCandidate.getMatchResult(), EmpiLinkSourceEnum.AUTO, theEmpiTransactionContext);
|
||||
}
|
||||
|
||||
private void handleExternalEidOverwrite(IAnyResource thePerson, IAnyResource theResource, EmpiTransactionContext theEmpiTransactionContext) {
|
||||
|
@ -102,7 +103,7 @@ public class EmpiEidUpdateService {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean candidateIsSameAsEmpiLinkPerson(EmpiLink theExistingMatchLink, MatchedPersonCandidate thePersonCandidate) {
|
||||
private boolean candidateIsSameAsEmpiLinkPerson(EmpiLink theExistingMatchLink, MatchedSourceResourceCandidate thePersonCandidate) {
|
||||
return theExistingMatchLink.getSourceResourcePid().equals(thePersonCandidate.getCandidatePersonPid().getIdAsLong());
|
||||
}
|
||||
|
||||
|
@ -142,8 +143,9 @@ public class EmpiEidUpdateService {
|
|||
|
||||
private final IAnyResource myMatchedPerson;
|
||||
|
||||
EmpiUpdateContext(MatchedPersonCandidate theMatchedPersonCandidate, IAnyResource theResource) {
|
||||
myMatchedPerson = myEmpiPersonFindingSvc.getPersonFromMatchedPersonCandidate(theMatchedPersonCandidate);
|
||||
EmpiUpdateContext(MatchedSourceResourceCandidate theMatchedSourceResourceCandidate, IAnyResource theResource) {
|
||||
final String resourceType = theResource.getIdElement().getResourceType();
|
||||
myMatchedPerson = myEmpiSourceResourceFindingSvc.getSourceResourceFromMatchedSourceResourceCandidate(theMatchedSourceResourceCandidate, resourceType);
|
||||
|
||||
myHasEidsInCommon = myEIDHelper.hasEidOverlap(myMatchedPerson, theResource);
|
||||
myIncomingResourceHasAnEid = !myEIDHelper.getExternalEid(theResource).isEmpty();
|
||||
|
@ -152,9 +154,10 @@ public class EmpiEidUpdateService {
|
|||
myExistingPerson = null;
|
||||
|
||||
if (theExistingMatchLink.isPresent()) {
|
||||
Long existingPersonPid = theExistingMatchLink.get().getSourceResourcePid();
|
||||
myExistingPerson = myEmpiResourceDaoSvc.readPersonByPid(new ResourcePersistentId(existingPersonPid));
|
||||
myRemainsMatchedToSamePerson = candidateIsSameAsEmpiLinkPerson(theExistingMatchLink.get(), theMatchedPersonCandidate);
|
||||
EmpiLink empiLink = theExistingMatchLink.get();
|
||||
Long existingPersonPid = empiLink.getSourceResourcePid();
|
||||
myExistingPerson = myEmpiResourceDaoSvc.readSourceResourceByPid(new ResourcePersistentId(existingPersonPid), resourceType);
|
||||
myRemainsMatchedToSamePerson = candidateIsSameAsEmpiLinkPerson(empiLink, theMatchedSourceResourceCandidate);
|
||||
} else {
|
||||
myRemainsMatchedToSamePerson = false;
|
||||
}
|
||||
|
|
|
@ -74,23 +74,23 @@ public class EmpiLinkSvcImpl implements IEmpiLinkSvc {
|
|||
" not linking as POSSIBLE_DUPLICATE.");
|
||||
return;
|
||||
}
|
||||
EmpiMatchResultEnum matchResultEnum = theMatchOutcome.getMatchResultEnum();
|
||||
validateRequestIsLegal(thePerson, theTarget, matchResultEnum, theLinkSource);
|
||||
switch (matchResultEnum) {
|
||||
case MATCH:
|
||||
myPersonHelper.addOrUpdateLink(thePerson, resourceId, AssuranceLevelUtil.getAssuranceLevel(matchResultEnum, theLinkSource), theEmpiTransactionContext);
|
||||
myEmpiResourceDaoSvc.updatePerson(thePerson);
|
||||
break;
|
||||
case POSSIBLE_MATCH:
|
||||
myPersonHelper.addOrUpdateLink(thePerson, resourceId, AssuranceLevelUtil.getAssuranceLevel(matchResultEnum, theLinkSource), theEmpiTransactionContext);
|
||||
break;
|
||||
case NO_MATCH:
|
||||
myPersonHelper.removeLink(thePerson, resourceId, theEmpiTransactionContext);
|
||||
break;
|
||||
case POSSIBLE_DUPLICATE:
|
||||
break;
|
||||
}
|
||||
myEmpiResourceDaoSvc.updatePerson(thePerson);
|
||||
// EmpiMatchResultEnum matchResultEnum = theMatchOutcome.getMatchResultEnum();
|
||||
// validateRequestIsLegal(thePerson, theTarget, matchResultEnum, theLinkSource);
|
||||
// switch (matchResultEnum) {
|
||||
// case MATCH:
|
||||
// myPersonHelper.addOrUpdateLink(thePerson, resourceId, AssuranceLevelUtil.getAssuranceLevel(matchResultEnum, theLinkSource), theEmpiTransactionContext);
|
||||
// myEmpiResourceDaoSvc.updatePerson(thePerson);
|
||||
// break;
|
||||
// case POSSIBLE_MATCH:
|
||||
// myPersonHelper.addOrUpdateLink(thePerson, resourceId, AssuranceLevelUtil.getAssuranceLevel(matchResultEnum, theLinkSource), theEmpiTransactionContext);
|
||||
// break;
|
||||
// case NO_MATCH:
|
||||
// myPersonHelper.removeLink(thePerson, resourceId, theEmpiTransactionContext);
|
||||
// break;
|
||||
// case POSSIBLE_DUPLICATE:
|
||||
// break;
|
||||
// }
|
||||
myEmpiResourceDaoSvc.upsertSourceResource(thePerson, theEmpiTransactionContext.getResourceType());
|
||||
createOrUpdateLinkEntity(thePerson, theTarget, theMatchOutcome, theLinkSource, theEmpiTransactionContext);
|
||||
}
|
||||
|
||||
|
@ -171,15 +171,15 @@ public class EmpiLinkSvcImpl implements IEmpiLinkSvc {
|
|||
if (thePerson.getIdElement().getIdPart() == null || theCandidate.getIdElement().getIdPart() == null) {
|
||||
return Optional.empty();
|
||||
} else {
|
||||
return myEmpiLinkDaoSvc.getLinkByPersonPidAndTargetPid(
|
||||
return myEmpiLinkDaoSvc.getLinkBySourceResourcePidAndTargetResourcePid(
|
||||
myIdHelperService.getPidOrNull(thePerson),
|
||||
myIdHelperService.getPidOrNull(theCandidate)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void createOrUpdateLinkEntity(IBaseResource thePerson, IBaseResource theResource, EmpiMatchOutcome theMatchOutcome, EmpiLinkSourceEnum theLinkSource, EmpiTransactionContext theEmpiTransactionContext) {
|
||||
myEmpiLinkDaoSvc.createOrUpdateLinkEntity(thePerson, theResource, theMatchOutcome, theLinkSource, theEmpiTransactionContext);
|
||||
private void createOrUpdateLinkEntity(IBaseResource theSourceResource, IBaseResource theTargetResource, EmpiMatchOutcome theMatchOutcome, EmpiLinkSourceEnum theLinkSource, EmpiTransactionContext theEmpiTransactionContext) {
|
||||
myEmpiLinkDaoSvc.createOrUpdateLinkEntity(theSourceResource, theTargetResource, theMatchOutcome, theLinkSource, theEmpiTransactionContext);
|
||||
}
|
||||
|
||||
private void log(EmpiTransactionContext theEmpiTransactionContext, String theMessage) {
|
||||
|
|
|
@ -67,7 +67,7 @@ public class EmpiLinkUpdaterSvcImpl implements IEmpiLinkUpdaterSvc {
|
|||
Long personId = myIdHelperService.getPidOrThrowException(thePerson);
|
||||
Long targetId = myIdHelperService.getPidOrThrowException(theTarget);
|
||||
|
||||
Optional<EmpiLink> oEmpiLink = myEmpiLinkDaoSvc.getLinkByPersonPidAndTargetPid(personId, targetId);
|
||||
Optional<EmpiLink> oEmpiLink = myEmpiLinkDaoSvc.getLinkBySourceResourcePidAndTargetResourcePid(personId, targetId);
|
||||
if (!oEmpiLink.isPresent()) {
|
||||
throw new InvalidRequestException("No link exists between " + thePerson.getIdElement().toVersionless() + " and " + theTarget.getIdElement().toVersionless());
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ public class EmpiLinkUpdaterSvcImpl implements IEmpiLinkUpdaterSvc {
|
|||
empiLink.setLinkSource(EmpiLinkSourceEnum.MANUAL);
|
||||
myEmpiLinkDaoSvc.save(empiLink);
|
||||
myEmpiLinkSvc.syncEmpiLinksToPersonLinks(thePerson, theEmpiContext);
|
||||
myEmpiResourceDaoSvc.updatePerson(thePerson);
|
||||
myEmpiResourceDaoSvc.upsertSourceResource(thePerson, theEmpiContext.getResourceType());
|
||||
if (theMatchResult == EmpiMatchResultEnum.NO_MATCH) {
|
||||
// Need to find a new Person to link this target to
|
||||
myEmpiMatchLinkSvc.updateEmpiLinksForEmpiTarget(theTarget, theEmpiContext);
|
||||
|
@ -121,7 +121,7 @@ public class EmpiLinkUpdaterSvcImpl implements IEmpiLinkUpdaterSvc {
|
|||
Long personId = myIdHelperService.getPidOrThrowException(thePerson);
|
||||
Long targetId = myIdHelperService.getPidOrThrowException(theTarget);
|
||||
|
||||
Optional<EmpiLink> oEmpiLink = myEmpiLinkDaoSvc.getLinkByPersonPidAndTargetPid(personId, targetId);
|
||||
Optional<EmpiLink> oEmpiLink = myEmpiLinkDaoSvc.getLinkBySourceResourcePidAndTargetResourcePid(personId, targetId);
|
||||
if (!oEmpiLink.isPresent()) {
|
||||
throw new InvalidRequestException("No link exists between " + thePerson.getIdElement().toVersionless() + " and " + theTarget.getIdElement().toVersionless());
|
||||
}
|
||||
|
|
|
@ -28,8 +28,8 @@ import ca.uhn.fhir.empi.model.EmpiTransactionContext;
|
|||
import ca.uhn.fhir.empi.util.EmpiUtil;
|
||||
import ca.uhn.fhir.empi.util.PersonHelper;
|
||||
import ca.uhn.fhir.jpa.empi.svc.candidate.CandidateList;
|
||||
import ca.uhn.fhir.jpa.empi.svc.candidate.EmpiPersonFindingSvc;
|
||||
import ca.uhn.fhir.jpa.empi.svc.candidate.MatchedPersonCandidate;
|
||||
import ca.uhn.fhir.jpa.empi.svc.candidate.EmpiSourceResourceFindingSvc;
|
||||
import ca.uhn.fhir.jpa.empi.svc.candidate.MatchedSourceResourceCandidate;
|
||||
import ca.uhn.fhir.rest.server.TransactionLogMessages;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -51,7 +51,7 @@ public class EmpiMatchLinkSvc {
|
|||
@Autowired
|
||||
private IEmpiLinkSvc myEmpiLinkSvc;
|
||||
@Autowired
|
||||
private EmpiPersonFindingSvc myEmpiPersonFindingSvc;
|
||||
private EmpiSourceResourceFindingSvc myEmpiSourceResourceFindingSvc;
|
||||
@Autowired
|
||||
private PersonHelper myPersonHelper;
|
||||
@Autowired
|
||||
|
@ -75,7 +75,7 @@ public class EmpiMatchLinkSvc {
|
|||
}
|
||||
|
||||
private EmpiTransactionContext doEmpiUpdate(IAnyResource theResource, EmpiTransactionContext theEmpiTransactionContext) {
|
||||
CandidateList candidateList = myEmpiPersonFindingSvc.findPersonCandidates(theResource);
|
||||
CandidateList candidateList = myEmpiSourceResourceFindingSvc.findSourceResourceCandidates(theResource);
|
||||
|
||||
if (candidateList.isEmpty()) {
|
||||
handleEmpiWithNoCandidates(theResource, theEmpiTransactionContext);
|
||||
|
@ -88,7 +88,7 @@ public class EmpiMatchLinkSvc {
|
|||
}
|
||||
|
||||
private void handleEmpiWithMultipleCandidates(IAnyResource theResource, CandidateList theCandidateList, EmpiTransactionContext theEmpiTransactionContext) {
|
||||
MatchedPersonCandidate firstMatch = theCandidateList.getFirstMatch();
|
||||
MatchedSourceResourceCandidate firstMatch = theCandidateList.getFirstMatch();
|
||||
Long samplePersonPid = firstMatch.getCandidatePersonPid().getIdAsLong();
|
||||
boolean allSamePerson = theCandidateList.stream()
|
||||
.allMatch(candidate -> candidate.getCandidatePersonPid().getIdAsLong().equals(samplePersonPid));
|
||||
|
@ -100,8 +100,9 @@ public class EmpiMatchLinkSvc {
|
|||
log(theEmpiTransactionContext, "EMPI received multiple match candidates, that were linked to different Persons. Setting POSSIBLE_DUPLICATES and POSSIBLE_MATCHES.");
|
||||
//Set them all as POSSIBLE_MATCH
|
||||
List<IAnyResource> persons = new ArrayList<>();
|
||||
for (MatchedPersonCandidate matchedPersonCandidate : theCandidateList.getCandidates()) {
|
||||
IAnyResource person = myEmpiPersonFindingSvc.getPersonFromMatchedPersonCandidate(matchedPersonCandidate);
|
||||
for (MatchedSourceResourceCandidate matchedSourceResourceCandidate : theCandidateList.getCandidates()) {
|
||||
IAnyResource person = myEmpiSourceResourceFindingSvc
|
||||
.getSourceResourceFromMatchedSourceResourceCandidate(matchedSourceResourceCandidate, theEmpiTransactionContext.getResourceType());
|
||||
EmpiMatchOutcome outcome = EmpiMatchOutcome.POSSIBLE_MATCH;
|
||||
outcome.setEidMatch(theCandidateList.isEidMatch());
|
||||
myEmpiLinkSvc.updateLink(person, theResource, outcome, EmpiLinkSourceEnum.AUTO, theEmpiTransactionContext);
|
||||
|
@ -130,9 +131,9 @@ public class EmpiMatchLinkSvc {
|
|||
myEmpiLinkSvc.updateLink(newPerson, theResource, EmpiMatchOutcome.NEW_PERSON_MATCH, EmpiLinkSourceEnum.AUTO, theEmpiTransactionContext);
|
||||
}
|
||||
|
||||
private void handleEmpiCreate(IAnyResource theResource, MatchedPersonCandidate thePersonCandidate, EmpiTransactionContext theEmpiTransactionContext) {
|
||||
private void handleEmpiCreate(IAnyResource theResource, MatchedSourceResourceCandidate thePersonCandidate, EmpiTransactionContext theEmpiTransactionContext) {
|
||||
log(theEmpiTransactionContext, "EMPI has narrowed down to one candidate for matching.");
|
||||
IAnyResource person = myEmpiPersonFindingSvc.getPersonFromMatchedPersonCandidate(thePersonCandidate);
|
||||
IAnyResource person = myEmpiSourceResourceFindingSvc.getSourceResourceFromMatchedSourceResourceCandidate(thePersonCandidate, theEmpiTransactionContext.getResourceType());
|
||||
if (myPersonHelper.isPotentialDuplicate(person, theResource)) {
|
||||
log(theEmpiTransactionContext, "Duplicate detected based on the fact that both resources have different external EIDs.");
|
||||
IAnyResource newPerson = myPersonHelper.createSourceResourceFromEmpiTarget(theResource);
|
||||
|
@ -141,13 +142,14 @@ public class EmpiMatchLinkSvc {
|
|||
} else {
|
||||
if (thePersonCandidate.isMatch()) {
|
||||
myPersonHelper.handleExternalEidAddition(person, theResource, theEmpiTransactionContext);
|
||||
myPersonHelper.updatePersonFromNewlyCreatedEmpiTarget(person, theResource, theEmpiTransactionContext);
|
||||
//
|
||||
// myPersonHelper.updatePersonFromNewlyCreatedEmpiTarget(person, theResource, theEmpiTransactionContext);
|
||||
}
|
||||
myEmpiLinkSvc.updateLink(person, theResource, thePersonCandidate.getMatchResult(), EmpiLinkSourceEnum.AUTO, theEmpiTransactionContext);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleEmpiWithSingleCandidate(IAnyResource theResource, MatchedPersonCandidate thePersonCandidate, EmpiTransactionContext theEmpiTransactionContext) {
|
||||
private void handleEmpiWithSingleCandidate(IAnyResource theResource, MatchedSourceResourceCandidate thePersonCandidate, EmpiTransactionContext theEmpiTransactionContext) {
|
||||
log(theEmpiTransactionContext, "EMPI has narrowed down to one candidate for matching.");
|
||||
if (theEmpiTransactionContext.getRestOperation().equals(EmpiTransactionContext.OperationType.UPDATE_RESOURCE)) {
|
||||
myEidUpdateService.handleEmpiUpdate(theResource, thePersonCandidate, theEmpiTransactionContext);
|
||||
|
|
|
@ -75,7 +75,7 @@ public class EmpiPersonMergerSvcImpl implements IEmpiPersonMergerSvc {
|
|||
}
|
||||
|
||||
private void addMergeLink(Long theDeactivatedPersonPid, Long theActivePersonPid) {
|
||||
EmpiLink empiLink = myEmpiLinkDaoSvc.getOrCreateEmpiLinkByPersonPidAndTargetPid(theDeactivatedPersonPid, theActivePersonPid);
|
||||
EmpiLink empiLink = myEmpiLinkDaoSvc.getOrCreateEmpiLinkBySourceResourcePidAndTargetResourcePid(theDeactivatedPersonPid, theActivePersonPid);
|
||||
empiLink
|
||||
.setEmpiTargetType("Person")
|
||||
.setMatchResult(EmpiMatchResultEnum.REDIRECT)
|
||||
|
@ -85,7 +85,7 @@ public class EmpiPersonMergerSvcImpl implements IEmpiPersonMergerSvc {
|
|||
|
||||
private void refreshLinksAndUpdatePerson(IAnyResource theToPerson, EmpiTransactionContext theEmpiTransactionContext) {
|
||||
myEmpiLinkSvc.syncEmpiLinksToPersonLinks(theToPerson, theEmpiTransactionContext);
|
||||
myEmpiResourceDaoSvc.updatePerson(theToPerson);
|
||||
myEmpiResourceDaoSvc.upsertSourceResource(theToPerson, theEmpiTransactionContext.getResourceType());
|
||||
}
|
||||
|
||||
private void mergeLinks(IAnyResource theFromPerson, IAnyResource theToPerson, Long theToPersonPid, EmpiTransactionContext theEmpiTransactionContext) {
|
||||
|
|
|
@ -73,16 +73,18 @@ public class EmpiResourceDaoSvc {
|
|||
return (IAnyResource) myPractitionerDao.read(theId);
|
||||
}
|
||||
|
||||
public DaoMethodOutcome updatePerson(IAnyResource thePerson) {
|
||||
if (thePerson.getIdElement().hasIdPart()) {
|
||||
return myPersonDao.update(thePerson);
|
||||
public DaoMethodOutcome upsertSourceResource(IAnyResource theSourceResource, String theResourceType) {
|
||||
IFhirResourceDao resourceDao = myDaoRegistry.getResourceDao(theResourceType);
|
||||
if (theSourceResource.getIdElement().hasIdPart()) {
|
||||
return resourceDao.update(theSourceResource);
|
||||
} else {
|
||||
return myPersonDao.create(thePerson);
|
||||
return resourceDao.create(theSourceResource);
|
||||
}
|
||||
}
|
||||
|
||||
public IAnyResource readPersonByPid(ResourcePersistentId thePersonPid) {
|
||||
return (IAnyResource) myPersonDao.readByPid(thePersonPid);
|
||||
public IAnyResource readSourceResourceByPid(ResourcePersistentId theSourceResourcePid, String theResourceType) {
|
||||
IFhirResourceDao resourceDao = myDaoRegistry.getResourceDao(theResourceType);
|
||||
return (IAnyResource) resourceDao.readByPid(theSourceResourcePid);
|
||||
}
|
||||
|
||||
public Optional<IAnyResource> searchPersonByEid(String theEid) {
|
||||
|
|
|
@ -35,11 +35,11 @@ public abstract class BaseCandidateFinder {
|
|||
|
||||
CandidateList findCandidates(IAnyResource theTarget) {
|
||||
CandidateList candidateList = new CandidateList(getStrategy());
|
||||
candidateList.addAll(findMatchPersonCandidates(theTarget));
|
||||
candidateList.addAll(findMatchSourceResourceCandidates(theTarget));
|
||||
return candidateList;
|
||||
}
|
||||
|
||||
protected abstract List<MatchedPersonCandidate> findMatchPersonCandidates(IAnyResource theTarget);
|
||||
protected abstract List<MatchedSourceResourceCandidate> findMatchSourceResourceCandidates(IAnyResource theTarget);
|
||||
|
||||
protected abstract CandidateStrategyEnum getStrategy();
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ import java.util.stream.Stream;
|
|||
|
||||
public class CandidateList {
|
||||
private final CandidateStrategyEnum myStrategy;
|
||||
private final List<MatchedPersonCandidate> myList = new ArrayList<>();
|
||||
private final List<MatchedSourceResourceCandidate> myList = new ArrayList<>();
|
||||
|
||||
public CandidateList(CandidateStrategyEnum theStrategy) {
|
||||
myStrategy = theStrategy;
|
||||
|
@ -41,9 +41,9 @@ public class CandidateList {
|
|||
return myList.isEmpty();
|
||||
}
|
||||
|
||||
public void addAll(List<MatchedPersonCandidate> theList) { myList.addAll(theList); }
|
||||
public void addAll(List<MatchedSourceResourceCandidate> theList) { myList.addAll(theList); }
|
||||
|
||||
public MatchedPersonCandidate getOnlyMatch() {
|
||||
public MatchedSourceResourceCandidate getOnlyMatch() {
|
||||
assert myList.size() == 1;
|
||||
return myList.get(0);
|
||||
}
|
||||
|
@ -52,15 +52,15 @@ public class CandidateList {
|
|||
return myList.size()== 1;
|
||||
}
|
||||
|
||||
public Stream<MatchedPersonCandidate> stream() {
|
||||
public Stream<MatchedSourceResourceCandidate> stream() {
|
||||
return myList.stream();
|
||||
}
|
||||
|
||||
public List<MatchedPersonCandidate> getCandidates() {
|
||||
public List<MatchedSourceResourceCandidate> getCandidates() {
|
||||
return Collections.unmodifiableList(myList);
|
||||
}
|
||||
|
||||
public MatchedPersonCandidate getFirstMatch() {
|
||||
public MatchedSourceResourceCandidate getFirstMatch() {
|
||||
return myList.get(0);
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class EmpiPersonFindingSvc {
|
||||
public class EmpiSourceResourceFindingSvc {
|
||||
private static final Logger ourLog = Logs.getEmpiTroubleshootingLog();
|
||||
|
||||
@Autowired
|
||||
|
@ -46,7 +46,7 @@ public class EmpiPersonFindingSvc {
|
|||
private FindCandidateByScoreSvc myFindCandidateByScoreSvc;
|
||||
|
||||
/**
|
||||
* Given an incoming IBaseResource, limited to Patient/Practitioner, return a list of {@link MatchedPersonCandidate}
|
||||
* Given an incoming IBaseResource, limited to Patient/Practitioner, return a list of {@link MatchedSourceResourceCandidate}
|
||||
* indicating possible candidates for a matching Person. 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.
|
||||
|
@ -57,27 +57,27 @@ public class EmpiPersonFindingSvc {
|
|||
* field matchers.
|
||||
*
|
||||
* @param theResource the {@link IBaseResource} we are attempting to find matching candidate Persons for.
|
||||
* @return A list of {@link MatchedPersonCandidate} indicating all potential Person matches.
|
||||
* @return A list of {@link MatchedSourceResourceCandidate} indicating all potential Person matches.
|
||||
*/
|
||||
public CandidateList findPersonCandidates(IAnyResource theResource) {
|
||||
CandidateList matchedPersonCandidates = myFindCandidateByEidSvc.findCandidates(theResource);
|
||||
public CandidateList findSourceResourceCandidates(IAnyResource theResource) {
|
||||
CandidateList matchedSourceResourceCandidates = myFindCandidateByEidSvc.findCandidates(theResource);
|
||||
|
||||
if (matchedPersonCandidates.isEmpty()) {
|
||||
matchedPersonCandidates = myFindCandidateByLinkSvc.findCandidates(theResource);
|
||||
if (matchedSourceResourceCandidates.isEmpty()) {
|
||||
matchedSourceResourceCandidates = myFindCandidateByLinkSvc.findCandidates(theResource);
|
||||
}
|
||||
|
||||
if (matchedPersonCandidates.isEmpty()) {
|
||||
if (matchedSourceResourceCandidates.isEmpty()) {
|
||||
//OK, so we have not found any links in the EmpiLink table with us as a target. Next, let's find possible Patient/Practitioner
|
||||
//matches by following EMPI rules.
|
||||
|
||||
matchedPersonCandidates = myFindCandidateByScoreSvc.findCandidates(theResource);
|
||||
matchedSourceResourceCandidates = myFindCandidateByScoreSvc.findCandidates(theResource);
|
||||
}
|
||||
|
||||
return matchedPersonCandidates;
|
||||
return matchedSourceResourceCandidates;
|
||||
}
|
||||
|
||||
public IAnyResource getPersonFromMatchedPersonCandidate(MatchedPersonCandidate theMatchedPersonCandidate) {
|
||||
ResourcePersistentId personPid = theMatchedPersonCandidate.getCandidatePersonPid();
|
||||
return myEmpiResourceDaoSvc.readPersonByPid(personPid);
|
||||
public IAnyResource getSourceResourceFromMatchedSourceResourceCandidate(MatchedSourceResourceCandidate theMatchedSourceResourceCandidate, String theResourceType) {
|
||||
ResourcePersistentId personPid = theMatchedSourceResourceCandidate.getCandidatePersonPid();
|
||||
return myEmpiResourceDaoSvc.readSourceResourceByPid(personPid, theResourceType);
|
||||
}
|
||||
}
|
|
@ -44,8 +44,8 @@ public class FindCandidateByEidSvc extends BaseCandidateFinder {
|
|||
@Autowired
|
||||
private EmpiResourceDaoSvc myEmpiResourceDaoSvc;
|
||||
|
||||
protected List<MatchedPersonCandidate> findMatchPersonCandidates(IAnyResource theBaseResource) {
|
||||
List<MatchedPersonCandidate> retval = new ArrayList<>();
|
||||
protected List<MatchedSourceResourceCandidate> findMatchSourceResourceCandidates(IAnyResource theBaseResource) {
|
||||
List<MatchedSourceResourceCandidate> retval = new ArrayList<>();
|
||||
|
||||
List<CanonicalEID> eidFromResource = myEIDHelper.getExternalEid(theBaseResource);
|
||||
if (!eidFromResource.isEmpty()) {
|
||||
|
@ -54,7 +54,7 @@ public class FindCandidateByEidSvc extends BaseCandidateFinder {
|
|||
if (oFoundPerson.isPresent()) {
|
||||
IAnyResource foundPerson = oFoundPerson.get();
|
||||
Long pidOrNull = myIdHelperService.getPidOrNull(foundPerson);
|
||||
MatchedPersonCandidate mpc = new MatchedPersonCandidate(new ResourcePersistentId(pidOrNull), EmpiMatchOutcome.EID_MATCH);
|
||||
MatchedSourceResourceCandidate mpc = new MatchedSourceResourceCandidate(new ResourcePersistentId(pidOrNull), EmpiMatchOutcome.EID_MATCH);
|
||||
ourLog.debug("Matched {} by EID {}", foundPerson.getIdElement(), eid);
|
||||
retval.add(mpc);
|
||||
}
|
||||
|
|
|
@ -39,11 +39,11 @@ public class FindCandidateByLinkSvc extends BaseCandidateFinder {
|
|||
* Attempt to find a currently matching Person, based on the presence of an {@link EmpiLink} entity.
|
||||
*
|
||||
* @param theTarget the {@link IAnyResource} that we want to find candidate Persons for.
|
||||
* @return an Optional list of {@link MatchedPersonCandidate} indicating matches.
|
||||
* @return an Optional list of {@link MatchedSourceResourceCandidate} indicating matches.
|
||||
*/
|
||||
@Override
|
||||
protected List<MatchedPersonCandidate> findMatchPersonCandidates(IAnyResource theTarget) {
|
||||
List<MatchedPersonCandidate> retval = new ArrayList<>();
|
||||
protected List<MatchedSourceResourceCandidate> findMatchSourceResourceCandidates(IAnyResource theTarget) {
|
||||
List<MatchedSourceResourceCandidate> retval = new ArrayList<>();
|
||||
|
||||
Long targetPid = myIdHelperService.getPidOrNull(theTarget);
|
||||
if (targetPid != null) {
|
||||
|
@ -51,7 +51,7 @@ public class FindCandidateByLinkSvc extends BaseCandidateFinder {
|
|||
if (oLink.isPresent()) {
|
||||
ResourcePersistentId personPid = new ResourcePersistentId(oLink.get().getSourceResourcePid());
|
||||
ourLog.debug("Resource previously linked. Using existing link.");
|
||||
retval.add(new MatchedPersonCandidate(personPid, oLink.get()));
|
||||
retval.add(new MatchedSourceResourceCandidate(personPid, oLink.get()));
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
|
|
|
@ -59,11 +59,11 @@ public class FindCandidateByScoreSvc extends BaseCandidateFinder {
|
|||
* entries in the EmpiLink table, and returns all the matches found therein.
|
||||
*
|
||||
* @param theTarget the {@link IBaseResource} which we want to find candidate Persons for.
|
||||
* @return an Optional list of {@link MatchedPersonCandidate} indicating matches.
|
||||
* @return an Optional list of {@link MatchedSourceResourceCandidate} indicating matches.
|
||||
*/
|
||||
@Override
|
||||
protected List<MatchedPersonCandidate> findMatchPersonCandidates(IAnyResource theTarget) {
|
||||
List<MatchedPersonCandidate> retval = new ArrayList<>();
|
||||
protected List<MatchedSourceResourceCandidate> findMatchSourceResourceCandidates(IAnyResource theTarget) {
|
||||
List<MatchedSourceResourceCandidate> retval = new ArrayList<>();
|
||||
|
||||
List<Long> personPidsToExclude = getNoMatchPersonPids(theTarget);
|
||||
|
||||
|
@ -87,7 +87,7 @@ public class FindCandidateByScoreSvc extends BaseCandidateFinder {
|
|||
continue;
|
||||
}
|
||||
|
||||
MatchedPersonCandidate candidate = new MatchedPersonCandidate(getResourcePersistentId(matchEmpiLink.getSourceResourcePid()), match.getMatchResult());
|
||||
MatchedSourceResourceCandidate candidate = new MatchedSourceResourceCandidate(getResourcePersistentId(matchEmpiLink.getSourceResourcePid()), match.getMatchResult());
|
||||
retval.add(candidate);
|
||||
}
|
||||
return retval;
|
||||
|
|
|
@ -24,22 +24,23 @@ import ca.uhn.fhir.empi.api.EmpiMatchOutcome;
|
|||
import ca.uhn.fhir.jpa.entity.EmpiLink;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
|
||||
public class MatchedPersonCandidate {
|
||||
private final ResourcePersistentId myCandidatePersonPid;
|
||||
public class MatchedSourceResourceCandidate {
|
||||
|
||||
private final ResourcePersistentId myCandidateSourceResourcePid;
|
||||
private final EmpiMatchOutcome myEmpiMatchOutcome;
|
||||
|
||||
public MatchedPersonCandidate(ResourcePersistentId theCandidate, EmpiMatchOutcome theEmpiMatchOutcome) {
|
||||
myCandidatePersonPid = theCandidate;
|
||||
public MatchedSourceResourceCandidate(ResourcePersistentId theCandidate, EmpiMatchOutcome theEmpiMatchOutcome) {
|
||||
myCandidateSourceResourcePid = theCandidate;
|
||||
myEmpiMatchOutcome = theEmpiMatchOutcome;
|
||||
}
|
||||
|
||||
public MatchedPersonCandidate(ResourcePersistentId thePersonPid, EmpiLink theEmpiLink) {
|
||||
myCandidatePersonPid = thePersonPid;
|
||||
public MatchedSourceResourceCandidate(ResourcePersistentId thePersonPid, EmpiLink theEmpiLink) {
|
||||
myCandidateSourceResourcePid = thePersonPid;
|
||||
myEmpiMatchOutcome = new EmpiMatchOutcome(theEmpiLink.getVector(), theEmpiLink.getScore()).setMatchResultEnum(theEmpiLink.getMatchResult());
|
||||
}
|
||||
|
||||
public ResourcePersistentId getCandidatePersonPid() {
|
||||
return myCandidatePersonPid;
|
||||
return myCandidateSourceResourcePid;
|
||||
}
|
||||
|
||||
public EmpiMatchOutcome getMatchResult() {
|
|
@ -308,27 +308,29 @@ abstract public class BaseEmpiR4Test extends BaseJpaR4Test {
|
|||
|
||||
protected Patient createPatientAndUpdateLinks(Patient thePatient) {
|
||||
thePatient = createPatient(thePatient);
|
||||
myEmpiMatchLinkSvc.updateEmpiLinksForEmpiTarget(thePatient, createContextForCreate());
|
||||
myEmpiMatchLinkSvc.updateEmpiLinksForEmpiTarget(thePatient, createContextForCreate("Patient"));
|
||||
return thePatient;
|
||||
}
|
||||
|
||||
protected EmpiTransactionContext createContextForCreate() {
|
||||
protected EmpiTransactionContext createContextForCreate(String theResourceType) {
|
||||
EmpiTransactionContext ctx = new EmpiTransactionContext();
|
||||
ctx.setRestOperation(EmpiTransactionContext.OperationType.CREATE_RESOURCE);
|
||||
ctx.setResourceType(theResourceType);
|
||||
ctx.setTransactionLogMessages(null);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
protected EmpiTransactionContext createContextForUpdate() {
|
||||
protected EmpiTransactionContext createContextForUpdate(String theResourceType) {
|
||||
EmpiTransactionContext ctx = new EmpiTransactionContext();
|
||||
ctx.setRestOperation(EmpiTransactionContext.OperationType.UPDATE_RESOURCE);
|
||||
ctx.setTransactionLogMessages(null);
|
||||
ctx.setResourceType(theResourceType);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
protected Patient updatePatientAndUpdateLinks(Patient thePatient) {
|
||||
thePatient = (Patient) myPatientDao.update(thePatient).getResource();
|
||||
myEmpiMatchLinkSvc.updateEmpiLinksForEmpiTarget(thePatient, createContextForUpdate());
|
||||
myEmpiMatchLinkSvc.updateEmpiLinksForEmpiTarget(thePatient, createContextForUpdate(thePatient.getIdElement().getResourceType()));
|
||||
return thePatient;
|
||||
}
|
||||
|
||||
|
@ -336,7 +338,7 @@ abstract public class BaseEmpiR4Test extends BaseJpaR4Test {
|
|||
thePractitioner.setActive(true);
|
||||
DaoMethodOutcome daoMethodOutcome = myPractitionerDao.create(thePractitioner);
|
||||
thePractitioner.setId(daoMethodOutcome.getId());
|
||||
myEmpiMatchLinkSvc.updateEmpiLinksForEmpiTarget(thePractitioner, createContextForCreate());
|
||||
myEmpiMatchLinkSvc.updateEmpiLinksForEmpiTarget(thePractitioner, createContextForCreate("Practitioner"));
|
||||
return thePractitioner;
|
||||
}
|
||||
|
||||
|
|
|
@ -53,14 +53,14 @@ public class EmpiLinkSvcTest extends BaseEmpiR4Test {
|
|||
Patient patient = createPatient();
|
||||
|
||||
{
|
||||
myEmpiLinkSvc.updateLink(person, patient, POSSIBLE_MATCH, EmpiLinkSourceEnum.AUTO, createContextForCreate());
|
||||
myEmpiLinkSvc.updateLink(person, patient, POSSIBLE_MATCH, EmpiLinkSourceEnum.AUTO, createContextForCreate("Patient"));
|
||||
assertLinkCount(1);
|
||||
Person newPerson = myPersonDao.read(personId);
|
||||
assertEquals(1, newPerson.getLink().size());
|
||||
}
|
||||
|
||||
{
|
||||
myEmpiLinkSvc.updateLink(person, patient, EmpiMatchOutcome.NO_MATCH, EmpiLinkSourceEnum.MANUAL, createContextForCreate());
|
||||
myEmpiLinkSvc.updateLink(person, patient, EmpiMatchOutcome.NO_MATCH, EmpiLinkSourceEnum.MANUAL, createContextForCreate("Patient"));
|
||||
assertLinkCount(1);
|
||||
Person newPerson = myPersonDao.read(personId);
|
||||
assertEquals(0, newPerson.getLink().size());
|
||||
|
@ -73,8 +73,8 @@ public class EmpiLinkSvcTest extends BaseEmpiR4Test {
|
|||
assertLinkCount(0);
|
||||
Person person = createPerson();
|
||||
Person target = createPerson();
|
||||
|
||||
myEmpiLinkSvc.updateLink(person, target, EmpiMatchOutcome.POSSIBLE_DUPLICATE, EmpiLinkSourceEnum.AUTO, createContextForCreate());
|
||||
// TODO NOT VALID
|
||||
myEmpiLinkSvc.updateLink(person, target, EmpiMatchOutcome.POSSIBLE_DUPLICATE, EmpiLinkSourceEnum.AUTO, createContextForCreate("Person"));
|
||||
assertLinkCount(1);
|
||||
}
|
||||
|
||||
|
@ -86,12 +86,12 @@ public class EmpiLinkSvcTest extends BaseEmpiR4Test {
|
|||
|
||||
Long personPid = myIdHelperService.getPidOrNull(person);
|
||||
Long targetPid = myIdHelperService.getPidOrNull(target);
|
||||
assertFalse(myEmpiLinkDaoSvc.getLinkByPersonPidAndTargetPid(personPid, targetPid).isPresent());
|
||||
assertFalse(myEmpiLinkDaoSvc.getLinkByPersonPidAndTargetPid(targetPid, personPid).isPresent());
|
||||
assertFalse(myEmpiLinkDaoSvc.getLinkBySourceResourcePidAndTargetResourcePid(personPid, targetPid).isPresent());
|
||||
assertFalse(myEmpiLinkDaoSvc.getLinkBySourceResourcePidAndTargetResourcePid(targetPid, personPid).isPresent());
|
||||
|
||||
saveNoMatchLink(personPid, targetPid);
|
||||
|
||||
myEmpiLinkSvc.updateLink(person, target, EmpiMatchOutcome.POSSIBLE_DUPLICATE, EmpiLinkSourceEnum.AUTO, createContextForCreate());
|
||||
myEmpiLinkSvc.updateLink(person, target, EmpiMatchOutcome.POSSIBLE_DUPLICATE, EmpiLinkSourceEnum.AUTO, createContextForCreate("Person"));
|
||||
assertFalse(myEmpiLinkDaoSvc.getEmpiLinksByPersonPidTargetPidAndMatchResult(personPid, targetPid, EmpiMatchResultEnum.POSSIBLE_DUPLICATE).isPresent());
|
||||
assertLinkCount(1);
|
||||
}
|
||||
|
@ -104,12 +104,12 @@ public class EmpiLinkSvcTest extends BaseEmpiR4Test {
|
|||
|
||||
Long personPid = myIdHelperService.getPidOrNull(person);
|
||||
Long targetPid = myIdHelperService.getPidOrNull(target);
|
||||
assertFalse(myEmpiLinkDaoSvc.getLinkByPersonPidAndTargetPid(personPid, targetPid).isPresent());
|
||||
assertFalse(myEmpiLinkDaoSvc.getLinkByPersonPidAndTargetPid(targetPid, personPid).isPresent());
|
||||
assertFalse(myEmpiLinkDaoSvc.getLinkBySourceResourcePidAndTargetResourcePid(personPid, targetPid).isPresent());
|
||||
assertFalse(myEmpiLinkDaoSvc.getLinkBySourceResourcePidAndTargetResourcePid(targetPid, personPid).isPresent());
|
||||
|
||||
saveNoMatchLink(targetPid, personPid);
|
||||
|
||||
myEmpiLinkSvc.updateLink(person, target, EmpiMatchOutcome.POSSIBLE_DUPLICATE, EmpiLinkSourceEnum.AUTO, createContextForCreate());
|
||||
myEmpiLinkSvc.updateLink(person, target, EmpiMatchOutcome.POSSIBLE_DUPLICATE, EmpiLinkSourceEnum.AUTO, createContextForCreate("Person"));
|
||||
assertFalse(myEmpiLinkDaoSvc.getEmpiLinksByPersonPidTargetPidAndMatchResult(personPid, targetPid, EmpiMatchResultEnum.POSSIBLE_DUPLICATE).isPresent());
|
||||
assertLinkCount(1);
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ public class EmpiLinkSvcTest extends BaseEmpiR4Test {
|
|||
Person person = createPerson(buildJanePerson());
|
||||
Patient patient = createPatient(buildJanePatient());
|
||||
|
||||
myEmpiLinkSvc.updateLink(person, patient, EmpiMatchOutcome.NO_MATCH, EmpiLinkSourceEnum.MANUAL, createContextForCreate());
|
||||
myEmpiLinkSvc.updateLink(person, patient, EmpiMatchOutcome.NO_MATCH, EmpiLinkSourceEnum.MANUAL, createContextForCreate("Patient"));
|
||||
try {
|
||||
myEmpiLinkSvc.updateLink(person, patient, EmpiMatchOutcome.NEW_PERSON_MATCH, EmpiLinkSourceEnum.AUTO, null);
|
||||
fail();
|
||||
|
@ -158,9 +158,9 @@ public class EmpiLinkSvcTest extends BaseEmpiR4Test {
|
|||
Patient patient2 = createPatient(buildJanePatient());
|
||||
assertEquals(0, myEmpiLinkDao.count());
|
||||
|
||||
myEmpiLinkDaoSvc.createOrUpdateLinkEntity(person, patient1, EmpiMatchOutcome.NEW_PERSON_MATCH, EmpiLinkSourceEnum.MANUAL, createContextForCreate());
|
||||
myEmpiLinkDaoSvc.createOrUpdateLinkEntity(person, patient2, EmpiMatchOutcome.NO_MATCH, EmpiLinkSourceEnum.MANUAL, createContextForCreate());
|
||||
myEmpiLinkSvc.syncEmpiLinksToPersonLinks(person, createContextForCreate());
|
||||
myEmpiLinkDaoSvc.createOrUpdateLinkEntity(person, patient1, EmpiMatchOutcome.NEW_PERSON_MATCH, EmpiLinkSourceEnum.MANUAL, createContextForCreate("Patient"));
|
||||
myEmpiLinkDaoSvc.createOrUpdateLinkEntity(person, patient2, EmpiMatchOutcome.NO_MATCH, EmpiLinkSourceEnum.MANUAL, createContextForCreate("Patient"));
|
||||
myEmpiLinkSvc.syncEmpiLinksToPersonLinks(person, createContextForCreate("Patient"));
|
||||
assertTrue(person.hasLink());
|
||||
assertEquals(patient1.getIdElement().toVersionless().getValue(), person.getLinkFirstRep().getTarget().getReference());
|
||||
}
|
||||
|
|
|
@ -97,10 +97,10 @@ public class EmpiMatchLinkSvcTest extends BaseEmpiR4Test {
|
|||
|
||||
//Create a manual NO_MATCH between janePerson and unmatchedJane.
|
||||
Patient unmatchedJane = createPatient(buildJanePatient());
|
||||
myEmpiLinkSvc.updateLink(janePerson, unmatchedJane, EmpiMatchOutcome.NO_MATCH, EmpiLinkSourceEnum.MANUAL, createContextForCreate());
|
||||
myEmpiLinkSvc.updateLink(janePerson, unmatchedJane, EmpiMatchOutcome.NO_MATCH, EmpiLinkSourceEnum.MANUAL, createContextForCreate("Patient"));
|
||||
|
||||
//rerun EMPI rules against unmatchedJane.
|
||||
myEmpiMatchLinkSvc.updateEmpiLinksForEmpiTarget(unmatchedJane, createContextForCreate());
|
||||
myEmpiMatchLinkSvc.updateEmpiLinksForEmpiTarget(unmatchedJane, createContextForCreate("Patient"));
|
||||
|
||||
assertThat(unmatchedJane, is(not(sameSourceResourceAs(janePerson))));
|
||||
assertThat(unmatchedJane, is(not(linkedTo(originalJane))));
|
||||
|
@ -119,12 +119,12 @@ public class EmpiMatchLinkSvcTest extends BaseEmpiR4Test {
|
|||
Patient unmatchedPatient = createPatient(buildJanePatient());
|
||||
|
||||
//This simulates an admin specifically saying that unmatchedPatient does NOT match janePerson.
|
||||
myEmpiLinkSvc.updateLink(janePerson, unmatchedPatient, EmpiMatchOutcome.NO_MATCH, EmpiLinkSourceEnum.MANUAL, createContextForCreate());
|
||||
myEmpiLinkSvc.updateLink(janePerson, unmatchedPatient, EmpiMatchOutcome.NO_MATCH, EmpiLinkSourceEnum.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.
|
||||
myEmpiMatchLinkSvc.updateEmpiLinksForEmpiTarget(unmatchedPatient, createContextForCreate());
|
||||
myEmpiMatchLinkSvc.updateEmpiLinksForEmpiTarget(unmatchedPatient, createContextForCreate("Patient"));
|
||||
|
||||
assertThat(unmatchedPatient, is(not(sameSourceResourceAs(janePerson))));
|
||||
assertThat(unmatchedPatient, is(not(linkedTo(originalJane))));
|
||||
|
@ -335,7 +335,7 @@ public class EmpiMatchLinkSvcTest extends BaseEmpiR4Test {
|
|||
//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 = myPersonHelper.createSourceResourceFromEmpiTarget(janePatient2);
|
||||
myEmpiLinkSvc.updateLink(person, janePatient2, EmpiMatchOutcome.NEW_PERSON_MATCH, EmpiLinkSourceEnum.AUTO, createContextForCreate());
|
||||
myEmpiLinkSvc.updateLink(person, janePatient2, EmpiMatchOutcome.NEW_PERSON_MATCH, EmpiLinkSourceEnum.AUTO, createContextForCreate("Patient"));
|
||||
assertThat(janePatient, is(not(sameSourceResourceAs(janePatient2))));
|
||||
|
||||
//In theory, this will match both Persons!
|
||||
|
@ -447,7 +447,9 @@ public class EmpiMatchLinkSvcTest extends BaseEmpiR4Test {
|
|||
//Ensure the related person was updated with new info.
|
||||
Patient sourcePatientFromTarget = (Patient) getSourceResourceFromTargetResource(janePaulPatient);
|
||||
HumanName nameFirstRep = sourcePatientFromTarget.getNameFirstRep();
|
||||
assertThat(nameFirstRep.getGivenAsSingleString(), is(equalToIgnoringCase("paul")));
|
||||
|
||||
// TODO NG attribute propagation has been removed - revisit once source survivorship rules are defined
|
||||
// assertThat(nameFirstRep.getGivenAsSingleString(), is(equalToIgnoringCase("paul")));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -402,7 +402,7 @@ public class EmpiPersonMergerSvcTest extends BaseEmpiR4Test {
|
|||
|
||||
private EmpiLink createEmpiLink(Person thePerson, Patient theTargetPatient) {
|
||||
thePerson.addLink().setTarget(new Reference(theTargetPatient));
|
||||
return myEmpiLinkDaoSvc.createOrUpdateLinkEntity(thePerson, theTargetPatient, POSSIBLE_MATCH, EmpiLinkSourceEnum.AUTO, createContextForCreate());
|
||||
return myEmpiLinkDaoSvc.createOrUpdateLinkEntity(thePerson, theTargetPatient, POSSIBLE_MATCH, EmpiLinkSourceEnum.AUTO, createContextForCreate("Patient"));
|
||||
}
|
||||
|
||||
private void populatePerson(Person thePerson) {
|
||||
|
|
|
@ -24,14 +24,6 @@ import ca.uhn.fhir.rest.server.TransactionLogMessages;
|
|||
|
||||
public class EmpiTransactionContext {
|
||||
|
||||
/**
|
||||
* Any EMPI methods may add transaction log messages.
|
||||
*/
|
||||
private TransactionLogMessages myTransactionLogMessages;
|
||||
|
||||
private OperationType myRestOperation;
|
||||
|
||||
|
||||
public enum OperationType {
|
||||
CREATE_RESOURCE,
|
||||
UPDATE_RESOURCE,
|
||||
|
@ -42,6 +34,16 @@ public class EmpiTransactionContext {
|
|||
NOT_DUPLICATE,
|
||||
MERGE_PERSONS
|
||||
}
|
||||
|
||||
/**
|
||||
* Any EMPI methods may add transaction log messages.
|
||||
*/
|
||||
private TransactionLogMessages myTransactionLogMessages;
|
||||
|
||||
private OperationType myRestOperation;
|
||||
|
||||
private String myResourceType;
|
||||
|
||||
public TransactionLogMessages getTransactionLogMessages() {
|
||||
return myTransactionLogMessages;
|
||||
}
|
||||
|
@ -54,6 +56,11 @@ public class EmpiTransactionContext {
|
|||
myRestOperation = theRestOperation;
|
||||
}
|
||||
|
||||
public EmpiTransactionContext(TransactionLogMessages theTransactionLogMessages, OperationType theRestOperation, String theResourceType) {
|
||||
this(theTransactionLogMessages, theRestOperation);
|
||||
setResourceType(theResourceType);
|
||||
}
|
||||
|
||||
public void addTransactionLogMessage(String theMessage) {
|
||||
if (myTransactionLogMessages == null) {
|
||||
return;
|
||||
|
@ -72,4 +79,13 @@ public class EmpiTransactionContext {
|
|||
public void setRestOperation(OperationType theRestOperation) {
|
||||
myRestOperation = theRestOperation;
|
||||
}
|
||||
|
||||
public String getResourceType() {
|
||||
return myResourceType;
|
||||
}
|
||||
|
||||
public void setResourceType(String myResourceType) {
|
||||
this.myResourceType = myResourceType;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -45,9 +45,7 @@ import org.hl7.fhir.r4.model.Coding;
|
|||
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.Patient;
|
||||
import org.hl7.fhir.r4.model.Person;
|
||||
import org.hl7.fhir.r4.model.Practitioner;
|
||||
import org.hl7.fhir.r4.model.Reference;
|
||||
import org.slf4j.Logger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -88,6 +86,10 @@ public class PersonHelper {
|
|||
* @return a Stream of {@link IIdType}.
|
||||
*/
|
||||
public Stream<IIdType> getLinkIds(IBaseResource thePerson) {
|
||||
// TODO we can't rely on links anymore, as the provided resource is likely not to have thoem
|
||||
// need a way to pull those from the underlying MDM functionality
|
||||
// how do we pull link IDs now???
|
||||
|
||||
switch (myFhirContext.getVersion().getVersion()) {
|
||||
case R4:
|
||||
Person personR4 = (Person) thePerson;
|
||||
|
@ -227,13 +229,6 @@ public class PersonHelper {
|
|||
public <T extends IAnyResource> T createSourceResourceFromEmpiTarget(T theSourceResource) {
|
||||
ensureContextSupported();
|
||||
|
||||
List<CanonicalEID> eidsToApply = myEIDHelper.getExternalEid(theSourceResource);
|
||||
if (eidsToApply.isEmpty()) {
|
||||
eidsToApply.add(myEIDHelper.createHapiEid());
|
||||
}
|
||||
|
||||
FhirTerser terser = myFhirContext.newTerser();
|
||||
|
||||
// get a ref to the actual ID Field
|
||||
RuntimeResourceDefinition resourceDefinition = myFhirContext.getResourceDefinition(theSourceResource);
|
||||
IBaseResource newSourceResource = resourceDefinition.newInstance();
|
||||
|
@ -245,6 +240,7 @@ public class PersonHelper {
|
|||
BaseRuntimeElementCompositeDefinition<?> childIdentifier =
|
||||
(BaseRuntimeElementCompositeDefinition<?>) sourceResourceIdentifier.getChildByName("identifier");
|
||||
|
||||
FhirTerser terser = myFhirContext.newTerser();
|
||||
List<IBase> sourceResourceEids = sourceResourceIdentifier.getAccessor().getValues(theSourceResource);
|
||||
for (IBase base : sourceResourceEids) {
|
||||
IBase sourceResourceNewIdentifier = childIdentifier.newInstance();
|
||||
|
@ -253,10 +249,26 @@ public class PersonHelper {
|
|||
sourceResourceIdentifier.getMutator().addValue(newSourceResource, sourceResourceNewIdentifier);
|
||||
}
|
||||
|
||||
// now we have all IDs pulled into it
|
||||
//Turns out this call actually literally fully clones the resource, and we don't quite want to do that.
|
||||
//Overall this looks great though!
|
||||
terser.cloneInto(theSourceResource, newSourceResource, true);
|
||||
List<CanonicalEID> eidsToApply = myEIDHelper.getExternalEid(theSourceResource);
|
||||
if (eidsToApply.isEmpty()) {
|
||||
eidsToApply.add(myEIDHelper.createHapiEid());
|
||||
}
|
||||
for (CanonicalEID eid : eidsToApply) {
|
||||
switch (myFhirContext.getVersion().getVersion()) {
|
||||
case R4:
|
||||
sourceResourceIdentifier.getMutator().addValue(newSourceResource, eid.toR4());
|
||||
break;
|
||||
case DSTU3:
|
||||
sourceResourceIdentifier.getMutator().addValue(newSourceResource, eid.toDSTU3());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
IBaseCoding tag = newSourceResource.getMeta().addTag();
|
||||
tag.setSystem(EmpiConstants.SYSTEM_EMPI_MANAGED);
|
||||
tag.setCode(EmpiConstants.CODE_HAPI_EMPI_MANAGED);
|
||||
tag.setDisplay(EmpiConstants.DISPLAY_HAPI_EMPI_MANAGED);
|
||||
|
||||
return (T) newSourceResource;
|
||||
|
||||
// switch (myFhirContext.getVersion().getVersion()) {
|
||||
|
@ -264,8 +276,8 @@ public class PersonHelper {
|
|||
// Person personR4 = new Person();
|
||||
//
|
||||
// personR4.setActive(true);
|
||||
// eidsToApply.forEach(eid -> personR4.addIdentifier(eid.toR4()));
|
||||
// personR4.getMeta().addTag((Coding) buildEmpiManagedTag());
|
||||
// >> eidsToApply.forEach(eid -> personR4.addIdentifier(eid.toR4()));
|
||||
// >> personR4.getMeta().addTag((Coding) buildEmpiManagedTag());
|
||||
// copyEmpiTargetDataIntoPerson(theSourceResource, personR4, true);
|
||||
// return personR4;
|
||||
// IAnyResource sourceResource = theSourceResource;
|
||||
|
@ -280,443 +292,420 @@ public class PersonHelper {
|
|||
// default:
|
||||
// throw new UnsupportedOperationException("Version not supported: " + myFhirContext.getVersion().getVersion());
|
||||
// }
|
||||
}
|
||||
|
||||
private void ensureContextSupported() {
|
||||
FhirVersionEnum fhirVersion = myFhirContext.getVersion().getVersion();
|
||||
if (fhirVersion == R4 || fhirVersion == DSTU3) {
|
||||
return;
|
||||
}
|
||||
throw new UnsupportedOperationException("Version not supported: " + myFhirContext.getVersion().getVersion());
|
||||
}
|
||||
|
||||
private void ensureContextSupported() {
|
||||
FhirVersionEnum fhirVersion = myFhirContext.getVersion().getVersion();
|
||||
if (fhirVersion == R4 || fhirVersion == DSTU3) {
|
||||
return;
|
||||
}
|
||||
throw new UnsupportedOperationException("Version not supported: " + myFhirContext.getVersion().getVersion());
|
||||
}
|
||||
// /**
|
||||
// * This will copy over all attributes that are copiable from Patient/Practitioner to Person.
|
||||
// *
|
||||
// * @param theBaseResource The incoming {@link Patient} or {@link Practitioner} who's data we want to copy into Person.
|
||||
// * @param thePerson The incoming {@link Person} who needs to have their data updated.
|
||||
// * @param theAllowOverwriting If enabled, will overwrite existing values on the person. Otherwise, will set them only if they are currently empty/null.
|
||||
// */
|
||||
// private void copyEmpiTargetDataIntoPerson (IBaseResource theBaseResource, IBaseResource thePerson, Boolean
|
||||
// theAllowOverwriting){
|
||||
// switch (myFhirContext.getVersion().getVersion()) {
|
||||
// case R4:
|
||||
// copyR4TargetInformation(theBaseResource, thePerson, theAllowOverwriting);
|
||||
// break;
|
||||
// case DSTU3:
|
||||
// copyDSTU3TargetInformation(theBaseResource, thePerson, theAllowOverwriting);
|
||||
// break;
|
||||
// default:
|
||||
// throw new UnsupportedOperationException("Version not supported: " + myFhirContext.getVersion().getVersion());
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* This will copy over all attributes that are copiable from Patient/Practitioner to Person.
|
||||
*
|
||||
* @param theBaseResource The incoming {@link Patient} or {@link Practitioner} who's data we want to copy into Person.
|
||||
* @param thePerson The incoming {@link Person} who needs to have their data updated.
|
||||
* @param theAllowOverwriting If enabled, will overwrite existing values on the person. Otherwise, will set them only if they are currently empty/null.
|
||||
*/
|
||||
private void copyEmpiTargetDataIntoPerson (IBaseResource theBaseResource, IBaseResource thePerson, Boolean
|
||||
theAllowOverwriting){
|
||||
switch (myFhirContext.getVersion().getVersion()) {
|
||||
case R4:
|
||||
copyR4TargetInformation(theBaseResource, thePerson, theAllowOverwriting);
|
||||
break;
|
||||
case DSTU3:
|
||||
copyDSTU3TargetInformation(theBaseResource, thePerson, theAllowOverwriting);
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Version not supported: " + myFhirContext.getVersion().getVersion());
|
||||
}
|
||||
}
|
||||
// private void copyR4TargetInformation (IBaseResource theBaseResource, IBaseResource thePerson, boolean theAllowOverwriting){
|
||||
// Person person = (Person) thePerson;
|
||||
// switch (myFhirContext.getResourceType(theBaseResource)) {
|
||||
// case "Patient":
|
||||
// Patient patient = (Patient) theBaseResource;
|
||||
// if (theAllowOverwriting || person.getName().isEmpty()) {
|
||||
// person.setName(patient.getName());
|
||||
// }
|
||||
// if (theAllowOverwriting || person.getAddress().isEmpty()) {
|
||||
// person.setAddress(patient.getAddress());
|
||||
// }
|
||||
// if (theAllowOverwriting || person.getTelecom().isEmpty()) {
|
||||
// person.setTelecom(patient.getTelecom());
|
||||
// }
|
||||
// if (theAllowOverwriting || person.getBirthDate() == null) {
|
||||
// person.setBirthDate(patient.getBirthDate());
|
||||
// }
|
||||
// if (theAllowOverwriting || person.getGender() == null) {
|
||||
// person.setGender(patient.getGender());
|
||||
// }
|
||||
// if (theAllowOverwriting || person.getPhoto().isEmpty()) {
|
||||
// person.setPhoto(patient.getPhotoFirstRep());
|
||||
// }
|
||||
// break;
|
||||
// case "Practitioner":
|
||||
// Practitioner practitioner = (Practitioner) theBaseResource;
|
||||
// if (theAllowOverwriting || person.getName().isEmpty()) {
|
||||
// person.setName(practitioner.getName());
|
||||
// }
|
||||
// if (theAllowOverwriting || person.getAddress().isEmpty()) {
|
||||
// person.setAddress(practitioner.getAddress());
|
||||
// }
|
||||
// if (theAllowOverwriting || person.getTelecom().isEmpty()) {
|
||||
// person.setTelecom(practitioner.getTelecom());
|
||||
// }
|
||||
// if (theAllowOverwriting || person.getBirthDate() == null) {
|
||||
// person.setBirthDate(practitioner.getBirthDate());
|
||||
// }
|
||||
// if (theAllowOverwriting || person.getGender() == null) {
|
||||
// person.setGender(practitioner.getGender());
|
||||
// }
|
||||
// if (theAllowOverwriting || person.getPhoto().isEmpty()) {
|
||||
// person.setPhoto(practitioner.getPhotoFirstRep());
|
||||
// }
|
||||
// break;
|
||||
// default:
|
||||
// throw new UnsupportedOperationException("EMPI targets are limited to Practitioner/Patient. This is a : " + myFhirContext.getResourceType(theBaseResource));
|
||||
// }
|
||||
// }
|
||||
|
||||
private void copyR4TargetInformation (IBaseResource theBaseResource, IBaseResource thePerson,
|
||||
boolean theAllowOverwriting){
|
||||
Person person = (Person) thePerson;
|
||||
switch (myFhirContext.getResourceType(theBaseResource)) {
|
||||
case "Patient":
|
||||
Patient patient = (Patient) theBaseResource;
|
||||
if (theAllowOverwriting || person.getName().isEmpty()) {
|
||||
person.setName(patient.getName());
|
||||
}
|
||||
if (theAllowOverwriting || person.getAddress().isEmpty()) {
|
||||
person.setAddress(patient.getAddress());
|
||||
}
|
||||
if (theAllowOverwriting || person.getTelecom().isEmpty()) {
|
||||
person.setTelecom(patient.getTelecom());
|
||||
}
|
||||
if (theAllowOverwriting || person.getBirthDate() == null) {
|
||||
person.setBirthDate(patient.getBirthDate());
|
||||
}
|
||||
if (theAllowOverwriting || person.getGender() == null) {
|
||||
person.setGender(patient.getGender());
|
||||
}
|
||||
if (theAllowOverwriting || person.getPhoto().isEmpty()) {
|
||||
person.setPhoto(patient.getPhotoFirstRep());
|
||||
}
|
||||
break;
|
||||
case "Practitioner":
|
||||
Practitioner practitioner = (Practitioner) theBaseResource;
|
||||
if (theAllowOverwriting || person.getName().isEmpty()) {
|
||||
person.setName(practitioner.getName());
|
||||
}
|
||||
if (theAllowOverwriting || person.getAddress().isEmpty()) {
|
||||
person.setAddress(practitioner.getAddress());
|
||||
}
|
||||
if (theAllowOverwriting || person.getTelecom().isEmpty()) {
|
||||
person.setTelecom(practitioner.getTelecom());
|
||||
}
|
||||
if (theAllowOverwriting || person.getBirthDate() == null) {
|
||||
person.setBirthDate(practitioner.getBirthDate());
|
||||
}
|
||||
if (theAllowOverwriting || person.getGender() == null) {
|
||||
person.setGender(practitioner.getGender());
|
||||
}
|
||||
if (theAllowOverwriting || person.getPhoto().isEmpty()) {
|
||||
person.setPhoto(practitioner.getPhotoFirstRep());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("EMPI targets are limited to Practitioner/Patient. This is a : " + myFhirContext.getResourceType(theBaseResource));
|
||||
}
|
||||
}
|
||||
// private void copyDSTU3TargetInformation (IBaseResource theBaseResource, IBaseResource thePerson,
|
||||
// boolean theAllowOverwriting){
|
||||
// org.hl7.fhir.dstu3.model.Person person = (org.hl7.fhir.dstu3.model.Person) thePerson;
|
||||
// switch (myFhirContext.getResourceType(theBaseResource)) {
|
||||
// case "Patient":
|
||||
// org.hl7.fhir.dstu3.model.Patient patient = (org.hl7.fhir.dstu3.model.Patient) theBaseResource;
|
||||
//
|
||||
// if (theAllowOverwriting || person.getName().isEmpty()) {
|
||||
// person.setName(patient.getName());
|
||||
// }
|
||||
// if (theAllowOverwriting || person.getAddress().isEmpty()) {
|
||||
// person.setAddress(patient.getAddress());
|
||||
// }
|
||||
// if (theAllowOverwriting || person.getTelecom().isEmpty()) {
|
||||
// person.setTelecom(patient.getTelecom());
|
||||
// }
|
||||
// if (theAllowOverwriting || person.getBirthDate() == null) {
|
||||
// person.setBirthDate(patient.getBirthDate());
|
||||
// }
|
||||
// if (theAllowOverwriting || person.getGender() == null) {
|
||||
// person.setGender(patient.getGender());
|
||||
// }
|
||||
// if (theAllowOverwriting || person.getPhoto().isEmpty()) {
|
||||
// person.setPhoto(patient.getPhotoFirstRep());
|
||||
// }
|
||||
// break;
|
||||
// case "Practitioner":
|
||||
// org.hl7.fhir.dstu3.model.Practitioner practitioner = (org.hl7.fhir.dstu3.model.Practitioner) theBaseResource;
|
||||
// if (theAllowOverwriting || person.getName().isEmpty()) {
|
||||
// person.setName(practitioner.getName());
|
||||
// }
|
||||
// if (theAllowOverwriting || person.getAddress().isEmpty()) {
|
||||
// person.setAddress(practitioner.getAddress());
|
||||
// }
|
||||
// if (theAllowOverwriting || person.getTelecom().isEmpty()) {
|
||||
// person.setTelecom(practitioner.getTelecom());
|
||||
// }
|
||||
// if (theAllowOverwriting || person.getBirthDate() == null) {
|
||||
// person.setBirthDate(practitioner.getBirthDate());
|
||||
// }
|
||||
// if (theAllowOverwriting || person.getGender() == null) {
|
||||
// person.setGender(practitioner.getGender());
|
||||
// }
|
||||
// if (theAllowOverwriting || person.getPhoto().isEmpty()) {
|
||||
// person.setPhoto(practitioner.getPhotoFirstRep());
|
||||
// }
|
||||
// break;
|
||||
// default:
|
||||
// throw new UnsupportedOperationException("EMPI targets are limited to Practitioner/Patient. This is a : " + myFhirContext.getResourceType(theBaseResource));
|
||||
// }
|
||||
// }
|
||||
|
||||
private void copyDSTU3TargetInformation (IBaseResource theBaseResource, IBaseResource thePerson,
|
||||
boolean theAllowOverwriting){
|
||||
org.hl7.fhir.dstu3.model.Person person = (org.hl7.fhir.dstu3.model.Person) thePerson;
|
||||
switch (myFhirContext.getResourceType(theBaseResource)) {
|
||||
case "Patient":
|
||||
org.hl7.fhir.dstu3.model.Patient patient = (org.hl7.fhir.dstu3.model.Patient) theBaseResource;
|
||||
/**
|
||||
* Update a Person's EID based on the incoming target resource. If the incoming resource has an external EID, it is applied
|
||||
* to the Person, unless that person 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 Person without checking for matches.
|
||||
*
|
||||
* @param theSourceResource The person to update the external EID on.
|
||||
* @param theTargetResource The target we will retrieve the external EID from.
|
||||
* @return the modified {@link IBaseResource} representing the person.
|
||||
*/
|
||||
public IAnyResource updateSourceResourceExternalEidFromTargetResource(IAnyResource theSourceResource, IAnyResource
|
||||
theTargetResource, EmpiTransactionContext theEmpiTransactionContext) {
|
||||
//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(theSourceResource);
|
||||
|
||||
if (theAllowOverwriting || person.getName().isEmpty()) {
|
||||
person.setName(patient.getName());
|
||||
}
|
||||
if (theAllowOverwriting || person.getAddress().isEmpty()) {
|
||||
person.setAddress(patient.getAddress());
|
||||
}
|
||||
if (theAllowOverwriting || person.getTelecom().isEmpty()) {
|
||||
person.setTelecom(patient.getTelecom());
|
||||
}
|
||||
if (theAllowOverwriting || person.getBirthDate() == null) {
|
||||
person.setBirthDate(patient.getBirthDate());
|
||||
}
|
||||
if (theAllowOverwriting || person.getGender() == null) {
|
||||
person.setGender(patient.getGender());
|
||||
}
|
||||
if (theAllowOverwriting || person.getPhoto().isEmpty()) {
|
||||
person.setPhoto(patient.getPhotoFirstRep());
|
||||
}
|
||||
break;
|
||||
case "Practitioner":
|
||||
org.hl7.fhir.dstu3.model.Practitioner practitioner = (org.hl7.fhir.dstu3.model.Practitioner) theBaseResource;
|
||||
if (theAllowOverwriting || person.getName().isEmpty()) {
|
||||
person.setName(practitioner.getName());
|
||||
}
|
||||
if (theAllowOverwriting || person.getAddress().isEmpty()) {
|
||||
person.setAddress(practitioner.getAddress());
|
||||
}
|
||||
if (theAllowOverwriting || person.getTelecom().isEmpty()) {
|
||||
person.setTelecom(practitioner.getTelecom());
|
||||
}
|
||||
if (theAllowOverwriting || person.getBirthDate() == null) {
|
||||
person.setBirthDate(practitioner.getBirthDate());
|
||||
}
|
||||
if (theAllowOverwriting || person.getGender() == null) {
|
||||
person.setGender(practitioner.getGender());
|
||||
}
|
||||
if (theAllowOverwriting || person.getPhoto().isEmpty()) {
|
||||
person.setPhoto(practitioner.getPhotoFirstRep());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("EMPI targets are limited to Practitioner/Patient. This is a : " + myFhirContext.getResourceType(theBaseResource));
|
||||
}
|
||||
}
|
||||
|
||||
private IBaseCoding buildEmpiManagedTag () {
|
||||
switch (myFhirContext.getVersion().getVersion()) {
|
||||
case R4:
|
||||
Coding empiManagedCoding = new Coding();
|
||||
empiManagedCoding.setSystem(EmpiConstants.SYSTEM_EMPI_MANAGED);
|
||||
empiManagedCoding.setCode(EmpiConstants.CODE_HAPI_EMPI_MANAGED);
|
||||
empiManagedCoding.setDisplay(EmpiConstants.DISPLAY_HAPI_EMPI_MANAGED);
|
||||
return empiManagedCoding;
|
||||
case DSTU3:
|
||||
org.hl7.fhir.dstu3.model.Coding empiManagedCodingDstu3 = new org.hl7.fhir.dstu3.model.Coding();
|
||||
empiManagedCodingDstu3.setSystem(EmpiConstants.SYSTEM_EMPI_MANAGED);
|
||||
empiManagedCodingDstu3.setCode(EmpiConstants.CODE_HAPI_EMPI_MANAGED);
|
||||
empiManagedCodingDstu3.setDisplay(EmpiConstants.DISPLAY_HAPI_EMPI_MANAGED);
|
||||
return empiManagedCodingDstu3;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Version not supported: " + myFhirContext.getVersion().getVersion());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a Person's EID based on the incoming target resource. If the incoming resource has an external EID, it is applied
|
||||
* to the Person, unless that person 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 Person without checking for matches.
|
||||
*
|
||||
* @param thePerson The person to update the external EID on.
|
||||
* @param theEmpiTarget The target we will retrieve the external EID from.
|
||||
* @return the modified {@link IBaseResource} representing the person.
|
||||
*/
|
||||
public IAnyResource updatePersonExternalEidFromEmpiTarget (IAnyResource thePerson, IAnyResource
|
||||
theEmpiTarget, EmpiTransactionContext theEmpiTransactionContext){
|
||||
//This handles overwriting an automatically assigned EID if a patient that links is coming in with an official EID.
|
||||
List<CanonicalEID> incomingTargetEid = myEIDHelper.getExternalEid(theEmpiTarget);
|
||||
List<CanonicalEID> personOfficialEid = myEIDHelper.getExternalEid(thePerson);
|
||||
|
||||
if (!incomingTargetEid.isEmpty()) {
|
||||
if (personOfficialEid.isEmpty() || !myEmpiConfig.isPreventMultipleEids()) {
|
||||
log(theEmpiTransactionContext, "Incoming resource:" + theEmpiTarget.getIdElement().toUnqualifiedVersionless() + " + with EID " + incomingTargetEid.stream().map(CanonicalEID::toString).collect(Collectors.joining(",")) + " is applying this EIDs to its related Person, as this person does not yet have an external EID");
|
||||
addCanonicalEidsToPersonIfAbsent(thePerson, incomingTargetEid);
|
||||
} else if (!personOfficialEid.isEmpty() && myEIDHelper.eidMatchExists(personOfficialEid, incomingTargetEid)) {
|
||||
log(theEmpiTransactionContext, "incoming resource:" + theEmpiTarget.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!");
|
||||
}
|
||||
}
|
||||
return thePerson;
|
||||
}
|
||||
|
||||
public IBaseResource overwriteExternalEids (IBaseResource thePerson, List < CanonicalEID > theNewEid){
|
||||
clearExternalEids(thePerson);
|
||||
addCanonicalEidsToPersonIfAbsent(thePerson, theNewEid);
|
||||
return thePerson;
|
||||
}
|
||||
|
||||
private void clearExternalEids (IBaseResource thePerson){
|
||||
switch (myFhirContext.getVersion().getVersion()) {
|
||||
case R4:
|
||||
Person personR4 = (Person) thePerson;
|
||||
personR4.getIdentifier().removeIf(theIdentifier -> theIdentifier.getSystem().equalsIgnoreCase(myEmpiConfig.getEmpiRules().getEnterpriseEIDSystem()));
|
||||
break;
|
||||
case DSTU3:
|
||||
org.hl7.fhir.dstu3.model.Person personDstu3 = (org.hl7.fhir.dstu3.model.Person) thePerson;
|
||||
personDstu3.getIdentifier().removeIf(theIdentifier -> theIdentifier.getSystem().equalsIgnoreCase(myEmpiConfig.getEmpiRules().getEnterpriseEIDSystem()));
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Version not supported: " + myFhirContext.getVersion().getVersion());
|
||||
}
|
||||
}
|
||||
|
||||
private void addCanonicalEidsToPersonIfAbsent (IBaseResource thePerson, List < CanonicalEID > theIncomingTargetEid)
|
||||
{
|
||||
switch (myFhirContext.getVersion().getVersion()) {
|
||||
case R4:
|
||||
theIncomingTargetEid.forEach(eid -> addIdentifierIfAbsent((Person) thePerson, eid.toR4()));
|
||||
break;
|
||||
case DSTU3:
|
||||
theIncomingTargetEid.forEach(eid -> addIdentifierIfAbsent((org.hl7.fhir.dstu3.model.Person) thePerson, eid.toDSTU3()));
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Version not supported: " + 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;
|
||||
if (!incomingTargetEid.isEmpty()) {
|
||||
if (personOfficialEid.isEmpty() || !myEmpiConfig.isPreventMultipleEids()) {
|
||||
log(theEmpiTransactionContext, "Incoming resource:" + theTargetResource.getIdElement().toUnqualifiedVersionless() + " + with EID " + incomingTargetEid.stream().map(CanonicalEID::toString).collect(Collectors.joining(",")) + " is applying this EIDs to its related Person, as this person does not yet have an external EID");
|
||||
addCanonicalEidsToPersonIfAbsent(theSourceResource, incomingTargetEid);
|
||||
} else if (!personOfficialEid.isEmpty() && myEIDHelper.eidMatchExists(personOfficialEid, incomingTargetEid)) {
|
||||
log(theEmpiTransactionContext, "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 {
|
||||
thePerson.addIdentifier(theIdentifier);
|
||||
throw new IllegalArgumentException("This would create a duplicate person!");
|
||||
}
|
||||
}
|
||||
return theSourceResource;
|
||||
}
|
||||
|
||||
private void addIdentifierIfAbsent (Person thePerson, Identifier theIdentifier){
|
||||
Optional<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 IBaseResource overwriteExternalEids(IBaseResource thePerson, List<CanonicalEID> theNewEid) {
|
||||
clearExternalEids(thePerson);
|
||||
addCanonicalEidsToPersonIfAbsent(thePerson, theNewEid);
|
||||
return thePerson;
|
||||
}
|
||||
|
||||
public void mergePersonFields (IBaseResource theFromPerson, IBaseResource theToPerson){
|
||||
switch (myFhirContext.getVersion().getVersion()) {
|
||||
case R4:
|
||||
mergeR4PersonFields(theFromPerson, theToPerson);
|
||||
break;
|
||||
case DSTU3:
|
||||
mergeDstu3PersonFields(theFromPerson, theToPerson);
|
||||
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
|
||||
*/
|
||||
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 void updatePersonFromNewlyCreatedEmpiTarget (IBaseResource thePerson, IBaseResource
|
||||
theResource, EmpiTransactionContext theEmpiTransactionContext){
|
||||
copyEmpiTargetDataIntoPerson(theResource, thePerson, false);
|
||||
}
|
||||
|
||||
public void updatePersonFromUpdatedEmpiTarget (IBaseResource thePerson, IBaseResource
|
||||
theResource, EmpiTransactionContext theEmpiTransactionContext){
|
||||
copyEmpiTargetDataIntoPerson(theResource, thePerson, true);
|
||||
}
|
||||
|
||||
public int getLinkCount (IAnyResource thePerson){
|
||||
switch (myFhirContext.getVersion().getVersion()) {
|
||||
case R4:
|
||||
Person personR4 = (Person) thePerson;
|
||||
return personR4.getLink().size();
|
||||
case DSTU3:
|
||||
org.hl7.fhir.dstu3.model.Person personStu3 = (org.hl7.fhir.dstu3.model.Person) thePerson;
|
||||
return personStu3.getLink().size();
|
||||
default:
|
||||
throw new UnsupportedOperationException("Version not supported: " + myFhirContext.getVersion().getVersion());
|
||||
}
|
||||
}
|
||||
|
||||
private void log (EmpiTransactionContext theEmpiTransactionContext, String theMessage){
|
||||
theEmpiTransactionContext.addTransactionLogMessage(theMessage);
|
||||
ourLog.debug(theMessage);
|
||||
}
|
||||
|
||||
public void handleExternalEidAddition (IAnyResource thePerson, IAnyResource theResource, EmpiTransactionContext
|
||||
theEmpiTransactionContext){
|
||||
List<CanonicalEID> eidFromResource = myEIDHelper.getExternalEid(theResource);
|
||||
if (!eidFromResource.isEmpty()) {
|
||||
updatePersonExternalEidFromEmpiTarget(thePerson, theResource, theEmpiTransactionContext);
|
||||
}
|
||||
}
|
||||
|
||||
public void deactivatePerson (IAnyResource thePerson){
|
||||
switch (myFhirContext.getVersion().getVersion()) {
|
||||
case R4:
|
||||
Person personR4 = (Person) thePerson;
|
||||
personR4.setActive(false);
|
||||
break;
|
||||
case DSTU3:
|
||||
org.hl7.fhir.dstu3.model.Person personStu3 = (org.hl7.fhir.dstu3.model.Person) thePerson;
|
||||
personStu3.setActive(false);
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Version not supported: " + myFhirContext.getVersion().getVersion());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDeactivated (IBaseResource thePerson){
|
||||
switch (myFhirContext.getVersion().getVersion()) {
|
||||
case R4:
|
||||
Person personR4 = (Person) thePerson;
|
||||
return !personR4.getActive();
|
||||
case DSTU3:
|
||||
org.hl7.fhir.dstu3.model.Person personStu3 = (org.hl7.fhir.dstu3.model.Person) thePerson;
|
||||
return !personStu3.getActive();
|
||||
default:
|
||||
throw new UnsupportedOperationException("Version not supported: " + myFhirContext.getVersion().getVersion());
|
||||
}
|
||||
private void clearExternalEids(IBaseResource thePerson) {
|
||||
switch (myFhirContext.getVersion().getVersion()) {
|
||||
case R4:
|
||||
Person personR4 = (Person) thePerson;
|
||||
personR4.getIdentifier().removeIf(theIdentifier -> theIdentifier.getSystem().equalsIgnoreCase(myEmpiConfig.getEmpiRules().getEnterpriseEIDSystem()));
|
||||
break;
|
||||
case DSTU3:
|
||||
org.hl7.fhir.dstu3.model.Person personDstu3 = (org.hl7.fhir.dstu3.model.Person) thePerson;
|
||||
personDstu3.getIdentifier().removeIf(theIdentifier -> theIdentifier.getSystem().equalsIgnoreCase(myEmpiConfig.getEmpiRules().getEnterpriseEIDSystem()));
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Version not supported: " + myFhirContext.getVersion().getVersion());
|
||||
}
|
||||
}
|
||||
|
||||
private void addCanonicalEidsToPersonIfAbsent(IBaseResource thePerson, List<CanonicalEID> theIncomingTargetEid) {
|
||||
switch (myFhirContext.getVersion().getVersion()) {
|
||||
case R4:
|
||||
theIncomingTargetEid.forEach(eid -> addIdentifierIfAbsent((Person) thePerson, eid.toR4()));
|
||||
break;
|
||||
case DSTU3:
|
||||
theIncomingTargetEid.forEach(eid -> addIdentifierIfAbsent((org.hl7.fhir.dstu3.model.Person) thePerson, eid.toDSTU3()));
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Version not supported: " + 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);
|
||||
}
|
||||
}
|
||||
|
||||
private void addIdentifierIfAbsent(Person thePerson, Identifier theIdentifier) {
|
||||
Optional<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 mergePersonFields(IBaseResource theFromPerson, IBaseResource theToPerson) {
|
||||
switch (myFhirContext.getVersion().getVersion()) {
|
||||
case R4:
|
||||
mergeR4PersonFields(theFromPerson, theToPerson);
|
||||
break;
|
||||
case DSTU3:
|
||||
mergeDstu3PersonFields(theFromPerson, theToPerson);
|
||||
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
|
||||
*/
|
||||
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 void updatePersonFromNewlyCreatedEmpiTarget(IBaseResource thePerson, IBaseResource
|
||||
// theResource, EmpiTransactionContext theEmpiTransactionContext) {
|
||||
// copyEmpiTargetDataIntoPerson(theResource, thePerson, false);
|
||||
// }
|
||||
|
||||
// public void updatePersonFromUpdatedEmpiTarget(IBaseResource thePerson, IBaseResource
|
||||
// theResource, EmpiTransactionContext theEmpiTransactionContext) {
|
||||
// // copyEmpiTargetDataIntoPerson(theResource, thePerson, true);
|
||||
// }
|
||||
|
||||
public int getLinkCount(IAnyResource thePerson) {
|
||||
switch (myFhirContext.getVersion().getVersion()) {
|
||||
case R4:
|
||||
Person personR4 = (Person) thePerson;
|
||||
return personR4.getLink().size();
|
||||
case DSTU3:
|
||||
org.hl7.fhir.dstu3.model.Person personStu3 = (org.hl7.fhir.dstu3.model.Person) thePerson;
|
||||
return personStu3.getLink().size();
|
||||
default:
|
||||
throw new UnsupportedOperationException("Version not supported: " + myFhirContext.getVersion().getVersion());
|
||||
}
|
||||
}
|
||||
|
||||
private void log(EmpiTransactionContext theEmpiTransactionContext, String theMessage) {
|
||||
theEmpiTransactionContext.addTransactionLogMessage(theMessage);
|
||||
ourLog.debug(theMessage);
|
||||
}
|
||||
|
||||
public void handleExternalEidAddition(IAnyResource theSourceResource, IAnyResource theTargetResource, EmpiTransactionContext
|
||||
theEmpiTransactionContext) {
|
||||
List<CanonicalEID> eidFromResource = myEIDHelper.getExternalEid(theTargetResource);
|
||||
if (!eidFromResource.isEmpty()) {
|
||||
updateSourceResourceExternalEidFromTargetResource(theSourceResource, theTargetResource, theEmpiTransactionContext);
|
||||
}
|
||||
}
|
||||
|
||||
public void deactivatePerson(IAnyResource thePerson) {
|
||||
switch (myFhirContext.getVersion().getVersion()) {
|
||||
case R4:
|
||||
Person personR4 = (Person) thePerson;
|
||||
personR4.setActive(false);
|
||||
break;
|
||||
case DSTU3:
|
||||
org.hl7.fhir.dstu3.model.Person personStu3 = (org.hl7.fhir.dstu3.model.Person) thePerson;
|
||||
personStu3.setActive(false);
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Version not supported: " + myFhirContext.getVersion().getVersion());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDeactivated(IBaseResource thePerson) {
|
||||
switch (myFhirContext.getVersion().getVersion()) {
|
||||
case R4:
|
||||
Person personR4 = (Person) thePerson;
|
||||
return !personR4.getActive();
|
||||
case DSTU3:
|
||||
org.hl7.fhir.dstu3.model.Person personStu3 = (org.hl7.fhir.dstu3.model.Person) thePerson;
|
||||
return !personStu3.getActive();
|
||||
default:
|
||||
throw new UnsupportedOperationException("Version not supported: " + myFhirContext.getVersion().getVersion());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue