Add type-based filtering to filter service. Add tests

This commit is contained in:
Tadgh 2020-08-06 10:58:37 -07:00
parent c92a77c889
commit ed618613a6
9 changed files with 86 additions and 22 deletions

View File

@ -65,7 +65,7 @@ public class EmpiMessageHandler implements MessageHandler {
ResourceModifiedMessage msg = ((ResourceModifiedJsonMessage) theMessage).getPayload();
try {
if (myEmpiResourceFileringSvc.shouldBeProcessed(msg)) {
if (myEmpiResourceFileringSvc.shouldBeProcessed(getResourceFromPayload(msg))) {
matchEmpiAndUpdateLinks(msg);
}
} catch (Exception e) {

View File

@ -1,25 +1,56 @@
package ca.uhn.fhir.jpa.empi.svc;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.empi.api.IEmpiSettings;
import ca.uhn.fhir.empi.log.Logs;
import ca.uhn.fhir.empi.rules.json.EmpiResourceSearchParamJson;
import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
*
*/
@Service
public class EmpiMessageFilteringSvc {
private static final Logger ourLog = Logs.getEmpiTroubleshootingLog();
@Autowired
private IEmpiSettings empiSettings;
@Autowired
EmpiSearchParamSvc myEmpiSearchParamSvc;
@Autowired
FhirContext myFhirContext;
public boolean shouldBeProcessed(ResourceModifiedMessage theMsg) {
/**
* Given a message from the EMPI Channel, determine whether or not EMPI processing should occur on the payload.
* EMPI processing should occur iff for any {@link EmpiResourceSearchParamJson) Search Param, the resource contains a value.
*
* If the payload has no attributes that appear in the Candidate Search Params, processing should be skipped, as there is not
* sufficient information to perform meaningful EMPI processing. (For example, how can EMPI processing occur on a patient that has _no_ attributes?)
*
* @param theMessage the message provided by the EMPI channel.
*
* @return whether or not EMPI processing should proceed
*/
public boolean shouldBeProcessed(IAnyResource theResource) {
String resourceType = myFhirContext.getResourceType(theResource);
List<EmpiResourceSearchParamJson> candidateSearchParams = empiSettings.getEmpiRules().getCandidateSearchParams();
List<String> valuesFromResourceForSearchParam = myEmpiSearchParamSvc.getValueFromResourceForSearchParam(theResource, searchParam);
boolean containsValueForSomeSearchParam = candidateSearchParams.stream()
.filter(csp -> searchParamIsValidForType(csp, resourceType))
.flatMap(csp -> csp.getSearchParams().stream())
.map(searchParam -> myEmpiSearchParamSvc.getValueFromResourceForSearchParam(theResource, searchParam))
.anyMatch(valueList -> !valueList.isEmpty());
return containsValueForSomeSearchParam;
}
private boolean searchParamIsValidForType(EmpiResourceSearchParamJson theSearchParamJson, String theResourceType) {
return theSearchParamJson.getResourceType().equalsIgnoreCase(theResourceType) || theSearchParamJson.getResourceType().equalsIgnoreCase("*");
}
}

View File

@ -19,7 +19,6 @@ import org.hl7.fhir.r4.model.Enumerations;
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.hl7.fhir.r4.model.SearchParameter;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@ -62,27 +61,21 @@ public class EmpiStorageInterceptorIT extends BaseEmpiR4Test {
super.loadEmpiSearchParameters();
}
@Test
public void testCreatePatient() throws InterruptedException {
myEmpiHelper.createWithLatch(new Patient());
assertLinkCount(1);
}
@Test
public void testCreatePractitioner() throws InterruptedException {
myEmpiHelper.createWithLatch(new Practitioner());
myEmpiHelper.createWithLatch(buildPractitionerWithNameAndId("somename", "some_id"));
assertLinkCount(1);
}
@Test
public void testCreatePerson() throws InterruptedException {
public void testCreatePerson() {
myPersonDao.create(new Person());
assertLinkCount(0);
}
@Test
public void testDeletePersonDeletesLinks() throws InterruptedException {
myEmpiHelper.createWithLatch(new Patient());
myEmpiHelper.createWithLatch(buildPaulPatient());
assertLinkCount(1);
Person person = getOnlyActivePerson();
myPersonDao.delete(person.getIdElement());
@ -175,7 +168,7 @@ public class EmpiStorageInterceptorIT extends BaseEmpiR4Test {
public void testEmpiManagedPersonCannotBeModifiedByPersonUpdateRequest() throws InterruptedException {
// When EMPI is enabled, only the EMPI system is allowed to modify Person links of Persons with the EMPI-MANAGED tag.
Patient patient = new Patient();
IIdType patientId = myEmpiHelper.createWithLatch(new Patient()).getDaoMethodOutcome().getId().toUnqualifiedVersionless();
IIdType patientId = myEmpiHelper.createWithLatch(buildPaulPatient()).getDaoMethodOutcome().getId().toUnqualifiedVersionless();
patient.setId(patientId);
@ -275,7 +268,7 @@ public class EmpiStorageInterceptorIT extends BaseEmpiR4Test {
@Test
public void testPatientsWithNoEIDCanBeUpdated() throws InterruptedException {
setPreventEidUpdates(true);
Patient p = new Patient();
Patient p = buildPaulPatient();
EmpiHelperR4.OutcomeAndLogMessageWrapper wrapper = myEmpiHelper.createWithLatch(p);
p.setId(wrapper.getDaoMethodOutcome().getId());
@ -287,7 +280,7 @@ public class EmpiStorageInterceptorIT extends BaseEmpiR4Test {
@Test
public void testPatientsCanHaveEIDAddedInStrictMode() throws InterruptedException {
setPreventEidUpdates(true);
Patient p = new Patient();
Patient p = buildPaulPatient();
EmpiHelperR4.OutcomeAndLogMessageWrapper messageWrapper = myEmpiHelper.createWithLatch(p);
p.setId(messageWrapper.getDaoMethodOutcome().getId());
addExternalEID(p, "external eid");

View File

@ -31,7 +31,7 @@ public abstract class BaseLinkR4Test extends BaseProviderR4Test {
public void before() {
super.before();
myPatient = createPatientAndUpdateLinks(new Patient());
myPatient = createPatientAndUpdateLinks(buildPaulPatient());
myPatientId = new StringType(myPatient.getIdElement().getValue());
myPerson = getPersonFromTarget(myPatient);

View File

@ -36,7 +36,7 @@ public class EmpiProviderBatchR4Test extends BaseLinkR4Test {
@BeforeEach
public void before() {
super.before();
myPractitioner = createPractitionerAndUpdateLinks(new Practitioner());
myPractitioner = createPractitionerAndUpdateLinks(buildPractitionerWithNameAndId("some_pract", "some_pract_id"));
myPractitionerId = new StringType(myPractitioner.getIdElement().getValue());
myPractitionerPerson = getPersonFromTarget(myPractitioner);
myPractitionerPersonId = new StringType(myPractitionerPerson.getIdElement().getValue());

View File

@ -0,0 +1,39 @@
package ca.uhn.fhir.jpa.empi.svc;
import ca.uhn.fhir.jpa.empi.BaseEmpiR4Test;
import org.hl7.fhir.r4.model.BooleanType;
import org.hl7.fhir.r4.model.Patient;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
class EmpiMessageFilteringSvcTest extends BaseEmpiR4Test {
@Autowired
private EmpiMessageFilteringSvc myEmpiMessageFilteringSvc;
@Test
public void testFilterResourcesWhichHaveNoRelevantAttributes() {
Patient patient = new Patient();
patient.setDeceased(new BooleanType(true)); //EMPI rules defined do not care about the deceased attribute.
//SUT
boolean shouldBeProcessed = myEmpiMessageFilteringSvc.shouldBeProcessed(patient);
assertThat(shouldBeProcessed, is(equalTo(false)));
}
@Test
public void testDoNotFilterResourcesWithEMPIAttributes() {
Patient patient = new Patient();
patient.addIdentifier().setValue("Hey I'm an ID! rules defined in empi-rules.json care about me!");
//SUT
boolean shouldBeProcessed = myEmpiMessageFilteringSvc.shouldBeProcessed(patient);
assertThat(shouldBeProcessed, is(equalTo(true)));
}
}

View File

@ -399,6 +399,7 @@ public class SearchParamExtractorService {
myInterceptorBroadcaster = theJpaInterceptorBroadcaster;
}
@Nonnull
public List<String> extractParamValuesAsStrings(RuntimeSearchParam theActiveSearchParam, IBaseResource theResource) {
return mySearchParamExtractor.extractParamValuesAsStrings(theActiveSearchParam, theResource);
}

View File

@ -54,7 +54,7 @@ public class EmpiResourceSearchParamJson implements IModelJson, Iterable<String>
return this;
}
private List<String> getSearchParams() {
public List<String> getSearchParams() {
if (mySearchParams == null) {
mySearchParams = new ArrayList<>();
}