diff --git a/api/src/main/java/org/openmrs/module/fhir2/FhirConstants.java b/api/src/main/java/org/openmrs/module/fhir2/FhirConstants.java index 5da7dbe78..9e4ac92e2 100644 --- a/api/src/main/java/org/openmrs/module/fhir2/FhirConstants.java +++ b/api/src/main/java/org/openmrs/module/fhir2/FhirConstants.java @@ -137,6 +137,8 @@ private FhirConstants() { public static final String MEDICATION = "Medication"; + public static final String GROUP = "Group"; + public static final String MEDICATION_DISPENSE = "MedicationDispense"; public static final String MEDICATION_REQUEST = "MedicationRequest"; @@ -364,4 +366,7 @@ private FhirConstants() { public static final String EXACT_TOTAL_SEARCH_PARAMETER = "_exactTotal"; public static final String COUNT_QUERY_CACHE = "countQueryCache"; + + public static final String INCLUDE_MEMBER_PARAM = "member"; + } diff --git a/api/src/main/java/org/openmrs/module/fhir2/api/dao/impl/FhirPatientDaoImpl.java b/api/src/main/java/org/openmrs/module/fhir2/api/dao/impl/FhirPatientDaoImpl.java index f7d1d9f16..51f9cd2f5 100644 --- a/api/src/main/java/org/openmrs/module/fhir2/api/dao/impl/FhirPatientDaoImpl.java +++ b/api/src/main/java/org/openmrs/module/fhir2/api/dao/impl/FhirPatientDaoImpl.java @@ -19,11 +19,15 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.NoSuchElementException; import java.util.Optional; +import java.util.Set; import ca.uhn.fhir.rest.param.DateRangeParam; +import ca.uhn.fhir.rest.param.HasAndListParam; import ca.uhn.fhir.rest.param.StringAndListParam; import ca.uhn.fhir.rest.param.StringParam; import ca.uhn.fhir.rest.param.TokenAndListParam; @@ -32,18 +36,25 @@ import org.apache.commons.lang3.StringUtils; import org.hibernate.Criteria; import org.hibernate.criterion.Criterion; +import org.hibernate.criterion.Projections; import org.hibernate.sql.JoinType; +import org.openmrs.CohortMembership; import org.openmrs.Patient; import org.openmrs.PatientIdentifierType; import org.openmrs.module.fhir2.FhirConstants; +import org.openmrs.module.fhir2.api.dao.FhirGroupDao; import org.openmrs.module.fhir2.api.dao.FhirPatientDao; import org.openmrs.module.fhir2.api.search.param.SearchParameterMap; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component @Setter(AccessLevel.PACKAGE) public class FhirPatientDaoImpl extends BasePersonDao implements FhirPatientDao { + @Autowired + private FhirGroupDao groupDao; + @Override public Patient getPatientById(@Nonnull Integer id) { return (Patient) getSessionFactory().getCurrentSession().createCriteria(Patient.class).add(eq("patientId", id)) @@ -112,10 +123,57 @@ protected void setupSearchParams(Criteria criteria, SearchParameterMap theParams case FhirConstants.COMMON_SEARCH_HANDLER: handleCommonSearchParameters(entry.getValue()).ifPresent(criteria::add); break; + case FhirConstants.HAS_SEARCH_HANDLER: + entry.getValue().forEach(param -> handleHasAndListParam(criteria, (HasAndListParam) param.getParam())); + break; } }); } + protected void handleHasAndListParam(Criteria criteria, HasAndListParam hasAndListParam) { + if (hasAndListParam != null) { + List groupIds = new ArrayList<>(); + hasAndListParam.getValuesAsQueryTokens().forEach(hasOrListParam -> { + hasOrListParam.getValuesAsQueryTokens().forEach(hasParam -> { + if (hasParam != null) { + String paramValue = hasParam.getParameterValue(); + switch (hasParam.getTargetResourceType()) { + case FhirConstants.GROUP: + switch (hasParam.getReferenceFieldName()) { + case FhirConstants.INCLUDE_MEMBER_PARAM: + switch (hasParam.getParameterName()) { + case "id": + groupIds.add(paramValue); + } + break; + } + break; + } + } + }); + }); + + if (!groupIds.isEmpty()) { + verifyPatientInGroups(criteria, groupIds); + } + } + } + + private void verifyPatientInGroups(Criteria criteria, List groupIds) { + Set patientIds = new HashSet<>(); + groupIds.forEach(groupId -> patientIds.addAll(getGroupMemberIds(groupId))); + + criteria.add(in("patientId", patientIds.isEmpty() ? Collections.emptyList() : patientIds)); + } + + private List getGroupMemberIds(String groupId) { + Criteria subquery = getSessionFactory().getCurrentSession().createCriteria(CohortMembership.class, "cm") + .createAlias("cm.cohort", "co").add(eq("co.uuid", groupId)) + .setProjection(Projections.property("cm.patientId")); + + return subquery.list(); + } + private void handlePatientQuery(Criteria criteria, @Nonnull StringAndListParam query) { if (query == null) { return; diff --git a/api/src/main/java/org/openmrs/module/fhir2/api/search/param/OpenmrsPatientSearchParams.java b/api/src/main/java/org/openmrs/module/fhir2/api/search/param/OpenmrsPatientSearchParams.java index e43e8cedf..a17c8d4e4 100644 --- a/api/src/main/java/org/openmrs/module/fhir2/api/search/param/OpenmrsPatientSearchParams.java +++ b/api/src/main/java/org/openmrs/module/fhir2/api/search/param/OpenmrsPatientSearchParams.java @@ -14,6 +14,7 @@ import ca.uhn.fhir.model.api.Include; import ca.uhn.fhir.rest.api.SortSpec; import ca.uhn.fhir.rest.param.DateRangeParam; +import ca.uhn.fhir.rest.param.HasAndListParam; import ca.uhn.fhir.rest.param.StringAndListParam; import ca.uhn.fhir.rest.param.TokenAndListParam; import lombok.Builder; @@ -45,11 +46,13 @@ public class OpenmrsPatientSearchParams extends BaseResourceSearchParams { private StringAndListParam country; + private HasAndListParam hasAndListParam; + @Builder public OpenmrsPatientSearchParams(StringAndListParam query, TokenAndListParam gender, DateRangeParam birthDate, DateRangeParam deathDate, TokenAndListParam deceased, StringAndListParam city, StringAndListParam state, - StringAndListParam postalCode, StringAndListParam country, TokenAndListParam id, DateRangeParam lastUpdated, - SortSpec sort, HashSet revIncludes) { + StringAndListParam postalCode, StringAndListParam country, TokenAndListParam id, HasAndListParam hasAndListParam, + DateRangeParam lastUpdated, SortSpec sort, HashSet revIncludes) { super(id, lastUpdated, sort, null, revIncludes); @@ -62,6 +65,7 @@ public OpenmrsPatientSearchParams(StringAndListParam query, TokenAndListParam ge this.state = state; this.postalCode = postalCode; this.country = country; + this.hasAndListParam = hasAndListParam; } @Override @@ -74,6 +78,7 @@ public SearchParameterMap toSearchParameterMap() { .addParameter(FhirConstants.ADDRESS_SEARCH_HANDLER, FhirConstants.CITY_PROPERTY, getCity()) .addParameter(FhirConstants.ADDRESS_SEARCH_HANDLER, FhirConstants.STATE_PROPERTY, getState()) .addParameter(FhirConstants.ADDRESS_SEARCH_HANDLER, FhirConstants.POSTAL_CODE_PROPERTY, getPostalCode()) - .addParameter(FhirConstants.ADDRESS_SEARCH_HANDLER, FhirConstants.COUNTRY_PROPERTY, getCountry()); + .addParameter(FhirConstants.ADDRESS_SEARCH_HANDLER, FhirConstants.COUNTRY_PROPERTY, getCountry()) + .addParameter(FhirConstants.HAS_SEARCH_HANDLER, getHasAndListParam()); } } diff --git a/api/src/main/java/org/openmrs/module/fhir2/api/search/param/PatientSearchParams.java b/api/src/main/java/org/openmrs/module/fhir2/api/search/param/PatientSearchParams.java index 9225fa137..da3609899 100644 --- a/api/src/main/java/org/openmrs/module/fhir2/api/search/param/PatientSearchParams.java +++ b/api/src/main/java/org/openmrs/module/fhir2/api/search/param/PatientSearchParams.java @@ -14,6 +14,7 @@ import ca.uhn.fhir.model.api.Include; import ca.uhn.fhir.rest.api.SortSpec; import ca.uhn.fhir.rest.param.DateRangeParam; +import ca.uhn.fhir.rest.param.HasAndListParam; import ca.uhn.fhir.rest.param.StringAndListParam; import ca.uhn.fhir.rest.param.TokenAndListParam; import lombok.Builder; @@ -51,12 +52,14 @@ public class PatientSearchParams extends BaseResourceSearchParams { private StringAndListParam country; + private HasAndListParam hasAndListParam; + @Builder public PatientSearchParams(StringAndListParam name, StringAndListParam given, StringAndListParam family, TokenAndListParam identifier, TokenAndListParam gender, DateRangeParam birthDate, DateRangeParam deathDate, TokenAndListParam deceased, StringAndListParam city, StringAndListParam state, StringAndListParam postalCode, - StringAndListParam country, TokenAndListParam id, DateRangeParam lastUpdated, SortSpec sort, - HashSet revIncludes) { + StringAndListParam country, TokenAndListParam id, HasAndListParam hasAndListParam, DateRangeParam lastUpdated, + SortSpec sort, HashSet revIncludes) { super(id, lastUpdated, sort, null, revIncludes); @@ -72,6 +75,7 @@ public PatientSearchParams(StringAndListParam name, StringAndListParam given, St this.state = state; this.postalCode = postalCode; this.country = country; + this.hasAndListParam = hasAndListParam; } @Override @@ -88,6 +92,7 @@ public SearchParameterMap toSearchParameterMap() { .addParameter(FhirConstants.ADDRESS_SEARCH_HANDLER, FhirConstants.CITY_PROPERTY, getCity()) .addParameter(FhirConstants.ADDRESS_SEARCH_HANDLER, FhirConstants.STATE_PROPERTY, getState()) .addParameter(FhirConstants.ADDRESS_SEARCH_HANDLER, FhirConstants.POSTAL_CODE_PROPERTY, getPostalCode()) - .addParameter(FhirConstants.ADDRESS_SEARCH_HANDLER, FhirConstants.COUNTRY_PROPERTY, getCountry()); + .addParameter(FhirConstants.ADDRESS_SEARCH_HANDLER, FhirConstants.COUNTRY_PROPERTY, getCountry()) + .addParameter(FhirConstants.HAS_SEARCH_HANDLER, getHasAndListParam()); } } diff --git a/api/src/main/java/org/openmrs/module/fhir2/providers/r3/PatientFhirResourceProvider.java b/api/src/main/java/org/openmrs/module/fhir2/providers/r3/PatientFhirResourceProvider.java index 0b20682ed..48d4a6d7a 100644 --- a/api/src/main/java/org/openmrs/module/fhir2/providers/r3/PatientFhirResourceProvider.java +++ b/api/src/main/java/org/openmrs/module/fhir2/providers/r3/PatientFhirResourceProvider.java @@ -32,6 +32,7 @@ import ca.uhn.fhir.rest.api.SortSpec; import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.param.DateRangeParam; +import ca.uhn.fhir.rest.param.HasAndListParam; import ca.uhn.fhir.rest.param.StringAndListParam; import ca.uhn.fhir.rest.param.TokenAndListParam; import ca.uhn.fhir.rest.param.TokenParam; @@ -53,6 +54,7 @@ import org.hl7.fhir.dstu3.model.ProcedureRequest; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.r4.model.ServiceRequest; +import org.openmrs.module.fhir2.FhirConstants; import org.openmrs.module.fhir2.api.FhirPatientService; import org.openmrs.module.fhir2.api.annotations.R3Provider; import org.openmrs.module.fhir2.api.search.SearchQueryBundleProviderR3Wrapper; @@ -128,6 +130,7 @@ public IBundleProvider searchPatients(@OptionalParam(name = Patient.SP_NAME) Str @OptionalParam(name = Patient.SP_ADDRESS_POSTALCODE) StringAndListParam postalCode, @OptionalParam(name = Patient.SP_ADDRESS_COUNTRY) StringAndListParam country, @OptionalParam(name = Patient.SP_RES_ID) TokenAndListParam id, + @OptionalParam(name = FhirConstants.HAS_SEARCH_HANDLER) HasAndListParam hasAndListParam, @OptionalParam(name = "_lastUpdated") DateRangeParam lastUpdated, @Sort SortSpec sort, @IncludeParam(reverse = true, allow = { "Observation:" + Observation.SP_PATIENT, "AllergyIntolerance:" + AllergyIntolerance.SP_PATIENT, "DiagnosticReport:" + DiagnosticReport.SP_PATIENT, @@ -138,9 +141,9 @@ public IBundleProvider searchPatients(@OptionalParam(name = Patient.SP_NAME) Str revIncludes = null; } - return new SearchQueryBundleProviderR3Wrapper( - patientService.searchForPatients(new PatientSearchParams(name, given, family, identifier, gender, birthDate, - deathDate, deceased, city, state, postalCode, country, id, lastUpdated, sort, revIncludes))); + return new SearchQueryBundleProviderR3Wrapper(patientService + .searchForPatients(new PatientSearchParams(name, given, family, identifier, gender, birthDate, deathDate, + deceased, city, state, postalCode, country, id, hasAndListParam, lastUpdated, sort, revIncludes))); } @Search(queryName = "openmrsPatients") @@ -155,6 +158,7 @@ public IBundleProvider searchOpenmrsPatients(@OptionalParam(name = "q") StringAn @OptionalParam(name = org.hl7.fhir.r4.model.Patient.SP_ADDRESS_POSTALCODE) StringAndListParam postalCode, @OptionalParam(name = org.hl7.fhir.r4.model.Patient.SP_ADDRESS_COUNTRY) StringAndListParam country, @OptionalParam(name = org.hl7.fhir.r4.model.Patient.SP_RES_ID) TokenAndListParam id, + @OptionalParam(name = FhirConstants.HAS_SEARCH_HANDLER) HasAndListParam hasAndListParam, @OptionalParam(name = "_lastUpdated") DateRangeParam lastUpdated, @Sort SortSpec sort, @IncludeParam(reverse = true, allow = { "Observation:" + org.hl7.fhir.r4.model.Observation.SP_PATIENT, "AllergyIntolerance:" + org.hl7.fhir.r4.model.AllergyIntolerance.SP_PATIENT, @@ -169,7 +173,7 @@ public IBundleProvider searchOpenmrsPatients(@OptionalParam(name = "q") StringAn return new SearchQueryBundleProviderR3Wrapper( patientService.searchForPatients(new OpenmrsPatientSearchParams(query, gender, birthDate, deathDate, - deceased, city, state, postalCode, country, id, lastUpdated, sort, revIncludes))); + deceased, city, state, postalCode, country, id, hasAndListParam, lastUpdated, sort, revIncludes))); } /** diff --git a/api/src/main/java/org/openmrs/module/fhir2/providers/r4/PatientFhirResourceProvider.java b/api/src/main/java/org/openmrs/module/fhir2/providers/r4/PatientFhirResourceProvider.java index 4ae6763c6..fe86c269d 100644 --- a/api/src/main/java/org/openmrs/module/fhir2/providers/r4/PatientFhirResourceProvider.java +++ b/api/src/main/java/org/openmrs/module/fhir2/providers/r4/PatientFhirResourceProvider.java @@ -35,6 +35,7 @@ import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.param.DateRangeParam; +import ca.uhn.fhir.rest.param.HasAndListParam; import ca.uhn.fhir.rest.param.StringAndListParam; import ca.uhn.fhir.rest.param.TokenAndListParam; import ca.uhn.fhir.rest.param.TokenParam; @@ -54,6 +55,7 @@ import org.hl7.fhir.r4.model.OperationOutcome; import org.hl7.fhir.r4.model.Patient; import org.hl7.fhir.r4.model.ServiceRequest; +import org.openmrs.module.fhir2.FhirConstants; import org.openmrs.module.fhir2.api.FhirPatientService; import org.openmrs.module.fhir2.api.annotations.R4Provider; import org.openmrs.module.fhir2.api.search.param.OpenmrsPatientSearchParams; @@ -136,6 +138,7 @@ public IBundleProvider searchPatients(@OptionalParam(name = Patient.SP_NAME) Str @OptionalParam(name = Patient.SP_ADDRESS_POSTALCODE) StringAndListParam postalCode, @OptionalParam(name = Patient.SP_ADDRESS_COUNTRY) StringAndListParam country, @OptionalParam(name = Patient.SP_RES_ID) TokenAndListParam id, + @OptionalParam(name = FhirConstants.HAS_SEARCH_HANDLER) HasAndListParam hasAndListParam, @OptionalParam(name = "_lastUpdated") DateRangeParam lastUpdated, @Sort SortSpec sort, @IncludeParam(reverse = true, allow = { "Observation:" + Observation.SP_PATIENT, "AllergyIntolerance:" + AllergyIntolerance.SP_PATIENT, "DiagnosticReport:" + DiagnosticReport.SP_PATIENT, @@ -147,7 +150,7 @@ public IBundleProvider searchPatients(@OptionalParam(name = Patient.SP_NAME) Str } return patientService.searchForPatients(new PatientSearchParams(name, given, family, identifier, gender, birthDate, - deathDate, deceased, city, state, postalCode, country, id, lastUpdated, sort, revIncludes)); + deathDate, deceased, city, state, postalCode, country, id, hasAndListParam, lastUpdated, sort, revIncludes)); } @Search(queryName = "openmrsPatients") @@ -162,6 +165,7 @@ public IBundleProvider searchOpenmrsPatients(@OptionalParam(name = "q") StringAn @OptionalParam(name = Patient.SP_ADDRESS_POSTALCODE) StringAndListParam postalCode, @OptionalParam(name = Patient.SP_ADDRESS_COUNTRY) StringAndListParam country, @OptionalParam(name = Patient.SP_RES_ID) TokenAndListParam id, + @OptionalParam(name = FhirConstants.HAS_SEARCH_HANDLER) HasAndListParam hasAndListParam, @OptionalParam(name = "_lastUpdated") DateRangeParam lastUpdated, @Sort SortSpec sort, @IncludeParam(reverse = true, allow = { "Observation:" + Observation.SP_PATIENT, "AllergyIntolerance:" + AllergyIntolerance.SP_PATIENT, "DiagnosticReport:" + DiagnosticReport.SP_PATIENT, @@ -173,7 +177,7 @@ public IBundleProvider searchOpenmrsPatients(@OptionalParam(name = "q") StringAn } return patientService.searchForPatients(new OpenmrsPatientSearchParams(query, gender, birthDate, deathDate, deceased, - city, state, postalCode, country, id, lastUpdated, sort, revIncludes)); + city, state, postalCode, country, id, hasAndListParam, lastUpdated, sort, revIncludes)); } /** diff --git a/api/src/test/java/org/openmrs/module/fhir2/api/dao/impl/FhirPatientDaoImplTest.java b/api/src/test/java/org/openmrs/module/fhir2/api/dao/impl/FhirPatientDaoImplTest.java index 3c891c858..104cf71a7 100644 --- a/api/src/test/java/org/openmrs/module/fhir2/api/dao/impl/FhirPatientDaoImplTest.java +++ b/api/src/test/java/org/openmrs/module/fhir2/api/dao/impl/FhirPatientDaoImplTest.java @@ -10,15 +10,23 @@ package org.openmrs.module.fhir2.api.dao.impl; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; +import java.util.List; + +import ca.uhn.fhir.rest.param.HasAndListParam; +import ca.uhn.fhir.rest.param.HasOrListParam; +import ca.uhn.fhir.rest.param.HasParam; import org.hibernate.SessionFactory; import org.junit.Before; import org.junit.Test; import org.openmrs.Patient; +import org.openmrs.module.fhir2.FhirConstants; import org.openmrs.module.fhir2.TestFhirSpringConfiguration; +import org.openmrs.module.fhir2.api.search.param.SearchParameterMap; import org.openmrs.test.BaseModuleContextSensitiveTest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; @@ -30,19 +38,40 @@ public class FhirPatientDaoImplTest extends BaseModuleContextSensitiveTest { private static final String BAD_PATIENT_UUID = "282390a6-3608-496d-9025-aecbc1235670"; + private static final String GROUP_A = "dfb29c44-2e39-46c4-8cd7-18f21c6d47b1"; + + private static final String GROUP_B = "a25ce1d7-326c-43ff-a87f-63d9d2f60f11"; + + private static final String GROUP_C = "6f4816fb-0b75-4e25-aac0-4944a6d3b697"; + + private static final String PATIENT1_GROUP_A = "256ccf6d-6b41-455c-9be2-51ff4386ae76"; + + private static final String PATIENT2_GROUP_A = "30e2aa2a-4ed1-415d-84c5-ba29016c14b7"; + + private static final String PATIENT3_GROUP_A = "8d703ff2-c3e2-4070-9737-73e713d5a50d"; + + private static final String PATIENT4_GROUP_A = "ca17fcc5-ec96-487f-b9ea-42973c8973e3"; + + private static final String PATIENT1_GROUP_C = "c7c1416f9-3beb-40fe-9043-1ce70ea9df53"; + private static final String[] PATIENT_SEARCH_DATA_FILES = { "org/openmrs/module/fhir2/api/dao/impl/FhirPatientDaoImplTest_initial_data.xml", "org/openmrs/module/fhir2/api/dao/impl/FhirPatientDaoImplTest_address_data.xml" }; private FhirPatientDaoImpl dao; + private FhirGroupDaoImpl groupDao; + @Autowired private SessionFactory sessionFactory; @Before public void setup() throws Exception { + groupDao = new FhirGroupDaoImpl(); + groupDao.setSessionFactory(sessionFactory); dao = new FhirPatientDaoImpl(); dao.setSessionFactory(sessionFactory); + dao.setGroupDao(groupDao); for (String search_data : PATIENT_SEARCH_DATA_FILES) { executeDataSet(search_data); } @@ -76,4 +105,49 @@ public void getPatientByUuid_shouldReturnNullIfPatientNotFound() { assertThat(result, nullValue()); } + + @Test + public void getSearchResults_shouldReturnPatientsSearchResults() { + HasAndListParam groupParam = new HasAndListParam().addAnd( + new HasOrListParam().add(new HasParam(FhirConstants.GROUP, FhirConstants.INCLUDE_MEMBER_PARAM, "id", GROUP_A))); + + SearchParameterMap theParams = new SearchParameterMap().addParameter(FhirConstants.HAS_SEARCH_HANDLER, groupParam); + List result = dao.getSearchResults(theParams); + + assertThat(result, notNullValue()); + assertThat(result.size(), equalTo(4)); + assertThat(result.get(0).getUuid(), equalTo(PATIENT1_GROUP_A)); + assertThat(result.get(1).getUuid(), equalTo(PATIENT2_GROUP_A)); + assertThat(result.get(2).getUuid(), equalTo(PATIENT3_GROUP_A)); + assertThat(result.get(3).getUuid(), equalTo(PATIENT4_GROUP_A)); + } + + @Test + public void getSearchResults_shouldReturnPatientsFromTwoGroupsSearchResults() { + HasAndListParam groupParam = new HasAndListParam().addAnd( + new HasOrListParam().add(new HasParam(FhirConstants.GROUP, FhirConstants.INCLUDE_MEMBER_PARAM, "id", GROUP_A)) + .add(new HasParam(FhirConstants.GROUP, FhirConstants.INCLUDE_MEMBER_PARAM, "id", GROUP_C))); + + SearchParameterMap theParams = new SearchParameterMap().addParameter(FhirConstants.HAS_SEARCH_HANDLER, groupParam); + List result = dao.getSearchResults(theParams); + + assertThat(result, notNullValue()); + assertThat(result.get(0).getUuid(), equalTo(PATIENT1_GROUP_A)); + assertThat(result.get(1).getUuid(), equalTo(PATIENT2_GROUP_A)); + assertThat(result.get(2).getUuid(), equalTo(PATIENT3_GROUP_A)); + assertThat(result.get(3).getUuid(), equalTo(PATIENT4_GROUP_A)); + assertThat(result.get(4).getUuid(), equalTo(PATIENT1_GROUP_C)); + } + + @Test + public void getSearchResults_shouldReturnEmptyList() { + HasAndListParam groupParam = new HasAndListParam().addAnd( + new HasOrListParam().add(new HasParam(FhirConstants.GROUP, FhirConstants.INCLUDE_MEMBER_PARAM, "id", GROUP_B))); + + SearchParameterMap theParams = new SearchParameterMap().addParameter(FhirConstants.HAS_SEARCH_HANDLER, groupParam); + List result = dao.getSearchResults(theParams); + + assertThat(result, notNullValue()); + assertThat(result, empty()); + } } diff --git a/api/src/test/java/org/openmrs/module/fhir2/api/impl/FhirPatientServiceImplTest.java b/api/src/test/java/org/openmrs/module/fhir2/api/impl/FhirPatientServiceImplTest.java index 503d8469c..badd0863e 100644 --- a/api/src/test/java/org/openmrs/module/fhir2/api/impl/FhirPatientServiceImplTest.java +++ b/api/src/test/java/org/openmrs/module/fhir2/api/impl/FhirPatientServiceImplTest.java @@ -234,7 +234,7 @@ public void searchForPatients_shouldSearchForPatientsByName() { when(patientTranslator.toFhirResource(patient)).thenReturn(fhirPatient); IBundleProvider results = patientService.searchForPatients(new PatientSearchParams(stringAndListParam, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, null)); + null, null, null, null, null, null, null, null, null, null, null, null, null, null)); assertThat(results, notNullValue()); assertThat(results.size(), equalTo(1)); @@ -258,7 +258,7 @@ public void searchForPatients_shouldSearchForPatientsByGivenName() { when(patientTranslator.toFhirResource(patient)).thenReturn(fhirPatient); IBundleProvider results = patientService.searchForPatients(new PatientSearchParams(null, stringAndListParam, null, - null, null, null, null, null, null, null, null, null, null, null, null, null)); + null, null, null, null, null, null, null, null, null, null, null, null, null, null)); assertThat(results, notNullValue()); assertThat(results.size(), equalTo(1)); @@ -284,7 +284,7 @@ public void searchForPatients_shouldSearchForPatientsByFamilyName() { when(patientTranslator.toFhirResource(patient)).thenReturn(fhirPatient); IBundleProvider results = patientService.searchForPatients(new PatientSearchParams(null, null, stringAndListParam, - null, null, null, null, null, null, null, null, null, null, null, null, null)); + null, null, null, null, null, null, null, null, null, null, null, null, null, null)); assertThat(results.getUuid(), notNullValue()); assertThat(results.size(), equalTo(1)); @@ -308,7 +308,7 @@ public void searchForPatients_shouldReturnCollectionOfPatientsForPartialMatchOnG when(patientTranslator.toFhirResource(patient)).thenReturn(fhirPatient); IBundleProvider results = patientService.searchForPatients(new PatientSearchParams(null, stringAndListParam, null, - null, null, null, null, null, null, null, null, null, null, null, null, null)); + null, null, null, null, null, null, null, null, null, null, null, null, null, null)); assertThat(results, notNullValue()); assertThat(results.size(), greaterThanOrEqualTo(1)); @@ -332,7 +332,7 @@ public void searchForPatients_shouldReturnCollectionOfPatientsForPartialMatchOnF when(patientTranslator.toFhirResource(patient)).thenReturn(fhirPatient); IBundleProvider results = patientService.searchForPatients(new PatientSearchParams(null, null, stringAndListParam, - null, null, null, null, null, null, null, null, null, null, null, null, null)); + null, null, null, null, null, null, null, null, null, null, null, null, null, null)); assertThat(results, notNullValue()); assertThat(results.size(), greaterThanOrEqualTo(1)); @@ -350,7 +350,7 @@ public void searchForPatients_shouldReturnEmptyCollectionWhenPatientNameNotMatch new SearchQueryBundleProvider<>(theParams, dao, patientTranslator, globalPropertyService, searchQueryInclude)); IBundleProvider results = patientService.searchForPatients(new PatientSearchParams(stringAndListParam, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, null)); + null, null, null, null, null, null, null, null, null, null, null, null, null, null)); assertThat(results, notNullValue()); assertThat(get(results), is(empty())); @@ -368,7 +368,7 @@ public void searchForPatients_shouldReturnEmptyCollectionWhenPatientGivenNameNot new SearchQueryBundleProvider<>(theParams, dao, patientTranslator, globalPropertyService, searchQueryInclude)); IBundleProvider results = patientService.searchForPatients(new PatientSearchParams(null, stringAndListParam, null, - null, null, null, null, null, null, null, null, null, null, null, null, null)); + null, null, null, null, null, null, null, null, null, null, null, null, null, null)); assertThat(results, notNullValue()); assertThat(get(results), is(empty())); @@ -385,7 +385,7 @@ public void searchForPatients_shouldReturnEmptyCollectionWhenPatientFamilyNameNo new SearchQueryBundleProvider<>(theParams, dao, patientTranslator, globalPropertyService, searchQueryInclude)); IBundleProvider results = patientService.searchForPatients(new PatientSearchParams(null, null, stringAndListParam, - null, null, null, null, null, null, null, null, null, null, null, null, null)); + null, null, null, null, null, null, null, null, null, null, null, null, null, null)); assertThat(results, notNullValue()); assertThat(get(results), is(empty())); @@ -406,7 +406,7 @@ public void searchForPatients_shouldReturnCollectionOfPatientWhenPatientGenderMa when(patientTranslator.toFhirResource(patient)).thenReturn(fhirPatient); IBundleProvider results = patientService.searchForPatients(new PatientSearchParams(null, null, null, null, - tokenAndListParam, null, null, null, null, null, null, null, null, null, null, null)); + tokenAndListParam, null, null, null, null, null, null, null, null, null, null, null, null)); assertThat(results, notNullValue()); assertThat(get(results), not(empty())); @@ -423,7 +423,7 @@ public void searchForPatients_shouldReturnEmptyCollectionWhenPatientGenderNotMat new SearchQueryBundleProvider<>(theParams, dao, patientTranslator, globalPropertyService, searchQueryInclude)); IBundleProvider results = patientService.searchForPatients(new PatientSearchParams(null, null, null, null, - tokenAndListParam, null, null, null, null, null, null, null, null, null, null, null)); + tokenAndListParam, null, null, null, null, null, null, null, null, null, null, null, null)); assertThat(results, notNullValue()); assertThat(get(results), is(empty())); @@ -449,7 +449,7 @@ public void searchForPatients_shouldReturnCollectionOfPatientWhenPatientBirthDat when(patientTranslator.toFhirResource(patient)).thenReturn(fhirPatient); IBundleProvider results = patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, - dateRangeParam, null, null, null, null, null, null, null, null, null, null)); + dateRangeParam, null, null, null, null, null, null, null, null, null, null, null)); assertThat(results, notNullValue()); assertThat(results.size(), greaterThanOrEqualTo(1)); @@ -466,7 +466,7 @@ public void searchForPatients_shouldReturnEmptyCollectionWhenPatientBirthDateNot new SearchQueryBundleProvider<>(theParams, dao, patientTranslator, globalPropertyService, searchQueryInclude)); IBundleProvider results = patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, - dateRangeParam, null, null, null, null, null, null, null, null, null, null)); + dateRangeParam, null, null, null, null, null, null, null, null, null, null, null)); assertThat(results, notNullValue()); assertThat(get(results), empty()); @@ -492,7 +492,7 @@ public void searchForPatients_shouldReturnCollectionOfPatientWhenPatientDeathDat when(patientTranslator.toFhirResource(patient)).thenReturn(fhirPatient); IBundleProvider results = patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, - null, dateRangeParam, null, null, null, null, null, null, null, null, null)); + null, dateRangeParam, null, null, null, null, null, null, null, null, null, null)); assertThat(results, notNullValue()); assertThat(results.size(), greaterThanOrEqualTo(1)); @@ -509,7 +509,7 @@ public void searchForPatients_shouldReturnEmptyCollectionWhenPatientDeathDateNot new SearchQueryBundleProvider<>(theParams, dao, patientTranslator, globalPropertyService, searchQueryInclude)); IBundleProvider results = patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, - null, dateRangeParam, null, null, null, null, null, null, null, null, null)); + null, dateRangeParam, null, null, null, null, null, null, null, null, null, null)); assertThat(results, notNullValue()); assertThat(get(results), empty()); @@ -531,7 +531,7 @@ public void searchForPatients_shouldReturnCollectionOfPatientWhenPatientCityMatc when(patientTranslator.toFhirResource(patient)).thenReturn(fhirPatient); IBundleProvider results = patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, - null, null, null, stringAndListParam, null, null, null, null, null, null, null)); + null, null, null, stringAndListParam, null, null, null, null, null, null, null, null)); assertThat(results, notNullValue()); assertThat(results.size(), greaterThanOrEqualTo(1)); @@ -548,7 +548,7 @@ public void searchForPatients_shouldReturnEmptyCollectionWhenPatientCityNotMatch new SearchQueryBundleProvider<>(theParams, dao, patientTranslator, globalPropertyService, searchQueryInclude)); IBundleProvider results = patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, - null, null, null, stringAndListParam, null, null, null, null, null, null, null)); + null, null, null, stringAndListParam, null, null, null, null, null, null, null, null)); assertThat(results, notNullValue()); assertThat(get(results), empty()); @@ -570,7 +570,7 @@ public void searchForPatients_shouldReturnCollectionOfPatientWhenPatientStateMat when(patientTranslator.toFhirResource(patient)).thenReturn(fhirPatient); IBundleProvider results = patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, - null, null, null, null, stringAndListParam, null, null, null, null, null, null)); + null, null, null, null, stringAndListParam, null, null, null, null, null, null, null)); assertThat(results, notNullValue()); assertThat(results.size(), greaterThanOrEqualTo(1)); @@ -587,7 +587,7 @@ public void searchForPatients_shouldReturnEmptyCollectionWhenPatientStateNotMatc new SearchQueryBundleProvider<>(theParams, dao, patientTranslator, globalPropertyService, searchQueryInclude)); IBundleProvider results = patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, - null, null, null, null, stringAndListParam, null, null, null, null, null, null)); + null, null, null, null, stringAndListParam, null, null, null, null, null, null, null)); assertThat(results, notNullValue()); assertThat(get(results), empty()); @@ -609,7 +609,7 @@ public void searchForPatients_shouldReturnCollectionOfPatientWhenPatientPostalCo when(patientTranslator.toFhirResource(patient)).thenReturn(fhirPatient); IBundleProvider results = patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, - null, null, null, null, null, stringAndListParam, null, null, null, null, null)); + null, null, null, null, null, stringAndListParam, null, null, null, null, null, null)); assertThat(results, notNullValue()); assertThat(results.size(), greaterThanOrEqualTo(1)); @@ -626,7 +626,7 @@ public void searchForPatients_shouldReturnEmptyCollectionWhenPatientPostalCodeNo new SearchQueryBundleProvider<>(theParams, dao, patientTranslator, globalPropertyService, searchQueryInclude)); IBundleProvider results = patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, - null, null, null, null, null, stringAndListParam, null, null, null, null, null)); + null, null, null, null, null, stringAndListParam, null, null, null, null, null, null)); assertThat(results, notNullValue()); assertThat(get(results), empty()); } @@ -647,7 +647,7 @@ public void searchForPatients_shouldReturnCollectionOfPatientWhenPatientCountryM when(patientTranslator.toFhirResource(patient)).thenReturn(fhirPatient); IBundleProvider results = patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, - null, null, null, null, null, null, stringAndListParam, null, null, null, null)); + null, null, null, null, null, null, stringAndListParam, null, null, null, null, null)); assertThat(results, notNullValue()); assertThat(results.size(), greaterThanOrEqualTo(1)); @@ -664,7 +664,7 @@ public void searchForPatients_shouldReturnEmptyCollectionWhenPatientCountryNotMa new SearchQueryBundleProvider<>(theParams, dao, patientTranslator, globalPropertyService, searchQueryInclude)); IBundleProvider results = patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, - null, null, null, null, null, null, stringAndListParam, null, null, null, null)); + null, null, null, null, null, null, stringAndListParam, null, null, null, null, null)); assertThat(results, notNullValue()); assertThat(get(results), empty()); @@ -685,7 +685,7 @@ public void searchForPatients_shouldReturnCollectionOfPatientWhenUUIDMatched() { when(patientTranslator.toFhirResource(patient)).thenReturn(fhirPatient); IBundleProvider results = patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, - null, null, null, null, null, null, null, uuid, null, null, null)); + null, null, null, null, null, null, null, uuid, null, null, null, null)); assertThat(results, notNullValue()); assertThat(results.size(), greaterThanOrEqualTo(1)); @@ -703,7 +703,7 @@ public void searchForPatients_shouldReturnEmptyCollectionWhenUUIDNotMatched() { new SearchQueryBundleProvider<>(theParams, dao, patientTranslator, globalPropertyService, searchQueryInclude)); IBundleProvider results = patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, - null, null, null, null, null, null, null, uuid, null, null, null)); + null, null, null, null, null, null, null, uuid, null, null, null, null)); assertThat(results, notNullValue()); assertThat(get(results), empty()); @@ -724,7 +724,7 @@ public void searchForPatients_shouldReturnCollectionOfPatientWhenLastUpdatedMatc when(patientTranslator.toFhirResource(patient)).thenReturn(fhirPatient); IBundleProvider results = patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, - null, null, null, null, null, null, null, null, lastUpdated, null, null)); + null, null, null, null, null, null, null, null, null, lastUpdated, null, null)); assertThat(results, notNullValue()); assertThat(results.size(), greaterThanOrEqualTo(1)); @@ -743,7 +743,7 @@ public void searchForPatients_shouldReturnEmptyCollectionWhenLastUpdatedNotMatch new SearchQueryBundleProvider<>(theParams, dao, patientTranslator, globalPropertyService, searchQueryInclude)); IBundleProvider results = patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, - null, null, null, null, null, null, null, null, lastUpdated, null, null)); + null, null, null, null, null, null, null, null, null, lastUpdated, null, null)); assertThat(results, notNullValue()); assertThat(get(results), empty()); @@ -764,7 +764,7 @@ public void searchForPatients_shouldAddReverseIncludedResourcesToResultList() { when(patientTranslator.toFhirResource(patient)).thenReturn(fhirPatient); IBundleProvider results = patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, revIncludes)); + null, null, null, null, null, null, null, null, null, null, null, revIncludes)); List resultList = get(results); @@ -788,7 +788,7 @@ public void searchForPatients_shouldNotAddRelatedResourcesToResultListForEmptyRe when(patientTranslator.toFhirResource(patient)).thenReturn(fhirPatient); IBundleProvider results = patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, revIncludes)); + null, null, null, null, null, null, null, null, null, null, null, revIncludes)); List resultList = get(results); diff --git a/api/src/test/java/org/openmrs/module/fhir2/providers/r3/PatientFhirResourceProviderTest.java b/api/src/test/java/org/openmrs/module/fhir2/providers/r3/PatientFhirResourceProviderTest.java index 5711c33dd..4559012b7 100644 --- a/api/src/test/java/org/openmrs/module/fhir2/providers/r3/PatientFhirResourceProviderTest.java +++ b/api/src/test/java/org/openmrs/module/fhir2/providers/r3/PatientFhirResourceProviderTest.java @@ -30,6 +30,9 @@ import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.param.DateRangeParam; +import ca.uhn.fhir.rest.param.HasAndListParam; +import ca.uhn.fhir.rest.param.HasOrListParam; +import ca.uhn.fhir.rest.param.HasParam; import ca.uhn.fhir.rest.param.StringAndListParam; import ca.uhn.fhir.rest.param.StringOrListParam; import ca.uhn.fhir.rest.param.StringParam; @@ -45,8 +48,10 @@ import org.hl7.fhir.dstu3.model.Patient; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.r4.model.Enumerations; +import org.hl7.fhir.r4.model.Group; import org.hl7.fhir.r4.model.HumanName; import org.hl7.fhir.r4.model.Observation; +import org.hl7.fhir.r4.model.Reference; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -87,6 +92,14 @@ public class PatientFhirResourceProviderTest extends BaseFhirR3ProvenanceResourc private static final String LAST_UPDATED_DATE = "2020-09-03"; + private static final String GROUP_A = "dfb29c44-2e39-46c4-8cd7-18f21c6d47b1"; + + private static final String GROUP_B = "284b505e-798c-4711-8c8f-64d3aa6c0bc1"; + + private static final String PATIENT_1_GROUP_A = "61b38324-e2fd-4feb-95b7-9e9a2a4400df"; + + private static final String PATIENT_2_GROUP_A = "5c521595-4e12-46b0-8248-b8f2d3697766"; + @Mock private FhirPatientService patientService; @@ -217,11 +230,11 @@ public void searchPatients_shouldReturnMatchingBundleOfPatientsByName() { StringAndListParam nameParam = new StringAndListParam().addAnd(new StringOrListParam().add(new StringParam(NAME))); when(patientService.searchForPatients(new PatientSearchParams(nameParam, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null))) + null, null, null, null, null, null, null, null, null))) .thenReturn(new MockIBundleProvider<>(Collections.singletonList(patient), 10, 1)); IBundleProvider results = patientFhirResourceProvider.searchPatients(nameParam, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null); + null, null, null, null, null, null, null, null, null, null); List resources = getResources(results); assertThat(resources, notNullValue()); @@ -235,11 +248,11 @@ public void searchPatients_shouldReturnMatchingBundleOfPatientsByGivenName() { StringAndListParam givenNameParam = new StringAndListParam() .addAnd(new StringOrListParam().add(new StringParam(NAME))); when(patientService.searchForPatients(new PatientSearchParams(null, givenNameParam, null, null, null, null, null, - null, null, null, null, null, null, null, null, null))) + null, null, null, null, null, null, null, null, null, null))) .thenReturn(new MockIBundleProvider<>(Collections.singletonList(patient), 10, 1)); IBundleProvider results = patientFhirResourceProvider.searchPatients(null, givenNameParam, null, null, null, null, - null, null, null, null, null, null, null, null, null, null); + null, null, null, null, null, null, null, null, null, null, null); List resources = getResources(results); assertThat(resources, notNullValue()); @@ -253,11 +266,11 @@ public void searchPatients_shouldReturnMatchingBundleOfPatientsByFamilyName() { StringAndListParam familyNameParam = new StringAndListParam() .addAnd(new StringOrListParam().add(new StringParam(FAMILY_NAME))); when(patientService.searchForPatients(new PatientSearchParams(null, null, familyNameParam, null, null, null, null, - null, null, null, null, null, null, null, null, null))) + null, null, null, null, null, null, null, null, null, null))) .thenReturn(new MockIBundleProvider<>(Collections.singletonList(patient), 10, 1)); IBundleProvider results = patientFhirResourceProvider.searchPatients(null, null, familyNameParam, null, null, null, - null, null, null, null, null, null, null, null, null, null); + null, null, null, null, null, null, null, null, null, null, null); List resources = getResources(results); assertThat(resources, notNullValue()); @@ -270,11 +283,11 @@ public void searchPatients_shouldReturnMatchingBundleOfPatientsByFamilyName() { public void searchPatients_shouldReturnMatchingBundleOfPatientsByIdentifier() { TokenAndListParam identifierParam = new TokenAndListParam().addAnd(new TokenOrListParam().add(IDENTIFIER)); when(patientService.searchForPatients(new PatientSearchParams(null, null, null, identifierParam, null, null, null, - null, null, null, null, null, null, null, null, null))) + null, null, null, null, null, null, null, null, null, null))) .thenReturn(new MockIBundleProvider<>(Collections.singletonList(patient), 10, 1)); IBundleProvider results = patientFhirResourceProvider.searchPatients(null, null, null, identifierParam, null, null, - null, null, null, null, null, null, null, null, null, null); + null, null, null, null, null, null, null, null, null, null, null); List resources = getResources(results); assertThat(resources, notNullValue()); @@ -287,11 +300,11 @@ public void searchPatients_shouldReturnMatchingBundleOfPatientsByIdentifier() { public void searchForPatients_shouldReturnMatchingBundleOfPatientsByGender() { TokenAndListParam genderParam = new TokenAndListParam().addAnd(new TokenOrListParam().add(GENDER)); when(patientService.searchForPatients(new PatientSearchParams(null, null, null, null, genderParam, null, null, null, - null, null, null, null, null, null, null, null))) + null, null, null, null, null, null, null, null, null))) .thenReturn(new MockIBundleProvider<>(Collections.singletonList(patient), 10, 1)); IBundleProvider results = patientFhirResourceProvider.searchPatients(null, null, null, null, genderParam, null, null, - null, null, null, null, null, null, null, null, null); + null, null, null, null, null, null, null, null, null, null); List resources = getResources(results); assertThat(resources, notNullValue()); @@ -304,11 +317,11 @@ public void searchForPatients_shouldReturnMatchingBundleOfPatientsByGender() { public void searchForPatients_shouldReturnMatchingBundleOfPatientsByBirthDate() { DateRangeParam birthDateParam = new DateRangeParam().setLowerBound(BIRTH_DATE).setUpperBound(BIRTH_DATE); when(patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, birthDateParam, null, - null, null, null, null, null, null, null, null, null))) + null, null, null, null, null, null, null, null, null, null))) .thenReturn(new MockIBundleProvider<>(Collections.singletonList(patient), 10, 1)); IBundleProvider results = patientFhirResourceProvider.searchPatients(null, null, null, null, null, birthDateParam, - null, null, null, null, null, null, null, null, null, null); + null, null, null, null, null, null, null, null, null, null, null); List resources = getResources(results); assertThat(resources, notNullValue()); @@ -321,11 +334,11 @@ public void searchForPatients_shouldReturnMatchingBundleOfPatientsByBirthDate() public void searchForPatients_shouldReturnMatchingBundleOfPatientsByDeathDate() { DateRangeParam deathDateParam = new DateRangeParam().setLowerBound(DEATH_DATE).setUpperBound(DEATH_DATE); when(patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, null, deathDateParam, - null, null, null, null, null, null, null, null, null))) + null, null, null, null, null, null, null, null, null, null))) .thenReturn(new MockIBundleProvider<>(Collections.singletonList(patient), 10, 1)); IBundleProvider results = patientFhirResourceProvider.searchPatients(null, null, null, null, null, null, - deathDateParam, null, null, null, null, null, null, null, null, null); + deathDateParam, null, null, null, null, null, null, null, null, null, null); List resources = getResources(results); assertThat(resources, notNullValue()); @@ -338,11 +351,11 @@ public void searchForPatients_shouldReturnMatchingBundleOfPatientsByDeathDate() public void searchForPatients_shouldReturnMatchingBundleOfPatientsByDeceased() { TokenAndListParam deceasedParam = new TokenAndListParam().addAnd(new TokenOrListParam().add("true")); when(patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, null, null, - deceasedParam, null, null, null, null, null, null, null, null))) + deceasedParam, null, null, null, null, null, null, null, null, null))) .thenReturn(new MockIBundleProvider<>(Collections.singletonList(patient), 10, 1)); IBundleProvider results = patientFhirResourceProvider.searchPatients(null, null, null, null, null, null, null, - deceasedParam, null, null, null, null, null, null, null, null); + deceasedParam, null, null, null, null, null, null, null, null, null); List resources = getResources(results); assertThat(resources, notNullValue()); @@ -355,11 +368,11 @@ public void searchForPatients_shouldReturnMatchingBundleOfPatientsByDeceased() { public void searchForPatients_shouldReturnMatchingBundleOfPatientsByCity() { StringAndListParam cityParam = new StringAndListParam().addAnd(new StringOrListParam().add(new StringParam(CITY))); when(patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, null, null, null, - cityParam, null, null, null, null, null, null, null))) + cityParam, null, null, null, null, null, null, null, null))) .thenReturn(new MockIBundleProvider<>(Collections.singletonList(patient), 10, 1)); IBundleProvider results = patientFhirResourceProvider.searchPatients(null, null, null, null, null, null, null, null, - cityParam, null, null, null, null, null, null, null); + cityParam, null, null, null, null, null, null, null, null); List resources = getResources(results); assertThat(resources, notNullValue()); @@ -372,11 +385,11 @@ public void searchForPatients_shouldReturnMatchingBundleOfPatientsByCity() { public void searchForPatients_shouldReturnMatchingBundleOfPatientsByState() { StringAndListParam stateParam = new StringAndListParam().addAnd(new StringOrListParam().add(new StringParam(STATE))); when(patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, null, null, null, null, - stateParam, null, null, null, null, null, null))) + stateParam, null, null, null, null, null, null, null))) .thenReturn(new MockIBundleProvider<>(Collections.singletonList(patient), 10, 1)); IBundleProvider results = patientFhirResourceProvider.searchPatients(null, null, null, null, null, null, null, null, - null, stateParam, null, null, null, null, null, null); + null, stateParam, null, null, null, null, null, null, null); List resources = getResources(results); assertThat(resources, notNullValue()); @@ -390,11 +403,11 @@ public void searchForPatients_shouldReturnMatchingBundleOfPatientsByPostalCode() StringAndListParam postalCodeParam = new StringAndListParam() .addAnd(new StringOrListParam().add(new StringParam(POSTAL_CODE))); when(patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, null, null, null, null, - null, postalCodeParam, null, null, null, null, null))) + null, postalCodeParam, null, null, null, null, null, null))) .thenReturn(new MockIBundleProvider<>(Collections.singletonList(patient), 10, 1)); IBundleProvider results = patientFhirResourceProvider.searchPatients(null, null, null, null, null, null, null, null, - null, null, postalCodeParam, null, null, null, null, null); + null, null, postalCodeParam, null, null, null, null, null, null); List resources = getResources(results); assertThat(resources, notNullValue()); @@ -408,11 +421,11 @@ public void searchForPatients_shouldReturnMatchingBundleOfPatientsByCountry() { StringAndListParam countryParam = new StringAndListParam() .addAnd(new StringOrListParam().add(new StringParam(COUNTRY))); when(patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, null, null, null, null, - null, null, countryParam, null, null, null, null))) + null, null, countryParam, null, null, null, null, null))) .thenReturn(new MockIBundleProvider<>(Collections.singletonList(patient), 10, 1)); IBundleProvider results = patientFhirResourceProvider.searchPatients(null, null, null, null, null, null, null, null, - null, null, null, countryParam, null, null, null, null); + null, null, null, countryParam, null, null, null, null, null); List resources = getResources(results); assertThat(resources, notNullValue()); @@ -426,11 +439,11 @@ public void searchForPatients_shouldReturnMatchingBundleOfPatientsByUUID() { TokenAndListParam uuid = new TokenAndListParam().addAnd(new TokenParam(PATIENT_UUID)); when(patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, null, null, null, null, - null, null, null, uuid, null, null, null))) + null, null, null, uuid, null, null, null, null))) .thenReturn(new MockIBundleProvider<>(Collections.singletonList(patient), 10, 1)); IBundleProvider results = patientFhirResourceProvider.searchPatients(null, null, null, null, null, null, null, null, - null, null, null, null, uuid, null, null, null); + null, null, null, null, uuid, null, null, null, null); List resources = getResources(results); assertThat(resources, notNullValue()); @@ -444,11 +457,11 @@ public void searchForPatients_shouldReturnMatchingBundleOfPatientsByLastUpdated( DateRangeParam lastUpdated = new DateRangeParam().setLowerBound(LAST_UPDATED_DATE).setUpperBound(LAST_UPDATED_DATE); when(patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, null, null, null, null, - null, null, null, null, lastUpdated, null, null))) + null, null, null, null, null, lastUpdated, null, null))) .thenReturn(new MockIBundleProvider<>(Collections.singletonList(patient), 10, 1)); IBundleProvider results = patientFhirResourceProvider.searchPatients(null, null, null, null, null, null, null, null, - null, null, null, null, null, lastUpdated, null, null); + null, null, null, null, null, null, lastUpdated, null, null); List resources = getResources(results); assertThat(resources, notNullValue()); @@ -463,11 +476,11 @@ public void searchForPatients_shouldAddRelatedResourcesForRevInclude() { revIncludes.add(new Include("Observation:patient")); when(patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, revIncludes))) + null, null, null, null, null, null, null, revIncludes))) .thenReturn(new MockIBundleProvider<>(Arrays.asList(patient, new Observation()), 10, 1)); IBundleProvider results = patientFhirResourceProvider.searchPatients(null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, revIncludes); + null, null, null, null, null, null, null, null, revIncludes); List resultList = getResources(results); @@ -481,13 +494,13 @@ public void searchForPatients_shouldAddRelatedResourcesForRevInclude() { @Test public void searchForPatients_shouldNotAddResourcesForEmptyRevInclude() { when(patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null))) + null, null, null, null, null, null, null, null))) .thenReturn(new MockIBundleProvider<>(Collections.singletonList(patient), 10, 1)); HashSet revIncludes = new HashSet<>(); IBundleProvider results = patientFhirResourceProvider.searchPatients(null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, revIncludes); + null, null, null, null, null, null, null, null, revIncludes); List resultList = getResources(results); @@ -497,6 +510,64 @@ public void searchForPatients_shouldNotAddResourcesForEmptyRevInclude() { assertThat(((Patient) resultList.iterator().next()).getId(), equalTo(PATIENT_UUID)); } + @Test + public void searchForPatients_shouldReturnMatchingBundleOfPatientsByGroup() { + // Prepare patient and group + Group group = new Group(); + group.setActive(true); + group.addMember(new Group.GroupMemberComponent(new Reference("Patient/" + patient.getId()))); + + HasAndListParam groupParam = new HasAndListParam().addAnd( + new HasOrListParam().add(new HasParam(FhirConstants.GROUP, FhirConstants.INCLUDE_MEMBER_PARAM, "id", GROUP_B))); + + when(patientService.searchForPatients(any(PatientSearchParams.class))) + .thenReturn(new org.openmrs.module.fhir2.providers.r4.MockIBundleProvider<>(Arrays.asList(patient), 10, 1)); + + IBundleProvider results = patientFhirResourceProvider.searchPatients(null, null, null, null, null, null, null, null, + null, null, null, null, null, groupParam, null, null, null); + List resources = getResources(results); + + assertThat(resources, notNullValue()); + assertThat(resources, hasSize(equalTo(1))); + assertThat(resources.get(0).fhirType(), is(FhirConstants.PATIENT)); + assertThat(resources.get(0).getIdElement().getIdPart(), is(PATIENT_UUID)); + } + + @Test + public void searchForPatients_shouldReturnMatchingBundleOfPatientsInGroups() { + // Prepare pateints and groups + org.hl7.fhir.r4.model.Patient patient1_grpA = new org.hl7.fhir.r4.model.Patient(); + org.hl7.fhir.r4.model.Patient patient2_grpA = new org.hl7.fhir.r4.model.Patient(); + patient1_grpA.setId(PATIENT_1_GROUP_A); + patient2_grpA.setId(PATIENT_2_GROUP_A); + + Group groupA = new Group(); + groupA.setActive(true); + groupA.addMember(new Group.GroupMemberComponent(new Reference("Patient/" + patient1_grpA.getId()))); + groupA.addMember(new Group.GroupMemberComponent(new Reference("Patient/" + patient2_grpA.getId()))); + + Group groupB = new Group(); + groupB.setActive(true); + groupB.addMember(new Group.GroupMemberComponent(new Reference("Patient/" + patient.getId()))); + + HasAndListParam groupParam = new HasAndListParam().addAnd(new HasOrListParam() + .add(new HasParam(FhirConstants.GROUP, FhirConstants.INCLUDE_MEMBER_PARAM, "id", GROUP_A + "," + GROUP_B))); + + when(patientService.searchForPatients(any(PatientSearchParams.class))) + .thenReturn(new org.openmrs.module.fhir2.providers.r4.MockIBundleProvider<>( + Arrays.asList(patient, patient1_grpA, patient2_grpA), 10, 3)); + + IBundleProvider results = patientFhirResourceProvider.searchPatients(null, null, null, null, null, null, null, null, + null, null, null, null, null, groupParam, null, null, null); + List resources = getResources(results); + + assertThat(resources, notNullValue()); + assertThat(resources, hasSize(equalTo(3))); + assertThat(resources.get(0).getIdElement().getIdPart(), is(PATIENT_UUID)); + assertThat(resources.get(1).getIdElement().getIdPart(), is(PATIENT_1_GROUP_A)); + assertThat(resources.get(2).getIdElement().getIdPart(), is(PATIENT_2_GROUP_A)); + } + @Test public void searchForPatients_shouldReturnPatientEverything() { when(patientService.getPatientEverything(any())) diff --git a/api/src/test/java/org/openmrs/module/fhir2/providers/r4/PatientFhirResourceProviderTest.java b/api/src/test/java/org/openmrs/module/fhir2/providers/r4/PatientFhirResourceProviderTest.java index c8894eaae..eec902141 100644 --- a/api/src/test/java/org/openmrs/module/fhir2/providers/r4/PatientFhirResourceProviderTest.java +++ b/api/src/test/java/org/openmrs/module/fhir2/providers/r4/PatientFhirResourceProviderTest.java @@ -29,6 +29,9 @@ import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.param.DateRangeParam; +import ca.uhn.fhir.rest.param.HasAndListParam; +import ca.uhn.fhir.rest.param.HasOrListParam; +import ca.uhn.fhir.rest.param.HasParam; import ca.uhn.fhir.rest.param.StringAndListParam; import ca.uhn.fhir.rest.param.StringOrListParam; import ca.uhn.fhir.rest.param.StringParam; @@ -40,11 +43,13 @@ import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.r4.model.Enumerations; +import org.hl7.fhir.r4.model.Group; import org.hl7.fhir.r4.model.HumanName; import org.hl7.fhir.r4.model.IdType; import org.hl7.fhir.r4.model.Observation; import org.hl7.fhir.r4.model.OperationOutcome; import org.hl7.fhir.r4.model.Patient; +import org.hl7.fhir.r4.model.Reference; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -86,6 +91,14 @@ public class PatientFhirResourceProviderTest extends BaseFhirProvenanceResourceT private static final String LAST_UPDATED_DATE = "2020-09-03"; + private static final String GROUP_A = "dfb29c44-2e39-46c4-8cd7-18f21c6d47b1"; + + private static final String GROUP_B = "284b505e-798c-4711-8c8f-64d3aa6c0bc1"; + + private static final String PATIENT_1_GROUP_A = "61b38324-e2fd-4feb-95b7-9e9a2a4400df"; + + private static final String PATIENT_2_GROUP_A = "5c521595-4e12-46b0-8248-b8f2d3697766"; + @Mock private FhirPatientService patientService; @@ -201,11 +214,11 @@ public void deletePatient_shouldDeleteRequestedPatient() { public void searchPatients_shouldReturnMatchingBundleOfPatientsByName() { StringAndListParam nameParam = new StringAndListParam().addAnd(new StringOrListParam().add(new StringParam(NAME))); when(patientService.searchForPatients(new PatientSearchParams(nameParam, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null))) + null, null, null, null, null, null, null, null, null))) .thenReturn(new MockIBundleProvider<>(Collections.singletonList(patient), 10, 1)); IBundleProvider results = resourceProvider.searchPatients(nameParam, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null); + null, null, null, null, null, null, null, null); List resources = getResources(results); assertThat(resources, notNullValue()); @@ -219,11 +232,11 @@ public void searchPatients_shouldReturnMatchingBundleOfPatientsByGivenName() { StringAndListParam givenNameParam = new StringAndListParam() .addAnd(new StringOrListParam().add(new StringParam(NAME))); when(patientService.searchForPatients(new PatientSearchParams(null, givenNameParam, null, null, null, null, null, - null, null, null, null, null, null, null, null, null))) + null, null, null, null, null, null, null, null, null, null))) .thenReturn(new MockIBundleProvider<>(Collections.singletonList(patient), 10, 1)); IBundleProvider results = resourceProvider.searchPatients(null, givenNameParam, null, null, null, null, null, null, - null, null, null, null, null, null, null, null); + null, null, null, null, null, null, null, null, null); List resources = getResources(results); assertThat(resources, notNullValue()); @@ -237,11 +250,11 @@ public void searchPatients_shouldReturnMatchingBundleOfPatientsByFamilyName() { StringAndListParam familyNameParam = new StringAndListParam() .addAnd(new StringOrListParam().add(new StringParam(FAMILY_NAME))); when(patientService.searchForPatients(new PatientSearchParams(null, null, familyNameParam, null, null, null, null, - null, null, null, null, null, null, null, null, null))) + null, null, null, null, null, null, null, null, null, null))) .thenReturn(new MockIBundleProvider<>(Collections.singletonList(patient), 10, 1)); IBundleProvider results = resourceProvider.searchPatients(null, null, familyNameParam, null, null, null, null, null, - null, null, null, null, null, null, null, null); + null, null, null, null, null, null, null, null, null); List resources = getResources(results); assertThat(resources, notNullValue()); @@ -254,11 +267,11 @@ public void searchPatients_shouldReturnMatchingBundleOfPatientsByFamilyName() { public void searchPatients_shouldReturnMatchingBundleOfPatientsByIdentifier() { TokenAndListParam identifierParam = new TokenAndListParam().addAnd(new TokenOrListParam().add(IDENTIFIER)); when(patientService.searchForPatients(new PatientSearchParams(null, null, null, identifierParam, null, null, null, - null, null, null, null, null, null, null, null, null))) + null, null, null, null, null, null, null, null, null, null))) .thenReturn(new MockIBundleProvider<>(Collections.singletonList(patient), 10, 1)); IBundleProvider results = resourceProvider.searchPatients(null, null, null, identifierParam, null, null, null, null, - null, null, null, null, null, null, null, null); + null, null, null, null, null, null, null, null, null); List resources = getResources(results); assertThat(resources, notNullValue()); @@ -271,11 +284,11 @@ public void searchPatients_shouldReturnMatchingBundleOfPatientsByIdentifier() { public void searchForPatients_shouldReturnMatchingBundleOfPatientsByGender() { TokenAndListParam genderParam = new TokenAndListParam().addAnd(new TokenOrListParam().add(GENDER)); when(patientService.searchForPatients(new PatientSearchParams(null, null, null, null, genderParam, null, null, null, - null, null, null, null, null, null, null, null))) + null, null, null, null, null, null, null, null, null))) .thenReturn(new MockIBundleProvider<>(Collections.singletonList(patient), 10, 1)); IBundleProvider results = resourceProvider.searchPatients(null, null, null, null, genderParam, null, null, null, - null, null, null, null, null, null, null, null); + null, null, null, null, null, null, null, null, null); List resources = getResources(results); assertThat(resources, notNullValue()); @@ -288,11 +301,11 @@ public void searchForPatients_shouldReturnMatchingBundleOfPatientsByGender() { public void searchForPatients_shouldReturnMatchingBundleOfPatientsByBirthDate() { DateRangeParam birthDateParam = new DateRangeParam().setLowerBound(BIRTH_DATE).setUpperBound(BIRTH_DATE); when(patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, birthDateParam, null, - null, null, null, null, null, null, null, null, null))) + null, null, null, null, null, null, null, null, null, null))) .thenReturn(new MockIBundleProvider<>(Collections.singletonList(patient), 10, 1)); IBundleProvider results = resourceProvider.searchPatients(null, null, null, null, null, birthDateParam, null, null, - null, null, null, null, null, null, null, null); + null, null, null, null, null, null, null, null, null); List resources = getResources(results); assertThat(resources, notNullValue()); @@ -305,11 +318,11 @@ public void searchForPatients_shouldReturnMatchingBundleOfPatientsByBirthDate() public void searchForPatients_shouldReturnMatchingBundleOfPatientsByDeathDate() { DateRangeParam deathDateParam = new DateRangeParam().setLowerBound(DEATH_DATE).setUpperBound(DEATH_DATE); when(patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, null, deathDateParam, - null, null, null, null, null, null, null, null, null))) + null, null, null, null, null, null, null, null, null, null))) .thenReturn(new MockIBundleProvider<>(Collections.singletonList(patient), 10, 1)); IBundleProvider results = resourceProvider.searchPatients(null, null, null, null, null, null, deathDateParam, null, - null, null, null, null, null, null, null, null); + null, null, null, null, null, null, null, null, null); List resources = getResources(results); assertThat(resources, notNullValue()); @@ -322,11 +335,11 @@ public void searchForPatients_shouldReturnMatchingBundleOfPatientsByDeathDate() public void searchForPatients_shouldReturnMatchingBundleOfPatientsByDeceased() { TokenAndListParam deceasedParam = new TokenAndListParam().addAnd(new TokenOrListParam().add("true")); when(patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, null, null, - deceasedParam, null, null, null, null, null, null, null, null))) + deceasedParam, null, null, null, null, null, null, null, null, null))) .thenReturn(new MockIBundleProvider<>(Collections.singletonList(patient), 10, 1)); IBundleProvider results = resourceProvider.searchPatients(null, null, null, null, null, null, null, deceasedParam, - null, null, null, null, null, null, null, null); + null, null, null, null, null, null, null, null, null); List resources = getResources(results); assertThat(resources, notNullValue()); @@ -339,11 +352,11 @@ public void searchForPatients_shouldReturnMatchingBundleOfPatientsByDeceased() { public void searchForPatients_shouldReturnMatchingBundleOfPatientsByCity() { StringAndListParam cityParam = new StringAndListParam().addAnd(new StringOrListParam().add(new StringParam(CITY))); when(patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, null, null, null, - cityParam, null, null, null, null, null, null, null))) + cityParam, null, null, null, null, null, null, null, null))) .thenReturn(new MockIBundleProvider<>(Collections.singletonList(patient), 10, 1)); IBundleProvider results = resourceProvider.searchPatients(null, null, null, null, null, null, null, null, cityParam, - null, null, null, null, null, null, null); + null, null, null, null, null, null, null, null); List resources = getResources(results); assertThat(resources, notNullValue()); @@ -356,11 +369,11 @@ public void searchForPatients_shouldReturnMatchingBundleOfPatientsByCity() { public void searchForPatients_shouldReturnMatchingBundleOfPatientsByState() { StringAndListParam stateParam = new StringAndListParam().addAnd(new StringOrListParam().add(new StringParam(STATE))); when(patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, null, null, null, null, - stateParam, null, null, null, null, null, null))) + stateParam, null, null, null, null, null, null, null))) .thenReturn(new MockIBundleProvider<>(Collections.singletonList(patient), 10, 1)); IBundleProvider results = resourceProvider.searchPatients(null, null, null, null, null, null, null, null, null, - stateParam, null, null, null, null, null, null); + stateParam, null, null, null, null, null, null, null); List resources = getResources(results); assertThat(resources, notNullValue()); @@ -374,11 +387,11 @@ public void searchForPatients_shouldReturnMatchingBundleOfPatientsByPostalCode() StringAndListParam postalCodeParam = new StringAndListParam() .addAnd(new StringOrListParam().add(new StringParam(POSTAL_CODE))); when(patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, null, null, null, null, - null, postalCodeParam, null, null, null, null, null))) + null, postalCodeParam, null, null, null, null, null, null))) .thenReturn(new MockIBundleProvider<>(Collections.singletonList(patient), 10, 1)); IBundleProvider results = resourceProvider.searchPatients(null, null, null, null, null, null, null, null, null, null, - postalCodeParam, null, null, null, null, null); + postalCodeParam, null, null, null, null, null, null); List resources = getResources(results); assertThat(resources, notNullValue()); @@ -392,11 +405,11 @@ public void searchForPatients_shouldReturnMatchingBundleOfPatientsByCountry() { StringAndListParam countryParam = new StringAndListParam() .addAnd(new StringOrListParam().add(new StringParam(COUNTRY))); when(patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, null, null, null, null, - null, null, countryParam, null, null, null, null))) + null, null, countryParam, null, null, null, null, null))) .thenReturn(new MockIBundleProvider<>(Collections.singletonList(patient), 10, 1)); IBundleProvider results = resourceProvider.searchPatients(null, null, null, null, null, null, null, null, null, null, - null, countryParam, null, null, null, null); + null, countryParam, null, null, null, null, null); List resources = getResources(results); assertThat(resources, notNullValue()); @@ -410,11 +423,11 @@ public void searchForPatients_shouldReturnMatchingBundleOfPatientsByUUID() { TokenAndListParam uuid = new TokenAndListParam().addAnd(new TokenParam(PATIENT_UUID)); when(patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, null, null, null, null, - null, null, null, uuid, null, null, null))) + null, null, null, uuid, null, null, null, null))) .thenReturn(new MockIBundleProvider<>(Collections.singletonList(patient), 10, 1)); IBundleProvider results = resourceProvider.searchPatients(null, null, null, null, null, null, null, null, null, null, - null, null, uuid, null, null, null); + null, null, uuid, null, null, null, null); List resources = getResources(results); assertThat(resources, notNullValue()); @@ -428,11 +441,11 @@ public void searchForPatients_shouldReturnMatchingBundleOfPatientsByLastUpdated( DateRangeParam lastUpdated = new DateRangeParam().setLowerBound(LAST_UPDATED_DATE).setUpperBound(LAST_UPDATED_DATE); when(patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, null, null, null, null, - null, null, null, null, lastUpdated, null, null))) + null, null, null, null, null, lastUpdated, null, null))) .thenReturn(new MockIBundleProvider<>(Collections.singletonList(patient), 10, 1)); IBundleProvider results = resourceProvider.searchPatients(null, null, null, null, null, null, null, null, null, null, - null, null, null, lastUpdated, null, null); + null, null, null, null, lastUpdated, null, null); List resources = getResources(results); assertThat(resources, notNullValue()); @@ -447,11 +460,11 @@ public void searchForPatients_shouldAddRelatedResourcesForRevInclude() { revIncludes.add(new Include("Observation:patient")); when(patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, revIncludes))) + null, null, null, null, null, null, null, revIncludes))) .thenReturn(new MockIBundleProvider<>(Arrays.asList(patient, new Observation()), 10, 1)); IBundleProvider results = resourceProvider.searchPatients(null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, revIncludes); + null, null, null, null, null, null, revIncludes); List resultList = getResources(results); @@ -465,13 +478,13 @@ public void searchForPatients_shouldAddRelatedResourcesForRevInclude() { @Test public void searchForPatients_shouldNotAddResourcesForEmptyRevInclude() { when(patientService.searchForPatients(new PatientSearchParams(null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null))) + null, null, null, null, null, null, null, null))) .thenReturn(new MockIBundleProvider<>(Collections.singletonList(patient), 10, 1)); HashSet revIncludes = new HashSet<>(); IBundleProvider results = resourceProvider.searchPatients(null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, revIncludes); + null, null, null, null, null, null, revIncludes); List resultList = getResources(results); @@ -481,6 +494,63 @@ public void searchForPatients_shouldNotAddResourcesForEmptyRevInclude() { assertThat(((Patient) resultList.iterator().next()).getId(), equalTo(PATIENT_UUID)); } + @Test + public void searchForPatients_shouldReturnMatchingBundleOfPatientsByGroup() { + // Prepare patient and group + Group group = new Group(); + group.setActive(true); + group.addMember(new Group.GroupMemberComponent(new Reference("Patient/" + patient.getId()))); + + HasAndListParam groupParam = new HasAndListParam().addAnd( + new HasOrListParam().add(new HasParam(FhirConstants.GROUP, FhirConstants.INCLUDE_MEMBER_PARAM, "id", GROUP_B))); + + when(patientService.searchForPatients(any(PatientSearchParams.class))) + .thenReturn(new MockIBundleProvider<>(Arrays.asList(patient), 10, 1)); + + IBundleProvider results = resourceProvider.searchPatients(null, null, null, null, null, null, null, null, null, null, + null, null, null, groupParam, null, null, null); + List resources = getResources(results); + + assertThat(resources, notNullValue()); + assertThat(resources, hasSize(equalTo(1))); + assertThat(resources.get(0).fhirType(), is(FhirConstants.PATIENT)); + assertThat(resources.get(0).getIdElement().getIdPart(), is(PATIENT_UUID)); + } + + @Test + public void searchForPatients_shouldReturnMatchingBundleOfPatientsInGroups() { + // Prepare patients and groups + Patient patient1_grpA = new Patient(); + Patient patient2_grpA = new Patient(); + patient1_grpA.setId(PATIENT_1_GROUP_A); + patient2_grpA.setId(PATIENT_2_GROUP_A); + + Group groupA = new Group(); + groupA.setActive(true); + groupA.addMember(new Group.GroupMemberComponent(new Reference("Patient/" + patient1_grpA.getId()))); + groupA.addMember(new Group.GroupMemberComponent(new Reference("Patient/" + patient2_grpA.getId()))); + + Group groupB = new Group(); + groupB.setActive(true); + groupB.addMember(new Group.GroupMemberComponent(new Reference("Patient/" + patient.getId()))); + + HasAndListParam groupParam = new HasAndListParam().addAnd(new HasOrListParam() + .add(new HasParam(FhirConstants.GROUP, FhirConstants.INCLUDE_MEMBER_PARAM, "id", GROUP_A + "," + GROUP_B))); + + when(patientService.searchForPatients(any(PatientSearchParams.class))) + .thenReturn(new MockIBundleProvider<>(Arrays.asList(patient, patient1_grpA, patient2_grpA), 10, 3)); + + IBundleProvider results = resourceProvider.searchPatients(null, null, null, null, null, null, null, null, null, null, + null, null, null, groupParam, null, null, null); + List resources = getResources(results); + + assertThat(resources, notNullValue()); + assertThat(resources, hasSize(equalTo(3))); + assertThat(resources.get(0).getIdElement().getIdPart(), is(PATIENT_UUID)); + assertThat(resources.get(1).getIdElement().getIdPart(), is(PATIENT_1_GROUP_A)); + assertThat(resources.get(2).getIdElement().getIdPart(), is(PATIENT_2_GROUP_A)); + } + @Test public void searchForPatients_shouldReturnPatientEverything() { when(patientService.getPatientEverything(any())) diff --git a/omod/src/test/java/org/openmrs/module/fhir2/providers/r4/PatientFhirResourceProviderWebTest.java b/omod/src/test/java/org/openmrs/module/fhir2/providers/r4/PatientFhirResourceProviderWebTest.java index 4ed9e51e8..46cda472f 100644 --- a/omod/src/test/java/org/openmrs/module/fhir2/providers/r4/PatientFhirResourceProviderWebTest.java +++ b/omod/src/test/java/org/openmrs/module/fhir2/providers/r4/PatientFhirResourceProviderWebTest.java @@ -31,13 +31,17 @@ import javax.servlet.ServletException; import java.io.InputStream; +import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Objects; import ca.uhn.fhir.model.api.Include; import ca.uhn.fhir.rest.param.DateRangeParam; +import ca.uhn.fhir.rest.param.HasAndListParam; +import ca.uhn.fhir.rest.param.HasOrListParam; import ca.uhn.fhir.rest.param.StringAndListParam; import ca.uhn.fhir.rest.param.TokenAndListParam; import ca.uhn.fhir.rest.param.TokenParam; @@ -495,6 +499,32 @@ public void shouldGetPatientByLastUpdatedDate() throws Exception { equalTo(DateUtils.truncate(calendar.getTime(), Calendar.DATE))); } + @Test + public void shouldHandleHasAndListParameterForGroupMemberId() throws Exception { + verifyUri("/Patient?_has:Group:member:id=123e4567-e89b-12d3-a456-426614174000,abcdefab-1234-abcd-1234-abcdefabcdef"); + + verify(patientService).searchForPatients(patientSearchParamsCaptor.capture()); + HasAndListParam hasAndListParam = patientSearchParamsCaptor.getValue().getHasAndListParam(); + + List hasOrListParams = hasAndListParam.getValuesAsQueryTokens(); + assertThat(hasOrListParams.size(), equalTo(1)); + + List valuesFound = new ArrayList<>(); + for (HasOrListParam hasOrListParam : hasOrListParams) { + hasOrListParam.getValuesAsQueryTokens().forEach(hasParam -> { + assertThat(hasParam.getTargetResourceType(), equalTo(FhirConstants.GROUP)); + assertThat(hasParam.getReferenceFieldName(), equalTo(FhirConstants.INCLUDE_MEMBER_PARAM)); + assertThat(hasParam.getParameterName(), equalTo("id")); + valuesFound.add(hasParam.getParameterValue()); + }); + } + Collections.sort(valuesFound); + + assertThat(valuesFound.size(), equalTo(2)); + assertThat(valuesFound.get(0), equalTo("123e4567-e89b-12d3-a456-426614174000")); + assertThat(valuesFound.get(1), equalTo("abcdefab-1234-abcd-1234-abcdefabcdef")); + } + @Test public void shouldAddReverseIncludedObservationsToReturnedResults() throws Exception { verifyUri("/Patient?_revinclude=Observation:patient"); diff --git a/test-data/src/main/resources/org/openmrs/module/fhir2/api/dao/impl/FhirPatientDaoImplTest_initial_data.xml b/test-data/src/main/resources/org/openmrs/module/fhir2/api/dao/impl/FhirPatientDaoImplTest_initial_data.xml index 4e1c7d11b..d0bdfa0a5 100644 --- a/test-data/src/main/resources/org/openmrs/module/fhir2/api/dao/impl/FhirPatientDaoImplTest_initial_data.xml +++ b/test-data/src/main/resources/org/openmrs/module/fhir2/api/dao/impl/FhirPatientDaoImplTest_initial_data.xml @@ -20,12 +20,14 @@ + + @@ -33,10 +35,19 @@ + + + + + + + + +