* Remove lines from image edges.  Thanks Max!

* fix case 4 docs
only mark possible match as eid if it was via an eid match
This commit is contained in:
Ken Stevens 2020-07-21 13:07:49 -04:00 committed by GitHub
parent 5f1078ac13
commit 160778d3fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 96 additions and 46 deletions

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 49 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 55 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 55 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 59 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 56 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 66 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 76 KiB

View File

@ -67,7 +67,7 @@ When a new Patient resource is compared with all other resources of that type in
* CASE 3: The MATCH Patient resources link to more than one Person -> Mark all links as POSSIBLE_MATCH. All other Person resources are marked as POSSIBLE_DUPLICATE of this first Person. These duplicates are manually reviewed later and either merged or marked as NO_MATCH and the system will no longer consider them as a POSSIBLE_DUPLICATE going forward. POSSIBLE_DUPLICATE is the only link type that can have a Person as both the source and target of the link.
* CASE 4: Only POSSIBLE_MATCH outcomes -> In this case, empi-link records are created with POSSIBLE_MATCH outcome and await manual assignment to either NO_MATCH or MATCH. Person resources are not changed.
* CASE 4: Only POSSIBLE_MATCH outcomes -> In this case, new POSSIBLE_MATCH links are created and await manual assignment to either NO_MATCH or MATCH.
# HAPI EMPI Technical Details

View File

@ -101,14 +101,20 @@ public class EmpiMatchLinkSvc {
List<IAnyResource> persons = new ArrayList<>();
for (MatchedPersonCandidate matchedPersonCandidate : theCandidateList.getCandidates()) {
IAnyResource person = myEmpiPersonFindingSvc.getPersonFromMatchedPersonCandidate(matchedPersonCandidate);
myEmpiLinkSvc.updateLink(person, theResource, EmpiMatchOutcome.EID_POSSIBLE_MATCH, EmpiLinkSourceEnum.AUTO, theEmpiTransactionContext);
EmpiMatchOutcome outcome = EmpiMatchOutcome.POSSIBLE_MATCH;
outcome.setEidMatch(theCandidateList.isEidMatch());
myEmpiLinkSvc.updateLink(person, theResource, outcome, EmpiLinkSourceEnum.AUTO, theEmpiTransactionContext);
persons.add(person);
}
//Set all Persons as POSSIBLE_DUPLICATE of the last person.
IAnyResource firstPerson = persons.get(0);
persons.subList(1, persons.size())
.forEach(possibleDuplicatePerson -> myEmpiLinkSvc.updateLink(firstPerson, possibleDuplicatePerson, EmpiMatchOutcome.EID_POSSIBLE_DUPLICATE, EmpiLinkSourceEnum.AUTO, theEmpiTransactionContext));
.forEach(possibleDuplicatePerson -> {
EmpiMatchOutcome outcome = EmpiMatchOutcome.POSSIBLE_DUPLICATE;
outcome.setEidMatch(theCandidateList.isEidMatch());
myEmpiLinkSvc.updateLink(firstPerson, possibleDuplicatePerson, outcome, EmpiLinkSourceEnum.AUTO, theEmpiTransactionContext);
});
}
}

View File

