Add Basic provider method, skeleton of tests

This commit is contained in:
Tadgh 2020-07-03 15:21:32 -07:00
parent 6259eada3c
commit 25d8668f55
16 changed files with 366 additions and 24 deletions

View File

@ -27,8 +27,9 @@ import ca.uhn.fhir.empi.model.EmpiTransactionContext;
import ca.uhn.fhir.jpa.dao.data.IEmpiLinkDao; import ca.uhn.fhir.jpa.dao.data.IEmpiLinkDao;
import ca.uhn.fhir.jpa.dao.index.IdHelperService; import ca.uhn.fhir.jpa.dao.index.IdHelperService;
import ca.uhn.fhir.jpa.entity.EmpiLink; import ca.uhn.fhir.jpa.entity.EmpiLink;
import ca.uhn.fhir.jpa.entity.EmpiTargetType;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.r4.model.Patient;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example; import org.springframework.data.domain.Example;
@ -42,6 +43,7 @@ import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Collectors;
@Service @Service
public class EmpiLinkDaoSvc { public class EmpiLinkDaoSvc {
@ -183,6 +185,26 @@ public class EmpiLinkDaoSvc {
return myEmpiLinkDao.findAll(example); return myEmpiLinkDao.findAll(example);
} }
public List<Long> deleteAllEmpiLinksAndReturnPersonPids() {
List<EmpiLink> all = myEmpiLinkDao.findAll();
return deleteEmpiLinksAndReturnPersonPids(all);
}
private List<Long> deleteEmpiLinksAndReturnPersonPids(List<EmpiLink> theLinks) {
List<Long> collect = theLinks.stream().map(link -> link.getPersonPid()).collect(Collectors.toList());
myEmpiLinkDao.deleteAll();
return collect;
}
public List<Long> deleteAllEmpiLinksOfTypeAndReturnPersonPids(EmpiTargetType theTargetType) {
EmpiLink link = new EmpiLink();
link.setEmpiTargetType(theTargetType);
Example<EmpiLink> exampleLink = Example.of(link);
List<EmpiLink> allOfType = myEmpiLinkDao.findAll(exampleLink);
return deleteEmpiLinksAndReturnPersonPids(allOfType);
}
public EmpiLink save(EmpiLink theEmpiLink) { public EmpiLink save(EmpiLink theEmpiLink) {
if (theEmpiLink.getCreated() == null) { if (theEmpiLink.getCreated() == null) {
theEmpiLink.setCreated(new Date()); theEmpiLink.setCreated(new Date());
@ -195,7 +217,7 @@ public class EmpiLinkDaoSvc {
return myEmpiLinkDao.findAll(theExampleLink); return myEmpiLinkDao.findAll(theExampleLink);
} }
public List<EmpiLink> findEmpiLinksByTarget(Patient theTargetResource) { public List<EmpiLink> findEmpiLinksByTarget(IAnyResource theTargetResource) {
Long pid = myIdHelperService.getPidOrNull(theTargetResource); Long pid = myIdHelperService.getPidOrNull(theTargetResource);
if (pid == null) { if (pid == null) {
return Collections.emptyList(); return Collections.emptyList();

View File

@ -37,13 +37,10 @@ import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId; import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException; import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.google.common.collect.ListMultimap; import com.google.common.collect.ListMultimap;
import com.google.common.collect.MultimapBuilder; import com.google.common.collect.MultimapBuilder;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import org.checkerframework.checker.nullness.qual.NonNull;
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;
import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IIdType;
@ -55,7 +52,6 @@ import org.springframework.stereotype.Service;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.annotation.PostConstruct;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -66,7 +62,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -481,7 +476,7 @@ public class IdHelperService {
} }
public Map<Long, IIdType> getPidToIdMap(Collection<IIdType> theIds, RequestDetails theRequestDetails) { public Map<Long, IIdType> getPidToIdMap(Collection<IIdType> theIds, RequestDetails theRequestDetails) {
return theIds.stream().collect(Collectors.toMap(t->getPidOrThrowException(t), Function.identity())); return theIds.stream().collect(Collectors.toMap(this::getPidOrThrowException, Function.identity()));
} }
public IIdType resourceIdFromPidOrThrowException(Long thePid) { public IIdType resourceIdFromPidOrThrowException(Long thePid) {

View File

@ -88,6 +88,12 @@ public class EmpiLink {
@Column(name = "UPDATED", nullable = false) @Column(name = "UPDATED", nullable = false)
private Date myUpdated; private Date myUpdated;
@Column(name = "TARGET_TYPE", nullable = true)
private EmpiTargetType myEmpiTargetType;
@Column(name = "SCORE", nullable = true)
private Double myScore;
public Long getId() { public Long getId() {
return myId; return myId;
} }
@ -205,4 +211,20 @@ public class EmpiLink {
myUpdated = theUpdated; myUpdated = theUpdated;
return this; return this;
} }
public EmpiTargetType getEmpiTargetType() {
return myEmpiTargetType;
}
public void setEmpiTargetType(EmpiTargetType theEmpiTargetType) {
myEmpiTargetType = theEmpiTargetType;
}
public Double getScore() {
return myScore;
}
public void setScore(Double theScore) {
myScore = theScore;
}
} }

View File

@ -0,0 +1,6 @@
package ca.uhn.fhir.jpa.entity;
public enum EmpiTargetType {
PATIENT,
PRACTITIONER
}

View File

@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.empi.config;
*/ */
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.empi.api.IEmpiExpungeSvc;
import ca.uhn.fhir.empi.api.IEmpiLinkQuerySvc; import ca.uhn.fhir.empi.api.IEmpiLinkQuerySvc;
import ca.uhn.fhir.empi.api.IEmpiLinkSvc; import ca.uhn.fhir.empi.api.IEmpiLinkSvc;
import ca.uhn.fhir.empi.api.IEmpiLinkUpdaterSvc; import ca.uhn.fhir.empi.api.IEmpiLinkUpdaterSvc;
@ -40,6 +41,7 @@ import ca.uhn.fhir.jpa.empi.interceptor.IEmpiStorageInterceptor;
import ca.uhn.fhir.jpa.empi.svc.EmpiCandidateSearchCriteriaBuilderSvc; import ca.uhn.fhir.jpa.empi.svc.EmpiCandidateSearchCriteriaBuilderSvc;
import ca.uhn.fhir.jpa.empi.svc.EmpiCandidateSearchSvc; import ca.uhn.fhir.jpa.empi.svc.EmpiCandidateSearchSvc;
import ca.uhn.fhir.jpa.empi.svc.EmpiEidUpdateService; import ca.uhn.fhir.jpa.empi.svc.EmpiEidUpdateService;
import ca.uhn.fhir.jpa.empi.svc.EmpiExpungeSvcImpl;
import ca.uhn.fhir.jpa.empi.svc.EmpiLinkQuerySvcImpl; import ca.uhn.fhir.jpa.empi.svc.EmpiLinkQuerySvcImpl;
import ca.uhn.fhir.jpa.empi.svc.EmpiLinkSvcImpl; import ca.uhn.fhir.jpa.empi.svc.EmpiLinkSvcImpl;
import ca.uhn.fhir.jpa.empi.svc.EmpiLinkUpdaterSvcImpl; import ca.uhn.fhir.jpa.empi.svc.EmpiLinkUpdaterSvcImpl;
@ -153,6 +155,11 @@ public class EmpiConsumerConfig {
return new EmpiLinkQuerySvcImpl(); return new EmpiLinkQuerySvcImpl();
} }
@Bean
IEmpiExpungeSvc empiExpungeSvc() {
return new EmpiExpungeSvcImpl();
}
@Bean @Bean
EmpiCandidateSearchSvc empiCandidateSearchSvc() { EmpiCandidateSearchSvc empiCandidateSearchSvc() {
return new EmpiCandidateSearchSvc(); return new EmpiCandidateSearchSvc();

View File

@ -0,0 +1,72 @@
package ca.uhn.fhir.jpa.empi.svc;
/*-
* #%L
* HAPI FHIR JPA Server - Enterprise Master Patient Index
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import ca.uhn.fhir.empi.api.IEmpiExpungeSvc;
import ca.uhn.fhir.jpa.dao.EmpiLinkDaoSvc;
import ca.uhn.fhir.jpa.dao.expunge.IResourceExpungeService;
import ca.uhn.fhir.jpa.entity.EmpiTargetType;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.provider.ProviderConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
/**
* This class is in charge of Clearing out existing EMPI links, as well as deleting all persons related to those EMPI Links.
*
*/
public class EmpiExpungeSvcImpl implements IEmpiExpungeSvc {
private static final Logger ourLog = LoggerFactory.getLogger(EmpiExpungeSvcImpl.class);
@Autowired
EmpiLinkDaoSvc myEmpiLinkDaoSvc;
@Autowired
private IResourceExpungeService myResourceExpungeService;
@Override
public void expungeEmpiLinks(String theResourceType) {
EmpiTargetType targetType = getTargetTypeOrThrowException(theResourceType);
List<Long> longs = myEmpiLinkDaoSvc.deleteAllEmpiLinksOfTypeAndReturnPersonPids(targetType);
myResourceExpungeService.expungeHistoricalVersionsOfIds(null, longs, new AtomicInteger(longs.size()));
}
private EmpiTargetType getTargetTypeOrThrowException(String theResourceType) {
if (theResourceType.equalsIgnoreCase("Patient")) {
return EmpiTargetType.PATIENT;
} else if(theResourceType.equalsIgnoreCase("Practitioner")) {
return EmpiTargetType.PRACTITIONER;
} else {
throw new InvalidRequestException(ProviderConstants.EMPI_CLEAR + " does not support resource type: " + theResourceType);
}
}
@Override
public void expungeEmpiLinks() {
List<Long> longs = myEmpiLinkDaoSvc.deleteAllEmpiLinksAndReturnPersonPids();
myResourceExpungeService.expungeHistoricalVersionsOfIds(null, longs, new AtomicInteger(longs.size()));;
}
}

View File

@ -1,11 +0,0 @@
package ca.uhn.fhir.jpa.empi.batch;
import org.junit.Test;
public class EmpiBatchTest {
@Test
public void testEmpiBatch() {
}
}

View File

@ -50,8 +50,10 @@ public abstract class BaseLinkR4Test extends BaseProviderR4Test {
return myEmpiLinkDaoSvc.findEmpiLinkByTarget(myPatient).get(); return myEmpiLinkDaoSvc.findEmpiLinkByTarget(myPatient).get();
} }
@Nonnull @Nonnull
protected List<EmpiLink> getPatientLinks() { protected List<EmpiLink> getPatientLinks() {
return myEmpiLinkDaoSvc.findEmpiLinksByTarget(myPatient); return myEmpiLinkDaoSvc.findEmpiLinksByTarget(myPatient);
} }
} }

View File

@ -1,5 +1,6 @@
package ca.uhn.fhir.jpa.empi.provider; package ca.uhn.fhir.jpa.empi.provider;
import ca.uhn.fhir.empi.api.IEmpiExpungeSvc;
import ca.uhn.fhir.empi.api.IEmpiLinkQuerySvc; import ca.uhn.fhir.empi.api.IEmpiLinkQuerySvc;
import ca.uhn.fhir.empi.api.IEmpiLinkUpdaterSvc; import ca.uhn.fhir.empi.api.IEmpiLinkUpdaterSvc;
import ca.uhn.fhir.empi.api.IEmpiMatchFinderSvc; import ca.uhn.fhir.empi.api.IEmpiMatchFinderSvc;
@ -21,11 +22,13 @@ public abstract class BaseProviderR4Test extends BaseEmpiR4Test {
private IEmpiLinkQuerySvc myEmpiLinkQuerySvc; private IEmpiLinkQuerySvc myEmpiLinkQuerySvc;
@Autowired @Autowired
private IResourceLoader myResourceLoader; private IResourceLoader myResourceLoader;
@Autowired
private IEmpiExpungeSvc myEmpiExpungeSvc;
EmpiProviderR4 myEmpiProviderR4; EmpiProviderR4 myEmpiProviderR4;
@Before @Before
public void before() { public void before() {
myEmpiProviderR4 = new EmpiProviderR4(myFhirContext, myEmpiMatchFinderSvc, myPersonMergerSvc, myEmpiLinkUpdaterSvc, myEmpiLinkQuerySvc, myResourceLoader); myEmpiProviderR4 = new EmpiProviderR4(myFhirContext, myEmpiMatchFinderSvc, myPersonMergerSvc, myEmpiLinkUpdaterSvc, myEmpiLinkQuerySvc, myResourceLoader, myEmpiExpungeSvc);
} }
} }

View File

@ -0,0 +1,173 @@
package ca.uhn.fhir.jpa.empi.provider;
import ca.uhn.fhir.empi.api.EmpiConstants;
import ca.uhn.fhir.empi.api.EmpiLinkSourceEnum;
import ca.uhn.fhir.empi.api.EmpiMatchResultEnum;
import ca.uhn.fhir.jpa.entity.EmpiLink;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
import org.hl7.fhir.r4.model.Patient;
import org.hl7.fhir.r4.model.Person;
import org.hl7.fhir.r4.model.Practitioner;
import org.hl7.fhir.r4.model.StringType;
import org.junit.Before;
import org.junit.Test;
import javax.annotation.Nonnull;
import java.util.List;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.matchesPattern;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
public class EmpiProviderClearLinkR4Test extends BaseLinkR4Test {
protected Practitioner myPractitioner;
protected StringType myPractitionerId;
@Before
public void before() {
super.before();
myPractitioner = createPractitionerAndUpdateLinks(new Practitioner());
myPractitionerId = new StringType(myPractitioner.getIdElement().getValue());
}
@Test
public void testClearAllLinks() {
assertLinkCount(2);
myEmpiProviderR4.clearEmpiLinks(null);
assertLinkCount(0);
assertNoLinksExist();
}
private void assertNoLinksExist() {
assertNoPatientLinksExist();
assertNoPractitionerLinksExist();
}
private void assertNoPatientLinksExist() {
assertThat(getPatientLinks(), hasSize(0));
}
private void assertNoPractitionerLinksExist() {
assertThat(getPractitionerLinks(), hasSize(0));
}
@Test
public void testClearPatientLinks() {
assertLinkCount(1);
myEmpiProviderR4.updateLink(myPersonId, myPatientId, MATCH_RESULT, myRequestDetails);
assertLinkCount(1);
List<EmpiLink> links = getPatientLinks();
assertEquals(EmpiLinkSourceEnum.MANUAL, links.get(0).getLinkSource());
assertEquals(EmpiMatchResultEnum.MATCH, links.get(0).getMatchResult());
}
@Test
public void testClearPractitionerLinks() {
myEmpiProviderR4.updateLink(myPersonId, myPatientId, MATCH_RESULT, myRequestDetails);
try {
myEmpiProviderR4.updateLink(myPersonId, myPatientId, NO_MATCH_RESULT, myRequestDetails);
fail();
} catch (ResourceVersionConflictException e) {
assertThat(e.getMessage(), matchesPattern("Requested resource Person/\\d+/_history/1 is not the latest version. Latest version is Person/\\d+/_history/2"));
}
}
@Test
public void testClearInvalidTargetType() {
myEmpiProviderR4.updateLink(myPersonId, myPatientId, MATCH_RESULT, myRequestDetails);
Person person = myEmpiProviderR4.updateLink(myVersionlessPersonId, myPatientId, NO_MATCH_RESULT, myRequestDetails);
assertThat(person.getLink(), hasSize(0));
}
@Test
public void testUnlinkLink() {
myEmpiProviderR4.updateLink(myPersonId, myPatientId, NO_MATCH_RESULT, myRequestDetails);
try {
myEmpiProviderR4.updateLink(myPersonId, myPatientId, MATCH_RESULT, myRequestDetails);
fail();
} catch (ResourceVersionConflictException e) {
assertThat(e.getMessage(), matchesPattern("Requested resource Person/\\d+/_history/1 is not the latest version. Latest version is Person/\\d+/_history/2"));
}
}
@Test
public void testUpdateIllegalResultPM() {
try {
myEmpiProviderR4.updateLink(myPersonId, myPatientId, POSSIBLE_MATCH_RESULT, myRequestDetails);
fail();
} catch (InvalidRequestException e) {
assertEquals("$empi-update-link illegal matchResult value 'POSSIBLE_MATCH'. Must be NO_MATCH or MATCH", e.getMessage());
}
}
@Test
public void testUpdateIllegalResultPD() {
try {
myEmpiProviderR4.updateLink(myPersonId, myPatientId, POSSIBLE_DUPLICATE_RESULT, myRequestDetails);
fail();
} catch (InvalidRequestException e) {
assertEquals("$empi-update-link illegal matchResult value 'POSSIBLE_DUPLICATE'. Must be NO_MATCH or MATCH", e.getMessage());
}
}
@Test
public void testUpdateIllegalFirstArg() {
try {
myEmpiProviderR4.updateLink(myPatientId, myPatientId, NO_MATCH_RESULT, myRequestDetails);
fail();
} catch (InvalidRequestException e) {
assertEquals("personId must have form Person/<id> where <id> is the id of the person", e.getMessage());
}
}
@Test
public void testUpdateIllegalSecondArg() {
try {
myEmpiProviderR4.updateLink(myPersonId, myPersonId, NO_MATCH_RESULT, myRequestDetails);
fail();
} catch (InvalidRequestException e) {
assertThat(e.getMessage(), endsWith("must have form Patient/<id> or Practitioner/<id> where <id> is the id of the resource"));
}
}
@Test
public void testUpdateStrangePerson() {
Person person = createUnmanagedPerson();
try {
myEmpiProviderR4.updateLink(new StringType(person.getIdElement().getValue()), myPatientId, NO_MATCH_RESULT, myRequestDetails);
fail();
} catch (InvalidRequestException e) {
assertEquals("Only EMPI Managed Person resources may be updated via this operation. The Person resource provided is not tagged as managed by hapi-empi", e.getMessage());
}
}
@Test
public void testExcludedPerson() {
Patient patient = new Patient();
patient.getMeta().addTag().setSystem(EmpiConstants.SYSTEM_EMPI_MANAGED).setCode(EmpiConstants.CODE_NO_EMPI_MANAGED);
createPatient(patient);
try {
myEmpiProviderR4.updateLink(myPersonId, new StringType(patient.getIdElement().getValue()), NO_MATCH_RESULT, myRequestDetails);
fail();
} catch (InvalidRequestException e) {
assertEquals("The target is marked with the " + EmpiConstants.CODE_NO_EMPI_MANAGED + " tag which means it may not be EMPI linked.", e.getMessage());
}
}
@Nonnull
protected EmpiLink getOnlyPractitionerLink() {
return myEmpiLinkDaoSvc.findEmpiLinkByTarget(myPractitioner).get();
}
@Nonnull
protected List<EmpiLink> getPractitionerLinks() {
return myEmpiLinkDaoSvc.findEmpiLinksByTarget(myPractitioner);
}
}

View File

@ -0,0 +1,28 @@
package ca.uhn.fhir.empi.api;
/*-
* #%L
* HAPI FHIR - Enterprise Master Patient Index
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
public interface IEmpiExpungeSvc {
void expungeEmpiLinks(String theResourceType);
void expungeEmpiLinks();
}

View File

@ -28,4 +28,5 @@ public interface IEmpiLinkQuerySvc {
IBaseParameters queryLinks(IIdType thePersonId, IIdType theTargetId, EmpiMatchResultEnum theMatchResult, EmpiLinkSourceEnum theLinkSource, EmpiTransactionContext theEmpiContext); IBaseParameters queryLinks(IIdType thePersonId, IIdType theTargetId, EmpiMatchResultEnum theMatchResult, EmpiLinkSourceEnum theLinkSource, EmpiTransactionContext theEmpiContext);
IBaseParameters getPossibleDuplicates(EmpiTransactionContext theEmpiContext); IBaseParameters getPossibleDuplicates(EmpiTransactionContext theEmpiContext);
} }

View File

@ -23,6 +23,7 @@ package ca.uhn.fhir.empi.provider;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.empi.api.EmpiLinkSourceEnum; import ca.uhn.fhir.empi.api.EmpiLinkSourceEnum;
import ca.uhn.fhir.empi.api.EmpiMatchResultEnum; import ca.uhn.fhir.empi.api.EmpiMatchResultEnum;
import ca.uhn.fhir.empi.api.IEmpiExpungeSvc;
import ca.uhn.fhir.empi.api.IEmpiLinkQuerySvc; import ca.uhn.fhir.empi.api.IEmpiLinkQuerySvc;
import ca.uhn.fhir.empi.api.IEmpiLinkUpdaterSvc; import ca.uhn.fhir.empi.api.IEmpiLinkUpdaterSvc;
import ca.uhn.fhir.empi.api.IEmpiMatchFinderSvc; import ca.uhn.fhir.empi.api.IEmpiMatchFinderSvc;
@ -52,6 +53,7 @@ public class EmpiProviderDstu3 extends BaseEmpiProvider {
private final IEmpiPersonMergerSvc myPersonMergerSvc; private final IEmpiPersonMergerSvc myPersonMergerSvc;
private final IEmpiLinkUpdaterSvc myEmpiLinkUpdaterSvc; private final IEmpiLinkUpdaterSvc myEmpiLinkUpdaterSvc;
private final IEmpiLinkQuerySvc myEmpiLinkQuerySvc; private final IEmpiLinkQuerySvc myEmpiLinkQuerySvc;
private final IEmpiExpungeSvc myEmpiExpungeSvc;
/** /**
* Constructor * Constructor
@ -59,12 +61,13 @@ public class EmpiProviderDstu3 extends BaseEmpiProvider {
* Note that this is not a spring bean. Any necessary injections should * Note that this is not a spring bean. Any necessary injections should
* happen in the constructor * happen in the constructor
*/ */
public EmpiProviderDstu3(FhirContext theFhirContext, IEmpiMatchFinderSvc theEmpiMatchFinderSvc, IEmpiPersonMergerSvc thePersonMergerSvc, IEmpiLinkUpdaterSvc theEmpiLinkUpdaterSvc, IEmpiLinkQuerySvc theEmpiLinkQuerySvc, IResourceLoader theResourceLoader) { public EmpiProviderDstu3(FhirContext theFhirContext, IEmpiMatchFinderSvc theEmpiMatchFinderSvc, IEmpiPersonMergerSvc thePersonMergerSvc, IEmpiLinkUpdaterSvc theEmpiLinkUpdaterSvc, IEmpiLinkQuerySvc theEmpiLinkQuerySvc, IResourceLoader theResourceLoader, IEmpiExpungeSvc theEmpiExpungeSvc) {
super(theFhirContext, theResourceLoader); super(theFhirContext, theResourceLoader);
myEmpiMatchFinderSvc = theEmpiMatchFinderSvc; myEmpiMatchFinderSvc = theEmpiMatchFinderSvc;
myPersonMergerSvc = thePersonMergerSvc; myPersonMergerSvc = thePersonMergerSvc;
myEmpiLinkUpdaterSvc = theEmpiLinkUpdaterSvc; myEmpiLinkUpdaterSvc = theEmpiLinkUpdaterSvc;
myEmpiLinkQuerySvc = theEmpiLinkQuerySvc; myEmpiLinkQuerySvc = theEmpiLinkQuerySvc;
myEmpiExpungeSvc = theEmpiExpungeSvc;
} }
@Operation(name = ProviderConstants.EMPI_MATCH, type = Patient.class) @Operation(name = ProviderConstants.EMPI_MATCH, type = Patient.class)

View File

@ -22,6 +22,7 @@ package ca.uhn.fhir.empi.provider;
import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.empi.api.IEmpiExpungeSvc;
import ca.uhn.fhir.empi.api.IEmpiLinkQuerySvc; import ca.uhn.fhir.empi.api.IEmpiLinkQuerySvc;
import ca.uhn.fhir.empi.api.IEmpiLinkUpdaterSvc; import ca.uhn.fhir.empi.api.IEmpiLinkUpdaterSvc;
import ca.uhn.fhir.empi.api.IEmpiMatchFinderSvc; import ca.uhn.fhir.empi.api.IEmpiMatchFinderSvc;
@ -47,14 +48,16 @@ public class EmpiProviderLoader {
private IEmpiLinkQuerySvc myEmpiLinkQuerySvc; private IEmpiLinkQuerySvc myEmpiLinkQuerySvc;
@Autowired @Autowired
private IResourceLoader myResourceLoader; private IResourceLoader myResourceLoader;
@Autowired
private IEmpiExpungeSvc myEmpiExpungeSvc;
public void loadProvider() { public void loadProvider() {
switch (myFhirContext.getVersion().getVersion()) { switch (myFhirContext.getVersion().getVersion()) {
case DSTU3: case DSTU3:
myResourceProviderFactory.addSupplier(() -> new EmpiProviderDstu3(myFhirContext, myEmpiMatchFinderSvc, myPersonMergerSvc, myEmpiLinkUpdaterSvc, myEmpiLinkQuerySvc, myResourceLoader)); myResourceProviderFactory.addSupplier(() -> new EmpiProviderDstu3(myFhirContext, myEmpiMatchFinderSvc, myPersonMergerSvc, myEmpiLinkUpdaterSvc, myEmpiLinkQuerySvc, myResourceLoader, myEmpiExpungeSvc));
break; break;
case R4: case R4:
myResourceProviderFactory.addSupplier(() -> new EmpiProviderR4(myFhirContext, myEmpiMatchFinderSvc, myPersonMergerSvc, myEmpiLinkUpdaterSvc, myEmpiLinkQuerySvc, myResourceLoader)); myResourceProviderFactory.addSupplier(() -> new EmpiProviderR4(myFhirContext, myEmpiMatchFinderSvc, myPersonMergerSvc, myEmpiLinkUpdaterSvc, myEmpiLinkQuerySvc, myResourceLoader, myEmpiExpungeSvc));
break; break;
default: default:
throw new ConfigurationException("EMPI not supported for FHIR version " + myFhirContext.getVersion().getVersion()); throw new ConfigurationException("EMPI not supported for FHIR version " + myFhirContext.getVersion().getVersion());

View File

@ -23,6 +23,7 @@ package ca.uhn.fhir.empi.provider;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.empi.api.EmpiLinkSourceEnum; import ca.uhn.fhir.empi.api.EmpiLinkSourceEnum;
import ca.uhn.fhir.empi.api.EmpiMatchResultEnum; import ca.uhn.fhir.empi.api.EmpiMatchResultEnum;
import ca.uhn.fhir.empi.api.IEmpiExpungeSvc;
import ca.uhn.fhir.empi.api.IEmpiLinkQuerySvc; import ca.uhn.fhir.empi.api.IEmpiLinkQuerySvc;
import ca.uhn.fhir.empi.api.IEmpiLinkUpdaterSvc; import ca.uhn.fhir.empi.api.IEmpiLinkUpdaterSvc;
import ca.uhn.fhir.empi.api.IEmpiMatchFinderSvc; import ca.uhn.fhir.empi.api.IEmpiMatchFinderSvc;
@ -52,6 +53,7 @@ public class EmpiProviderR4 extends BaseEmpiProvider {
private final IEmpiPersonMergerSvc myPersonMergerSvc; private final IEmpiPersonMergerSvc myPersonMergerSvc;
private final IEmpiLinkUpdaterSvc myEmpiLinkUpdaterSvc; private final IEmpiLinkUpdaterSvc myEmpiLinkUpdaterSvc;
private final IEmpiLinkQuerySvc myEmpiLinkQuerySvc; private final IEmpiLinkQuerySvc myEmpiLinkQuerySvc;
private final IEmpiExpungeSvc myEmpiExpungeSvc;
/** /**
* Constructor * Constructor
@ -59,12 +61,13 @@ public class EmpiProviderR4 extends BaseEmpiProvider {
* Note that this is not a spring bean. Any necessary injections should * Note that this is not a spring bean. Any necessary injections should
* happen in the constructor * happen in the constructor
*/ */
public EmpiProviderR4(FhirContext theFhirContext, IEmpiMatchFinderSvc theEmpiMatchFinderSvc, IEmpiPersonMergerSvc thePersonMergerSvc, IEmpiLinkUpdaterSvc theEmpiLinkUpdaterSvc, IEmpiLinkQuerySvc theEmpiLinkQuerySvc, IResourceLoader theResourceLoader) { public EmpiProviderR4(FhirContext theFhirContext, IEmpiMatchFinderSvc theEmpiMatchFinderSvc, IEmpiPersonMergerSvc thePersonMergerSvc, IEmpiLinkUpdaterSvc theEmpiLinkUpdaterSvc, IEmpiLinkQuerySvc theEmpiLinkQuerySvc, IResourceLoader theResourceLoader, IEmpiExpungeSvc theEmpiExpungeSvc) {
super(theFhirContext, theResourceLoader); super(theFhirContext, theResourceLoader);
myEmpiMatchFinderSvc = theEmpiMatchFinderSvc; myEmpiMatchFinderSvc = theEmpiMatchFinderSvc;
myPersonMergerSvc = thePersonMergerSvc; myPersonMergerSvc = thePersonMergerSvc;
myEmpiLinkUpdaterSvc = theEmpiLinkUpdaterSvc; myEmpiLinkUpdaterSvc = theEmpiLinkUpdaterSvc;
myEmpiLinkQuerySvc = theEmpiLinkQuerySvc; myEmpiLinkQuerySvc = theEmpiLinkQuerySvc;
myEmpiExpungeSvc = theEmpiExpungeSvc;
} }
@Operation(name = ProviderConstants.EMPI_MATCH, type = Patient.class) @Operation(name = ProviderConstants.EMPI_MATCH, type = Patient.class)
@ -117,6 +120,16 @@ public class EmpiProviderR4 extends BaseEmpiProvider {
return (Person) myEmpiLinkUpdaterSvc.updateLink(person, target, matchResult, createEmpiContext(theRequestDetails)); return (Person) myEmpiLinkUpdaterSvc.updateLink(person, target, matchResult, createEmpiContext(theRequestDetails));
} }
@Operation(name = ProviderConstants.EMPI_CLEAR)
public Parameters clearEmpiLinks(@OperationParam(name=ProviderConstants.EMPI_CLEAR_TARGET_TYPE, min = 0, max = 1) StringType theTargetType) {
if (theTargetType == null) {
myEmpiExpungeSvc.expungeEmpiLinks();
} else {
myEmpiExpungeSvc.expungeEmpiLinks(theTargetType.getValueNotNull());
}
return new Parameters();
}
@Operation(name = ProviderConstants.EMPI_QUERY_LINKS, idempotent = true) @Operation(name = ProviderConstants.EMPI_QUERY_LINKS, idempotent = true)
public Parameters queryLinks(@OperationParam(name=ProviderConstants.EMPI_QUERY_LINKS_PERSON_ID, min = 0, max = 1) StringType thePersonId, public Parameters queryLinks(@OperationParam(name=ProviderConstants.EMPI_QUERY_LINKS_PERSON_ID, min = 0, max = 1) StringType thePersonId,
@OperationParam(name=ProviderConstants.EMPI_QUERY_LINKS_TARGET_ID, min = 0, max = 1) StringType theTargetId, @OperationParam(name=ProviderConstants.EMPI_QUERY_LINKS_TARGET_ID, min = 0, max = 1) StringType theTargetId,

View File

@ -81,4 +81,7 @@ public class ProviderConstants {
public static final String EMPI_DUPLICATE_PERSONS = "$empi-duplicate-persons"; public static final String EMPI_DUPLICATE_PERSONS = "$empi-duplicate-persons";
public static final String EMPI_NOT_DUPLICATE = "$empi-not-duplicate"; public static final String EMPI_NOT_DUPLICATE = "$empi-not-duplicate";
public static final String EMPI_CLEAR = "$empi-clear";
public static final String EMPI_CLEAR_TARGET_TYPE = "targetType";
} }