Merge branch 'gg_20201105-remove-person-references' of github.com:jamesagnew/hapi-fhir into gg_20201105-remove-person-references

This commit is contained in:
Tadgh 2020-11-12 18:37:53 -05:00
commit 687e24fa83
10 changed files with 393 additions and 166 deletions

View File

@ -60,8 +60,7 @@ public class GoldenResourceMergerSvcImpl implements IGoldenResourceMergerSvc {
public IAnyResource mergeGoldenResources(IAnyResource theFromGoldenResource, IAnyResource theToGoldenResource, MdmTransactionContext theMdmTransactionContext) { public IAnyResource mergeGoldenResources(IAnyResource theFromGoldenResource, IAnyResource theToGoldenResource, MdmTransactionContext theMdmTransactionContext) {
Long toGoldenResourcePid = myIdHelperService.getPidOrThrowException(theToGoldenResource); Long toGoldenResourcePid = myIdHelperService.getPidOrThrowException(theToGoldenResource);
// TODO NG - Revisit when merge rules are defined myPersonHelper.mergeFields(theFrom, theTo);
// myPersonHelper.mergeFields(theFrom, theTo);
mergeSourceResourceLinks(theFromGoldenResource, theToGoldenResource, toGoldenResourcePid, theMdmTransactionContext); mergeSourceResourceLinks(theFromGoldenResource, theToGoldenResource, toGoldenResourcePid, theMdmTransactionContext);

View File

@ -36,6 +36,7 @@ import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId; import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
import ca.uhn.fhir.rest.param.TokenParam; import ca.uhn.fhir.rest.param.TokenParam;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import org.apache.commons.lang3.StringUtils;
import org.hamcrest.Matcher; import org.hamcrest.Matcher;
import org.hl7.fhir.instance.model.api.IAnyResource; import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
@ -138,12 +139,12 @@ abstract public class BaseEmpiR4Test extends BaseJpaR4Test {
@Nonnull @Nonnull
protected Patient createUnmanagedSourceResource() { protected Patient createUnmanagedSourceResource() {
return createSourceResourcePatient(new Patient(), false); return createGoldenPatient(new Patient(), false);
} }
@Nonnull @Nonnull
protected Patient createSourceResourcePatient() { protected Patient createGoldenPatient() {
return createSourceResourcePatient(new Patient(), true); return createGoldenPatient(new Patient(), true);
} }
@Nonnull @Nonnull
@ -152,17 +153,17 @@ abstract public class BaseEmpiR4Test extends BaseJpaR4Test {
} }
@Nonnull @Nonnull
protected Patient createSourceResourcePatient(Patient theSourceResourcePatient) { protected Patient createGoldenPatient(Patient thePatient) {
return createSourceResourcePatient(theSourceResourcePatient, true); return createGoldenPatient(thePatient, true);
} }
@Nonnull @Nonnull
protected Patient createSourceResourcePatient(Patient theSourceResourcePatient, boolean theEmpiManaged) { protected Patient createGoldenPatient(Patient thePatient, boolean theEmpiManaged) {
if (theEmpiManaged) { if (theEmpiManaged) {
theSourceResourcePatient.getMeta().addTag().setSystem(EmpiConstants.SYSTEM_EMPI_MANAGED).setCode(EmpiConstants.CODE_HAPI_EMPI_MANAGED); thePatient.getMeta().addTag().setSystem(EmpiConstants.SYSTEM_EMPI_MANAGED).setCode(EmpiConstants.CODE_HAPI_EMPI_MANAGED);
theSourceResourcePatient.setActive(true); thePatient.setActive(true);
} }
DaoMethodOutcome outcome = myPatientDao.create(theSourceResourcePatient); DaoMethodOutcome outcome = myPatientDao.create(thePatient);
Patient patient = (Patient) outcome.getResource(); Patient patient = (Patient) outcome.getResource();
patient.setId(outcome.getId()); patient.setId(outcome.getId());
return patient; return patient;
@ -392,23 +393,23 @@ abstract public class BaseEmpiR4Test extends BaseJpaR4Test {
} }
protected Patient getOnlyActiveSourcePatient() { protected Patient getOnlyActiveSourcePatient() {
List<IBaseResource> resources = getAllActiveSourcePatients(); List<IBaseResource> resources = getAllActiveGoldenPatients();
assertEquals(1, resources.size()); assertEquals(1, resources.size());
return (Patient) resources.get(0); return (Patient) resources.get(0);
} }
@Nonnull @Nonnull
protected List<IBaseResource> getAllActiveSourcePatients() { protected List<IBaseResource> getAllActiveGoldenPatients() {
return getAllSourcePatients(true); return getAllGoldenPatients(true);
} }
@Nonnull @Nonnull
protected List<IBaseResource> getAllSourcePatients() { protected List<IBaseResource> getAllGoldenPatients() {
return getAllSourcePatients(false); return getAllGoldenPatients(false);
} }
@Nonnull @Nonnull
private List<IBaseResource> getAllSourcePatients(boolean theOnlyActive) { private List<IBaseResource> getAllGoldenPatients(boolean theOnlyActive) {
SearchParameterMap map = new SearchParameterMap(); SearchParameterMap map = new SearchParameterMap();
map.setLoadSynchronous(true); map.setLoadSynchronous(true);
//TODO GGG ensure that this tag search works effectively. //TODO GGG ensure that this tag search works effectively.
@ -422,7 +423,7 @@ abstract public class BaseEmpiR4Test extends BaseJpaR4Test {
@Nonnull @Nonnull
protected EmpiLink createResourcesAndBuildTestEmpiLink() { protected EmpiLink createResourcesAndBuildTestEmpiLink() {
Patient sourcePatient = createSourceResourcePatient(); Patient sourcePatient = createGoldenPatient();
Patient patient = createPatient(); Patient patient = createPatient();
EmpiLink empiLink = myEmpiLinkDaoSvc.newEmpiLink(); EmpiLink empiLink = myEmpiLinkDaoSvc.newEmpiLink();
@ -467,10 +468,18 @@ abstract public class BaseEmpiR4Test extends BaseJpaR4Test {
} }
protected void print(IBaseResource ... theResource) { protected void print(String message, IBaseResource ... theResource) {
for (IBaseResource r : theResource) { if (StringUtils.isNotEmpty(message)) {
System.out.println(myFhirContext.newJsonParser().encodeResourceToString(r)); ourLog.info(message);
} }
for (IBaseResource r : theResource) {
ourLog.info(myFhirContext.newJsonParser().encodeResourceToString(r));
}
}
protected void print(IBaseResource ... theResource) {
print(null, theResource);
} }
@ -486,7 +495,7 @@ abstract public class BaseEmpiR4Test extends BaseJpaR4Test {
protected void printLinks() { protected void printLinks() {
myEmpiLinkDao.findAll().forEach(empiLink -> { myEmpiLinkDao.findAll().forEach(empiLink -> {
System.out.println(empiLink); ourLog.info(String.valueOf(empiLink));
}); });
} }

View File

@ -31,9 +31,9 @@ public class EmpiProviderMergePersonsR4Test extends BaseProviderR4Test {
super.before(); super.before();
super.loadEmpiSearchParameters(); super.loadEmpiSearchParameters();
myFromSourcePatient = createSourceResourcePatient(); myFromSourcePatient = createGoldenPatient();
myFromSourcePatientId = new StringType(myFromSourcePatient.getIdElement().getValue()); myFromSourcePatientId = new StringType(myFromSourcePatient.getIdElement().getValue());
myToSourcePatient = createSourceResourcePatient(); myToSourcePatient = createGoldenPatient();
myToSourcePatientId = new StringType(myToSourcePatient.getIdElement().getValue()); myToSourcePatientId = new StringType(myToSourcePatient.getIdElement().getValue());
} }
@ -44,8 +44,8 @@ public class EmpiProviderMergePersonsR4Test extends BaseProviderR4Test {
assertEquals(myToSourcePatient.getIdElement(), mergedSourcePatient.getIdElement()); assertEquals(myToSourcePatient.getIdElement(), mergedSourcePatient.getIdElement());
// TODO GGG RP FIX // TODO GGG RP FIX
//assertThat(mergedSourcePatient, is(sameSourceResourceAs(myToSourcePatient))); //assertThat(mergedSourcePatient, is(sameSourceResourceAs(myToSourcePatient)));
assertEquals(2, getAllSourcePatients().size()); assertEquals(2, getAllGoldenPatients().size());
assertEquals(1, getAllActiveSourcePatients().size()); assertEquals(1, getAllActiveGoldenPatients().size());
Patient fromSourcePatient = myPatientDao.read(myFromSourcePatient.getIdElement().toUnqualifiedVersionless()); Patient fromSourcePatient = myPatientDao.read(myFromSourcePatient.getIdElement().toUnqualifiedVersionless());
assertThat(fromSourcePatient.getActive(), is(false)); assertThat(fromSourcePatient.getActive(), is(false));

View File

@ -42,10 +42,10 @@ public class EmpiProviderQueryLinkR4Test extends BaseLinkR4Test {
// Add a possible duplicate // Add a possible duplicate
myLinkSource = new StringType(EmpiLinkSourceEnum.AUTO.name()); myLinkSource = new StringType(EmpiLinkSourceEnum.AUTO.name());
Patient sourcePatient1 = createSourceResourcePatient(); Patient sourcePatient1 = createGoldenPatient();
myPerson1Id = new StringType(sourcePatient1.getIdElement().toVersionless().getValue()); myPerson1Id = new StringType(sourcePatient1.getIdElement().toVersionless().getValue());
Long sourcePatient1Pid = myIdHelperService.getPidOrNull(sourcePatient1); Long sourcePatient1Pid = myIdHelperService.getPidOrNull(sourcePatient1);
Patient sourcePatient2 = createSourceResourcePatient(); Patient sourcePatient2 = createGoldenPatient();
myPerson2Id = new StringType(sourcePatient2.getIdElement().toVersionless().getValue()); myPerson2Id = new StringType(sourcePatient2.getIdElement().toVersionless().getValue());
Long sourcePatient2Pid = myIdHelperService.getPidOrNull(sourcePatient2); Long sourcePatient2Pid = myIdHelperService.getPidOrNull(sourcePatient2);

View File

@ -46,7 +46,7 @@ public class EmpiLinkSvcTest extends BaseEmpiR4Test {
@Test @Test
public void testCreateRemoveLink() { public void testCreateRemoveLink() {
assertLinkCount(0); assertLinkCount(0);
Patient sourcePatient = createSourceResourcePatient(); Patient sourcePatient = createGoldenPatient();
IdType sourcePatientId = sourcePatient.getIdElement().toUnqualifiedVersionless(); IdType sourcePatientId = sourcePatient.getIdElement().toUnqualifiedVersionless();
assertEquals(0, sourcePatient.getLink().size()); assertEquals(0, sourcePatient.getLink().size());
Patient patient = createPatient(); Patient patient = createPatient();
@ -70,8 +70,8 @@ public class EmpiLinkSvcTest extends BaseEmpiR4Test {
@Test @Test
public void testPossibleDuplicate() { public void testPossibleDuplicate() {
assertLinkCount(0); assertLinkCount(0);
Patient sourcePatient1 = createSourceResourcePatient(); Patient sourcePatient1 = createGoldenPatient();
Patient sourcePatient2 = createSourceResourcePatient(); Patient sourcePatient2 = createGoldenPatient();
// TODO GGG MDM NOT VALID // TODO GGG MDM NOT VALID
myEmpiLinkSvc.updateLink(sourcePatient1, sourcePatient2, EmpiMatchOutcome.POSSIBLE_DUPLICATE, EmpiLinkSourceEnum.AUTO, createContextForCreate("Patient")); myEmpiLinkSvc.updateLink(sourcePatient1, sourcePatient2, EmpiMatchOutcome.POSSIBLE_DUPLICATE, EmpiLinkSourceEnum.AUTO, createContextForCreate("Patient"));
assertLinkCount(1); assertLinkCount(1);
@ -80,8 +80,8 @@ public class EmpiLinkSvcTest extends BaseEmpiR4Test {
@Test @Test
public void testNoMatchBlocksPossibleDuplicate() { public void testNoMatchBlocksPossibleDuplicate() {
assertLinkCount(0); assertLinkCount(0);
Patient sourcePatient1 = createSourceResourcePatient(); Patient sourcePatient1 = createGoldenPatient();
Patient sourcePatient2 = createSourceResourcePatient(); Patient sourcePatient2 = createGoldenPatient();
Long sourcePatient1Pid = myIdHelperService.getPidOrNull(sourcePatient1); Long sourcePatient1Pid = myIdHelperService.getPidOrNull(sourcePatient1);
Long sourcePatient2Pid = myIdHelperService.getPidOrNull(sourcePatient2); Long sourcePatient2Pid = myIdHelperService.getPidOrNull(sourcePatient2);
@ -98,8 +98,8 @@ public class EmpiLinkSvcTest extends BaseEmpiR4Test {
@Test @Test
public void testNoMatchBlocksPossibleDuplicateReversed() { public void testNoMatchBlocksPossibleDuplicateReversed() {
assertLinkCount(0); assertLinkCount(0);
Patient sourcePatient1 = createSourceResourcePatient(); Patient sourcePatient1 = createGoldenPatient();
Patient sourcePatient2 = createSourceResourcePatient(); Patient sourcePatient2 = createGoldenPatient();
Long sourcePatient1Pid = myIdHelperService.getPidOrNull(sourcePatient1); Long sourcePatient1Pid = myIdHelperService.getPidOrNull(sourcePatient1);
Long sourcePatient2Pid = myIdHelperService.getPidOrNull(sourcePatient2); Long sourcePatient2Pid = myIdHelperService.getPidOrNull(sourcePatient2);
@ -124,7 +124,7 @@ public class EmpiLinkSvcTest extends BaseEmpiR4Test {
@Test @Test
public void testManualEmpiLinksCannotBeModifiedBySystem() { public void testManualEmpiLinksCannotBeModifiedBySystem() {
Patient sourcePatient = createSourceResourcePatient(buildJaneSourcePatient()); Patient sourcePatient = createGoldenPatient(buildJaneSourcePatient());
Patient patient = createPatient(buildJanePatient()); Patient patient = createPatient(buildJanePatient());
myEmpiLinkSvc.updateLink(sourcePatient, patient, EmpiMatchOutcome.NO_MATCH, EmpiLinkSourceEnum.MANUAL, createContextForCreate("Patient")); myEmpiLinkSvc.updateLink(sourcePatient, patient, EmpiMatchOutcome.NO_MATCH, EmpiLinkSourceEnum.MANUAL, createContextForCreate("Patient"));
@ -138,7 +138,7 @@ public class EmpiLinkSvcTest extends BaseEmpiR4Test {
@Test @Test
public void testAutomaticallyAddedNO_MATCHEmpiLinksAreNotAllowed() { public void testAutomaticallyAddedNO_MATCHEmpiLinksAreNotAllowed() {
Patient sourcePatient = createSourceResourcePatient(buildJaneSourcePatient()); Patient sourcePatient = createGoldenPatient(buildJaneSourcePatient());
Patient patient = createPatient(buildJanePatient()); Patient patient = createPatient(buildJanePatient());
// Test: it should be impossible to have a AUTO NO_MATCH record. The only NO_MATCH records in the system must be MANUAL. // Test: it should be impossible to have a AUTO NO_MATCH record. The only NO_MATCH records in the system must be MANUAL.
@ -152,7 +152,7 @@ public class EmpiLinkSvcTest extends BaseEmpiR4Test {
@Test @Test
public void testSyncDoesNotSyncNoMatchLinks() { public void testSyncDoesNotSyncNoMatchLinks() {
Patient sourcePatient = createSourceResourcePatient(buildJaneSourcePatient()); Patient sourcePatient = createGoldenPatient(buildJaneSourcePatient());
Patient patient1 = createPatient(buildJanePatient()); Patient patient1 = createPatient(buildJanePatient());
Patient patient2 = createPatient(buildJanePatient()); Patient patient2 = createPatient(buildJanePatient());
assertEquals(0, myEmpiLinkDao.count()); assertEquals(0, myEmpiLinkDao.count());

View File

@ -29,7 +29,6 @@ import java.io.IOException;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.function.Predicate;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
@ -54,10 +53,10 @@ public class EmpiPersonMergerSvcTest extends BaseEmpiR4Test {
@Autowired @Autowired
IInterceptorService myInterceptorService; IInterceptorService myInterceptorService;
private Patient myFromSourcePatient; private Patient myFromGoldenPatient;
private Patient myToSourcePatient; private Patient myToGoldenPatient;
private Long myFromSourcePatientPid; private Long myFromGoldenPatientPid;
private Long myToSourcePatientPid; private Long myToGoldenPatientPid;
private Patient myTargetPatient1; private Patient myTargetPatient1;
private Patient myTargetPatient2; private Patient myTargetPatient2;
private Patient myTargetPatient3; private Patient myTargetPatient3;
@ -66,12 +65,12 @@ public class EmpiPersonMergerSvcTest extends BaseEmpiR4Test {
public void before() { public void before() {
super.loadEmpiSearchParameters(); super.loadEmpiSearchParameters();
myFromSourcePatient = createSourceResourcePatient(); myFromGoldenPatient = createGoldenPatient();
IdType fromSourcePatientId = myFromSourcePatient.getIdElement().toUnqualifiedVersionless(); IdType fromSourcePatientId = myFromGoldenPatient.getIdElement().toUnqualifiedVersionless();
myFromSourcePatientPid = myIdHelperService.getPidOrThrowException(fromSourcePatientId); myFromGoldenPatientPid = myIdHelperService.getPidOrThrowException(fromSourcePatientId);
myToSourcePatient = createSourceResourcePatient(); myToGoldenPatient = createGoldenPatient();
IdType toSourcePatientId = myToSourcePatient.getIdElement().toUnqualifiedVersionless(); IdType toGoldenPatientId = myToGoldenPatient.getIdElement().toUnqualifiedVersionless();
myToSourcePatientPid = myIdHelperService.getPidOrThrowException(toSourcePatientId); myToGoldenPatientPid = myIdHelperService.getPidOrThrowException(toGoldenPatientId);
myTargetPatient1 = createPatient(); myTargetPatient1 = createPatient();
myTargetPatient2 = createPatient(); myTargetPatient2 = createPatient();
@ -90,19 +89,19 @@ public class EmpiPersonMergerSvcTest extends BaseEmpiR4Test {
@Test @Test
public void emptyMerge() { public void emptyMerge() {
assertEquals(2, getAllSourcePatients().size()); assertEquals(2, getAllGoldenPatients().size());
assertEquals(2, getAllActiveSourcePatients().size()); assertEquals(2, getAllActiveGoldenPatients().size());
Patient mergedSourcePatients = mergeSourcePatients(); Patient mergedGoldenPatient = mergeGoldenPatients();
assertEquals(myToSourcePatient.getIdElement(), mergedSourcePatients.getIdElement()); assertEquals(myToGoldenPatient.getIdElement(), mergedGoldenPatient.getIdElement());
assertThat(mergedSourcePatients, is(sameSourceResourceAs(mergedSourcePatients))); assertThat(mergedGoldenPatient, is(sameSourceResourceAs(mergedGoldenPatient)));
assertEquals(2, getAllSourcePatients().size()); assertEquals(2, getAllGoldenPatients().size());
assertEquals(1, getAllActiveSourcePatients().size()); assertEquals(1, getAllActiveGoldenPatients().size());
} }
private Patient mergeSourcePatients() { private Patient mergeGoldenPatients() {
assertEquals(0, redirectLinkCount()); assertEquals(0, redirectLinkCount());
Patient retval = (Patient) myEmpiPersonMergerSvc.mergeGoldenResources(myFromSourcePatient, myToSourcePatient, createEmpiContext()); Patient retval = (Patient) myEmpiPersonMergerSvc.mergeGoldenResources(myFromGoldenPatient, myToGoldenPatient, createEmpiContext());
assertEquals(1, redirectLinkCount()); assertEquals(1, redirectLinkCount());
return retval; return retval;
} }
@ -122,8 +121,8 @@ public class EmpiPersonMergerSvcTest extends BaseEmpiR4Test {
@Test @Test
public void mergeRemovesPossibleDuplicatesLink() { public void mergeRemovesPossibleDuplicatesLink() {
EmpiLink empiLink = myEmpiLinkDaoSvc.newEmpiLink() EmpiLink empiLink = myEmpiLinkDaoSvc.newEmpiLink()
.setSourceResourcePid(myToSourcePatientPid) .setSourceResourcePid(myToGoldenPatientPid)
.setTargetPid(myFromSourcePatientPid) .setTargetPid(myFromGoldenPatientPid)
.setEmpiTargetType("Patient") .setEmpiTargetType("Patient")
.setMatchResult(EmpiMatchResultEnum.POSSIBLE_DUPLICATE) .setMatchResult(EmpiMatchResultEnum.POSSIBLE_DUPLICATE)
.setLinkSource(EmpiLinkSourceEnum.AUTO); .setLinkSource(EmpiLinkSourceEnum.AUTO);
@ -138,7 +137,7 @@ public class EmpiPersonMergerSvcTest extends BaseEmpiR4Test {
myEmpiLinkHelper.logEmpiLinks(); myEmpiLinkHelper.logEmpiLinks();
mergeSourcePatients(); mergeGoldenPatients();
{ {
List<EmpiLink> foundLinks = myEmpiLinkDao.findAll(); List<EmpiLink> foundLinks = myEmpiLinkDao.findAll();
@ -149,9 +148,9 @@ public class EmpiPersonMergerSvcTest extends BaseEmpiR4Test {
@Test @Test
public void fullFromEmptyTo() { public void fullFromEmptyTo() {
populatePerson(myFromSourcePatient); populatePerson(myFromGoldenPatient);
Patient mergedSourcePatient = mergeSourcePatients(); Patient mergedSourcePatient = mergeGoldenPatients();
// TODO NG - Revisit when rules are ready // TODO NG - Revisit when rules are ready
// HumanName returnedName = mergedSourcePatient.getNameFirstRep(); // HumanName returnedName = mergedSourcePatient.getNameFirstRep();
// assertEquals(GIVEN_NAME, returnedName.getGivenAsSingleString()); // assertEquals(GIVEN_NAME, returnedName.getGivenAsSingleString());
@ -161,10 +160,10 @@ public class EmpiPersonMergerSvcTest extends BaseEmpiR4Test {
@Test @Test
public void emptyFromFullTo() { public void emptyFromFullTo() {
myFromSourcePatient.getName().add(new HumanName().addGiven(BAD_GIVEN_NAME)); myFromGoldenPatient.getName().add(new HumanName().addGiven(BAD_GIVEN_NAME));
populatePerson(myToSourcePatient); populatePerson(myToGoldenPatient);
Patient mergedSourcePatient = mergeSourcePatients(); Patient mergedSourcePatient = mergeGoldenPatients();
HumanName returnedName = mergedSourcePatient.getNameFirstRep(); HumanName returnedName = mergedSourcePatient.getNameFirstRep();
assertEquals(GIVEN_NAME, returnedName.getGivenAsSingleString()); assertEquals(GIVEN_NAME, returnedName.getGivenAsSingleString());
assertEquals(FAMILY_NAME, returnedName.getFamily()); assertEquals(FAMILY_NAME, returnedName.getFamily());
@ -173,92 +172,92 @@ public class EmpiPersonMergerSvcTest extends BaseEmpiR4Test {
@Test @Test
public void fromLinkToNoLink() { public void fromLinkToNoLink() {
createEmpiLink(myFromSourcePatient, myTargetPatient1); createEmpiLink(myFromGoldenPatient, myTargetPatient1);
Patient mergedSourcePatient = mergeSourcePatients(); Patient mergedGoldenPatient = mergeGoldenPatients();
List<EmpiLink> links = getNonRedirectLinksByPerson(mergedSourcePatient); List<EmpiLink> links = getNonRedirectLinksByPerson(mergedGoldenPatient);
assertEquals(1, links.size()); assertEquals(1, links.size());
assertThat(mergedSourcePatient, is(possibleLinkedTo(myTargetPatient1))); assertThat(mergedGoldenPatient, is(possibleLinkedTo(myTargetPatient1)));
// fail("FIXME"); TODO NG - Confirm it's ok
} }
@Test @Test
public void fromNoLinkToLink() { public void fromNoLinkToLink() {
createEmpiLink(myToSourcePatient, myTargetPatient1); createEmpiLink(myToGoldenPatient, myTargetPatient1);
Patient mergedSourcePatient = mergeSourcePatients(); Patient mergedSourcePatient = mergeGoldenPatients();
List<EmpiLink> links = getNonRedirectLinksByPerson(mergedSourcePatient); List<EmpiLink> links = getNonRedirectLinksByPerson(mergedSourcePatient);
assertEquals(1, links.size()); assertEquals(1, links.size());
assertThat(mergedSourcePatient, is(possibleLinkedTo(myTargetPatient1))); assertThat(mergedSourcePatient, is(possibleLinkedTo(myTargetPatient1)));
// fail("FIXME"); TODO NG - Confirm it's ok
} }
@Test @Test
public void fromManualLinkOverridesAutoToLink() { public void fromManualLinkOverridesAutoToLink() {
EmpiLink fromLink = createEmpiLink(myFromSourcePatient, myTargetPatient1); EmpiLink fromLink = createEmpiLink(myFromGoldenPatient, myTargetPatient1);
fromLink.setLinkSource(EmpiLinkSourceEnum.MANUAL); fromLink.setLinkSource(EmpiLinkSourceEnum.MANUAL);
fromLink.setMatchResult(EmpiMatchResultEnum.MATCH); fromLink.setMatchResult(EmpiMatchResultEnum.MATCH);
saveLink(fromLink); saveLink(fromLink);
createEmpiLink(myToSourcePatient, myTargetPatient1); createEmpiLink(myToGoldenPatient, myTargetPatient1);
mergeSourcePatients(); mergeGoldenPatients();
List<EmpiLink> links = getNonRedirectLinksByPerson(myToSourcePatient); List<EmpiLink> links = getNonRedirectLinksByPerson(myToGoldenPatient);
assertEquals(1, links.size()); assertEquals(1, links.size());
assertEquals(EmpiLinkSourceEnum.MANUAL, links.get(0).getLinkSource()); assertEquals(EmpiLinkSourceEnum.MANUAL, links.get(0).getLinkSource());
} }
private List<EmpiLink> getNonRedirectLinksByPerson(Patient theSourcePatient) { private List<EmpiLink> getNonRedirectLinksByPerson(Patient theGoldenPatient) {
return myEmpiLinkDaoSvc.findEmpiLinksBySourceResource(theSourcePatient).stream() return myEmpiLinkDaoSvc.findEmpiLinksBySourceResource(theGoldenPatient).stream()
.filter(link -> !link.isRedirect()) .filter(link -> !link.isRedirect())
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
@Test @Test
public void fromManualNoMatchLinkOverridesAutoToLink() { public void fromManualNoMatchLinkOverridesAutoToLink() {
EmpiLink fromLink = createEmpiLink(myFromSourcePatient, myTargetPatient1); EmpiLink fromLink = createEmpiLink(myFromGoldenPatient, myTargetPatient1);
fromLink.setLinkSource(EmpiLinkSourceEnum.MANUAL); fromLink.setLinkSource(EmpiLinkSourceEnum.MANUAL);
fromLink.setMatchResult(EmpiMatchResultEnum.NO_MATCH); fromLink.setMatchResult(EmpiMatchResultEnum.NO_MATCH);
saveLink(fromLink); saveLink(fromLink);
createEmpiLink(myToSourcePatient, myTargetPatient1); createEmpiLink(myToGoldenPatient, myTargetPatient1);
mergeSourcePatients(); mergeGoldenPatients();
List<EmpiLink> links = getNonRedirectLinksByPerson(myToSourcePatient); List<EmpiLink> links = getNonRedirectLinksByPerson(myToGoldenPatient);
assertEquals(1, links.size()); assertEquals(1, links.size());
assertEquals(EmpiLinkSourceEnum.MANUAL, links.get(0).getLinkSource()); assertEquals(EmpiLinkSourceEnum.MANUAL, links.get(0).getLinkSource());
assertEquals(EmpiMatchResultEnum.NO_MATCH, links.get(0).getMatchResult());
} }
@Test @Test
public void fromManualAutoMatchLinkNoOverridesManualToLink() { public void fromManualAutoMatchLinkNoOverridesManualToLink() {
createEmpiLink(myFromSourcePatient, myTargetPatient1); createEmpiLink(myFromGoldenPatient, myTargetPatient1);
EmpiLink toLink = createEmpiLink(myToSourcePatient, myTargetPatient1); EmpiLink toLink = createEmpiLink(myToGoldenPatient, myTargetPatient1);
toLink.setLinkSource(EmpiLinkSourceEnum.MANUAL); toLink.setLinkSource(EmpiLinkSourceEnum.MANUAL);
toLink.setMatchResult(EmpiMatchResultEnum.NO_MATCH); toLink.setMatchResult(EmpiMatchResultEnum.NO_MATCH);
saveLink(toLink); saveLink(toLink);
mergeSourcePatients(); mergeGoldenPatients();
List<EmpiLink> links = getNonRedirectLinksByPerson(myToSourcePatient); List<EmpiLink> links = getNonRedirectLinksByPerson(myToGoldenPatient);
assertEquals(1, links.size()); assertEquals(1, links.size());
assertEquals(EmpiLinkSourceEnum.MANUAL, links.get(0).getLinkSource()); assertEquals(EmpiLinkSourceEnum.MANUAL, links.get(0).getLinkSource());
assertEquals(EmpiMatchResultEnum.NO_MATCH, links.get(0).getMatchResult());
} }
@Test @Test
public void fromNoMatchMergeToManualMatchIsError() { public void fromNoMatchMergeToManualMatchIsError() {
EmpiLink fromLink = createEmpiLink(myFromSourcePatient, myTargetPatient1); EmpiLink fromLink = createEmpiLink(myFromGoldenPatient, myTargetPatient1);
fromLink.setLinkSource(EmpiLinkSourceEnum.MANUAL); fromLink.setLinkSource(EmpiLinkSourceEnum.MANUAL);
fromLink.setMatchResult(EmpiMatchResultEnum.NO_MATCH); fromLink.setMatchResult(EmpiMatchResultEnum.NO_MATCH);
saveLink(fromLink); saveLink(fromLink);
EmpiLink toLink = createEmpiLink(myToSourcePatient, myTargetPatient1); EmpiLink toLink = createEmpiLink(myToGoldenPatient, myTargetPatient1);
toLink.setLinkSource(EmpiLinkSourceEnum.MANUAL); toLink.setLinkSource(EmpiLinkSourceEnum.MANUAL);
toLink.setMatchResult(EmpiMatchResultEnum.MATCH); toLink.setMatchResult(EmpiMatchResultEnum.MATCH);
saveLink(toLink); saveLink(toLink);
try { try {
mergeSourcePatients(); mergeGoldenPatients();
fail(); fail();
} catch (InvalidRequestException e) { } catch (InvalidRequestException e) {
assertEquals("A MANUAL NO_MATCH link may not be merged into a MANUAL MATCH link for the same target", e.getMessage()); assertEquals("A MANUAL NO_MATCH link may not be merged into a MANUAL MATCH link for the same target", e.getMessage());
@ -267,18 +266,18 @@ public class EmpiPersonMergerSvcTest extends BaseEmpiR4Test {
@Test @Test
public void fromMatchMergeToManualNoMatchIsError() { public void fromMatchMergeToManualNoMatchIsError() {
EmpiLink fromLink = createEmpiLink(myFromSourcePatient, myTargetPatient1); EmpiLink fromLink = createEmpiLink(myFromGoldenPatient, myTargetPatient1);
fromLink.setLinkSource(EmpiLinkSourceEnum.MANUAL); fromLink.setLinkSource(EmpiLinkSourceEnum.MANUAL);
fromLink.setMatchResult(EmpiMatchResultEnum.MATCH); fromLink.setMatchResult(EmpiMatchResultEnum.MATCH);
saveLink(fromLink); saveLink(fromLink);
EmpiLink toLink = createEmpiLink(myToSourcePatient, myTargetPatient1); EmpiLink toLink = createEmpiLink(myToGoldenPatient, myTargetPatient1);
toLink.setLinkSource(EmpiLinkSourceEnum.MANUAL); toLink.setLinkSource(EmpiLinkSourceEnum.MANUAL);
toLink.setMatchResult(EmpiMatchResultEnum.NO_MATCH); toLink.setMatchResult(EmpiMatchResultEnum.NO_MATCH);
saveLink(toLink); saveLink(toLink);
try { try {
mergeSourcePatients(); mergeGoldenPatients();
fail(); fail();
} catch (InvalidRequestException e) { } catch (InvalidRequestException e) {
assertEquals("A MANUAL MATCH link may not be merged into a MANUAL NO_MATCH link for the same target", e.getMessage()); assertEquals("A MANUAL MATCH link may not be merged into a MANUAL NO_MATCH link for the same target", e.getMessage());
@ -287,91 +286,92 @@ public class EmpiPersonMergerSvcTest extends BaseEmpiR4Test {
@Test @Test
public void fromNoMatchMergeToManualMatchDifferentPatientIsOk() { public void fromNoMatchMergeToManualMatchDifferentPatientIsOk() {
EmpiLink fromLink = createEmpiLink(myFromSourcePatient, myTargetPatient1); EmpiLink fromLink = createEmpiLink(myFromGoldenPatient, myTargetPatient1);
fromLink.setLinkSource(EmpiLinkSourceEnum.MANUAL); fromLink.setLinkSource(EmpiLinkSourceEnum.MANUAL);
fromLink.setMatchResult(EmpiMatchResultEnum.NO_MATCH); fromLink.setMatchResult(EmpiMatchResultEnum.NO_MATCH);
saveLink(fromLink); saveLink(fromLink);
EmpiLink toLink = createEmpiLink(myToSourcePatient, myTargetPatient2); EmpiLink toLink = createEmpiLink(myToGoldenPatient, myTargetPatient2);
toLink.setLinkSource(EmpiLinkSourceEnum.MANUAL); toLink.setLinkSource(EmpiLinkSourceEnum.MANUAL);
toLink.setMatchResult(EmpiMatchResultEnum.MATCH); toLink.setMatchResult(EmpiMatchResultEnum.MATCH);
saveLink(toLink); saveLink(toLink);
mergeSourcePatients(); mergeGoldenPatients();
assertResourceHasLinkCount(myToSourcePatient, 1, (e) -> false);
// assertEquals(1, myToSourcePatient.getLink().size()); assertResourceHasLinkCount(myToGoldenPatient, 3);
assertResourceHasLinkCount(myFromGoldenPatient, 0);
// TODO ENSURE PROPER LINK TYPES
assertEquals(3, myEmpiLinkDao.count()); assertEquals(3, myEmpiLinkDao.count());
} }
@Test @Test
public void from123To1() { public void from123To1() {
createEmpiLink(myFromSourcePatient, myTargetPatient1); createEmpiLink(myFromGoldenPatient, myTargetPatient1);
createEmpiLink(myFromSourcePatient, myTargetPatient2); createEmpiLink(myFromGoldenPatient, myTargetPatient2);
createEmpiLink(myFromSourcePatient, myTargetPatient3); createEmpiLink(myFromGoldenPatient, myTargetPatient3);
createEmpiLink(myToSourcePatient, myTargetPatient1); createEmpiLink(myToGoldenPatient, myTargetPatient1);
mergeSourcePatients(); mergeGoldenPatients();
myEmpiLinkHelper.logEmpiLinks(); myEmpiLinkHelper.logEmpiLinks();
assertThat(myToSourcePatient, is(possibleLinkedTo(myTargetPatient1, myTargetPatient2, myTargetPatient3))); assertThat(myToGoldenPatient, is(possibleLinkedTo(myTargetPatient1, myTargetPatient2, myTargetPatient3)));
// assertEquals(3, myToSourcePatient.getLink().size()); assertResourceHasAutoLinkCount(myToGoldenPatient, 3);
assertResourceHasAutoLinkCount(myToSourcePatient, 3);
} }
private void assertResourceHasAutoLinkCount(IBaseResource theResource, int theCount) {
assertResourceHasLinkCount(theResource, theCount, EmpiLink::isAuto);
}
private void assertResourceHasLinkCount(IBaseResource theResource, int theCount, Predicate<EmpiLink> thePredicate) { private void assertResourceHasLinkCount(IBaseResource theResource, int theCount) {
List<EmpiLink> links = myEmpiLinkDaoSvc.findEmpiLinksBySourceResource(theResource); List<EmpiLink> links = myEmpiLinkDaoSvc.findEmpiLinksBySourceResource(theResource);
assertEquals(theCount, links.stream().filter(thePredicate).count()); assertEquals(theCount, links.size());
} }
@Test @Test
public void from1To123() { public void from1To123() {
createEmpiLink(myFromSourcePatient, myTargetPatient1); createEmpiLink(myFromGoldenPatient, myTargetPatient1);
createEmpiLink(myToSourcePatient, myTargetPatient1); createEmpiLink(myToGoldenPatient, myTargetPatient1);
createEmpiLink(myToSourcePatient, myTargetPatient2); createEmpiLink(myToGoldenPatient, myTargetPatient2);
createEmpiLink(myToSourcePatient, myTargetPatient3); createEmpiLink(myToGoldenPatient, myTargetPatient3);
mergeSourcePatients(); mergeGoldenPatients();
myEmpiLinkHelper.logEmpiLinks(); myEmpiLinkHelper.logEmpiLinks();
assertThat(myToSourcePatient, is(possibleLinkedTo(myTargetPatient1, myTargetPatient2, myTargetPatient3))); assertThat(myToGoldenPatient, is(possibleLinkedTo(myTargetPatient1, myTargetPatient2, myTargetPatient3)));
assertResourceHasAutoLinkCount(myToSourcePatient, 3); assertResourceHasAutoLinkCount(myToGoldenPatient, 3);
}
private void assertResourceHasAutoLinkCount(Patient myToGoldenPatient, int theCount) {
List<EmpiLink> links = myEmpiLinkDaoSvc.findEmpiLinksBySourceResource(myToGoldenPatient);
assertEquals(theCount, links.stream().filter(EmpiLink::isAuto).count());
} }
@Test @Test
public void from123To123() { public void from123To123() {
createEmpiLink(myFromSourcePatient, myTargetPatient1); createEmpiLink(myFromGoldenPatient, myTargetPatient1);
createEmpiLink(myFromSourcePatient, myTargetPatient2); createEmpiLink(myFromGoldenPatient, myTargetPatient2);
createEmpiLink(myFromSourcePatient, myTargetPatient3); createEmpiLink(myFromGoldenPatient, myTargetPatient3);
createEmpiLink(myToSourcePatient, myTargetPatient1); createEmpiLink(myToGoldenPatient, myTargetPatient1);
createEmpiLink(myToSourcePatient, myTargetPatient2); createEmpiLink(myToGoldenPatient, myTargetPatient2);
createEmpiLink(myToSourcePatient, myTargetPatient3); createEmpiLink(myToGoldenPatient, myTargetPatient3);
mergeSourcePatients(); mergeGoldenPatients();
assertThat(myToSourcePatient, is(possibleLinkedTo(myTargetPatient1, myTargetPatient2, myTargetPatient3))); assertThat(myToGoldenPatient, is(possibleLinkedTo(myTargetPatient1, myTargetPatient2, myTargetPatient3)));
// assertEquals(3, myToSourcePatient.getLink().size()); assertResourceHasAutoLinkCount(myToGoldenPatient, 3);
assertResourceHasAutoLinkCount(myToSourcePatient, 3);
} }
@Test @Test
public void from12To23() { public void from12To23() {
createEmpiLink(myFromSourcePatient, myTargetPatient1); createEmpiLink(myFromGoldenPatient, myTargetPatient1);
createEmpiLink(myFromSourcePatient, myTargetPatient2); createEmpiLink(myFromGoldenPatient, myTargetPatient2);
createEmpiLink(myToSourcePatient, myTargetPatient2); createEmpiLink(myToGoldenPatient, myTargetPatient2);
createEmpiLink(myToSourcePatient, myTargetPatient3); createEmpiLink(myToGoldenPatient, myTargetPatient3);
mergeSourcePatients(); mergeGoldenPatients();
myEmpiLinkHelper.logEmpiLinks(); myEmpiLinkHelper.logEmpiLinks();
assertThat(myToSourcePatient, is(possibleLinkedTo(myTargetPatient1, myTargetPatient2, myTargetPatient3))); assertThat(myToGoldenPatient, is(possibleLinkedTo(myTargetPatient1, myTargetPatient2, myTargetPatient3)));
// assertEquals(3, myToSourcePatient.getLink().size()); assertResourceHasAutoLinkCount(myToGoldenPatient, 3);
assertResourceHasAutoLinkCount(myToSourcePatient, 3);
} }
@Test @Test
@ -412,17 +412,19 @@ public class EmpiPersonMergerSvcTest extends BaseEmpiR4Test {
} }
@Test @Test
public void testMergeIdentities() { public void testMergeIdentifiers() {
myFromSourcePatient.addIdentifier().setValue("aaa"); myFromGoldenPatient.addIdentifier().setValue("aaa").setSystem("SYSTEM1");
myFromSourcePatient.addIdentifier().setValue("bbb"); myFromGoldenPatient.addIdentifier().setValue("bbb").setSystem("SYSTEM1");
assertThat(myFromSourcePatient.getIdentifier(), hasSize(2)); myFromGoldenPatient.addIdentifier().setValue("ccc").setSystem("SYSTEM2");
assertThat(myFromGoldenPatient.getIdentifier(), hasSize(3));
myToSourcePatient.addIdentifier().setValue("aaa"); myToGoldenPatient.addIdentifier().setValue("aaa").setSystem("SYSTEM1");
myToSourcePatient.addIdentifier().setValue("ccc"); myToGoldenPatient.addIdentifier().setValue("ccc").setSystem("SYSTEM1");
assertThat(myToSourcePatient.getIdentifier(), hasSize(2)); assertThat(myToGoldenPatient.getIdentifier(), hasSize(2));
mergeSourcePatients(); mergeGoldenPatients();
assertThat(myToSourcePatient.getIdentifier(), hasSize(3));
assertThat(myToGoldenPatient.getIdentifier(), hasSize(4));
} }
private EmpiLink createEmpiLink(Patient theSourcePatient, Patient theTargetPatient) { private EmpiLink createEmpiLink(Patient theSourcePatient, Patient theTargetPatient) {

View File

@ -25,10 +25,10 @@ public class EmpiResourceDaoSvcTest extends BaseEmpiR4Test {
@Test @Test
public void testSearchPersonByEidExcludesInactive() { public void testSearchPersonByEidExcludesInactive() {
Patient goodSourcePatient = addExternalEID(createSourceResourcePatient(), TEST_EID); Patient goodSourcePatient = addExternalEID(createGoldenPatient(), TEST_EID);
myPatientDao.update(goodSourcePatient); myPatientDao.update(goodSourcePatient);
Patient badSourcePatient = addExternalEID(createSourceResourcePatient(), TEST_EID); Patient badSourcePatient = addExternalEID(createGoldenPatient(), TEST_EID);
badSourcePatient.setActive(false); badSourcePatient.setActive(false);
myPatientDao.update(badSourcePatient); myPatientDao.update(badSourcePatient);
@ -39,10 +39,10 @@ public class EmpiResourceDaoSvcTest extends BaseEmpiR4Test {
@Test @Test
public void testSearchPersonByEidExcludesNonEmpiManaged() { public void testSearchPersonByEidExcludesNonEmpiManaged() {
Patient goodSourcePatient = addExternalEID(createSourceResourcePatient(), TEST_EID); Patient goodSourcePatient = addExternalEID(createGoldenPatient(), TEST_EID);
myPatientDao.update(goodSourcePatient); myPatientDao.update(goodSourcePatient);
Patient badSourcePatient = addExternalEID(createSourceResourcePatient(new Patient(), false), TEST_EID); Patient badSourcePatient = addExternalEID(createGoldenPatient(new Patient(), false), TEST_EID);
myPatientDao.update(badSourcePatient); myPatientDao.update(badSourcePatient);
Optional<IAnyResource> foundSourcePatient = myResourceDaoSvc.searchSourceResourceByEID(TEST_EID, "Patient"); Optional<IAnyResource> foundSourcePatient = myResourceDaoSvc.searchSourceResourceByEID(TEST_EID, "Patient");

View File

@ -65,6 +65,8 @@ import static ca.uhn.fhir.context.FhirVersionEnum.R4;
public class PersonHelper { public class PersonHelper {
private static final Logger ourLog = Logs.getEmpiTroubleshootingLog(); private static final Logger ourLog = Logs.getEmpiTroubleshootingLog();
private static final String FIELD_NAME_IDENTIFIER = "identifier";
@Autowired @Autowired
private IEmpiSettings myEmpiConfig; private IEmpiSettings myEmpiConfig;
@Autowired @Autowired
@ -94,7 +96,7 @@ public class PersonHelper {
IBaseResource newSourceResource = resourceDefinition.newInstance(); IBaseResource newSourceResource = resourceDefinition.newInstance();
// hapi has 2 metamodels: for children and types // hapi has 2 metamodels: for children and types
BaseRuntimeChildDefinition sourceResourceIdentifier = resourceDefinition.getChildByName("identifier"); BaseRuntimeChildDefinition sourceResourceIdentifier = resourceDefinition.getChildByName(FIELD_NAME_IDENTIFIER);
cloneAllExternalEidsIntoNewSourceResource(sourceResourceIdentifier, theIncomingResource, newSourceResource); cloneAllExternalEidsIntoNewSourceResource(sourceResourceIdentifier, theIncomingResource, newSourceResource);
@ -143,7 +145,7 @@ public class PersonHelper {
// get a ref to the actual ID Field // get a ref to the actual ID Field
RuntimeResourceDefinition resourceDefinition = myFhirContext.getResourceDefinition(theResourceToCloneInto); RuntimeResourceDefinition resourceDefinition = myFhirContext.getResourceDefinition(theResourceToCloneInto);
// hapi has 2 metamodels: for children and types // hapi has 2 metamodels: for children and types
BaseRuntimeChildDefinition resourceIdentifier = resourceDefinition.getChildByName("identifier"); BaseRuntimeChildDefinition resourceIdentifier = resourceDefinition.getChildByName(FIELD_NAME_IDENTIFIER);
cloneEidIntoResource(resourceIdentifier, toId(theEid), theResourceToCloneInto); cloneEidIntoResource(resourceIdentifier, toId(theEid), theResourceToCloneInto);
} }
@ -152,7 +154,7 @@ public class PersonHelper {
*/ */
private void cloneEidIntoResource(BaseRuntimeChildDefinition theIdentifierDefinition, IBase theEid, IBase theResourceToCloneEidInto) { private void cloneEidIntoResource(BaseRuntimeChildDefinition theIdentifierDefinition, IBase theEid, IBase theResourceToCloneEidInto) {
// FHIR choice types - fields within fhir where we have a choice of ids // FHIR choice types - fields within fhir where we have a choice of ids
BaseRuntimeElementCompositeDefinition<?> childIdentifier = (BaseRuntimeElementCompositeDefinition<?>) theIdentifierDefinition.getChildByName("identifier"); BaseRuntimeElementCompositeDefinition<?> childIdentifier = (BaseRuntimeElementCompositeDefinition<?>) theIdentifierDefinition.getChildByName(FIELD_NAME_IDENTIFIER);
IBase resourceNewIdentifier = childIdentifier.newInstance(); IBase resourceNewIdentifier = childIdentifier.newInstance();
FhirTerser terser = myFhirContext.newTerser(); FhirTerser terser = myFhirContext.newTerser();
@ -160,6 +162,44 @@ public class PersonHelper {
theIdentifierDefinition.getMutator().addValue(theResourceToCloneEidInto, resourceNewIdentifier); theIdentifierDefinition.getMutator().addValue(theResourceToCloneEidInto, resourceNewIdentifier);
} }
/**
* Clones specified composite field (collection). Composite field values must confirm to the collections
* contract.
*
* @param theFrom Resource to clone the specified filed from
* @param theTo Resource to clone the specified filed to
* @param field Field name to be copied
*/
private void cloneCompositeField(IBaseResource theFrom, IBaseResource theTo, String field) {
FhirTerser terser = myFhirContext.newTerser();
RuntimeResourceDefinition definition = myFhirContext.getResourceDefinition(theFrom);
BaseRuntimeChildDefinition childDefinition = definition.getChildByName(field);
IFhirPath fhirPath = myFhirContext.newFhirPath();
List<IBase> theFromFieldValues = childDefinition.getAccessor().getValues(theFrom);
List<IBase> theToFieldValues = childDefinition.getAccessor().getValues(theTo);
for (IBase theFromFieldValue: theFromFieldValues) {
if (contains(theFromFieldValue, theToFieldValues)) {
continue;
}
BaseRuntimeElementCompositeDefinition<?> compositeDefinition = (BaseRuntimeElementCompositeDefinition<?>) childDefinition.getChildByName(field);
IBase newFieldValue = compositeDefinition.newInstance();
terser.cloneInto(theFromFieldValue, newFieldValue, true);
theToFieldValues.add(newFieldValue);
}
}
private boolean contains(IBase theItem, List<IBase> theItems) {
PrimitiveTypeComparingPredicate predicate = new PrimitiveTypeComparingPredicate();
return theItems.stream().filter(i -> {
return predicate.test(i, theItem);
}).findFirst().isPresent();
}
private void cloneAllExternalEidsIntoNewSourceResource(BaseRuntimeChildDefinition theSourceResourceIdentifier, IBase theSourceResource, IBase theNewSourceResource) { private void cloneAllExternalEidsIntoNewSourceResource(BaseRuntimeChildDefinition theSourceResourceIdentifier, IBase theSourceResource, IBase theNewSourceResource) {
// FHIR choice types - fields within fhir where we have a choice of ids // FHIR choice types - fields within fhir where we have a choice of ids
IFhirPath fhirPath = myFhirContext.newFhirPath(); IFhirPath fhirPath = myFhirContext.newFhirPath();
@ -244,7 +284,7 @@ public class PersonHelper {
} }
BaseRuntimeElementCompositeDefinition<?> childIdentifier = (BaseRuntimeElementCompositeDefinition<?>) BaseRuntimeElementCompositeDefinition<?> childIdentifier = (BaseRuntimeElementCompositeDefinition<?>)
theSourceResourceIdentifier.getChildByName("identifier"); theSourceResourceIdentifier.getChildByName(FIELD_NAME_IDENTIFIER);
IBase sourceResourceNewIdentifier = childIdentifier.newInstance(); IBase sourceResourceNewIdentifier = childIdentifier.newInstance();
terser.cloneInto(base, sourceResourceNewIdentifier, true); terser.cloneInto(base, sourceResourceNewIdentifier, true);
@ -261,7 +301,7 @@ public class PersonHelper {
// get a ref to the actual ID Field // get a ref to the actual ID Field
RuntimeResourceDefinition resourceDefinition = myFhirContext.getResourceDefinition(theSourceResource); RuntimeResourceDefinition resourceDefinition = myFhirContext.getResourceDefinition(theSourceResource);
BaseRuntimeChildDefinition sourceResourceIdentifier = resourceDefinition.getChildByName("identifier"); BaseRuntimeChildDefinition sourceResourceIdentifier = resourceDefinition.getChildByName(FIELD_NAME_IDENTIFIER);
clearExternalEidsFromTheSourceResource(sourceResourceIdentifier, theSourceResource); clearExternalEidsFromTheSourceResource(sourceResourceIdentifier, theSourceResource);
} }
@ -280,7 +320,7 @@ public class PersonHelper {
} }
} }
private <T> T toId(CanonicalEID eid) { private <T extends IBase> T toId(CanonicalEID eid) {
switch (myFhirContext.getVersion().getVersion()) { switch (myFhirContext.getVersion().getVersion()) {
case R4: case R4:
return (T) eid.toR4(); return (T) eid.toR4();
@ -328,16 +368,19 @@ public class PersonHelper {
} }
public void mergeFields(IBaseResource theFromPerson, IBaseResource theToPerson) { public void mergeFields(IBaseResource theFromPerson, IBaseResource theToPerson) {
switch (myFhirContext.getVersion().getVersion()) { // TODO NG - Revisit when merge rules are defined
case R4: cloneCompositeField(theFromPerson, theToPerson, FIELD_NAME_IDENTIFIER);
mergeR4PersonFields(theFromPerson, theToPerson);
break; // switch (myFhirContext.getVersion().getVersion()) {
case DSTU3: // case R4:
mergeDstu3PersonFields(theFromPerson, theToPerson); // mergeR4PersonFields(theFromPerson, theToPerson);
break; // break;
default: // case DSTU3:
throw new UnsupportedOperationException("Version not supported: " + myFhirContext.getVersion().getVersion()); // mergeDstu3PersonFields(theFromPerson, theToPerson);
} // break;
// default:
// throw new UnsupportedOperationException("Version not supported: " + myFhirContext.getVersion().getVersion());
// }
} }
private void mergeR4PersonFields(IBaseResource theFromPerson, IBaseResource theToPerson) { private void mergeR4PersonFields(IBaseResource theFromPerson, IBaseResource theToPerson) {

View File

@ -0,0 +1,70 @@
package ca.uhn.fhir.empi.util;
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.util.FhirTerser;
import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import java.lang.reflect.Field;
import java.util.function.BiPredicate;
public class PrimitiveTypeComparingPredicate implements BiPredicate {
@Override
public boolean test(Object theBase1, Object theBase2) {
if (theBase1 == null) {
return theBase2 == null;
}
if (theBase2 == null) {
return false;
}
if (!theBase1.getClass().equals(theBase2.getClass())) {
return false;
}
for (Field f : theBase1.getClass().getDeclaredFields()) {
Class<?> fieldClass = f.getType();
if (!IPrimitiveType.class.isAssignableFrom(fieldClass)) {
continue;
}
IPrimitiveType<?> val1, val2;
f.setAccessible(true);
try {
val1 = (IPrimitiveType<?>) f.get(theBase1);
val2 = (IPrimitiveType<?>) f.get(theBase2);
} catch (Exception e) {
// swallow
continue;
}
if (val1 == null && val2 == null) {
continue;
}
if (val1 == null && val2 != null) {
return false;
}
Object actualVal1 = val1.getValue();
Object actualVal2 = val2.getValue();
if (actualVal1 == null && actualVal2 == null) {
continue;
}
if (actualVal1 == null && actualVal2 != null) {
return false;
}
if (!actualVal1.equals(actualVal2)) {
return false;
}
}
return true;
}
}

View File

@ -0,0 +1,104 @@
package ca.uhn.fhir.empi.util;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.util.FhirTerser;
import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.r4.model.Address;
import org.hl7.fhir.r4.model.BooleanType;
import org.hl7.fhir.r4.model.DateType;
import org.hl7.fhir.r4.model.Enumerations;
import org.hl7.fhir.r4.model.Identifier;
import org.hl7.fhir.r4.model.Patient;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.Collections;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
class PrimitiveTypeComparingPredicateTest {
private static FhirContext myFhirContext;
private FhirTerser myTerser;
private IBase myPositiveTest1;
private IBase myPositiveTest2;
private IBase myPositiveTest3;
private IBase myNegativeTest;
private PrimitiveTypeComparingPredicate cut = new PrimitiveTypeComparingPredicate();
@BeforeAll
public static void initContext() {
myFhirContext = FhirContext.forR4();
}
@BeforeEach
public void init() {
myTerser = myFhirContext.newTerser();
myPositiveTest1 = newPatient();
myPositiveTest2 = newPatient();
myPositiveTest3 = newPatient();
Patient patient = newPatient();
patient.setActive(false);
patient.setMultipleBirth(new BooleanType(false));
myNegativeTest = patient;
}
private Patient newPatient() {
Patient patient;
patient = new Patient();
patient.setActive(true);
patient.setGender(Enumerations.AdministrativeGender.FEMALE);
patient.setBirthDateElement(new DateType("1901-01-01"));
Address address = new Address();
address.addLine("Somwhere");
address.setCity("Toronto");
address.setCountry("Canada");
patient.setAddress(Collections.singletonList(address));
return patient;
}
@Test
public void testNegativeMatchOnTheSameType() {
assertFalse(cut.test(myPositiveTest1, myNegativeTest));
assertFalse(cut.test(myNegativeTest, myPositiveTest1));
}
@Test
public void testNegativeMatchOnDifferentTypes() {
Patient patient = newPatient();
Identifier identifier = patient.addIdentifier();
identifier.setValue("TEST_VALUE");
assertFalse(cut.test(myNegativeTest, identifier));
}
@Test
public void testSymmetry() {
assertTrue(cut.test(myPositiveTest1, myPositiveTest2));
assertTrue(cut.test(myPositiveTest2, myPositiveTest1));
}
@Test
public void testReflexivity() {
assertTrue(cut.test(myPositiveTest1, myPositiveTest1));
}
@Test
public void testTransitivity() {
assertTrue(cut.test(myPositiveTest1, myPositiveTest2));
assertTrue(cut.test(myPositiveTest2, myPositiveTest3));
assertTrue(cut.test(myPositiveTest1, myPositiveTest3));
}
}