Empi 55 deactivate merged (#1883)

This commit is contained in:
Ken Stevens 2020-06-03 13:12:01 -04:00 committed by GitHub
parent 86ef0ec0e2
commit 33753881e2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 358 additions and 254 deletions

View File

@ -243,7 +243,7 @@ The operation returns the updated `Person` resource. Note that this is the only
## Merge Persons
The `$empi-merge-persons` operation can be used to merge one Person resource with another. When doing this, you will need to decide which resource to delete and which one to keep. Data from the personToKeep will be given precedence over data in the personToDelete. This operation takes the following parameters:
The `$empi-merge-persons` operation can be used to merge one Person resource with another. When doing this, you will need to decide which resource to merge from and which one to merge to. In most cases, fields will be merged (e.g. names, identifiers, and links will be the union of two). However when there is a conflict (e.g. birthday), fields in the toPerson will take precedence over fields in the fromPerson. This operation takes the following parameters:
<table class="table table-striped table-condensed">
<thead>
@ -256,15 +256,15 @@ The `$empi-merge-persons` operation can be used to merge one Person resource wit
</thead>
<tbody>
<tr>
<td>personIdToDelete</td>
<td>fromPersonId</td>
<td>String</td>
<td>1..1</td>
<td>
The id of the Person resource to merge data from. This resource will be deleted after the merge.
The id of the Person resource to merge data from. "active" will be set to "false" on this resource after the merge.
</td>
</tr>
<tr>
<td>personIdToKeep</td>
<td>toPersonId</td>
<td>String</td>
<td>1..1</td>
<td>
@ -288,10 +288,10 @@ The following request body could be used:
{
"resourceType": "Parameters",
"parameter": [ {
"name": "personIdToDelete",
"name": "fromPersonId",
"valueString": "Person/123"
}, {
"name": "personIdToKeep",
"name": "toPersonId",
"valueString": "Patient/128"
} ]
}

View File

@ -34,6 +34,7 @@ import org.springframework.stereotype.Service;
@Service
public class EmpiSearchParameterLoader {
public static final String EMPI_PERSON_ASSURANCE_SEARCH_PARAMETER_ID = "person-assurance";
public static final String EMPI_PERSON_ACTIVE_SEARCH_PARAMETER_ID = "person-active";
@Autowired
public FhirContext myFhirContext;
@Autowired
@ -41,12 +42,15 @@ public class EmpiSearchParameterLoader {
synchronized public void daoUpdateEmpiSearchParameters() {
IBaseResource personAssurance;
IBaseResource personActive;
switch (myFhirContext.getVersion().getVersion()) {
case DSTU3:
personAssurance = buildEmpiSearchParameterDstu3();
personAssurance = buildAssuranceEmpiSearchParameterDstu3();
personActive = buildActiveEmpiSearchParameterDstu3();
break;
case R4:
personAssurance = buildEmpiSearchParameterR4();
personAssurance = buildAssuranceEmpiSearchParameterR4();
personActive = buildActiveEmpiSearchParameterR4();
break;
default:
throw new ConfigurationException("EMPI not supported for FHIR version " + myFhirContext.getVersion().getVersion());
@ -54,9 +58,10 @@ public class EmpiSearchParameterLoader {
IFhirResourceDao<IBaseResource> searchParameterDao = myDaoRegistry.getResourceDao("SearchParameter");
searchParameterDao.update(personAssurance);
searchParameterDao.update(personActive);
}
private org.hl7.fhir.dstu3.model.SearchParameter buildEmpiSearchParameterDstu3() {
private org.hl7.fhir.dstu3.model.SearchParameter buildAssuranceEmpiSearchParameterDstu3() {
org.hl7.fhir.dstu3.model.SearchParameter retval = new org.hl7.fhir.dstu3.model.SearchParameter();
retval.setId(EMPI_PERSON_ASSURANCE_SEARCH_PARAMETER_ID);
retval.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE);
@ -69,7 +74,7 @@ public class EmpiSearchParameterLoader {
return retval;
}
private SearchParameter buildEmpiSearchParameterR4() {
private SearchParameter buildAssuranceEmpiSearchParameterR4() {
SearchParameter retval = new SearchParameter();
retval.setId(EMPI_PERSON_ASSURANCE_SEARCH_PARAMETER_ID);
retval.setStatus(Enumerations.PublicationStatus.ACTIVE);
@ -81,4 +86,30 @@ public class EmpiSearchParameterLoader {
retval.setExpression("Person.link.assurance");
return retval;
}
private org.hl7.fhir.dstu3.model.SearchParameter buildActiveEmpiSearchParameterDstu3() {
org.hl7.fhir.dstu3.model.SearchParameter retval = new org.hl7.fhir.dstu3.model.SearchParameter();
retval.setId(EMPI_PERSON_ACTIVE_SEARCH_PARAMETER_ID);
retval.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE);
retval.getMeta().addTag().setSystem(EmpiConstants.SYSTEM_EMPI_MANAGED).setCode(EmpiConstants.CODE_HAPI_EMPI_MANAGED);
retval.setCode("active");
retval.addBase("Person");
retval.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN);
retval.setDescription("The active status of a Person");
retval.setExpression("Person.active");
return retval;
}
private SearchParameter buildActiveEmpiSearchParameterR4() {
SearchParameter retval = new SearchParameter();
retval.setId(EMPI_PERSON_ACTIVE_SEARCH_PARAMETER_ID);
retval.setStatus(Enumerations.PublicationStatus.ACTIVE);
retval.getMeta().addTag().setSystem(EmpiConstants.SYSTEM_EMPI_MANAGED).setCode(EmpiConstants.CODE_HAPI_EMPI_MANAGED);
retval.setCode("active");
retval.addBase("Person");
retval.setType(Enumerations.SearchParamType.TOKEN);
retval.setDescription("The active status of a Person");
retval.setExpression("Person.active");
return retval;
}
}

View File

@ -26,6 +26,7 @@ import ca.uhn.fhir.empi.api.IEmpiSettings;
import ca.uhn.fhir.empi.model.CanonicalEID;
import ca.uhn.fhir.empi.util.EIDHelper;
import ca.uhn.fhir.empi.util.EmpiUtil;
import ca.uhn.fhir.empi.util.PersonHelper;
import ca.uhn.fhir.interceptor.api.Hook;
import ca.uhn.fhir.interceptor.api.Pointcut;
import ca.uhn.fhir.jpa.dao.EmpiLinkDaoSvc;
@ -56,6 +57,8 @@ public class EmpiStorageInterceptor implements IEmpiStorageInterceptor {
private EIDHelper myEIDHelper;
@Autowired
private IEmpiSettings myEmpiSettings;
@Autowired
private PersonHelper myPersonHelper;
@Hook(Pointcut.STORAGE_PRESTORAGE_RESOURCE_CREATED)
public void blockManualPersonManipulationOnCreate(IBaseResource theBaseResource, RequestDetails theRequestDetails, ServletRequestDetails theServletRequestDetails) {
@ -80,6 +83,12 @@ public class EmpiStorageInterceptor implements IEmpiStorageInterceptor {
forbidIfHasMultipleEids(theNewResource);
}
if (EmpiUtil.isEmpiManagedPerson(myFhirContext, theNewResource) &&
myPersonHelper.isDeactivated(theNewResource)) {
ourLog.debug("Deleting empi links to deactivated Person {}", theNewResource.getIdElement().toUnqualifiedVersionless());
myEmpiLinkDaoSvc.deleteWithAnyReferenceTo(theNewResource);
}
if (isInternalRequest(theRequestDetails)) {
return;
}

View File

@ -99,7 +99,6 @@ public class EmpiLinkSvcImpl implements IEmpiLinkSvc {
.map(this::personLinkFromEmpiLink)
.collect(Collectors.toList());
myPersonHelper.setLinks(thePersonResource, newLinks);
myEmpiResourceDaoSvc.updatePerson(thePersonResource);
if (newLinks.size() > origLinkCount) {
log(theEmpiTransactionContext, thePersonResource.getIdElement().toVersionless() + " links increased from " + origLinkCount + " to " + newLinks.size());
} else if (newLinks.size() < origLinkCount) {

View File

@ -51,6 +51,8 @@ public class EmpiLinkUpdaterSvcImpl implements IEmpiLinkUpdaterSvc {
EmpiLinkDaoSvc myEmpiLinkDaoSvc;
@Autowired
IEmpiLinkSvc myEmpiLinkSvc;
@Autowired
EmpiResourceDaoSvc myEmpiResourceDaoSvc;
@Transactional
@Override
@ -95,6 +97,7 @@ public class EmpiLinkUpdaterSvcImpl implements IEmpiLinkUpdaterSvc {
empiLink.setLinkSource(EmpiLinkSourceEnum.MANUAL);
myEmpiLinkDaoSvc.save(empiLink);
myEmpiLinkSvc.syncEmpiLinksToPersonLinks(thePerson, theEmpiContext);
myEmpiResourceDaoSvc.updatePerson(thePerson);
return thePerson;
}
}

View File

@ -55,28 +55,30 @@ public class EmpiPersonMergerSvcImpl implements IEmpiPersonMergerSvc {
@Override
@Transactional
public IAnyResource mergePersons(IAnyResource thePersonToDelete, IAnyResource thePersonToKeep, EmpiTransactionContext theEmpiTransactionContext) {
public IAnyResource mergePersons(IAnyResource theFromPerson, IAnyResource theToPerson, EmpiTransactionContext theEmpiTransactionContext) {
// TODO EMPI replace this with a post containing the manually merged fields
myPersonHelper.mergePersonFields(thePersonToDelete, thePersonToKeep);
mergeLinks(thePersonToDelete, thePersonToKeep, theEmpiTransactionContext);
myEmpiResourceDaoSvc.updatePerson(thePersonToKeep);
log(theEmpiTransactionContext, "Merged " + thePersonToDelete.getIdElement().toVersionless() + " into " + thePersonToKeep.getIdElement().toVersionless());
myEmpiResourceDaoSvc.deletePerson(thePersonToDelete);
log(theEmpiTransactionContext, "Deleted " + thePersonToDelete.getIdElement().toVersionless());
return thePersonToKeep;
myPersonHelper.mergePersonFields(theFromPerson, theToPerson);
mergeLinks(theFromPerson, theToPerson, theEmpiTransactionContext);
myEmpiResourceDaoSvc.updatePerson(theToPerson);
log(theEmpiTransactionContext, "Merged " + theFromPerson.getIdElement().toVersionless() + " into " + theToPerson.getIdElement().toVersionless());
myPersonHelper.deactivatePerson(theFromPerson);
myEmpiResourceDaoSvc.updatePerson(theFromPerson);
log(theEmpiTransactionContext, "Deactivated " + theFromPerson.getIdElement().toVersionless());
return theToPerson;
}
private void mergeLinks(IAnyResource thePersonToDelete, IAnyResource thePersonToKeep, EmpiTransactionContext theEmpiTransactionContext) {
long personToKeepPid = myIdHelperService.getPidOrThrowException(thePersonToKeep);
List<EmpiLink> incomingLinks = myEmpiLinkDaoSvc.findEmpiLinksByPersonId(thePersonToDelete);
List<EmpiLink> origLinks = myEmpiLinkDaoSvc.findEmpiLinksByPersonId(thePersonToKeep);
private void mergeLinks(IAnyResource theFromPerson, IAnyResource theToPerson, EmpiTransactionContext theEmpiTransactionContext) {
long toPersonPid = myIdHelperService.getPidOrThrowException(theToPerson);
List<EmpiLink> incomingLinks = myEmpiLinkDaoSvc.findEmpiLinksByPersonId(theFromPerson);
List<EmpiLink> origLinks = myEmpiLinkDaoSvc.findEmpiLinksByPersonId(theToPerson);
// For each incomingLink, either ignore it, move it, or replace the original one
for (EmpiLink incomingLink : incomingLinks) {
Optional<EmpiLink> optionalOrigLink = findLinkWithMatchingTarget(origLinks, incomingLink);
if (optionalOrigLink.isPresent()) {
// The original links already contain this target, so move it over to the personToKeep
// The original links already contain this target, so move it over to the toPerson
EmpiLink origLink = optionalOrigLink.get();
if (incomingLink.isManual()) {
switch (origLink.getLinkSource()) {
@ -94,14 +96,14 @@ public class EmpiPersonMergerSvcImpl implements IEmpiPersonMergerSvc {
continue;
}
}
// The original links didn't contain this target, so move it over to the personToKeep
incomingLink.setPersonPid(personToKeepPid);
// The original links didn't contain this target, so move it over to the toPerson
incomingLink.setPersonPid(toPersonPid);
ourLog.trace("Saving link {}", incomingLink);
myEmpiLinkDaoSvc.save(incomingLink);
}
myEmpiLinkSvc.syncEmpiLinksToPersonLinks(thePersonToDelete, theEmpiTransactionContext);
myEmpiLinkSvc.syncEmpiLinksToPersonLinks(thePersonToKeep, theEmpiTransactionContext);
myEmpiLinkSvc.syncEmpiLinksToPersonLinks(theFromPerson, theEmpiTransactionContext);
myEmpiLinkSvc.syncEmpiLinksToPersonLinks(theToPerson, theEmpiTransactionContext);
}
private Optional<EmpiLink> findLinkWithMatchingTarget(List<EmpiLink> theEmpiLinks, EmpiLink theLinkWithTargetToMatch) {

View File

@ -86,7 +86,4 @@ public class EmpiResourceDaoSvc {
}
}
public void deletePerson(IAnyResource thePersonToDelete) {
myPersonDao.delete(thePersonToDelete.getIdElement());
}
}

View File

@ -14,6 +14,7 @@ import ca.uhn.fhir.jpa.dao.EmpiLinkDaoSvc;
import ca.uhn.fhir.jpa.dao.data.IEmpiLinkDao;
import ca.uhn.fhir.jpa.dao.index.IdHelperService;
import ca.uhn.fhir.jpa.empi.config.EmpiConsumerConfig;
import ca.uhn.fhir.jpa.empi.config.EmpiSearchParameterLoader;
import ca.uhn.fhir.jpa.empi.config.EmpiSubmitterConfig;
import ca.uhn.fhir.jpa.empi.config.TestEmpiConfigR4;
import ca.uhn.fhir.jpa.empi.matcher.IsLinkedTo;
@ -25,11 +26,13 @@ import ca.uhn.fhir.jpa.empi.matcher.IsSamePersonAs;
import ca.uhn.fhir.jpa.empi.svc.EmpiMatchLinkSvc;
import ca.uhn.fhir.jpa.entity.EmpiLink;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.registry.SearchParamRegistryImpl;
import ca.uhn.fhir.jpa.subscription.match.config.SubscriptionProcessorConfig;
import ca.uhn.fhir.jpa.test.BaseJpaR4Test;
import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
import ca.uhn.fhir.rest.param.TokenParam;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import org.hamcrest.Matcher;
import org.hl7.fhir.instance.model.api.IAnyResource;
@ -39,7 +42,6 @@ import org.hl7.fhir.r4.model.DateType;
import org.hl7.fhir.r4.model.Patient;
import org.hl7.fhir.r4.model.Person;
import org.hl7.fhir.r4.model.Practitioner;
import org.jetbrains.annotations.NotNull;
import org.junit.After;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
@ -93,6 +95,10 @@ abstract public class BaseEmpiR4Test extends BaseJpaR4Test {
protected EmpiMatchLinkSvc myEmpiMatchLinkSvc;
@Autowired
protected EIDHelper myEIDHelper;
@Autowired
EmpiSearchParameterLoader myEmpiSearchParameterLoader;
@Autowired
SearchParamRegistryImpl mySearchParamRegistry;
protected ServletRequestDetails myRequestDetails = new ServletRequestDetails(null);
@ -126,6 +132,7 @@ abstract public class BaseEmpiR4Test extends BaseJpaR4Test {
protected Person createPerson(Person thePerson, boolean theEmpiManaged) {
if (theEmpiManaged) {
thePerson.getMeta().addTag().setSystem(EmpiConstants.SYSTEM_EMPI_MANAGED).setCode(EmpiConstants.CODE_HAPI_EMPI_MANAGED);
thePerson.setActive(true);
}
DaoMethodOutcome outcome = myPersonDao.create(thePerson);
Person person = (Person) outcome.getResource();
@ -311,16 +318,29 @@ abstract public class BaseEmpiR4Test extends BaseJpaR4Test {
return IsMatchedToAPerson.matchedToAPerson(myIdHelperService, myEmpiLinkDaoSvc);
}
protected Person getOnlyPerson() {
List<IBaseResource> resources = getAllPersons();
protected Person getOnlyActivePerson() {
List<IBaseResource> resources = getAllActivePersons();
assertEquals(1, resources.size());
return (Person) resources.get(0);
}
@NotNull
@Nonnull
protected List<IBaseResource> getAllActivePersons() {
return getAllPersons(true);
}
@Nonnull
protected List<IBaseResource> getAllPersons() {
return getAllPersons(false);
}
@Nonnull
private List<IBaseResource> getAllPersons(boolean theOnlyActive) {
SearchParameterMap map = new SearchParameterMap();
map.setLoadSynchronous(true);
if (theOnlyActive) {
map.add("active", new TokenParam().setValue("true"));
}
IBundleProvider bundle = myPersonDao.search(map);
return bundle.getResources(0, 999);
}
@ -337,4 +357,9 @@ abstract public class BaseEmpiR4Test extends BaseJpaR4Test {
empiLink.setTargetPid(myIdHelperService.getPidOrNull(patient));
return empiLink;
}
protected void loadEmpiSearchParameters() {
myEmpiSearchParameterLoader.daoUpdateEmpiSearchParameters();
mySearchParamRegistry.forceRefresh();
}
}

View File

@ -20,6 +20,7 @@ import org.hl7.fhir.r4.model.Organization;
import org.hl7.fhir.r4.model.Patient;
import org.hl7.fhir.r4.model.Person;
import org.hl7.fhir.r4.model.Practitioner;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.slf4j.Logger;
@ -54,6 +55,11 @@ public class EmpiStorageInterceptorIT extends BaseEmpiR4Test {
@Autowired
private IdHelperService myIdHelperService;
@Before
public void before() {
super.loadEmpiSearchParameters();
}
@Test
public void testCreatePatient() throws InterruptedException {
myEmpiHelper.createWithLatch(new Patient());
@ -76,7 +82,7 @@ public class EmpiStorageInterceptorIT extends BaseEmpiR4Test {
public void testDeletePersonDeletesLinks() throws InterruptedException {
myEmpiHelper.createWithLatch(new Patient());
assertLinkCount(1);
Person person = getOnlyPerson();
Person person = getOnlyActivePerson();
myPersonDao.delete(person.getIdElement());
assertLinkCount(0);
}

View File

@ -16,19 +16,20 @@ import static org.junit.Assert.fail;
public class EmpiProviderMergePersonsR4Test extends BaseProviderR4Test {
private Person myDeletePerson;
private StringType myDeletePersonId;
private Person myKeepPerson;
private StringType myKeepPersonId;
private Person myFromPerson;
private StringType myFromPersonId;
private Person myToPerson;
private StringType myToPersonId;
@Before
public void before() {
super.before();
super.loadEmpiSearchParameters();
myDeletePerson = createPerson();
myDeletePersonId = new StringType(myDeletePerson.getIdElement().toUnqualifiedVersionless().getValue());
myKeepPerson = createPerson();
myKeepPersonId = new StringType(myKeepPerson.getIdElement().toUnqualifiedVersionless().getValue());
myFromPerson = createPerson();
myFromPersonId = new StringType(myFromPerson.getIdElement().toUnqualifiedVersionless().getValue());
myToPerson = createPerson();
myToPersonId = new StringType(myToPerson.getIdElement().toUnqualifiedVersionless().getValue());
}
@Test
@ -45,18 +46,19 @@ public class EmpiProviderMergePersonsR4Test extends BaseProviderR4Test {
@Test
public void testMerge() {
Person mergedPerson = myEmpiProviderR4.mergePersons(myDeletePersonId, myKeepPersonId, myRequestDetails);
assertEquals(myKeepPerson.getIdElement(), mergedPerson.getIdElement());
Person mergedPerson = myEmpiProviderR4.mergePersons(myFromPersonId, myToPersonId, myRequestDetails);
assertEquals(myToPerson.getIdElement(), mergedPerson.getIdElement());
assertThat(mergedPerson, is(samePersonAs(mergedPerson)));
assertEquals(1, getAllPersons().size());
assertEquals(2, getAllPersons().size());
assertEquals(1, getAllActivePersons().size());
}
@Test
public void testUnmanagedMerge() {
StringType deletePersonId = new StringType(createUnmanagedPerson().getIdElement().toVersionless().getValue());
StringType keepPersonId = new StringType(createUnmanagedPerson().getIdElement().toVersionless().getValue());
StringType fromPersonId = new StringType(createUnmanagedPerson().getIdElement().toVersionless().getValue());
StringType toPersonId = new StringType(createUnmanagedPerson().getIdElement().toVersionless().getValue());
try {
myEmpiProviderR4.mergePersons(deletePersonId, keepPersonId, myRequestDetails);
myEmpiProviderR4.mergePersons(fromPersonId, toPersonId, myRequestDetails);
fail();
} catch (InvalidRequestException e) {
assertEquals("Only EMPI managed resources can be merged. Empi managed resource have the HAPI-EMPI tag.", e.getMessage());
@ -71,7 +73,7 @@ public class EmpiProviderMergePersonsR4Test extends BaseProviderR4Test {
myEmpiProviderR4.mergePersons(patientId, otherPatientId, myRequestDetails);
fail();
} catch (InvalidRequestException e) {
assertEquals("personIdToDelete must have form Person/<id> where <id> is the id of the person", e.getMessage());
assertEquals("fromPersonId must have form Person/<id> where <id> is the id of the person", e.getMessage());
}
}
@ -82,50 +84,50 @@ public class EmpiProviderMergePersonsR4Test extends BaseProviderR4Test {
myEmpiProviderR4.mergePersons(null, null, myRequestDetails);
fail();
} catch (InvalidRequestException e) {
assertEquals("personIdToDelete cannot be null", e.getMessage());
assertEquals("fromPersonId cannot be null", e.getMessage());
}
try {
myEmpiProviderR4.mergePersons(null, myKeepPersonId, myRequestDetails);
myEmpiProviderR4.mergePersons(null, myToPersonId, myRequestDetails);
fail();
} catch (InvalidRequestException e) {
assertEquals("personIdToDelete cannot be null", e.getMessage());
assertEquals("fromPersonId cannot be null", e.getMessage());
}
try {
myEmpiProviderR4.mergePersons(myDeletePersonId, null, myRequestDetails);
myEmpiProviderR4.mergePersons(myFromPersonId, null, myRequestDetails);
fail();
} catch (InvalidRequestException e) {
assertEquals("personIdToKeep cannot be null", e.getMessage());
assertEquals("toPersonId cannot be null", e.getMessage());
}
}
@Test
public void testBadParams() {
try {
myEmpiProviderR4.mergePersons(new StringType("Patient/1"), new StringType("Patient/2"), myRequestDetails);
myEmpiProviderR4.mergePersons(new StringType("Patient/1"), new StringType("Patient/2"), myRequestDetails);
fail();
} catch (InvalidRequestException e) {
assertEquals("personIdToDelete must have form Person/<id> where <id> is the id of the person", e.getMessage());
assertEquals("fromPersonId must have form Person/<id> where <id> is the id of the person", e.getMessage());
}
try {
myEmpiProviderR4.mergePersons(myDeletePersonId, new StringType("Patient/2"), myRequestDetails);
myEmpiProviderR4.mergePersons(myFromPersonId, new StringType("Patient/2"), myRequestDetails);
fail();
} catch (InvalidRequestException e) {
assertEquals("personIdToKeep must have form Person/<id> where <id> is the id of the person", e.getMessage());
assertEquals("toPersonId must have form Person/<id> where <id> is the id of the person", e.getMessage());
}
try {
myEmpiProviderR4.mergePersons(new StringType("Person/1"), new StringType("Person/1"), myRequestDetails);
fail();
} catch (InvalidRequestException e) {
assertEquals("personIdToDelete must be different from personToKeep", e.getMessage());
assertEquals("fromPersonId must be different from toPersonId", e.getMessage());
}
try {
myEmpiProviderR4.mergePersons(new StringType("Person/abc"), myKeepPersonId, myRequestDetails);
myEmpiProviderR4.mergePersons(new StringType("Person/abc"), myToPersonId, myRequestDetails);
fail();
} catch (ResourceNotFoundException e) {
assertEquals("Resource Person/abc is not known", e.getMessage());
}
try {
myEmpiProviderR4.mergePersons(myDeletePersonId, new StringType("Person/abc"), myRequestDetails);
myEmpiProviderR4.mergePersons(myFromPersonId, new StringType("Person/abc"), myRequestDetails);
fail();
} catch (ResourceNotFoundException e) {
assertEquals("Resource Person/abc is not known", e.getMessage());

View File

@ -1,9 +1,7 @@
package ca.uhn.fhir.jpa.empi.searchparam;
import ca.uhn.fhir.jpa.empi.BaseEmpiR4Test;
import ca.uhn.fhir.jpa.empi.config.EmpiSearchParameterLoader;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.registry.SearchParamRegistryImpl;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.TokenParam;
import org.hl7.fhir.r4.model.Patient;
@ -12,7 +10,6 @@ import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
@ -22,15 +19,10 @@ import static org.junit.Assert.assertThat;
public class SearchParameterTest extends BaseEmpiR4Test {
private static final Logger ourLog = LoggerFactory.getLogger(SearchParameterTest.class);
@Autowired
EmpiSearchParameterLoader myEmpiSearchParameterLoader;
@Autowired
SearchParamRegistryImpl mySearchParamRegistry;
@Before
public void before() {
myEmpiSearchParameterLoader.daoUpdateEmpiSearchParameters();
mySearchParamRegistry.forceRefresh();
super.loadEmpiSearchParameters();
}
@Test

View File

@ -49,24 +49,24 @@ public class EmpiPersonMergerSvcTest extends BaseEmpiR4Test {
@Autowired
IInterceptorService myInterceptorService;
private Person myDeletePerson;
private Person myKeepPerson;
private IdType myDeletePersonId;
private IdType myKeepPersonId;
private Long myDeletePersonPid;
private Long myKeepPersonPid;
private Person myFromPerson;
private Person myToPerson;
private Long myFromPersonPid;
private Long myToPersonPid;
private Patient myTargetPatient1;
private Patient myTargetPatient2;
private Patient myTargetPatient3;
@Before
public void before() {
myDeletePerson = createPerson();
myDeletePersonId = myDeletePerson.getIdElement().toUnqualifiedVersionless();
myDeletePersonPid = myIdHelperService.getPidOrThrowException(myDeletePersonId);
myKeepPerson = createPerson();
myKeepPersonId = myKeepPerson.getIdElement().toUnqualifiedVersionless();
myKeepPersonPid = myIdHelperService.getPidOrThrowException(myKeepPersonId);
super.loadEmpiSearchParameters();
myFromPerson = createPerson();
IdType fromPersonId = myFromPerson.getIdElement().toUnqualifiedVersionless();
myFromPersonPid = myIdHelperService.getPidOrThrowException(fromPersonId);
myToPerson = createPerson();
IdType toPersonId = myToPerson.getIdElement().toUnqualifiedVersionless();
myToPersonPid = myIdHelperService.getPidOrThrowException(toPersonId);
myTargetPatient1 = createPatient();
@ -87,15 +87,17 @@ public class EmpiPersonMergerSvcTest extends BaseEmpiR4Test {
@Test
public void emptyMerge() {
assertEquals(2, getAllPersons().size());
assertEquals(2, getAllActivePersons().size());
Person mergedPerson = mergePersons();
assertEquals(myKeepPerson.getIdElement(), mergedPerson.getIdElement());
assertEquals(myToPerson.getIdElement(), mergedPerson.getIdElement());
assertThat(mergedPerson, is(samePersonAs(mergedPerson)));
assertEquals(1, getAllPersons().size());
assertEquals(2, getAllPersons().size());
assertEquals(1, getAllActivePersons().size());
}
private Person mergePersons() {
return (Person) myEmpiPersonMergerSvc.mergePersons(myDeletePerson, myKeepPerson, createEmpiContext());
return (Person) myEmpiPersonMergerSvc.mergePersons(myFromPerson, myToPerson, createEmpiContext());
}
private EmpiTransactionContext createEmpiContext() {
@ -104,7 +106,7 @@ public class EmpiPersonMergerSvcTest extends BaseEmpiR4Test {
@Test
public void mergeRemovesPossibleDuplicatesLink() {
EmpiLink empiLink = new EmpiLink().setPersonPid(myKeepPersonPid).setTargetPid(myDeletePersonPid).setMatchResult(EmpiMatchResultEnum.POSSIBLE_DUPLICATE).setLinkSource(EmpiLinkSourceEnum.AUTO);
EmpiLink empiLink = new EmpiLink().setPersonPid(myToPersonPid).setTargetPid(myFromPersonPid).setMatchResult(EmpiMatchResultEnum.POSSIBLE_DUPLICATE).setLinkSource(EmpiLinkSourceEnum.AUTO);
myEmpiLinkDaoSvc.save(empiLink);
assertEquals(1, myEmpiLinkDao.count());
mergePersons();
@ -112,8 +114,8 @@ public class EmpiPersonMergerSvcTest extends BaseEmpiR4Test {
}
@Test
public void fullDeleteEmptyKeep() {
populatePerson(myDeletePerson);
public void fullFromEmptyTo() {
populatePerson(myFromPerson);
Person mergedPerson = mergePersons();
HumanName returnedName = mergedPerson.getNameFirstRep();
@ -123,9 +125,9 @@ public class EmpiPersonMergerSvcTest extends BaseEmpiR4Test {
}
@Test
public void emptyDeleteFullKeep() {
myDeletePerson.getName().add(new HumanName().addGiven(BAD_GIVEN_NAME));
populatePerson(myKeepPerson);
public void emptyFromFullTo() {
myFromPerson.getName().add(new HumanName().addGiven(BAD_GIVEN_NAME));
populatePerson(myToPerson);
Person mergedPerson = mergePersons();
HumanName returnedName = mergedPerson.getNameFirstRep();
@ -135,83 +137,83 @@ public class EmpiPersonMergerSvcTest extends BaseEmpiR4Test {
}
@Test
public void deleteLinkKeepNoLink() {
createEmpiLink(myDeletePerson, myTargetPatient1);
public void fromLinkToNoLink() {
createEmpiLink(myFromPerson, myTargetPatient1);
mergePersons();
List<EmpiLink> links = myEmpiLinkDaoSvc.findEmpiLinksByPersonId(myKeepPerson);
List<EmpiLink> links = myEmpiLinkDaoSvc.findEmpiLinksByPersonId(myToPerson);
assertEquals(1, links.size());
assertThat(myKeepPerson, is(possibleLinkedTo(myTargetPatient1)));
assertEquals(1, myKeepPerson.getLink().size());
assertThat(myToPerson, is(possibleLinkedTo(myTargetPatient1)));
assertEquals(1, myToPerson.getLink().size());
}
@Test
public void deleteNoLinkKeepLink() {
createEmpiLink(myKeepPerson, myTargetPatient1);
public void fromNoLinkToLink() {
createEmpiLink(myToPerson, myTargetPatient1);
mergePersons();
List<EmpiLink> links = myEmpiLinkDaoSvc.findEmpiLinksByPersonId(myKeepPerson);
List<EmpiLink> links = myEmpiLinkDaoSvc.findEmpiLinksByPersonId(myToPerson);
assertEquals(1, links.size());
assertThat(myKeepPerson, is(possibleLinkedTo(myTargetPatient1)));
assertEquals(1, myKeepPerson.getLink().size());
assertThat(myToPerson, is(possibleLinkedTo(myTargetPatient1)));
assertEquals(1, myToPerson.getLink().size());
}
@Test
public void deleteManualLinkOverridesAutoKeepLink() {
EmpiLink deleteLink = createEmpiLink(myDeletePerson, myTargetPatient1);
deleteLink.setLinkSource(EmpiLinkSourceEnum.MANUAL);
deleteLink.setMatchResult(EmpiMatchResultEnum.MATCH);
myEmpiLinkDaoSvc.save(deleteLink);
public void fromManualLinkOverridesAutoToLink() {
EmpiLink fromLink = createEmpiLink(myFromPerson, myTargetPatient1);
fromLink.setLinkSource(EmpiLinkSourceEnum.MANUAL);
fromLink.setMatchResult(EmpiMatchResultEnum.MATCH);
myEmpiLinkDaoSvc.save(fromLink);
createEmpiLink(myKeepPerson, myTargetPatient1);
createEmpiLink(myToPerson, myTargetPatient1);
mergePersons();
List<EmpiLink> links = myEmpiLinkDaoSvc.findEmpiLinksByPersonId(myKeepPerson);
List<EmpiLink> links = myEmpiLinkDaoSvc.findEmpiLinksByPersonId(myToPerson);
assertEquals(1, links.size());
assertEquals(EmpiLinkSourceEnum.MANUAL, links.get(0).getLinkSource());
}
@Test
public void deleteManualNoMatchLinkOverridesAutoKeepLink() {
EmpiLink deleteLink = createEmpiLink(myDeletePerson, myTargetPatient1);
deleteLink.setLinkSource(EmpiLinkSourceEnum.MANUAL);
deleteLink.setMatchResult(EmpiMatchResultEnum.NO_MATCH);
myEmpiLinkDaoSvc.save(deleteLink);
public void fromManualNoMatchLinkOverridesAutoToLink() {
EmpiLink fromLink = createEmpiLink(myFromPerson, myTargetPatient1);
fromLink.setLinkSource(EmpiLinkSourceEnum.MANUAL);
fromLink.setMatchResult(EmpiMatchResultEnum.NO_MATCH);
myEmpiLinkDaoSvc.save(fromLink);
createEmpiLink(myKeepPerson, myTargetPatient1);
createEmpiLink(myToPerson, myTargetPatient1);
mergePersons();
List<EmpiLink> links = myEmpiLinkDaoSvc.findEmpiLinksByPersonId(myKeepPerson);
List<EmpiLink> links = myEmpiLinkDaoSvc.findEmpiLinksByPersonId(myToPerson);
assertEquals(1, links.size());
assertEquals(EmpiLinkSourceEnum.MANUAL, links.get(0).getLinkSource());
}
@Test
public void deleteManualAutoMatchLinkNoOverridesManualKeepLink() {
createEmpiLink(myDeletePerson, myTargetPatient1);
public void fromManualAutoMatchLinkNoOverridesManualToLink() {
createEmpiLink(myFromPerson, myTargetPatient1);
EmpiLink keepLink = createEmpiLink(myKeepPerson, myTargetPatient1);
keepLink.setLinkSource(EmpiLinkSourceEnum.MANUAL);
keepLink.setMatchResult(EmpiMatchResultEnum.NO_MATCH);
myEmpiLinkDaoSvc.save(keepLink);
EmpiLink toLink = createEmpiLink(myToPerson, myTargetPatient1);
toLink.setLinkSource(EmpiLinkSourceEnum.MANUAL);
toLink.setMatchResult(EmpiMatchResultEnum.NO_MATCH);
myEmpiLinkDaoSvc.save(toLink);
mergePersons();
List<EmpiLink> links = myEmpiLinkDaoSvc.findEmpiLinksByPersonId(myKeepPerson);
List<EmpiLink> links = myEmpiLinkDaoSvc.findEmpiLinksByPersonId(myToPerson);
assertEquals(1, links.size());
assertEquals(EmpiLinkSourceEnum.MANUAL, links.get(0).getLinkSource());
}
@Test
public void deleteNoMatchMergeToManualMatchIsError() {
EmpiLink deleteLink = createEmpiLink(myDeletePerson, myTargetPatient1);
deleteLink.setLinkSource(EmpiLinkSourceEnum.MANUAL);
deleteLink.setMatchResult(EmpiMatchResultEnum.NO_MATCH);
myEmpiLinkDaoSvc.save(deleteLink);
public void fromNoMatchMergeToManualMatchIsError() {
EmpiLink fromLink = createEmpiLink(myFromPerson, myTargetPatient1);
fromLink.setLinkSource(EmpiLinkSourceEnum.MANUAL);
fromLink.setMatchResult(EmpiMatchResultEnum.NO_MATCH);
myEmpiLinkDaoSvc.save(fromLink);
EmpiLink keepLink = createEmpiLink(myKeepPerson, myTargetPatient1);
keepLink.setLinkSource(EmpiLinkSourceEnum.MANUAL);
keepLink.setMatchResult(EmpiMatchResultEnum.MATCH);
myEmpiLinkDaoSvc.save(keepLink);
EmpiLink toLink = createEmpiLink(myToPerson, myTargetPatient1);
toLink.setLinkSource(EmpiLinkSourceEnum.MANUAL);
toLink.setMatchResult(EmpiMatchResultEnum.MATCH);
myEmpiLinkDaoSvc.save(toLink);
try {
mergePersons();
@ -222,16 +224,16 @@ public class EmpiPersonMergerSvcTest extends BaseEmpiR4Test {
}
@Test
public void deleteMatchMergeToManualNoMatchIsError() {
EmpiLink deleteLink = createEmpiLink(myDeletePerson, myTargetPatient1);
deleteLink.setLinkSource(EmpiLinkSourceEnum.MANUAL);
deleteLink.setMatchResult(EmpiMatchResultEnum.MATCH);
myEmpiLinkDaoSvc.save(deleteLink);
public void fromMatchMergeToManualNoMatchIsError() {
EmpiLink fromLink = createEmpiLink(myFromPerson, myTargetPatient1);
fromLink.setLinkSource(EmpiLinkSourceEnum.MANUAL);
fromLink.setMatchResult(EmpiMatchResultEnum.MATCH);
myEmpiLinkDaoSvc.save(fromLink);
EmpiLink keepLink = createEmpiLink(myKeepPerson, myTargetPatient1);
keepLink.setLinkSource(EmpiLinkSourceEnum.MANUAL);
keepLink.setMatchResult(EmpiMatchResultEnum.NO_MATCH);
myEmpiLinkDaoSvc.save(keepLink);
EmpiLink toLink = createEmpiLink(myToPerson, myTargetPatient1);
toLink.setLinkSource(EmpiLinkSourceEnum.MANUAL);
toLink.setMatchResult(EmpiMatchResultEnum.NO_MATCH);
myEmpiLinkDaoSvc.save(toLink);
try {
mergePersons();
@ -242,127 +244,127 @@ public class EmpiPersonMergerSvcTest extends BaseEmpiR4Test {
}
@Test
public void deleteNoMatchMergeToManualMatchDifferentPatientIsOk() {
EmpiLink deleteLink = createEmpiLink(myDeletePerson, myTargetPatient1);
deleteLink.setLinkSource(EmpiLinkSourceEnum.MANUAL);
deleteLink.setMatchResult(EmpiMatchResultEnum.NO_MATCH);
myEmpiLinkDaoSvc.save(deleteLink);
public void fromNoMatchMergeToManualMatchDifferentPatientIsOk() {
EmpiLink fromLink = createEmpiLink(myFromPerson, myTargetPatient1);
fromLink.setLinkSource(EmpiLinkSourceEnum.MANUAL);
fromLink.setMatchResult(EmpiMatchResultEnum.NO_MATCH);
myEmpiLinkDaoSvc.save(fromLink);
EmpiLink keepLink = createEmpiLink(myKeepPerson, myTargetPatient2);
keepLink.setLinkSource(EmpiLinkSourceEnum.MANUAL);
keepLink.setMatchResult(EmpiMatchResultEnum.MATCH);
myEmpiLinkDaoSvc.save(keepLink);
EmpiLink toLink = createEmpiLink(myToPerson, myTargetPatient2);
toLink.setLinkSource(EmpiLinkSourceEnum.MANUAL);
toLink.setMatchResult(EmpiMatchResultEnum.MATCH);
myEmpiLinkDaoSvc.save(toLink);
mergePersons();
assertEquals(1, myKeepPerson.getLink().size());
assertEquals(1, myToPerson.getLink().size());
assertEquals(2, myEmpiLinkDao.count());
}
@Test
public void delete123Keep1() {
createEmpiLink(myDeletePerson, myTargetPatient1);
createEmpiLink(myDeletePerson, myTargetPatient2);
createEmpiLink(myDeletePerson, myTargetPatient3);
createEmpiLink(myKeepPerson, myTargetPatient1);
public void from123To1() {
createEmpiLink(myFromPerson, myTargetPatient1);
createEmpiLink(myFromPerson, myTargetPatient2);
createEmpiLink(myFromPerson, myTargetPatient3);
createEmpiLink(myToPerson, myTargetPatient1);
mergePersons();
myEmpiLinkHelper.logEmpiLinks();
assertThat(myKeepPerson, is(possibleLinkedTo(myTargetPatient1, myTargetPatient2, myTargetPatient3)));
assertEquals(3, myKeepPerson.getLink().size());
assertThat(myToPerson, is(possibleLinkedTo(myTargetPatient1, myTargetPatient2, myTargetPatient3)));
assertEquals(3, myToPerson.getLink().size());
}
@Test
public void delete1Keep123() {
createEmpiLink(myDeletePerson, myTargetPatient1);
createEmpiLink(myKeepPerson, myTargetPatient1);
createEmpiLink(myKeepPerson, myTargetPatient2);
createEmpiLink(myKeepPerson, myTargetPatient3);
public void from1To123() {
createEmpiLink(myFromPerson, myTargetPatient1);
createEmpiLink(myToPerson, myTargetPatient1);
createEmpiLink(myToPerson, myTargetPatient2);
createEmpiLink(myToPerson, myTargetPatient3);
mergePersons();
myEmpiLinkHelper.logEmpiLinks();
assertThat(myKeepPerson, is(possibleLinkedTo(myTargetPatient1, myTargetPatient2, myTargetPatient3)));
assertEquals(3, myKeepPerson.getLink().size());
assertThat(myToPerson, is(possibleLinkedTo(myTargetPatient1, myTargetPatient2, myTargetPatient3)));
assertEquals(3, myToPerson.getLink().size());
}
@Test
public void delete123Keep123() {
createEmpiLink(myDeletePerson, myTargetPatient1);
createEmpiLink(myDeletePerson, myTargetPatient2);
createEmpiLink(myDeletePerson, myTargetPatient3);
createEmpiLink(myKeepPerson, myTargetPatient1);
createEmpiLink(myKeepPerson, myTargetPatient2);
createEmpiLink(myKeepPerson, myTargetPatient3);
public void from123To123() {
createEmpiLink(myFromPerson, myTargetPatient1);
createEmpiLink(myFromPerson, myTargetPatient2);
createEmpiLink(myFromPerson, myTargetPatient3);
createEmpiLink(myToPerson, myTargetPatient1);
createEmpiLink(myToPerson, myTargetPatient2);
createEmpiLink(myToPerson, myTargetPatient3);
mergePersons();
myEmpiLinkHelper.logEmpiLinks();
assertThat(myKeepPerson, is(possibleLinkedTo(myTargetPatient1, myTargetPatient2, myTargetPatient3)));
assertEquals(3, myKeepPerson.getLink().size());
assertThat(myToPerson, is(possibleLinkedTo(myTargetPatient1, myTargetPatient2, myTargetPatient3)));
assertEquals(3, myToPerson.getLink().size());
}
@Test
public void delete12Keep23() {
createEmpiLink(myDeletePerson, myTargetPatient1);
createEmpiLink(myDeletePerson, myTargetPatient2);
createEmpiLink(myKeepPerson, myTargetPatient2);
createEmpiLink(myKeepPerson, myTargetPatient3);
public void from12To23() {
createEmpiLink(myFromPerson, myTargetPatient1);
createEmpiLink(myFromPerson, myTargetPatient2);
createEmpiLink(myToPerson, myTargetPatient2);
createEmpiLink(myToPerson, myTargetPatient3);
mergePersons();
myEmpiLinkHelper.logEmpiLinks();
assertThat(myKeepPerson, is(possibleLinkedTo(myTargetPatient1, myTargetPatient2, myTargetPatient3)));
assertEquals(3, myKeepPerson.getLink().size());
assertThat(myToPerson, is(possibleLinkedTo(myTargetPatient1, myTargetPatient2, myTargetPatient3)));
assertEquals(3, myToPerson.getLink().size());
}
@Test
public void testMergeNames() {
myDeletePerson.addName().addGiven("Jim");
myDeletePerson.getNameFirstRep().addGiven("George");
assertThat(myDeletePerson.getName(), hasSize(1));
assertThat(myDeletePerson.getName().get(0).getGiven(), hasSize(2));
myFromPerson.addName().addGiven("Jim");
myFromPerson.getNameFirstRep().addGiven("George");
assertThat(myFromPerson.getName(), hasSize(1));
assertThat(myFromPerson.getName().get(0).getGiven(), hasSize(2));
myKeepPerson.addName().addGiven("Jeff");
myKeepPerson.getNameFirstRep().addGiven("George");
assertThat(myKeepPerson.getName(), hasSize(1));
assertThat(myKeepPerson.getName().get(0).getGiven(), hasSize(2));
myToPerson.addName().addGiven("Jeff");
myToPerson.getNameFirstRep().addGiven("George");
assertThat(myToPerson.getName(), hasSize(1));
assertThat(myToPerson.getName().get(0).getGiven(), hasSize(2));
mergePersons();
assertThat(myKeepPerson.getName(), hasSize(2));
assertThat(myKeepPerson.getName().get(0).getGiven(), hasSize(2));
assertThat(myKeepPerson.getName().get(1).getGiven(), hasSize(2));
assertThat(myToPerson.getName(), hasSize(2));
assertThat(myToPerson.getName().get(0).getGiven(), hasSize(2));
assertThat(myToPerson.getName().get(1).getGiven(), hasSize(2));
}
@Test
public void testMergeNamesAllSame() {
myDeletePerson.addName().addGiven("Jim");
myDeletePerson.getNameFirstRep().addGiven("George");
assertThat(myDeletePerson.getName(), hasSize(1));
assertThat(myDeletePerson.getName().get(0).getGiven(), hasSize(2));
myFromPerson.addName().addGiven("Jim");
myFromPerson.getNameFirstRep().addGiven("George");
assertThat(myFromPerson.getName(), hasSize(1));
assertThat(myFromPerson.getName().get(0).getGiven(), hasSize(2));
myKeepPerson.addName().addGiven("Jim");
myKeepPerson.getNameFirstRep().addGiven("George");
assertThat(myKeepPerson.getName(), hasSize(1));
assertThat(myKeepPerson.getName().get(0).getGiven(), hasSize(2));
myToPerson.addName().addGiven("Jim");
myToPerson.getNameFirstRep().addGiven("George");
assertThat(myToPerson.getName(), hasSize(1));
assertThat(myToPerson.getName().get(0).getGiven(), hasSize(2));
mergePersons();
assertThat(myKeepPerson.getName(), hasSize(1));
assertThat(myKeepPerson.getName().get(0).getGiven(), hasSize(2));
assertThat(myToPerson.getName(), hasSize(1));
assertThat(myToPerson.getName().get(0).getGiven(), hasSize(2));
}
@Test
public void testMergeIdentities() {
myDeletePerson.addIdentifier().setValue("aaa");
myDeletePerson.addIdentifier().setValue("bbb");
assertThat(myDeletePerson.getIdentifier(), hasSize(2));
myFromPerson.addIdentifier().setValue("aaa");
myFromPerson.addIdentifier().setValue("bbb");
assertThat(myFromPerson.getIdentifier(), hasSize(2));
myKeepPerson.addIdentifier().setValue("aaa");
myKeepPerson.addIdentifier().setValue("ccc");
assertThat(myKeepPerson.getIdentifier(), hasSize(2));
myToPerson.addIdentifier().setValue("aaa");
myToPerson.addIdentifier().setValue("ccc");
assertThat(myToPerson.getIdentifier(), hasSize(2));
mergePersons();
assertThat(myKeepPerson.getIdentifier(), hasSize(3));
assertThat(myToPerson.getIdentifier(), hasSize(3));
}
private EmpiLink createEmpiLink(Person thePerson, Patient theTargetPatient) {

View File

@ -25,11 +25,11 @@ import org.hl7.fhir.instance.model.api.IAnyResource;
public interface IEmpiPersonMergerSvc {
/**
* Move all links from the thePersonToDelete to thePersonToKeep and then delete thePersonToDelete. Merge all Person
* fields, with fields in thePersonToKeep overriding fields in thePersonToDelete
* @param thePersonToDelete the person we are merging from
* @param thePersonToKeep the person we are merging to
* @return updated thePersonToKeep with the merged fields and links.
* Move all links from the theFromPerson to theToPerson and then set active=false on theFromPerson. Merge all Person
* fields.
* @param theFromPerson the person we are merging from
* @param theToPerson the person we are merging to
* @return updated theToPerson with the merged fields and links.
*/
IAnyResource mergePersons(IAnyResource thePersonToDelete, IAnyResource thePersonToKeep, EmpiTransactionContext theEmpiTransactionContext);
IAnyResource mergePersons(IAnyResource theFromPerson, IAnyResource theToPerson, EmpiTransactionContext theEmpiTransactionContext);
}

View File

@ -81,17 +81,17 @@ public abstract class BaseEmpiProvider {
return (IAnyResource) myResourceLoader.load(resourceClass, theResourceId);
}
protected void validateMergeParameters(IPrimitiveType<String> thePersonIdToDelete, IPrimitiveType<String> thePersonIdToKeep) {
validateNotNull(ProviderConstants.EMPI_MERGE_PERSONS_PERSON_ID_TO_DELETE, thePersonIdToDelete);
validateNotNull(ProviderConstants.EMPI_MERGE_PERSONS_PERSON_ID_TO_KEEP, thePersonIdToKeep);
if (thePersonIdToDelete.getValue().equals(thePersonIdToKeep.getValue())) {
throw new InvalidRequestException("personIdToDelete must be different from personToKeep");
protected void validateMergeParameters(IPrimitiveType<String> theFromPersonId, IPrimitiveType<String> theToPersonId) {
validateNotNull(ProviderConstants.EMPI_MERGE_PERSONS_FROM_PERSON_ID, theFromPersonId);
validateNotNull(ProviderConstants.EMPI_MERGE_PERSONS_TO_PERSON_ID, theToPersonId);
if (theFromPersonId.getValue().equals(theToPersonId.getValue())) {
throw new InvalidRequestException("fromPersonId must be different from toPersonId");
}
}
protected void validateMergeResources(IAnyResource thePersonToDelete, IAnyResource thePersonToKeep) {
validateIsEmpiManaged(ProviderConstants.EMPI_MERGE_PERSONS_PERSON_ID_TO_DELETE, thePersonToDelete);
validateIsEmpiManaged(ProviderConstants.EMPI_MERGE_PERSONS_PERSON_ID_TO_KEEP, thePersonToKeep);
protected void validateMergeResources(IAnyResource theFromPerson, IAnyResource theToPerson) {
validateIsEmpiManaged(ProviderConstants.EMPI_MERGE_PERSONS_FROM_PERSON_ID, theFromPerson);
validateIsEmpiManaged(ProviderConstants.EMPI_MERGE_PERSONS_TO_PERSON_ID, theToPerson);
}
private void validateIsEmpiManaged(String theName, IAnyResource thePerson) {

View File

@ -87,15 +87,15 @@ public class EmpiProviderDstu3 extends BaseEmpiProvider {
}
@Operation(name = ProviderConstants.EMPI_MERGE_PERSONS, type = Person.class)
public Person mergePerson(@OperationParam(name=ProviderConstants.EMPI_MERGE_PERSONS_PERSON_ID_TO_DELETE, min = 1, max = 1) StringType thePersonIdToDelete,
@OperationParam(name=ProviderConstants.EMPI_MERGE_PERSONS_PERSON_ID_TO_KEEP, min = 1, max = 1) StringType thePersonIdToKeep,
public Person mergePerson(@OperationParam(name=ProviderConstants.EMPI_MERGE_PERSONS_FROM_PERSON_ID, min = 1, max = 1) StringType theFromPersonId,
@OperationParam(name=ProviderConstants.EMPI_MERGE_PERSONS_TO_PERSON_ID, min = 1, max = 1) StringType theToPersonId,
RequestDetails theRequestDetails) {
validateMergeParameters(thePersonIdToDelete, thePersonIdToKeep);
IAnyResource personToDelete = getPersonFromIdOrThrowException(ProviderConstants.EMPI_MERGE_PERSONS_PERSON_ID_TO_DELETE, thePersonIdToDelete.getValue());
IAnyResource personToKeep = getPersonFromIdOrThrowException(ProviderConstants.EMPI_MERGE_PERSONS_PERSON_ID_TO_KEEP, thePersonIdToKeep.getValue());
validateMergeResources(personToDelete, personToKeep);
validateMergeParameters(theFromPersonId, theToPersonId);
IAnyResource fromPerson = getPersonFromIdOrThrowException(ProviderConstants.EMPI_MERGE_PERSONS_FROM_PERSON_ID, theFromPersonId.getValue());
IAnyResource toPerson = getPersonFromIdOrThrowException(ProviderConstants.EMPI_MERGE_PERSONS_TO_PERSON_ID, theToPersonId.getValue());
validateMergeResources(fromPerson, toPerson);
return (Person) myPersonMergerSvc.mergePersons(personToDelete, personToKeep, createEmpiContext(theRequestDetails));
return (Person) myPersonMergerSvc.mergePersons(fromPerson, toPerson, createEmpiContext(theRequestDetails));
}
@Operation(name = ProviderConstants.EMPI_UPDATE_LINK, type = Person.class)

View File

@ -88,15 +88,15 @@ public class EmpiProviderR4 extends BaseEmpiProvider {
}
@Operation(name = ProviderConstants.EMPI_MERGE_PERSONS, type = Person.class)
public Person mergePersons(@OperationParam(name=ProviderConstants.EMPI_MERGE_PERSONS_PERSON_ID_TO_DELETE, min = 1, max = 1) StringType thePersonIdToDelete,
@OperationParam(name=ProviderConstants.EMPI_MERGE_PERSONS_PERSON_ID_TO_KEEP, min = 1, max = 1) StringType thePersonIdToKeep,
public Person mergePersons(@OperationParam(name=ProviderConstants.EMPI_MERGE_PERSONS_FROM_PERSON_ID, min = 1, max = 1) StringType theFromPersonId,
@OperationParam(name=ProviderConstants.EMPI_MERGE_PERSONS_TO_PERSON_ID, min = 1, max = 1) StringType theToPersonId,
RequestDetails theRequestDetails) {
validateMergeParameters(thePersonIdToDelete, thePersonIdToKeep);
IAnyResource personToDelete = getPersonFromIdOrThrowException(ProviderConstants.EMPI_MERGE_PERSONS_PERSON_ID_TO_DELETE, thePersonIdToDelete.getValue());
IAnyResource personToKeep = getPersonFromIdOrThrowException(ProviderConstants.EMPI_MERGE_PERSONS_PERSON_ID_TO_KEEP, thePersonIdToKeep.getValue());
validateMergeResources(personToDelete, personToKeep);
validateMergeParameters(theFromPersonId, theToPersonId);
IAnyResource fromPerson = getPersonFromIdOrThrowException(ProviderConstants.EMPI_MERGE_PERSONS_FROM_PERSON_ID, theFromPersonId.getValue());
IAnyResource toPerson = getPersonFromIdOrThrowException(ProviderConstants.EMPI_MERGE_PERSONS_TO_PERSON_ID, theToPersonId.getValue());
validateMergeResources(fromPerson, toPerson);
return (Person) myPersonMergerSvc.mergePersons(personToDelete, personToKeep, createEmpiContext(theRequestDetails));
return (Person) myPersonMergerSvc.mergePersons(fromPerson, toPerson, createEmpiContext(theRequestDetails));
}
@Operation(name = ProviderConstants.EMPI_UPDATE_LINK, type = Person.class)

View File

@ -57,4 +57,10 @@ public final class EmpiUtil {
public static boolean isEmpiManaged(IBaseResource theBaseResource) {
return theBaseResource.getMeta().getTag(EmpiConstants.SYSTEM_EMPI_MANAGED, EmpiConstants.CODE_HAPI_EMPI_MANAGED) != null;
}
public static boolean isEmpiManagedPerson(FhirContext theFhirContext, IBaseResource theResource) {
String resourceType = theFhirContext.getResourceType(theResource);
return "Person".equals(resourceType) && isEmpiManaged(theResource);
}
}

View File

@ -222,16 +222,18 @@ public class PersonHelper {
switch (myFhirContext.getVersion().getVersion()) {
case R4:
Person personR4 = new Person();
personR4.setActive(true);
eidsToApply.forEach(eid -> personR4.addIdentifier(eid.toR4()));
personR4.getMeta().addTag((Coding) buildEmpiManagedTag());
copyEmpiTargetDataIntoPerson(theSourceResource, personR4, true);
return personR4;
case DSTU3:
org.hl7.fhir.dstu3.model.Person personDSTU3 = new org.hl7.fhir.dstu3.model.Person();
eidsToApply.forEach(eid -> personDSTU3.addIdentifier(eid.toDSTU3()));
personDSTU3.getMeta().addTag((org.hl7.fhir.dstu3.model.Coding) buildEmpiManagedTag());
copyEmpiTargetDataIntoPerson(theSourceResource, personDSTU3, true);
return personDSTU3;
org.hl7.fhir.dstu3.model.Person personDstu3 = new org.hl7.fhir.dstu3.model.Person();
personDstu3.setActive(true);
eidsToApply.forEach(eid -> personDstu3.addIdentifier(eid.toDSTU3()));
personDstu3.getMeta().addTag((org.hl7.fhir.dstu3.model.Coding) buildEmpiManagedTag());
copyEmpiTargetDataIntoPerson(theSourceResource, personDstu3, true);
return personDstu3;
default:
throw new UnsupportedOperationException("Version not supported: " + myFhirContext.getVersion().getVersion());
}
@ -466,22 +468,22 @@ public class PersonHelper {
}
}
public void mergePersonFields(IBaseResource thePersonToDelete, IBaseResource thePersonToKeep) {
public void mergePersonFields(IBaseResource theFromPerson, IBaseResource theToPerson) {
switch (myFhirContext.getVersion().getVersion()) {
case R4:
mergeR4PersonFields(thePersonToDelete, thePersonToKeep);
mergeR4PersonFields(theFromPerson, theToPerson);
break;
case DSTU3:
mergeDstu3PersonFields(thePersonToDelete, thePersonToKeep);
mergeDstu3PersonFields(theFromPerson, theToPerson);
break;
default:
throw new UnsupportedOperationException("Version not supported: " + myFhirContext.getVersion().getVersion());
}
}
private void mergeR4PersonFields(IBaseResource thePersonToDelete, IBaseResource thePersonToKeep) {
Person fromPerson = (Person) thePersonToDelete;
Person toPerson = (Person) thePersonToKeep;
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);
@ -511,9 +513,9 @@ public class PersonHelper {
toList.addAll(itemsToAdd);
}
private void mergeDstu3PersonFields(IBaseResource thePersonToDelete, IBaseResource thePersonToKeep) {
org.hl7.fhir.dstu3.model.Person fromPerson = (org.hl7.fhir.dstu3.model.Person) thePersonToDelete;
org.hl7.fhir.dstu3.model.Person toPerson = (org.hl7.fhir.dstu3.model.Person) thePersonToKeep;
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);
@ -627,4 +629,32 @@ public class PersonHelper {
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());
}
}
}

View File

@ -65,8 +65,8 @@ public class ProviderConstants {
public static final String EMPI_MATCH_RESOURCE = "resource";
public static final String EMPI_MERGE_PERSONS = "$empi-merge-persons";
public static final String EMPI_MERGE_PERSONS_PERSON_ID_TO_DELETE = "personIdToDelete";
public static final String EMPI_MERGE_PERSONS_PERSON_ID_TO_KEEP = "personIdToKeep";
public static final String EMPI_MERGE_PERSONS_FROM_PERSON_ID = "fromPersonId";
public static final String EMPI_MERGE_PERSONS_TO_PERSON_ID = "toPersonId";
public static final String EMPI_UPDATE_LINK = "$empi-update-link";
public static final String EMPI_UPDATE_LINK_PERSON_ID = "personId";