@ -26,15 +26,15 @@ import java.util.List;
import java.util.stream.Stream;
public class CandidateList {
private final CandidateStrategyEnum mySource;
private final CandidateStrategyEnum myStrategy;
private final List<MatchedPersonCandidate> myList = new ArrayList<>();
public CandidateList(CandidateStrategyEnum theSource) {
mySource = theSource;
public CandidateList(CandidateStrategyEnum theStrategy) {
myStrategy = theStrategy;
}
public CandidateStrategyEnum getSource() {
return mySource;
public CandidateStrategyEnum getStrategy() {
return myStrategy;
}
public boolean isEmpty() {
@ -63,4 +63,8 @@ public class CandidateList {
public MatchedPersonCandidate getFirstMatch() {
return myList.get(0);
}
public boolean isEidMatch() {
return myStrategy.isEidMatch();
}
}

View File

@ -26,5 +26,9 @@ public enum CandidateStrategyEnum {
/** Find Person candidates based on a link already existing for the target resource */
LINK,
/** Find Person candidates based on other targets that match the incoming target using the EMPI Matching rules */
SCORE
SCORE;
public boolean isEidMatch() {
return this == EID;
}
}

View File

@ -54,6 +54,7 @@ import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.slf4j.LoggerFactory.getLogger;
@ -381,4 +382,25 @@ abstract public class BaseEmpiR4Test extends BaseJpaR4Test {
ourLog.info(link.toString());
}
}
protected void assertLinksMatchResult(EmpiMatchResultEnum... theExpectedValues) {
assertFields(EmpiLink::getMatchResult, theExpectedValues);
}
protected void assertLinksNewPerson(Boolean... theExpectedValues) {
assertFields(EmpiLink::getNewPerson, theExpectedValues);
}
protected void assertLinksMatchedByEid(Boolean... theExpectedValues) {
assertFields(EmpiLink::getEidMatch, theExpectedValues);
}
private <T> void assertFields(Function<EmpiLink, T> theAccessor, T... theExpectedValues) {
List<EmpiLink> links = myEmpiLinkDao.findAll();
assertEquals(theExpectedValues.length, links.size());
for (int i = 0; i < links.size(); ++i) {
assertEquals(theExpectedValues[i], theAccessor.apply(links.get(i)), "Value at index " + i + " was not equal");
}
}
}

View File

@ -1,7 +1,6 @@
package ca.uhn.fhir.jpa.empi.svc;
import ca.uhn.fhir.empi.api.EmpiConstants;
import ca.uhn.fhir.empi.api.EmpiMatchResultEnum;
import ca.uhn.fhir.empi.model.CanonicalEID;
import ca.uhn.fhir.empi.util.EIDHelper;
import ca.uhn.fhir.jpa.empi.BaseEmpiR4Test;
@ -16,7 +15,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.TestPropertySource;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -29,7 +27,6 @@ import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.in;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.slf4j.LoggerFactory.getLogger;
@TestPropertySource(properties = {
@ -87,26 +84,6 @@ public class EmpiMatchLinkSvcMultipleEidModeTest extends BaseEmpiR4Test {
assertThat(thirdIdentifier.getValue(), is(equalTo("67890")));
}
private void assertLinksMatchResult(EmpiMatchResultEnum... theExpectedValues) {
assertFields(EmpiLink::getMatchResult, theExpectedValues);
}
private void assertLinksNewPerson(Boolean... theExpectedValues) {
assertFields(EmpiLink::getNewPerson, theExpectedValues);
}
private void assertLinksMatchedByEid(Boolean... theExpectedValues) {
assertFields(EmpiLink::getEidMatch, theExpectedValues);
}
private <T> void assertFields(Function<EmpiLink, T> theAccessor, T... theExpectedValues) {
List<EmpiLink> links = myEmpiLinkDao.findAll();
assertEquals(theExpectedValues.length, links.size());
for (int i = 0; i < links.size(); ++i) {
assertEquals(theExpectedValues[i], theAccessor.apply(links.get(i)), "Value at index " + i + " was not equal");
}
}
@Test
// Test Case #4
public void testHavingMultipleEIDsOnIncomingPatientMatchesCorrectly() {

View File

@ -29,6 +29,10 @@ import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static ca.uhn.fhir.empi.api.EmpiMatchResultEnum.MATCH;
import static ca.uhn.fhir.empi.api.EmpiMatchResultEnum.NO_MATCH;
import static ca.uhn.fhir.empi.api.EmpiMatchResultEnum.POSSIBLE_DUPLICATE;
import static ca.uhn.fhir.empi.api.EmpiMatchResultEnum.POSSIBLE_MATCH;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.blankOrNullString;
import static org.hamcrest.Matchers.equalTo;
@ -37,6 +41,7 @@ import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.in;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.slf4j.LoggerFactory.getLogger;
public class EmpiMatchLinkSvcTest extends BaseEmpiR4Test {
@ -57,6 +62,9 @@ public class EmpiMatchLinkSvcTest extends BaseEmpiR4Test {
public void testAddPatientLinksToNewPersonIfNoneFound() {
createPatientAndUpdateLinks(buildJanePatient());
assertLinkCount(1);
assertLinksMatchResult(MATCH);
assertLinksNewPerson(true);
assertLinksMatchedByEid(false);
}
@Test
@ -66,6 +74,9 @@ public class EmpiMatchLinkSvcTest extends BaseEmpiR4Test {
assertLinkCount(2);
assertThat(patient1, is(not(samePersonAs(patient2))));
assertLinksMatchResult(MATCH, MATCH);
assertLinksNewPerson(true, true);
assertLinksMatchedByEid(false, false);
}
@Test
@ -77,6 +88,9 @@ public class EmpiMatchLinkSvcTest extends BaseEmpiR4Test {
assertLinkCount(2);
assertThat(patient1, is(samePersonAs(patient2)));
assertLinksMatchResult(MATCH, MATCH);
assertLinksNewPerson(true, false);
assertLinksMatchedByEid(false, false);
}
@Test
@ -94,6 +108,10 @@ public class EmpiMatchLinkSvcTest extends BaseEmpiR4Test {
assertThat(unmatchedJane, is(not(samePersonAs(janePerson))));
assertThat(unmatchedJane, is(not(linkedTo(originalJane))));
assertLinksMatchResult(MATCH, NO_MATCH, MATCH);
assertLinksNewPerson(true, false, true);
assertLinksMatchedByEid(false, false, false);
}
@Test
@ -114,6 +132,10 @@ public class EmpiMatchLinkSvcTest extends BaseEmpiR4Test {
assertThat(unmatchedPatient, is(not(samePersonAs(janePerson))));
assertThat(unmatchedPatient, is(not(linkedTo(originalJane))));
assertLinksMatchResult(MATCH, NO_MATCH, MATCH);
assertLinksNewPerson(true, false, true);
assertLinksMatchedByEid(false, false, false);
}
@Test
@ -332,13 +354,18 @@ public class EmpiMatchLinkSvcTest extends BaseEmpiR4Test {
//Ensure there is no successful MATCH links for incomingJanePatient
Optional<EmpiLink> matchedLinkForTargetPid = myEmpiLinkDaoSvc.getMatchedLinkForTargetPid(myIdHelperService.getPidOrNull(incomingJanePatient));
assertThat(matchedLinkForTargetPid.isPresent(), is(false));
logAllLinks();
assertLinksMatchResult(MATCH, MATCH, POSSIBLE_MATCH, POSSIBLE_MATCH, POSSIBLE_DUPLICATE);
assertLinksNewPerson(true, true, false, false, false);
assertLinksMatchedByEid(false, false, false, false, false);
}
@Test
public void testWhenAllMatchResultsArePOSSIBLE_MATCHThattheyAreLinkedAndNoPersonIsCreated() {
/**
* CASE 4: Only POSSIBLE_MATCH outcomes -> In this case, empi-link records are created with POSSIBLE_MATCH
* outcome and await manual assignment to either NO_MATCH or MATCHED. Person resources are not changed.
* outcome and await manual assignment to either NO_MATCH or MATCHED. Person link is added.
*/
Patient patient = buildJanePatient();
patient.getNameFirstRep().setFamily("familyone");
@ -357,6 +384,17 @@ public class EmpiMatchLinkSvcTest extends BaseEmpiR4Test {
assertThat(patient3, is(possibleMatchWith(patient2)));
assertThat(patient3, is(possibleMatchWith(patient)));
IBundleProvider bundle = myPersonDao.search(new SearchParameterMap());
assertEquals(1, bundle.size());
Person person = (Person) bundle.getResources(0, 0);
assertEquals(Person.IdentityAssuranceLevel.LEVEL2, person.getLink().get(0).getAssurance());
assertEquals(Person.IdentityAssuranceLevel.LEVEL1, person.getLink().get(1).getAssurance());
assertEquals(Person.IdentityAssuranceLevel.LEVEL1, person.getLink().get(2).getAssurance());
assertLinksMatchResult(MATCH, POSSIBLE_MATCH, POSSIBLE_MATCH);
assertLinksNewPerson(true, false, false);
assertLinksMatchedByEid(false, false, false);
}
@Test

View File

@ -28,8 +28,7 @@ public final class EmpiMatchOutcome {
public static final EmpiMatchOutcome NO_MATCH = new EmpiMatchOutcome(null, null).setMatchResultEnum(EmpiMatchResultEnum.NO_MATCH);
public static final EmpiMatchOutcome NEW_PERSON_MATCH = new EmpiMatchOutcome(null, null).setMatchResultEnum(EmpiMatchResultEnum.MATCH).setNewPerson(true);
public static final EmpiMatchOutcome EID_MATCH = new EmpiMatchOutcome(null, null).setMatchResultEnum(EmpiMatchResultEnum.MATCH).setEidMatch(true);
public static final EmpiMatchOutcome EID_POSSIBLE_MATCH = new EmpiMatchOutcome(null, null).setMatchResultEnum(EmpiMatchResultEnum.POSSIBLE_MATCH).setEidMatch(true);
public static final EmpiMatchOutcome EID_POSSIBLE_DUPLICATE = new EmpiMatchOutcome(null, null).setMatchResultEnum(EmpiMatchResultEnum.POSSIBLE_DUPLICATE).setEidMatch(true);
public static final EmpiMatchOutcome POSSIBLE_MATCH = new EmpiMatchOutcome(null, null).setMatchResultEnum(EmpiMatchResultEnum.POSSIBLE_MATCH);
/**
* A bitmap that indicates which rules matched