diff --git a/api/src/main/java/org/openmrs/module/cohort/api/CohortService.java b/api/src/main/java/org/openmrs/module/cohort/api/CohortService.java index 25d94fb..2bde513 100644 --- a/api/src/main/java/org/openmrs/module/cohort/api/CohortService.java +++ b/api/src/main/java/org/openmrs/module/cohort/api/CohortService.java @@ -12,6 +12,7 @@ import javax.validation.constraints.NotNull; import java.util.Collection; +import java.util.Date; import java.util.List; import java.util.Map; @@ -68,4 +69,6 @@ public interface CohortService extends OpenmrsService { //Search List findMatchingCohorts(String nameMatching, Map attributes, CohortType cohortType, boolean includeVoided); + + Collection findCohortsByMembership(String patientUuid, Date startDate, Date endDate, boolean includeVoided); } diff --git a/api/src/main/java/org/openmrs/module/cohort/api/dao/search/AbstractSearchHandler.java b/api/src/main/java/org/openmrs/module/cohort/api/dao/search/AbstractSearchHandler.java index a70ccc7..fe88be5 100644 --- a/api/src/main/java/org/openmrs/module/cohort/api/dao/search/AbstractSearchHandler.java +++ b/api/src/main/java/org/openmrs/module/cohort/api/dao/search/AbstractSearchHandler.java @@ -22,7 +22,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; -public abstract class AbstractSearchHandler implements ISearchQuery { +public abstract class AbstractSearchHandler { @Autowired @Qualifier("sessionFactory") diff --git a/api/src/main/java/org/openmrs/module/cohort/api/dao/search/CohortSearchHandler.java b/api/src/main/java/org/openmrs/module/cohort/api/dao/search/CohortSearchHandler.java new file mode 100644 index 0000000..2729f0e --- /dev/null +++ b/api/src/main/java/org/openmrs/module/cohort/api/dao/search/CohortSearchHandler.java @@ -0,0 +1,44 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under + * the terms of the Healthcare Disclaimer located at http://openmrs.org/license. + * + * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS + * graphic logo is a trademark of OpenMRS Inc. + */ +package org.openmrs.module.cohort.api.dao.search; + +import javax.validation.constraints.NotNull; + +import java.util.Collection; +import java.util.Date; + +import lombok.extern.slf4j.Slf4j; +import org.hibernate.Criteria; +import org.hibernate.criterion.Restrictions; +import org.openmrs.module.cohort.CohortM; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +@SuppressWarnings("unchecked") +public class CohortSearchHandler extends AbstractSearchHandler { + + public Collection findCohortsByMemberships(@NotNull String patientUuid, Date startDate, Date endDate, + boolean includeVoided) { + Criteria criteria = getCurrentSession().createCriteria(CohortM.class, "c"); + //Exclude/include voided cohorts + if (!includeVoided) { + criteria.add(Restrictions.eq("c.voided", false)); + } + if (patientUuid != null) { + criteria.createCriteria("cohortMembers", "cm").createCriteria("cm.patient", "cmp") + .add(Restrictions.eq("cmp.uuid", patientUuid)); + } + //Fixme handle startDate & endDate + + return criteria.list(); + } + +} diff --git a/api/src/main/java/org/openmrs/module/cohort/api/impl/CohortServiceImpl.java b/api/src/main/java/org/openmrs/module/cohort/api/impl/CohortServiceImpl.java index 7a01ad0..c20f45e 100644 --- a/api/src/main/java/org/openmrs/module/cohort/api/impl/CohortServiceImpl.java +++ b/api/src/main/java/org/openmrs/module/cohort/api/impl/CohortServiceImpl.java @@ -28,6 +28,7 @@ import org.openmrs.module.cohort.api.CohortService; import org.openmrs.module.cohort.api.dao.IGenericDao; import org.openmrs.module.cohort.api.dao.PropValue; +import org.openmrs.module.cohort.api.dao.search.CohortSearchHandler; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; @@ -44,15 +45,18 @@ public class CohortServiceImpl extends BaseOpenmrsService implements CohortServi private final IGenericDao cohortAttributeTypeDao; + private final CohortSearchHandler searchHandler; + @Autowired public CohortServiceImpl(IGenericDao cohortDao, IGenericDao cohortAttributeDao, - IGenericDao cohortAttributeTypeDao) { + IGenericDao cohortAttributeTypeDao, CohortSearchHandler searchHandler) { this.cohortDao = cohortDao; this.cohortDao.setClazz(CohortM.class); this.cohortAttributeDao = cohortAttributeDao; this.cohortAttributeDao.setClazz(CohortAttribute.class); this.cohortAttributeTypeDao = cohortAttributeTypeDao; this.cohortAttributeTypeDao.setClazz(CohortAttributeType.class); + this.searchHandler = searchHandler; } @Override @@ -179,4 +183,10 @@ public List findMatchingCohorts(String nameMatching, Map findCohortsByMembership(String patientUuid, Date startDate, Date endDate, + boolean includeVoided) { + return searchHandler.findCohortsByMemberships(patientUuid, startDate, endDate, includeVoided); + } } diff --git a/api/src/test/java/org/openmrs/module/cohort/api/dao/search/CohortSearchHandlerTest.java b/api/src/test/java/org/openmrs/module/cohort/api/dao/search/CohortSearchHandlerTest.java new file mode 100644 index 0000000..0b1c71e --- /dev/null +++ b/api/src/test/java/org/openmrs/module/cohort/api/dao/search/CohortSearchHandlerTest.java @@ -0,0 +1,70 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under + * the terms of the Healthcare Disclaimer located at http://openmrs.org/license. + * + * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS + * graphic logo is a trademark of OpenMRS Inc. + */ +package org.openmrs.module.cohort.api.dao.search; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +import java.util.Collection; + +import org.junit.Before; +import org.junit.Test; +import org.openmrs.module.cohort.CohortM; +import org.openmrs.module.cohort.CohortMember; +import org.openmrs.module.cohort.api.SpringTestConfiguration; +import org.openmrs.test.BaseModuleContextSensitiveTest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; + +@ContextConfiguration(classes = SpringTestConfiguration.class, inheritLocations = false) +public class CohortSearchHandlerTest extends BaseModuleContextSensitiveTest { + + private static final String[] COHORT_INITIAL_TEST_DATA_XML = { + "org/openmrs/module/cohort/api/hibernate/db/CohortDaoTest_initialTestData.xml", + "org/openmrs/module/cohort/api/hibernate/db/CohortMemberDaoTest_initialTestData.xml" }; + + private static final String PATIENT_UUID = "61b38324-e2fd-4feb-95b7-9e9a2a4400df"; + + private static final String BAD_PATIENT_UUID = "xx78-bad-patient-uuid-9349hj34l"; + + @Autowired + private CohortSearchHandler searchHandler; + + @Before + public void setup() throws Exception { + for (String data : COHORT_INITIAL_TEST_DATA_XML) { + executeDataSet(data); + } + } + + @Test + public void findCohortsByPatientUuid_shouldReturnCollectionOfCohorts() { + Collection cohorts = searchHandler.findCohortsByMemberships(PATIENT_UUID, null, null, false); + + assertThat(cohorts, notNullValue()); + assertThat(cohorts, hasSize(1)); + for (CohortM cohort : cohorts) { + for (CohortMember cohortMember : cohort.getCohortMembers()) { + assertThat(cohortMember.getPatient().getUuid(), is(PATIENT_UUID)); + } + } + } + + @Test + public void findCohortsByBadPatientUuid_shouldReturnEmptyCollection() { + Collection cohorts = searchHandler.findCohortsByMemberships(BAD_PATIENT_UUID, null, null, false); + + assertThat(cohorts, notNullValue()); + assertThat(cohorts.isEmpty(), is(true)); + } + +} diff --git a/api/src/test/java/org/openmrs/module/cohort/api/impl/CohortServiceImplTest.java b/api/src/test/java/org/openmrs/module/cohort/api/impl/CohortServiceImplTest.java index 2bf5d4d..fb9c5d0 100644 --- a/api/src/test/java/org/openmrs/module/cohort/api/impl/CohortServiceImplTest.java +++ b/api/src/test/java/org/openmrs/module/cohort/api/impl/CohortServiceImplTest.java @@ -32,6 +32,7 @@ import org.openmrs.module.cohort.CohortType; import org.openmrs.module.cohort.api.dao.IGenericDao; import org.openmrs.module.cohort.api.dao.PropValue; +import org.openmrs.module.cohort.api.dao.search.CohortSearchHandler; @RunWith(MockitoJUnitRunner.class) public class CohortServiceImplTest { @@ -49,11 +50,14 @@ public class CohortServiceImplTest { @Mock private IGenericDao cohortAttributeTypeDao; + @Mock + private CohortSearchHandler searchHandler; + private CohortServiceImpl cohortService; @Before public void setup() { - cohortService = new CohortServiceImpl(cohortDao, cohortAttributeDao, cohortAttributeTypeDao); + cohortService = new CohortServiceImpl(cohortDao, cohortAttributeDao, cohortAttributeTypeDao, searchHandler); } @Test diff --git a/omod/src/main/java/org/openmrs/module/cohort/web/search/CohortPatientSearchHandler.java b/omod/src/main/java/org/openmrs/module/cohort/web/search/CohortPatientSearchHandler.java new file mode 100644 index 0000000..758531a --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/cohort/web/search/CohortPatientSearchHandler.java @@ -0,0 +1,81 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under + * the terms of the Healthcare Disclaimer located at http://openmrs.org/license. + * + * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS + * graphic logo is a trademark of OpenMRS Inc. + */ +package org.openmrs.module.cohort.web.search; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; + +import lombok.extern.slf4j.Slf4j; +import org.openmrs.module.cohort.api.CohortService; +import org.openmrs.module.cohort.web.resource.CohortMainRestController; +import org.openmrs.module.webservices.rest.web.ConversionUtil; +import org.openmrs.module.webservices.rest.web.RequestContext; +import org.openmrs.module.webservices.rest.web.RestConstants; +import org.openmrs.module.webservices.rest.web.resource.api.PageableResult; +import org.openmrs.module.webservices.rest.web.resource.api.SearchConfig; +import org.openmrs.module.webservices.rest.web.resource.api.SearchHandler; +import org.openmrs.module.webservices.rest.web.resource.api.SearchQuery; +import org.openmrs.module.webservices.rest.web.resource.impl.NeedsPaging; +import org.openmrs.module.webservices.rest.web.response.ResponseException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Component; + +/* + * Allows searching for cohorts by patient fields i.e. UUID, patient-identifier + */ +@Slf4j +@Component +public class CohortPatientSearchHandler implements SearchHandler { + + @Autowired + @Qualifier("cohort.cohortService") + private CohortService cohortService; + + /** + * @see org.openmrs.module.webservices.rest.web.resource.api.SearchHandler#getSearchConfig() + */ + @Override + public SearchConfig getSearchConfig() { + return new SearchConfig("default", RestConstants.VERSION_1 + CohortMainRestController.COHORT_NAMESPACE + "/cohort", + Arrays.asList("1.8.*", "1.9.*", "1.10.*", "1.11.*", "1.12.*", "2.0.*", "2.1.*", "2.2.*", "2.3.*", "2.4.*", + "2.5.*"), + Arrays.asList( + new SearchQuery.Builder("Allows you to find cohorts by patient uuid") + .withRequiredParameters("patient.uuid").build(), + new SearchQuery.Builder("Allow you to find cohort by cohort membership period") + .withOptionalParameters("fromStartDate", "toEndDate").build(), + new SearchQuery.Builder("Include/exclude inactive cohorts").withOptionalParameters("includeInactive") + .build())); + } + + /** + * @see org.openmrs.module.webservices.rest.web.resource.api.SearchHandler#search(org.openmrs.module.webservices.rest.web.RequestContext) + */ + @Override + public PageableResult search(RequestContext context) throws ResponseException { + String patientUuid = context.getParameter("patient.uuid"); + String fromStartDate = context.getParameter("fromStartDate"); + String toEndDate = context.getParameter("toEndDate"); + String includeInactive = context.getParameter("includeInactive"); + + if (patientUuid != null || fromStartDate != null || toEndDate != null || includeInactive != null) { + Date startDate = fromStartDate != null ? (Date) ConversionUtil.convert(fromStartDate, Date.class) : null; + Date endDate = toEndDate != null ? (Date) ConversionUtil.convert(toEndDate, Date.class) : null; + boolean includeVoided = includeInactive != null && Boolean.getBoolean(includeInactive); + + return new NeedsPaging<>( + new ArrayList<>(cohortService.findCohortsByMembership(patientUuid, startDate, endDate, includeVoided)), + context); + } + return new NeedsPaging<>(new ArrayList<>(), context); + } +}