diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..45d85f8
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,15 @@
+.classpath
+.project
+.settings/*
+target/*
+api/.classpath
+api/.project
+api/.settings/*
+api/target/*
+omod/.classpath
+omod/.project
+omod/.settings/*
+omod/target/*
+/.settings
+
+
diff --git a/README.md b/README.md
index 7f9417a..bff4fee 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,9 @@
-# openmrs-module-patientsearchcriteria
\ No newline at end of file
+![alt text](https://camo.githubusercontent.com/93680c923c12178e9fa6b523b1bbb644d32f4039/68747470733a2f2f74616c6b2e6f70656e6d72732e6f72672f75706c6f6164732f64656661756c742f6f726967696e616c2f32582f662f663165633537396230333938636230346338306135346335366461323139623234343066653234392e6a7067)
+
+Patient Search Criteria Module
+==========================
+
+Description
+-----------
+This module provides the different patient search criteria which are used in core apps module
+
diff --git a/api/.gitignore b/api/.gitignore
new file mode 100644
index 0000000..b83d222
--- /dev/null
+++ b/api/.gitignore
@@ -0,0 +1 @@
+/target/
diff --git a/api/pom.xml b/api/pom.xml
new file mode 100644
index 0000000..83e3bb4
--- /dev/null
+++ b/api/pom.xml
@@ -0,0 +1,37 @@
+
+ 4.0.0
+
+ org.openmrs.module
+ patientsearch
+ 1.0.0-SNAPSHOT
+
+
+ patientsearch-api
+ jar
+ PatientSearchCriteria API
+ API project for PatientSearchCriteria
+
+
+
+ jitpack.io
+ https://jitpack.io
+
+
+
+
+
+ com.github.Reyano132.openmrs-core
+ openmrs-api
+ 0112f622
+ provided
+
+
+ com.github.Reyano132.openmrs-core
+ openmrs-api
+ 0112f622
+ test-jar
+ provided
+
+
+
diff --git a/api/src/main/java/org/openmrs/module/patientsearch/PatientSearchCriteriaActivator.java b/api/src/main/java/org/openmrs/module/patientsearch/PatientSearchCriteriaActivator.java
new file mode 100644
index 0000000..56e33cc
--- /dev/null
+++ b/api/src/main/java/org/openmrs/module/patientsearch/PatientSearchCriteriaActivator.java
@@ -0,0 +1,37 @@
+/**
+ * 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.patientsearch;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.openmrs.module.BaseModuleActivator;
+
+/**
+ * This class contains the logic that is run every time this module is either started or shutdown
+ */
+public class PatientSearchCriteriaActivator extends BaseModuleActivator {
+
+ private Log log = LogFactory.getLog(this.getClass());
+
+ /**
+ * @see #started()
+ */
+ public void started() {
+ log.info("Started PatientSearchCriteria");
+ }
+
+ /**
+ * @see #shutdown()
+ */
+ public void shutdown() {
+ log.info("Shutdown PatientSearchCriteria");
+ }
+
+}
diff --git a/api/src/main/java/org/openmrs/module/patientsearch/PatientSearchCriteriaConfig.java b/api/src/main/java/org/openmrs/module/patientsearch/PatientSearchCriteriaConfig.java
new file mode 100644
index 0000000..68514ce
--- /dev/null
+++ b/api/src/main/java/org/openmrs/module/patientsearch/PatientSearchCriteriaConfig.java
@@ -0,0 +1,21 @@
+/**
+ * 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.patientsearch;
+
+import org.springframework.stereotype.Component;
+
+/**
+ * Contains module's config.
+ */
+@Component("patientsearch.PatientSearchCriteriaConfig")
+public class PatientSearchCriteriaConfig {
+
+ public final static String MODULE_PRIVILEGE = "PatientSearchCriteria Privilege";
+}
diff --git a/api/src/main/java/org/openmrs/module/patientsearch/api/PatientSearchCriteriaService.java b/api/src/main/java/org/openmrs/module/patientsearch/api/PatientSearchCriteriaService.java
new file mode 100644
index 0000000..922967f
--- /dev/null
+++ b/api/src/main/java/org/openmrs/module/patientsearch/api/PatientSearchCriteriaService.java
@@ -0,0 +1,71 @@
+/**
+ * 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.patientsearch.api;
+
+import java.util.Date;
+import java.util.List;
+
+import org.openmrs.Patient;
+import org.openmrs.PatientIdentifierType;
+import org.openmrs.annotation.Authorized;
+import org.openmrs.api.APIException;
+import org.openmrs.api.PatientService;
+import org.openmrs.util.PrivilegeConstants;
+
+/**
+ * This provide patient search criteria service. It helps to retrieve patient with different fields
+ * such as gender, birthdate, age.
+ */
+public interface PatientSearchCriteriaService extends PatientService {
+
+ /**
+ * Return the list of patient which has required name or identifier or gender or birthdate or
+ * age.
+ *
+ * @param name (optional) this is a slight break from the norm, patients with a partial match on
+ * this name will be returned
+ * @param identifier (optional) only patients with a matching identifier are returned. This
+ * however applies only if name argument is null. Otherwise, its
+ * ignored.
+ * @param identifierTypes (optional) the PatientIdentifierTypes to restrict to
+ * @param matchIdentifierExactly (required) if true, then the given identifier must
+ * equal the id in the database. if false, then the identifier is 'searched' for by
+ * using a regular expression
+ * @param gender(optional) : if user want to search patient by gender or filter the search
+ * result by gender. value of gender parameter is either "M" or "F".
+ * @param to(optional) : user wants to search patients having age between some range, at that
+ * time this paramater represent the upper boundary of range.
+ * @param from(optional):user wants to search patients having age between some range, at that
+ * time this paramater represent the lower boundary of range.
+ * @param birthdate(optional) : User can search patient by birthdate.
+ * @return patients that matched the given criteria (and are not voided)
+ * @throws APIException
+ * @should fetch all patients that partially match given name
+ * @should fetch all patients that partially match given identifier if name
+ * argument is null
+ * @should fetch all patients that partially match given identifier when match identifier
+ * exactly equals false and if name argument is null
+ * @should fetch all patients that exactly match given identifier when match identifier exactly
+ * equals true and if name argument is null
+ * @should fetch all patients that match given identifier types
+ * @should not return duplicates
+ * @should not return voided patients
+ * @should return empty list when no match is found
+ * @should search familyName2 with name
+ * @should support simple regex
+ * @should support pattern using last digit as check digit
+ * @should return empty list if name and identifier is empty
+ * @should support all the search criteria
+ */
+ @Authorized({ PrivilegeConstants.GET_PATIENTS })
+ public List getPatients(String name, String identifier, List identifierTypes,
+ boolean matchIdentifierExactly, String gender, Integer from, Integer to, Date birthdate) throws APIException;
+
+}
diff --git a/api/src/main/java/org/openmrs/module/patientsearch/api/dao/PatientSearchCriteriaDAO.java b/api/src/main/java/org/openmrs/module/patientsearch/api/dao/PatientSearchCriteriaDAO.java
new file mode 100644
index 0000000..fa2aef4
--- /dev/null
+++ b/api/src/main/java/org/openmrs/module/patientsearch/api/dao/PatientSearchCriteriaDAO.java
@@ -0,0 +1,117 @@
+/**
+ * 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.patientsearch.api.dao;
+
+import java.util.Date;
+import java.util.List;
+
+import org.openmrs.Patient;
+import org.openmrs.api.db.DAOException;
+import org.openmrs.api.db.PatientDAO;
+
+/**
+ * methods to search patients with different fields
+ */
+public interface PatientSearchCriteriaDAO extends PatientDAO {
+
+ /**
+ * @param query : name or identifier of patients
+ * @param gender : gender of patients
+ * @param length : maximum number of patients should return
+ * @return : list of patients who follow the query regex and having required gender
+ * @throws DAOException
+ */
+ public List getPatientsByNameOrIdAndGender(String query, String gender, Integer start, Integer length,
+ Boolean includeVoided) throws DAOException;
+
+ /**
+ * @return : list of patient having required gender
+ * @throws DAOException
+ */
+ public List getPatientsByGender(String gender, Integer start, Integer length, Boolean includeVoided)
+ throws DAOException;
+
+ /**
+ * @param from: lower boundary of range of age
+ * @param to : upper boundary of range of age
+ * @return list of patients, who's age is in between the required range
+ * @throws DAOException
+ */
+ public List getPatientsByRangeOfAge(Date from, Date to, Integer start, Integer length, Boolean includeVoided)
+ throws DAOException;
+
+ /**
+ * @param birthdate : birthdate of patient
+ * @return list of patient/s , who's birthdate is similar to required birthdate
+ * @throws DAOException
+ */
+ public List getPatientsByBirthdate(Date birthdate, Integer start, Integer length, Boolean includeVoided)
+ throws DAOException;
+
+ /**
+ * @param query : name or identifier of patient/s.
+ * @param gender : gender of patient
+ * @param from : lower boundary of range of age
+ * @param to : upper boundary of range of age
+ * @return list of patients who follow the query regex and having required gender and having age
+ * in required range
+ * @throws DAOException
+ */
+ public List getPatientsByNameOrIdAndGenderAndRangeOfAge(String query, String gender, Date from, Date to,
+ Integer start, Integer length, Boolean includeVoided) throws DAOException;
+
+ /**
+ * @param query : name or identifier of patient/s
+ * @param gender : gender of patient
+ * @param birthdate : birthdate of patient
+ * @return list of patients who follow the query regex and having required gender and having
+ * required birthdate
+ * @throws DAOException
+ */
+ public List getPatientsByNameOrIdAndGenderAndBirthdate(String query, String gender, Date birthdate,
+ Integer start, Integer length, Boolean includeVoided) throws DAOException;
+
+ /**
+ * @param from: lower boundary of range of age
+ * @param to : upper boundary of range of age
+ * @return list of patients who follow the query regex and having age in required range
+ * @throws DAOException
+ */
+ public List getPatientsByNameOrIdAndRangeOfAge(String query, Date from, Date to, Integer start, Integer length,
+ Boolean includeVoided) throws DAOException;
+
+ /**
+ * @param birthdate: birthdate of patient
+ * @return list of patients who follow the query regex and having birthdate as required.
+ * @throws DAOException
+ */
+ public List getPatientsByNameOrIdAndBirthdate(String query, Date birthdate, Integer start, Integer length,
+ Boolean includeVoided) throws DAOException;
+
+ /**
+ * @param gender : gender of patients
+ * @param birthdate: birthdate of patient
+ * @return list of patients which have required birthdate and gender
+ * @throws DAOException
+ */
+ public List getPatientsByGenderAndBirthdate(String gender, Date birthdate, Integer start, Integer length,
+ Boolean includeVoided) throws DAOException;
+
+ /**
+ * @param gender : gender of patients
+ * @param from: lower boundary of range of age
+ * @param to : upper boundary of range of age
+ * @return list of patients which have required gender and age in required range.
+ * @throws DAOException
+ */
+ public List getPatientsByGenderAndAge(String gender, Date from, Date to, Integer start, Integer length,
+ Boolean includeVoided) throws DAOException;
+
+}
diff --git a/api/src/main/java/org/openmrs/module/patientsearch/api/dao/hibernate/HibernatePatientSearchCriteriaDAO.java b/api/src/main/java/org/openmrs/module/patientsearch/api/dao/hibernate/HibernatePatientSearchCriteriaDAO.java
new file mode 100644
index 0000000..0053148
--- /dev/null
+++ b/api/src/main/java/org/openmrs/module/patientsearch/api/dao/hibernate/HibernatePatientSearchCriteriaDAO.java
@@ -0,0 +1,243 @@
+/**
+ * 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.patientsearch.api.dao.hibernate;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+import org.apache.commons.lang3.StringUtils;
+import org.hibernate.SessionFactory;
+import org.openmrs.Patient;
+import org.openmrs.PatientIdentifier;
+import org.openmrs.PatientIdentifierType;
+import org.openmrs.Person;
+import org.openmrs.api.context.Context;
+import org.openmrs.api.db.DAOException;
+import org.openmrs.api.db.hibernate.HibernatePatientDAO;
+import org.openmrs.api.db.hibernate.HibernatePersonDAO;
+import org.openmrs.api.db.hibernate.search.LuceneQuery;
+import org.openmrs.collection.ListPart;
+import org.openmrs.module.patientsearch.api.dao.PatientSearchCriteriaDAO;
+import org.openmrs.util.OpenmrsConstants;
+
+/**
+ * With help of Hibernate API , implement the methods of PatientSearchCriteriaDAO
+ *
+ * @see org.openmrs.module.patientcriteria.api.dao.PatientSearchCriteriaDao
+ */
+
+public class HibernatePatientSearchCriteriaDAO extends HibernatePatientDAO implements PatientSearchCriteriaDAO {
+
+ private SessionFactory sessionFactory;
+
+ public void setSessionFactory(SessionFactory sessionFactory) {
+ super.setSessionFactory(sessionFactory);
+ this.sessionFactory = sessionFactory;
+ }
+
+ @Override
+ public List getPatientsByGender(String gender, Integer start, Integer length, Boolean includeVoided)
+ throws DAOException {
+
+ PatientLuceneQuery patientLuceneQuery = new PatientLuceneQuery(sessionFactory);
+ LuceneQuery genderQuery = patientLuceneQuery.getPatinetWithGender(gender, includeVoided);
+ return getPatientsWithLuceneQuery(genderQuery, start, length);
+ }
+
+ @Override
+ public List getPatientsByRangeOfAge(Date from, Date to, Integer start, Integer length, Boolean includeVoided)
+ throws DAOException {
+
+ PatientLuceneQuery personLuceneQuery = new PatientLuceneQuery(sessionFactory);
+ LuceneQuery ageQuery = personLuceneQuery.getPatinetWithAgeRange(from, to, includeVoided);
+ return getPatientsWithLuceneQuery(ageQuery, start, length);
+ }
+
+ @Override
+ public List getPatientsByBirthdate(Date birthdate, Integer start, Integer length, Boolean includeVoided)
+ throws DAOException {
+
+ PatientLuceneQuery personLuceneQuery = new PatientLuceneQuery(sessionFactory);
+ LuceneQuery birthdateQuery = personLuceneQuery.getPatinetWithBirthdate(birthdate, includeVoided);
+ return getPatientsWithLuceneQuery(birthdateQuery, start, length);
+ }
+
+ @Override
+ public List getPatientsByNameOrIdAndGender(String query, String gender, Integer start, Integer length, Boolean includeVoided)
+ throws DAOException {
+ return findPatients(query, includeVoided, start, length).stream().filter(patient -> patient.getGender().equals(gender)).collect(Collectors.toList());
+ }
+
+ @Override
+ public List getPatientsByNameOrIdAndRangeOfAge(String query, Date from, Date to, Integer start, Integer length,
+ Boolean includeVoided) throws DAOException {
+
+ PatientLuceneQuery patientLuceneQuery=new PatientLuceneQuery(sessionFactory);
+ LuceneQuery ageQuery=patientLuceneQuery.getPatinetWithAgeRange(from, to, includeVoided);
+ List temp=getPatientsWithLuceneQuery(ageQuery,start,length);
+ return findPatients(query, includeVoided, start, length).stream().filter(patient -> temp.contains(patient)).collect(Collectors.toList());
+ }
+
+ @Override
+ public List getPatientsByNameOrIdAndBirthdate(String query,Date birthdate, Integer start, Integer length,
+ Boolean includeVoided) throws DAOException {
+
+ PatientLuceneQuery patientLuceneQuery=new PatientLuceneQuery(sessionFactory);
+ LuceneQuery birthdateQuery=patientLuceneQuery.getPatinetWithBirthdate(birthdate, includeVoided);
+ List temp=getPatientsWithLuceneQuery(birthdateQuery,start,length);
+ return findPatients(query, includeVoided, start, length).stream().filter(patient -> temp.contains(patient)).collect(Collectors.toList());
+ }
+
+ @Override
+ public List getPatientsByNameOrIdAndGenderAndRangeOfAge(String query, String gender, Date from, Date to, Integer start, Integer length,
+ Boolean includeVoided) throws DAOException {
+ return getPatientsByNameOrIdAndRangeOfAge(query, from, to, start, length, includeVoided).stream().filter(patient -> patient.getGender().equals(gender)).collect(Collectors.toList());
+ }
+
+ @Override
+ public List getPatientsByNameOrIdAndGenderAndBirthdate(String query, String gender, Date birthdate, Integer start, Integer length,
+ Boolean includeVoided) throws DAOException {
+ return getPatientsByNameOrIdAndBirthdate(query, birthdate, start, length, includeVoided).stream().filter(patient -> patient.getGender().equals(gender)).collect(Collectors.toList());
+ }
+
+ @Override
+ public List getPatientsByGenderAndBirthdate(String gender, Date birthdate, Integer start, Integer length,
+ Boolean includeVoided) throws DAOException {
+ return getPatientsByBirthdate(birthdate, start, length, includeVoided).stream().filter(patient -> patient.getGender().equals(gender)).collect(Collectors.toList());
+ }
+
+ @Override
+ public List getPatientsByGenderAndAge(String gender, Date from, Date to, Integer start, Integer length,
+ Boolean includeVoided) throws DAOException {
+ return getPatientsByRangeOfAge(from, to, start, length, includeVoided).stream().filter(patient -> patient.getGender().equals(gender)).collect(Collectors.toList());
+ }
+
+ private List getPatientsWithLuceneQuery(LuceneQuery query, Integer start, Integer length){
+ Integer tmpStart = start;
+ if (tmpStart == null) {
+ tmpStart = 0;
+ }
+ Integer maxLength = HibernatePersonDAO.getMaximumSearchResults();
+ Integer tmpLength = length;
+ if (tmpLength == null || tmpLength > maxLength) {
+ tmpLength = maxLength;
+ }
+
+ List patients = new LinkedList<>();
+
+ long querySize = query.resultSize();
+ if (querySize > tmpStart) {
+ ListPart