← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 13803: (light) fixed search result list, support search by dynamic attribute

 

------------------------------------------------------------
revno: 13803
committer: Hong Em <em.hispvietnam@xxxxxxxxx>
branch nick: dhis2
timestamp: Wed 2014-01-22 11:25:46 +0700
message:
  (light) fixed search result list, support search by dynamic attribute
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/patient/PatientService.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/patient/PatientStore.java
  dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patient/DefaultPatientService.java
  dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patient/hibernate/HibernatePatientStore.java
  dhis-2/dhis-web/dhis-web-light/src/main/java/org/hisp/dhis/light/namebaseddataentry/action/FindBeneficiarytAction.java
  dhis-2/dhis-web/dhis-web-light/src/main/java/org/hisp/dhis/light/namebaseddataentry/action/GetFindBeneficiaryFormAction.java
  dhis-2/dhis-web/dhis-web-light/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-web/dhis-web-light/src/main/resources/org/hisp/dhis/light/i18n_module.properties
  dhis-2/dhis-web/dhis-web-light/src/main/resources/struts.xml
  dhis-2/dhis-web/dhis-web-light/src/main/webapp/dhis-web-light/namebased/beneficiaryList.vm
  dhis-2/dhis-web/dhis-web-light/src/main/webapp/dhis-web-light/namebased/findBeneficiaryForm.vm


--
lp:dhis2
https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk

Your team DHIS 2 developers is subscribed to branch lp:dhis2.
To unsubscribe from this branch go to https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk/+edit-subscription
=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/patient/PatientService.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/patient/PatientService.java	2014-01-07 19:37:58 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/patient/PatientService.java	2014-01-22 04:25:46 +0000
@@ -44,348 +44,436 @@
  * @version $Id$
  */
 
-public interface PatientService
-{
-    String ID = PatientService.class.getName();
-
-    public static final int ERROR_NONE = 0;
-
-    public static final int ERROR_DUPLICATE_IDENTIFIER = 1;
-
-    public static final int ERROR_ENROLLMENT = 2;
-
-    /**
-     * Adds an {@link Patient}
-     * 
-     * @param patient The to Patient add.
-     * 
-     * @return A generated unique id of the added {@link Patient}.
-     */
-    int savePatient( Patient patient );
-
-    /**
-     * Deletes a {@link Patient}.
-     * 
-     * @param patient the Patient to delete.
-     */
-    void deletePatient( Patient patient );
-
-    /**
-     * Updates a {@link Patient}.
-     * 
-     * @param patient the Patient to update.
-     */
-    void updatePatient( Patient patient );
-
-    /**
-     * Returns a {@link Patient}.
-     * 
-     * @param id the id of the PatientAttribute to return.
-     * 
-     * @return the PatientAttribute with the given id
-     */
-    Patient getPatient( int id );
-
-    /**
-     * Returns the {@link PatientAttribute} with the given UID.
-     * 
-     * @param uid the UID.
-     * @return the PatientAttribute with the given UID, or null if no match.
-     */
-    Patient getPatient( String uid );
-
-    /**
-     * Returns all {@link Patient}
-     * 
-     * @return a collection of all Patient, or an empty collection if there are
-     *         no Patients.
-     */
-    Collection<Patient> getAllPatients();
-
-    /**
-     * Retrieve patients for mobile base on identifier value
-     * 
-     * @param searchText value
-     * @param orgUnitId
-     * 
-     * @return Patient List
-     */
-    Collection<Patient> getPatientsForMobile( String searchText, int orgUnitId );
-
-    /**
-     * Retrieve patients base on organization unit with result limited
-     * 
-     * @param organisationUnit organisationUnit
-     * @param min
-     * @param max
-     * 
-     * @return Patient List
-     */
-    Collection<Patient> getPatients( OrganisationUnit organisationUnit, Integer min, Integer max );
-
-    /**
-     * Retrieve patients who enrolled into a program with active status
-     * 
-     * @param program Program
-     * @return Patient list
-     */
-    Collection<Patient> getPatients( Program program );
-
-    /**
-     * Retrieve patients registered in a orgunit and enrolled into a program
-     * with active status
-     * 
-     * @param organisationUnit
-     * @param program
-     * @return
-     */
-    Collection<Patient> getPatients( OrganisationUnit organisationUnit, Program program );
-
-    /**
-     * Retrieve patients base on PatientIdentifierType or Attribute or Patient's
-     * name
-     * 
-     * @param identifierTypeId
-     * @param attributeId
-     * @param value
-     * @return
-     */
-    Collection<Patient> getPatient( Integer identifierTypeId, Integer attributeId, String value );
-
-    /**
-     * Search patients base on OrganisationUnit and Program with result limited
-     * name
-     * 
-     * @param organisationUnit
-     * @param program
-     * @param min
-     * @param max
-     * @return
-     */
-    Collection<Patient> getPatients( OrganisationUnit organisationUnit, Program program, Integer min, Integer max );
-
-    /**
-     * Sort the result by PatientAttribute
-     * 
-     * @param patients
-     * @param patientAttribute
-     * @return Patient List
-     */
-    Collection<Patient> sortPatientsByAttribute( Collection<Patient> patients, PatientAttribute patientAttribute );
-
-    /**
-     * Get patients who has the same representative
-     * 
-     * @params patient The representatives
-     * 
-     * @return Patient List
-     * **/
-    Collection<Patient> getRepresentatives( Patient patient );
-    
-    /**
-     * Register a new patient
-     * 
-     * @param patient Patient
-     * @param representativeId The id of patient who is representative
-     * @param relationshipTypeId The id of relationship type defined
-     * @param attributeValues Set of attribute values
-     * 
-     * @return The error code after registering patient
-     */
-    int createPatient( Patient patient, Integer representativeId, Integer relationshipTypeId,
-        Set<PatientAttributeValue> attributeValues );
-
-    /**
-     * Update information of an patient existed
-     * 
-     * @param patient Patient
-     * @param representativeId The id of representative of this patient
-     * @param relationshipTypeId The id of relationship type of this person
-     * @param valuesForSave The patient attribute values for adding
-     * @param valuesForUpdate The patient attribute values for updating
-     * @param valuesForDelete The patient attribute values for deleting
-     * 
-     */
-    void updatePatient( Patient patient, Integer representativeId, Integer relationshipTypeId,
-        List<PatientAttributeValue> valuesForSave, List<PatientAttributeValue> valuesForUpdate,
-        Collection<PatientAttributeValue> valuesForDelete );
-
-    /**
-     * Get the number of patients who registered into an organisation unit
-     * 
-     * @param organisationUnit Organisation Unit
-     * 
-     * @return The number of patients
-     */
-    int countGetPatientsByOrgUnit( OrganisationUnit organisationUnit );
-
-    /**
-     * Get the number of patients who registered into an organisation unit and
-     * enrolled into a program
-     * 
-     * @param organisationUnit Organisation Unit
-     * @param program Program
-     * 
-     * @return The number of patients
-     */
-    int countGetPatientsByOrgUnitProgram( OrganisationUnit organisationUnit, Program program );
-
-    /**
-     * Cache value from String to the value type based on property
-     * 
-     * @param property Property name of patient
-     * @param value Value
-     * @param format I18nFormat
-     * 
-     * @return An object
-     */
-    Object getObjectValue( String property, String value, I18nFormat format );
-
-    /**
-     * Search patients by attribute values, identifiers and/or a program which
-     * patients enrolled into
-     * 
-     * @param searchKeys The key for searching patients by attribute values,
-     *        identifiers and/or a program
-     * @param orgunit Organisation unit where patients registered
-     * @param followup Only getting patients with program risked if this
-     *        property is true. And getting patients without program risked if
-     *        its value is false
-     * @param patientAttributes The attribute values of these attribute are
-     *        displayed into result
-     * @param identifierTypes The identifiers are displayed into the result
-     * @param statusEnrollment The status of program of patients. There are
-     *        three status, includes Active enrollments only, Completed
-     *        enrollments only and Active and completed enrollments
-     * @param min
-     * @param max
-     * 
-     * @return An object
-     */
-    Collection<Patient> searchPatients( List<String> searchKeys, Collection<OrganisationUnit> orgunit,
-        Boolean followup, Collection<PatientAttribute> patientAttributes,
-        Collection<PatientIdentifierType> identifierTypes, Integer statusEnrollment, Integer min, Integer max );
-
-    /**
-     * Get the number of patients who meet the criteria for searching
-     * 
-     * @param searchKeys The key for searching patients by attribute values,
-     *        identifiers and/or a program
-     * @param orgunit Organisation unit where patients registered
-     * @param followup Only getting patients with program risked if this
-     *        property is true. And getting patients without program risked if
-     *        its value is false
-     * @param statusEnrollment The status of program of patients. There are
-     *        three status, includes Active enrollments only, Completed
-     *        enrollments only and Active and completed enrollments
-     * 
-     * @return The number of patients
-     */
-    int countSearchPatients( List<String> searchKeys, Collection<OrganisationUnit> orgunit, Boolean followup,
-        Integer statusEnrollment );
-
-    /**
-     * Get phone numbers of persons who meet the criteria for searching *
-     * 
-     * @param searchKeys The key for searching patients by attribute values,
-     *        identifiers and/or a program
-     * @param orgunit Organisation unit where patients registered
-     * @param followup Only getting patients with program risked if this
-     *        property is true. And getting patients without program risked if
-     *        its value is false
-     * @param statusEnrollment The status of program of patients. There are
-     *        three status, includes Active enrollments only, Completed
-     *        enrollments only and Active and completed enrollments
-     * @param min
-     * @param max
-     * 
-     * @return List of patient
-     */
-    Collection<String> getPatientPhoneNumbers( List<String> searchKeys, Collection<OrganisationUnit> orgunit,
-        Boolean followup, Integer statusEnrollment, Integer min, Integer max );
-
-    /**
-     * Get events which meet the criteria for searching
-     * 
-     * @param searchKeys The key for searching patients by attribute values,
-     *        identifiers and/or a program
-     * @param orgunit Organisation unit where patients registered
-     * @param followup Only getting patients with program risked if this
-     *        property is true. And getting patients without program risked if
-     *        its value is false
-     * @param statusEnrollment The status of program of patients. There are
-     *        three status, includes Active enrollments only, Completed
-     *        enrollments only and Active and completed enrollments
-     * @parma min
-     * @param max
-     * 
-     * @return List of patient
-     */
-    List<Integer> getProgramStageInstances( List<String> searchKeys, Collection<OrganisationUnit> orgunit,
-        Boolean followup, Integer statusEnrollment, Integer min, Integer max );
-
-    /**
-     * Get visit schedule of person who meet the criteria for searching
-     * 
-     * @param searchKeys The key for searching patients by attribute values,
-     *        identifiers and/or a program
-     * @param orgunit Organisation unit where patients registered
-     * @param followup Only getting patients with program risked if this
-     *        property is true. And getting patients without program risked if
-     *        its value is false
-     * @param statusEnrollment The status of program of patients. There are
-     *        three status, includes Active enrollments only, Completed
-     *        enrollments only and Active and completed enrollments
-     * @parma min
-     * @param max
-     * 
-     * @return Grid
-     */
-    Grid getScheduledEventsReport( List<String> searchKeys, Collection<OrganisationUnit> orgunits, Boolean followup,
-        Integer statusEnrollment, Integer min, Integer max, I18n i18n );
-
-    /**
-     * Search patients by phone number (performs partial search)
-     * 
-     * @param phoneNumber The string for searching by phone number
-     * @param min
-     * @param max
-     * 
-     * @return List of patient
-     */
-    Collection<Patient> getPatientsByPhone( String phoneNumber, Integer min, Integer max );
-
-    /**
-     * Get events of patients who meet the criteria for searching
-     * 
-     * @param program Program. It's is used for getting identifier-types of this
-     *        program and put identifiers of patients into the result
-     * @param searchKeys The key for searching patients by attribute values,
-     *        identifiers and/or a program
-     * @param orgunit Organisation unit where patients registered
-     * @param followup Only getting patients with program risked if this
-     *        property is true. And getting patients without program risked if
-     *        its value is false
-     * @param statusEnrollment The status of program of patients. There are
-     *        three status, includes Active enrollments only, Completed
-     *        enrollments only and Active and completed enrollments
-     * @param i18n I18n
-     * 
-     * @return Grid
-     */
-    Grid getTrackingEventsReport( Program program, List<String> searchKeys, Collection<OrganisationUnit> orgunits,
-        Boolean followup, Integer statusEnrollment, I18n i18n );
-
-    /**
-     * Validate patient identifiers and validation criteria by program before
-     * registering or updating information
-     * 
-     * @param patient Patient object
-     * @param program Program which person needs to enroll. If this parameter
-     *        is null, the system check identifiers of the patient
-     * 
-     * @return Error code 0 : Validation is OK 1 : The identifier is duplicated
-     *         2 : Violate validation criteria of the program
-     */
-    int validatePatient( Patient patient, Program program );
+public interface PatientService {
+	String ID = PatientService.class.getName();
+
+	public static final int ERROR_NONE = 0;
+
+	public static final int ERROR_DUPLICATE_IDENTIFIER = 1;
+
+	public static final int ERROR_ENROLLMENT = 2;
+
+	/**
+	 * Adds an {@link Patient}
+	 * 
+	 * @param patient
+	 *            The to Patient add.
+	 * 
+	 * @return A generated unique id of the added {@link Patient}.
+	 */
+	int savePatient(Patient patient);
+
+	/**
+	 * Deletes a {@link Patient}.
+	 * 
+	 * @param patient
+	 *            the Patient to delete.
+	 */
+	void deletePatient(Patient patient);
+
+	/**
+	 * Updates a {@link Patient}.
+	 * 
+	 * @param patient
+	 *            the Patient to update.
+	 */
+	void updatePatient(Patient patient);
+
+	/**
+	 * Returns a {@link Patient}.
+	 * 
+	 * @param id
+	 *            the id of the PatientAttribute to return.
+	 * 
+	 * @return the PatientAttribute with the given id
+	 */
+	Patient getPatient(int id);
+
+	/**
+	 * Returns the {@link PatientAttribute} with the given UID.
+	 * 
+	 * @param uid
+	 *            the UID.
+	 * @return the PatientAttribute with the given UID, or null if no match.
+	 */
+	Patient getPatient(String uid);
+
+	/**
+	 * Returns all {@link Patient}
+	 * 
+	 * @return a collection of all Patient, or an empty collection if there are
+	 *         no Patients.
+	 */
+	Collection<Patient> getAllPatients();
+
+	/**
+	 * Retrieve patients for mobile base on identifier value
+	 * 
+	 * @param searchText
+	 *            value
+	 * @param orgUnitId
+	 * 
+	 * @return Patient List
+	 */
+	Collection<Patient> getPatientsForMobile(String searchText, int orgUnitId);
+
+	Collection<Patient> searchPatientsForMobile(String searchText,
+			int orgUnitId, int patientAttributeId);
+
+	/**
+	 * Retrieve patients for mobile base on organization unit, patient attribute
+	 * value
+	 * 
+	 * @param searchText
+	 *            value
+	 * @param patientAttributeId
+	 * @param orgUnitId
+	 * 
+	 * @return Patient List
+	 */
+	Collection<Patient> getPatientsByAttributeValue(String searchText,
+			int patientAttributeId, Integer min, Integer max);
+
+	/**
+	 * Retrieve patients base on organization unit with result limited
+	 * 
+	 * @param organisationUnit
+	 *            organisationUnit
+	 * @param min
+	 * @param max
+	 * 
+	 * @return Patient List
+	 */
+	Collection<Patient> getPatients(OrganisationUnit organisationUnit,
+			Integer min, Integer max);
+
+	/**
+	 * Retrieve patients who enrolled into a program with active status
+	 * 
+	 * @param program
+	 *            Program
+	 * @return Patient list
+	 */
+	Collection<Patient> getPatients(Program program);
+
+	/**
+	 * Retrieve patients registered in a orgunit and enrolled into a program
+	 * with active status
+	 * 
+	 * @param organisationUnit
+	 * @param program
+	 * @return
+	 */
+	Collection<Patient> getPatients(OrganisationUnit organisationUnit,
+			Program program);
+
+	/**
+	 * Retrieve patients base on PatientIdentifierType or Attribute or Patient's
+	 * name
+	 * 
+	 * @param identifierTypeId
+	 * @param attributeId
+	 * @param value
+	 * @return
+	 */
+	Collection<Patient> getPatient(Integer identifierTypeId,
+			Integer attributeId, String value);
+
+	/**
+	 * Search patients base on OrganisationUnit and Program with result limited
+	 * name
+	 * 
+	 * @param organisationUnit
+	 * @param program
+	 * @param min
+	 * @param max
+	 * @return
+	 */
+	Collection<Patient> getPatients(OrganisationUnit organisationUnit,
+			Program program, Integer min, Integer max);
+
+	/**
+	 * Sort the result by PatientAttribute
+	 * 
+	 * @param patients
+	 * @param patientAttribute
+	 * @return Patient List
+	 */
+	Collection<Patient> sortPatientsByAttribute(Collection<Patient> patients,
+			PatientAttribute patientAttribute);
+
+	/**
+	 * Get patients who has the same representative
+	 * 
+	 * @params patient The representatives
+	 * 
+	 * @return Patient List
+	 * **/
+	Collection<Patient> getRepresentatives(Patient patient);
+
+	/**
+	 * Register a new patient
+	 * 
+	 * @param patient
+	 *            Patient
+	 * @param representativeId
+	 *            The id of patient who is representative
+	 * @param relationshipTypeId
+	 *            The id of relationship type defined
+	 * @param attributeValues
+	 *            Set of attribute values
+	 * 
+	 * @return The error code after registering patient
+	 */
+	int createPatient(Patient patient, Integer representativeId,
+			Integer relationshipTypeId,
+			Set<PatientAttributeValue> attributeValues);
+
+	/**
+	 * Update information of an patient existed
+	 * 
+	 * @param patient
+	 *            Patient
+	 * @param representativeId
+	 *            The id of representative of this patient
+	 * @param relationshipTypeId
+	 *            The id of relationship type of this person
+	 * @param valuesForSave
+	 *            The patient attribute values for adding
+	 * @param valuesForUpdate
+	 *            The patient attribute values for updating
+	 * @param valuesForDelete
+	 *            The patient attribute values for deleting
+	 * 
+	 */
+	void updatePatient(Patient patient, Integer representativeId,
+			Integer relationshipTypeId,
+			List<PatientAttributeValue> valuesForSave,
+			List<PatientAttributeValue> valuesForUpdate,
+			Collection<PatientAttributeValue> valuesForDelete);
+
+	/**
+	 * Get the number of patients who registered into an organisation unit
+	 * 
+	 * @param organisationUnit
+	 *            Organisation Unit
+	 * 
+	 * @return The number of patients
+	 */
+	int countGetPatientsByOrgUnit(OrganisationUnit organisationUnit);
+
+	/**
+	 * Get the number of patients who registered into an organisation unit and
+	 * enrolled into a program
+	 * 
+	 * @param organisationUnit
+	 *            Organisation Unit
+	 * @param program
+	 *            Program
+	 * 
+	 * @return The number of patients
+	 */
+	int countGetPatientsByOrgUnitProgram(OrganisationUnit organisationUnit,
+			Program program);
+
+	/**
+	 * Cache value from String to the value type based on property
+	 * 
+	 * @param property
+	 *            Property name of patient
+	 * @param value
+	 *            Value
+	 * @param format
+	 *            I18nFormat
+	 * 
+	 * @return An object
+	 */
+	Object getObjectValue(String property, String value, I18nFormat format);
+
+	/**
+	 * Search patients by attribute values, identifiers and/or a program which
+	 * patients enrolled into
+	 * 
+	 * @param searchKeys
+	 *            The key for searching patients by attribute values,
+	 *            identifiers and/or a program
+	 * @param orgunit
+	 *            Organisation unit where patients registered
+	 * @param followup
+	 *            Only getting patients with program risked if this property is
+	 *            true. And getting patients without program risked if its value
+	 *            is false
+	 * @param patientAttributes
+	 *            The attribute values of these attribute are displayed into
+	 *            result
+	 * @param identifierTypes
+	 *            The identifiers are displayed into the result
+	 * @param statusEnrollment
+	 *            The status of program of patients. There are three status,
+	 *            includes Active enrollments only, Completed enrollments only
+	 *            and Active and completed enrollments
+	 * @param min
+	 * @param max
+	 * 
+	 * @return An object
+	 */
+	Collection<Patient> searchPatients(List<String> searchKeys,
+			Collection<OrganisationUnit> orgunit, Boolean followup,
+			Collection<PatientAttribute> patientAttributes,
+			Collection<PatientIdentifierType> identifierTypes,
+			Integer statusEnrollment, Integer min, Integer max);
+
+	/**
+	 * Get the number of patients who meet the criteria for searching
+	 * 
+	 * @param searchKeys
+	 *            The key for searching patients by attribute values,
+	 *            identifiers and/or a program
+	 * @param orgunit
+	 *            Organisation unit where patients registered
+	 * @param followup
+	 *            Only getting patients with program risked if this property is
+	 *            true. And getting patients without program risked if its value
+	 *            is false
+	 * @param statusEnrollment
+	 *            The status of program of patients. There are three status,
+	 *            includes Active enrollments only, Completed enrollments only
+	 *            and Active and completed enrollments
+	 * 
+	 * @return The number of patients
+	 */
+	int countSearchPatients(List<String> searchKeys,
+			Collection<OrganisationUnit> orgunit, Boolean followup,
+			Integer statusEnrollment);
+
+	/**
+	 * Get phone numbers of persons who meet the criteria for searching *
+	 * 
+	 * @param searchKeys
+	 *            The key for searching patients by attribute values,
+	 *            identifiers and/or a program
+	 * @param orgunit
+	 *            Organisation unit where patients registered
+	 * @param followup
+	 *            Only getting patients with program risked if this property is
+	 *            true. And getting patients without program risked if its value
+	 *            is false
+	 * @param statusEnrollment
+	 *            The status of program of patients. There are three status,
+	 *            includes Active enrollments only, Completed enrollments only
+	 *            and Active and completed enrollments
+	 * @param min
+	 * @param max
+	 * 
+	 * @return List of patient
+	 */
+	Collection<String> getPatientPhoneNumbers(List<String> searchKeys,
+			Collection<OrganisationUnit> orgunit, Boolean followup,
+			Integer statusEnrollment, Integer min, Integer max);
+
+	/**
+	 * Get events which meet the criteria for searching
+	 * 
+	 * @param searchKeys
+	 *            The key for searching patients by attribute values,
+	 *            identifiers and/or a program
+	 * @param orgunit
+	 *            Organisation unit where patients registered
+	 * @param followup
+	 *            Only getting patients with program risked if this property is
+	 *            true. And getting patients without program risked if its value
+	 *            is false
+	 * @param statusEnrollment
+	 *            The status of program of patients. There are three status,
+	 *            includes Active enrollments only, Completed enrollments only
+	 *            and Active and completed enrollments
+	 * @parma min
+	 * @param max
+	 * 
+	 * @return List of patient
+	 */
+	List<Integer> getProgramStageInstances(List<String> searchKeys,
+			Collection<OrganisationUnit> orgunit, Boolean followup,
+			Integer statusEnrollment, Integer min, Integer max);
+
+	/**
+	 * Get visit schedule of person who meet the criteria for searching
+	 * 
+	 * @param searchKeys
+	 *            The key for searching patients by attribute values,
+	 *            identifiers and/or a program
+	 * @param orgunit
+	 *            Organisation unit where patients registered
+	 * @param followup
+	 *            Only getting patients with program risked if this property is
+	 *            true. And getting patients without program risked if its value
+	 *            is false
+	 * @param statusEnrollment
+	 *            The status of program of patients. There are three status,
+	 *            includes Active enrollments only, Completed enrollments only
+	 *            and Active and completed enrollments
+	 * @parma min
+	 * @param max
+	 * 
+	 * @return Grid
+	 */
+	Grid getScheduledEventsReport(List<String> searchKeys,
+			Collection<OrganisationUnit> orgunits, Boolean followup,
+			Integer statusEnrollment, Integer min, Integer max, I18n i18n);
+
+	/**
+	 * Search patients by phone number (performs partial search)
+	 * 
+	 * @param phoneNumber
+	 *            The string for searching by phone number
+	 * @param min
+	 * @param max
+	 * 
+	 * @return List of patient
+	 */
+	Collection<Patient> getPatientsByPhone(String phoneNumber, Integer min,
+			Integer max);
+
+	/**
+	 * Get events of patients who meet the criteria for searching
+	 * 
+	 * @param program
+	 *            Program. It's is used for getting identifier-types of this
+	 *            program and put identifiers of patients into the result
+	 * @param searchKeys
+	 *            The key for searching patients by attribute values,
+	 *            identifiers and/or a program
+	 * @param orgunit
+	 *            Organisation unit where patients registered
+	 * @param followup
+	 *            Only getting patients with program risked if this property is
+	 *            true. And getting patients without program risked if its value
+	 *            is false
+	 * @param statusEnrollment
+	 *            The status of program of patients. There are three status,
+	 *            includes Active enrollments only, Completed enrollments only
+	 *            and Active and completed enrollments
+	 * @param i18n
+	 *            I18n
+	 * 
+	 * @return Grid
+	 */
+	Grid getTrackingEventsReport(Program program, List<String> searchKeys,
+			Collection<OrganisationUnit> orgunits, Boolean followup,
+			Integer statusEnrollment, I18n i18n);
+
+	/**
+	 * Validate patient identifiers and validation criteria by program before
+	 * registering or updating information
+	 * 
+	 * @param patient
+	 *            Patient object
+	 * @param program
+	 *            Program which person needs to enroll. If this parameter is
+	 *            null, the system check identifiers of the patient
+	 * 
+	 * @return Error code 0 : Validation is OK 1 : The identifier is duplicated
+	 *         2 : Violate validation criteria of the program
+	 */
+	int validatePatient(Patient patient, Program program);
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/patient/PatientStore.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/patient/PatientStore.java	2014-01-07 19:37:58 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/patient/PatientStore.java	2014-01-22 04:25:46 +0000
@@ -40,203 +40,261 @@
  * @author Abyot Asalefew Gizaw
  * @version $Id$
  */
-public interface PatientStore
-    extends GenericIdentifiableObjectStore<Patient>
-{
-    final String ID = PatientStore.class.getName();
-
-    final int MAX_RESULTS = 50000;
-
-    /**
-     * Search patients who registered in a certain organisation unit
-     * 
-     * @param organisationUnit Organisation unit where patients registered
-     * @param min
-     * @param max
-     * 
-     * @return List of patients
-     */
-    Collection<Patient> getByOrgUnit( OrganisationUnit organisationUnit, Integer min, Integer max );
-
-    /**
-     * Search patients registered into a certain organisation unit and enrolled
-     * into a program with active status
-     * 
-     * @param organisationUnit Organisation unit where patients registered
-     * @param program Program. It's is used for getting identifier-types of this
-     *        program and put identifiers of patients into the result
-     * @param min
-     * @param max
-     * 
-     * @return List of patients
-     */
-    Collection<Patient> getByOrgUnitProgram( OrganisationUnit organisationUnit, Program program, Integer min,
-        Integer max );
-
-    List<Patient> query( TrackedEntityQueryParams params );
-
-    /**
-     * Search patient who has the same representative
-     * 
-     * @param patient Representative
-     * 
-     * @return List of patients
-     */
-    Collection<Patient> getRepresentatives( Patient patient );
-
-    /**
-     * Search the number of patients who registered into an organisation unit
-     * 
-     * @param organisationUnit Organisation unit
-     * 
-     * @return The number of patients
-     */
-    int countListPatientByOrgunit( OrganisationUnit organisationUnit );
-
-    /**
-     * Get the number of patients by full name (performs partial search )
-     * 
-     * @param name A string for searching by full name
-     * 
-     * @return The number of patients
-     */
-    int countGetPatientsByName( String name );
-
-    /**
-     * Get the number of patients who registered into a certain organisation
-     * unit and enrolled into a program with active status
-     * 
-     * @param organisationUnit Organisation unit where patients registered
-     * @param program Program. It's is used for getting identifier-types of this
-     *        program and put identifiers of patients into the result
-     * 
-     * @return The number of patients
-     */
-    int countGetPatientsByOrgUnitProgram( OrganisationUnit organisationUnit, Program program );
-
-    /**
-     * Get number of patients who meet the criteria for searching
-     * 
-     * @param searchKeys The key for searching patients by attribute values,
-     *        identifiers and/or a program
-     * @param orgunit Organisation unit where patients registered
-     * @param followup Only getting patients with program risked if this
-     *        property is true. And getting patients without program risked if
-     *        its value is false
-     * @param statusEnrollment The status of program of patients. There are
-     *        three status, includes Active enrollments only, Completed
-     *        enrollments only and Active and completed enrollments
-     * 
-     * @return The number of patients
-     */
-    int countSearch( List<String> searchKeys, Collection<OrganisationUnit> orgunit, Boolean followup,
-        Integer statusEnrollment );
-
-    /**
-     * Search patients by phone number (performs partial search)
-     * 
-     * @param phoneNumber The string for searching by phone number
-     * @param min
-     * @param max
-     * 
-     * @return List of patient
-     */
-    Collection<Patient> getByPhoneNumber( String phoneNumber, Integer min, Integer max );
-
-    /**
-     * Search events of patients who meet the criteria for searching
-     * 
-     * @param searchKeys The key for searching patients by attribute values,
-     *        identifiers and/or a program
-     * @param orgunit Organisation unit where patients registered
-     * @param followup Only getting patients with program risked if this
-     *        property is true. And getting patients without program risked if
-     *        its value is false
-     * @param patientAttributes The attribute values of these attribute are
-     *        displayed into result
-     * @param identifierTypes The identifiers are displayed into the result
-     * @param statusEnrollment The status of program of patients. There are
-     *        three status, includes Active enrollments only, Completed
-     *        enrollments only and Active and completed enrollments
-     * @param min
-     * @param max
-     * 
-     * @return List of patients
-     */
-    Collection<Patient> search( List<String> searchKeys, Collection<OrganisationUnit> orgunit, Boolean followup,
-        Collection<PatientAttribute> patientAttributes, Collection<PatientIdentifierType> identifierTypes,
-        Integer statusEnrollment, Integer min, Integer max );
-
-    /**
-     * Search events which meet the criteria for searching
-     * 
-     * @param searchKeys The key for searching patients by attribute values,
-     *        identifiers and/or a program
-     * @param orgunit Organisation unit where patients registered
-     * @param followup Only getting patients with program risked if this
-     *        property is true. And getting patients without program risked if
-     *        its value is false
-     * @param patientAttributes The attribute values of these attribute are
-     *        displayed into result
-     * @param identifierTypes The identifiers are displayed into the result
-     * @param statusEnrollment The status of program of patients. There are
-     *        three status, includes Active enrollments only, Completed
-     *        enrollments only and Active and completed enrollments
-     * @param min
-     * @param max
-     * 
-     * @return List of patients
-     */
-    List<Integer> getProgramStageInstances( List<String> searchKeys, Collection<OrganisationUnit> orgunits,
-        Boolean followup, Collection<PatientAttribute> patientAttributes,
-        Collection<PatientIdentifierType> identifierTypes, Integer statusEnrollment, Integer min, Integer max );
-
-    /**
-     * Search patients who enrolled into a program with active status
-     * 
-     * @param program Program
-     * @param min
-     * @param max
-     * 
-     *        return List of patients
-     */
-    Collection<Patient> getByProgram( Program program, Integer min, Integer max );
-
-    /**
-     * Search events of patients who meet the criteria for searching
-     * 
-     * @param grid Grid with headers
-     * @param searchKeys The key for searching patients by attribute values,
-     *        identifiers and/or a program
-     * @param orgunit Organisation unit where patients registered
-     * @param followup Only getting patients with program risked if this
-     *        property is true. And getting patients without program risked if
-     *        its value is false
-     * @param patientAttributes The attribute values of these attribute are
-     *        displayed into result
-     * @param identifierTypes The identifiers are displayed into the result
-     * @param statusEnrollment The status of program of patients. There are
-     *        three status, includes Active enrollments only, Completed
-     *        enrollments only and Active and completed enrollments
-     * @param min
-     * @param max
-     * 
-     * @return Grid
-     */
-    Grid getPatientEventReport( Grid grid, List<String> searchKeys, Collection<OrganisationUnit> orgunit,
-        Boolean followup, Collection<PatientAttribute> patientAttributes,
-        Collection<PatientIdentifierType> identifierTypes, Integer statusEnrollment, Integer min, Integer max );
-
-    /**
-     * Validate patient identifiers and validation criteria by program before
-     * registering / updating information
-     * 
-     * @param patient Patient object
-     * @param program Program which person needs to enroll. If this parameter
-     *        is null, the system check identifiers of the patient
-     * 
-     * @return Error code 0 : Validation is OK 1 : The identifier is duplicated
-     *         2 : Violate validation criteria of the program
-     */
-    int validate( Patient patient, Program program );
+public interface PatientStore extends GenericIdentifiableObjectStore<Patient> {
+	final String ID = PatientStore.class.getName();
+
+	final int MAX_RESULTS = 50000;
+
+	/**
+	 * Search patients who registered in a certain organisation unit
+	 * 
+	 * @param organisationUnit
+	 *            Organisation unit where patients registered
+	 * @param min
+	 * @param max
+	 * 
+	 * @return List of patients
+	 */
+	Collection<Patient> getByOrgUnit(OrganisationUnit organisationUnit,
+			Integer min, Integer max);
+
+	/**
+	 * Search patients registered into a certain organisation unit and enrolled
+	 * into a program with active status
+	 * 
+	 * @param organisationUnit
+	 *            Organisation unit where patients registered
+	 * @param program
+	 *            Program. It's is used for getting identifier-types of this
+	 *            program and put identifiers of patients into the result
+	 * @param min
+	 * @param max
+	 * 
+	 * @return List of patients
+	 */
+	Collection<Patient> getByOrgUnitProgram(OrganisationUnit organisationUnit,
+			Program program, Integer min, Integer max);
+
+	List<Patient> query(TrackedEntityQueryParams params);
+
+	/**
+	 * Search patient who has the same representative
+	 * 
+	 * @param patient
+	 *            Representative
+	 * 
+	 * @return List of patients
+	 */
+	Collection<Patient> getRepresentatives(Patient patient);
+
+	/**
+	 * Search the number of patients who registered into an organisation unit
+	 * 
+	 * @param organisationUnit
+	 *            Organisation unit
+	 * 
+	 * @return The number of patients
+	 */
+	int countListPatientByOrgunit(OrganisationUnit organisationUnit);
+
+	/**
+	 * Get the number of patients by full name (performs partial search )
+	 * 
+	 * @param name
+	 *            A string for searching by full name
+	 * 
+	 * @return The number of patients
+	 */
+	int countGetPatientsByName(String name);
+
+	/**
+	 * Get the number of patients who registered into a certain organisation
+	 * unit and enrolled into a program with active status
+	 * 
+	 * @param organisationUnit
+	 *            Organisation unit where patients registered
+	 * @param program
+	 *            Program. It's is used for getting identifier-types of this
+	 *            program and put identifiers of patients into the result
+	 * 
+	 * @return The number of patients
+	 */
+	int countGetPatientsByOrgUnitProgram(OrganisationUnit organisationUnit,
+			Program program);
+
+	/**
+	 * Get number of patients who meet the criteria for searching
+	 * 
+	 * @param searchKeys
+	 *            The key for searching patients by attribute values,
+	 *            identifiers and/or a program
+	 * @param orgunit
+	 *            Organisation unit where patients registered
+	 * @param followup
+	 *            Only getting patients with program risked if this property is
+	 *            true. And getting patients without program risked if its value
+	 *            is false
+	 * @param statusEnrollment
+	 *            The status of program of patients. There are three status,
+	 *            includes Active enrollments only, Completed enrollments only
+	 *            and Active and completed enrollments
+	 * 
+	 * @return The number of patients
+	 */
+	int countSearch(List<String> searchKeys,
+			Collection<OrganisationUnit> orgunit, Boolean followup,
+			Integer statusEnrollment);
+
+	/**
+	 * Search patients by phone number (performs partial search)
+	 * 
+	 * @param phoneNumber
+	 *            The string for searching by phone number
+	 * @param min
+	 * @param max
+	 * 
+	 * @return List of patient
+	 */
+
+	Collection<Patient> getByPhoneNumber(String phoneNumber, Integer min,
+			Integer max);
+
+	/**
+	 * Search patients by attribute value (performs partial search)
+	 * 
+	 * @param searchText
+	 *            The string for searching by attribute value
+	 * @param patientAttributeId
+	 * @param min
+	 * @param max
+	 * 
+	 * @return List of patient
+	 */
+	Collection<Patient> getByPatientAttributeValue(String searchText,
+			int patientAttributeId, Integer min, Integer max);
+
+	/**
+	 * Search events of patients who meet the criteria for searching
+	 * 
+	 * @param searchKeys
+	 *            The key for searching patients by attribute values,
+	 *            identifiers and/or a program
+	 * @param orgunit
+	 *            Organisation unit where patients registered
+	 * @param followup
+	 *            Only getting patients with program risked if this property is
+	 *            true. And getting patients without program risked if its value
+	 *            is false
+	 * @param patientAttributes
+	 *            The attribute values of these attribute are displayed into
+	 *            result
+	 * @param identifierTypes
+	 *            The identifiers are displayed into the result
+	 * @param statusEnrollment
+	 *            The status of program of patients. There are three status,
+	 *            includes Active enrollments only, Completed enrollments only
+	 *            and Active and completed enrollments
+	 * @param min
+	 * @param max
+	 * 
+	 * @return List of patients
+	 */
+	Collection<Patient> search(List<String> searchKeys,
+			Collection<OrganisationUnit> orgunit, Boolean followup,
+			Collection<PatientAttribute> patientAttributes,
+			Collection<PatientIdentifierType> identifierTypes,
+			Integer statusEnrollment, Integer min, Integer max);
+
+	/**
+	 * Search events which meet the criteria for searching
+	 * 
+	 * @param searchKeys
+	 *            The key for searching patients by attribute values,
+	 *            identifiers and/or a program
+	 * @param orgunit
+	 *            Organisation unit where patients registered
+	 * @param followup
+	 *            Only getting patients with program risked if this property is
+	 *            true. And getting patients without program risked if its value
+	 *            is false
+	 * @param patientAttributes
+	 *            The attribute values of these attribute are displayed into
+	 *            result
+	 * @param identifierTypes
+	 *            The identifiers are displayed into the result
+	 * @param statusEnrollment
+	 *            The status of program of patients. There are three status,
+	 *            includes Active enrollments only, Completed enrollments only
+	 *            and Active and completed enrollments
+	 * @param min
+	 * @param max
+	 * 
+	 * @return List of patients
+	 */
+	List<Integer> getProgramStageInstances(List<String> searchKeys,
+			Collection<OrganisationUnit> orgunits, Boolean followup,
+			Collection<PatientAttribute> patientAttributes,
+			Collection<PatientIdentifierType> identifierTypes,
+			Integer statusEnrollment, Integer min, Integer max);
+
+	/**
+	 * Search patients who enrolled into a program with active status
+	 * 
+	 * @param program
+	 *            Program
+	 * @param min
+	 * @param max
+	 * 
+	 *            return List of patients
+	 */
+	Collection<Patient> getByProgram(Program program, Integer min, Integer max);
+
+	/**
+	 * Search events of patients who meet the criteria for searching
+	 * 
+	 * @param grid
+	 *            Grid with headers
+	 * @param searchKeys
+	 *            The key for searching patients by attribute values,
+	 *            identifiers and/or a program
+	 * @param orgunit
+	 *            Organisation unit where patients registered
+	 * @param followup
+	 *            Only getting patients with program risked if this property is
+	 *            true. And getting patients without program risked if its value
+	 *            is false
+	 * @param patientAttributes
+	 *            The attribute values of these attribute are displayed into
+	 *            result
+	 * @param identifierTypes
+	 *            The identifiers are displayed into the result
+	 * @param statusEnrollment
+	 *            The status of program of patients. There are three status,
+	 *            includes Active enrollments only, Completed enrollments only
+	 *            and Active and completed enrollments
+	 * @param min
+	 * @param max
+	 * 
+	 * @return Grid
+	 */
+	Grid getPatientEventReport(Grid grid, List<String> searchKeys,
+			Collection<OrganisationUnit> orgunit, Boolean followup,
+			Collection<PatientAttribute> patientAttributes,
+			Collection<PatientIdentifierType> identifierTypes,
+			Integer statusEnrollment, Integer min, Integer max);
+
+	/**
+	 * Validate patient identifiers and validation criteria by program before
+	 * registering / updating information
+	 * 
+	 * @param patient
+	 *            Patient object
+	 * @param program
+	 *            Program which person needs to enroll. If this parameter is
+	 *            null, the system check identifiers of the patient
+	 * 
+	 * @return Error code 0 : Validation is OK 1 : The identifier is duplicated
+	 *         2 : Violate validation criteria of the program
+	 */
+	int validate(Patient patient, Program program);
 }

=== modified file 'dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patient/DefaultPatientService.java'
--- dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patient/DefaultPatientService.java	2014-01-09 15:34:25 +0000
+++ dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patient/DefaultPatientService.java	2014-01-22 04:25:46 +0000
@@ -57,523 +57,521 @@
  * @version $Id$
  */
 @Transactional
-public class DefaultPatientService
-    implements PatientService
-{
-    // -------------------------------------------------------------------------
-    // Dependencies
-    // -------------------------------------------------------------------------
-
-    private PatientStore patientStore;
-
-    public void setPatientStore( PatientStore patientStore )
-    {
-        this.patientStore = patientStore;
-    }
-
-    private PatientIdentifierService patientIdentifierService;
-
-    public void setPatientIdentifierService( PatientIdentifierService patientIdentifierService )
-    {
-        this.patientIdentifierService = patientIdentifierService;
-    }
-
-    private PatientAttributeValueService patientAttributeValueService;
-
-    public void setPatientAttributeValueService( PatientAttributeValueService patientAttributeValueService )
-    {
-        this.patientAttributeValueService = patientAttributeValueService;
-    }
-
-    private PatientAttributeService patientAttributeService;
-
-    public void setPatientAttributeService( PatientAttributeService patientAttributeService )
-    {
-        this.patientAttributeService = patientAttributeService;
-    }
-
-    private PatientIdentifierTypeService patientIdentifierTypeService;
-
-    public void setPatientIdentifierTypeService( PatientIdentifierTypeService patientIdentifierTypeService )
-    {
-        this.patientIdentifierTypeService = patientIdentifierTypeService;
-    }
-
-    private RelationshipService relationshipService;
-
-    public void setRelationshipService( RelationshipService relationshipService )
-    {
-        this.relationshipService = relationshipService;
-    }
-
-    private RelationshipTypeService relationshipTypeService;
-
-    public void setRelationshipTypeService( RelationshipTypeService relationshipTypeService )
-    {
-        this.relationshipTypeService = relationshipTypeService;
-    }
-
-    // -------------------------------------------------------------------------
-    // Implementation methods
-    // -------------------------------------------------------------------------
-
-    @Override
-    public int savePatient( Patient patient )
-    {
-        return patientStore.save( patient );
-    }
-
-    @Override
-    public int createPatient( Patient patient, Integer representativeId, Integer relationshipTypeId,
-        Set<PatientAttributeValue> patientAttributeValues )
-    {
-        int id = savePatient( patient );
-
-        for ( PatientAttributeValue pav : patientAttributeValues )
-        {
-            patientAttributeValueService.savePatientAttributeValue( pav );
-            patient.getAttributeValues().add( pav );
-        }
-
-        // ---------------------------------------------------------------------
-        // If under age, save representative information
-        // ---------------------------------------------------------------------
-
-        if ( representativeId != null )
-        {
-            Patient representative = patientStore.get( representativeId );
-            if ( representative != null )
-            {
-                patient.setRepresentative( representative );
-
-                Relationship rel = new Relationship();
-                rel.setPatientA( representative );
-                rel.setPatientB( patient );
-
-                if ( relationshipTypeId != null )
-                {
-                    RelationshipType relType = relationshipTypeService.getRelationshipType( relationshipTypeId );
-                    if ( relType != null )
-                    {
-                        rel.setRelationshipType( relType );
-                        relationshipService.saveRelationship( rel );
-                    }
-                }
-            }
-        }
-
-        updatePatient( patient ); // Save patient to update associations
-
-        return id;
-    }
-
-    @Override
-    public void updatePatient( Patient patient )
-    {
-        patientStore.update( patient );
-    }
-
-    @Override
-    public void deletePatient( Patient patient )
-    {
-        patientStore.delete( patient );
-    }
-
-    @Override
-    public Patient getPatient( int id )
-    {
-        return patientStore.get( id );
-    }
-
-    @Override
-    public Patient getPatient( String uid )
-    {
-        return patientStore.getByUid( uid );
-    }
-
-    @Override
-    public Collection<Patient> getAllPatients()
-    {
-        return patientStore.getAll();
-    }
-
-    @Override
-    public Collection<Patient> getPatientsForMobile( String searchText, int orgUnitId )
-    {
-        Set<Patient> patients = new HashSet<Patient>();
-        patients.addAll( patientIdentifierService.getPatientsByIdentifier( searchText, 0, Integer.MAX_VALUE ) );
-        patients.addAll( getPatientsByPhone( searchText, 0, Integer.MAX_VALUE ) );
-
-        // if an org-unit has been selected, filter out every patient that has a
-        // different org-unit
-        if ( orgUnitId != 0 )
-        {
-            Set<Patient> toRemoveList = new HashSet<Patient>();
-
-            for ( Patient patient : patients )
-            {
-                if ( patient.getOrganisationUnit().getId() != orgUnitId )
-                {
-                    toRemoveList.add( patient );
-                }
-            }
-
-            patients.removeAll( toRemoveList );
-        }
-
-        return patients;
-    }
-
-    @Override
-    public Collection<Patient> getPatients( OrganisationUnit organisationUnit, Integer min, Integer max )
-    {
-        return patientStore.getByOrgUnit( organisationUnit, min, max );
-    }
-
-    @Override
-    public Collection<Patient> getPatients( Program program )
-    {
-        return patientStore.getByProgram( program, 0, Integer.MAX_VALUE );
-    }
-
-    @Override
-    public Collection<Patient> getPatients( OrganisationUnit organisationUnit, Program program )
-    {
-        return patientStore.getByOrgUnitProgram( organisationUnit, program, 0, Integer.MAX_VALUE );
-    }
-
-    @Override
-    public Collection<Patient> getPatient( Integer identifierTypeId, Integer attributeId, String value )
-    {
-        if ( attributeId != null )
-        {
-            PatientAttribute attribute = patientAttributeService.getPatientAttribute( attributeId );
-            if ( attribute != null )
-            {
-                return patientAttributeValueService.getPatient( attribute, value );
-            }
-        }
-        else if ( identifierTypeId != null )
-        {
-            PatientIdentifierType identifierType = patientIdentifierTypeService
-                .getPatientIdentifierType( identifierTypeId );
-
-            if ( identifierType != null )
-            {
-                Patient p = patientIdentifierService.getPatient( identifierType, value );
-                if ( p != null )
-                {
-                    Set<Patient> set = new HashSet<Patient>();
-                    set.add( p );
-                    return set;
-                }
-            }
-        }
-
-        return null;
-    }
-
-    @Override
-    public Collection<Patient> sortPatientsByAttribute( Collection<Patient> patients, PatientAttribute patientAttribute )
-    {
-        Collection<Patient> sortedPatients = new ArrayList<Patient>();
-
-        // ---------------------------------------------------------------------
-        // Better to fetch all attribute values at once than fetching the
-        // required attribute value of each patient using loop
-        // ---------------------------------------------------------------------
-
-        Collection<PatientAttributeValue> patientAttributeValues = patientAttributeValueService
-            .getPatientAttributeValues( patients );
-
-        if ( patientAttributeValues != null )
-        {
-            for ( PatientAttributeValue patientAttributeValue : patientAttributeValues )
-            {
-                if ( patientAttribute == patientAttributeValue.getPatientAttribute() )
-                {
-                    sortedPatients.add( patientAttributeValue.getPatient() );
-                    patients.remove( patientAttributeValue.getPatient() );
-                }
-            }
-        }
-
-        // ---------------------------------------------------------------------
-        // Make sure all patients are in the sorted list - because all
-        // patients might not have the sorting attribute/value
-        // ---------------------------------------------------------------------
-
-        sortedPatients.addAll( patients );
-
-        return sortedPatients;
-    }
-
-    @Override
-    public int countGetPatientsByOrgUnit( OrganisationUnit organisationUnit )
-    {
-        return patientStore.countListPatientByOrgunit( organisationUnit );
-    }
-
-    @Override
-    public void updatePatient( Patient patient, Integer representativeId, Integer relationshipTypeId,
-        List<PatientAttributeValue> valuesForSave, List<PatientAttributeValue> valuesForUpdate,
-        Collection<PatientAttributeValue> valuesForDelete )
-    {
-        patientStore.update( patient );
-
-        for ( PatientAttributeValue av : valuesForSave )
-        {
-            patientAttributeValueService.savePatientAttributeValue( av );
-        }
-
-        for ( PatientAttributeValue av : valuesForUpdate )
-        {
-            patientAttributeValueService.updatePatientAttributeValue( av );
-        }
-
-        for ( PatientAttributeValue av : valuesForDelete )
-        {
-            patientAttributeValueService.deletePatientAttributeValue( av );
-        }
-
-        if ( shouldSaveRepresentativeInformation( patient, representativeId ) )
-        {
-            Patient representative = patientStore.get( representativeId );
-
-            if ( representative != null )
-            {
-                patient.setRepresentative( representative );
-
-                Relationship rel = new Relationship();
-                rel.setPatientA( representative );
-                rel.setPatientB( patient );
-
-                if ( relationshipTypeId != null )
-                {
-                    RelationshipType relType = relationshipTypeService.getRelationshipType( relationshipTypeId );
-                    if ( relType != null )
-                    {
-                        rel.setRelationshipType( relType );
-                        relationshipService.saveRelationship( rel );
-                    }
-                }
-            }
-        }
-    }
-
-    private boolean shouldSaveRepresentativeInformation( Patient patient, Integer representativeId )
-    {
-        if ( representativeId == null )
-        {
-            return false;
-        }
-
-        return patient.getRepresentative() == null || !(patient.getRepresentative().getId() == representativeId);
-    }
-
-    @Override
-    public Collection<Patient> getPatients( OrganisationUnit organisationUnit, Program program, Integer min, Integer max )
-    {
-        return patientStore.getByOrgUnitProgram( organisationUnit, program, min, max );
-    }
-
-    @Override
-    public int countGetPatientsByOrgUnitProgram( OrganisationUnit organisationUnit, Program program )
-    {
-        return patientStore.countGetPatientsByOrgUnitProgram( organisationUnit, program );
-    }
-
-    @Override
-    public Object getObjectValue( String property, String value, I18nFormat format )
-    {
-        try
-        {
-            Type type = Patient.class.getMethod( "get" + StringUtils.capitalize( property ) ).getReturnType();
-
-            if ( type == Integer.class || type == Integer.TYPE )
-            {
-                return Integer.valueOf( value );
-            }
-            else if ( type.equals( Boolean.class ) || type == Boolean.TYPE )
-            {
-                return Boolean.valueOf( value );
-            }
-            else if ( type.equals( Date.class ) )
-            {
-                return format.parseDate( value.trim() );
-            }
-            else if ( type.equals( Character.class ) || type == Character.TYPE )
-            {
-                return Character.valueOf( value.charAt( 0 ) );
-            }
-
-            return value;
-        }
-        catch ( Exception ex )
-        {
-            ex.printStackTrace();
-        }
-
-        return null;
-    }
-
-    @Override
-    public Collection<Patient> getRepresentatives( Patient patient )
-    {
-        return patientStore.getRepresentatives( patient );
-    }
-
-    @Override
-    public Collection<Patient> searchPatients( List<String> searchKeys, Collection<OrganisationUnit> orgunits,
-        Boolean followup, Collection<PatientAttribute> patientAttributes,
-        Collection<PatientIdentifierType> identifierTypes, Integer statusEnrollment, Integer min, Integer max )
-    {
-        return patientStore.search( searchKeys, orgunits, followup, patientAttributes, identifierTypes,
-            statusEnrollment, min, max );
-    }
-
-    @Override
-    public int countSearchPatients( List<String> searchKeys, Collection<OrganisationUnit> orgunits, Boolean followup,
-        Integer statusEnrollment )
-    {
-        return patientStore.countSearch( searchKeys, orgunits, followup, statusEnrollment );
-    }
-
-    @Override
-    public Collection<String> getPatientPhoneNumbers( List<String> searchKeys, Collection<OrganisationUnit> orgunits,
-        Boolean followup, Integer statusEnrollment, Integer min, Integer max )
-    {
-        Collection<Patient> patients = patientStore.search( searchKeys, orgunits, followup, null, null,
-            statusEnrollment, min, max );
-        Set<String> phoneNumbers = new HashSet<String>();
-
-        for ( Patient patient : patients )
-        {
-            Collection<PatientAttributeValue> attributeValues = patient.getAttributeValues();
-            if ( attributeValues != null )
-            {
-                for ( PatientAttributeValue attributeValue : attributeValues )
-                {
-                    if ( attributeValue.getPatientAttribute().getValueType()
-                        .equals( PatientAttribute.TYPE_PHONE_NUMBER ) )
-                    {
-                        phoneNumbers.add( attributeValue.getValue() );
-                    }
-                }
-            }
-        }
-
-        return phoneNumbers;
-    }
-
-    @Override
-    public List<Integer> getProgramStageInstances( List<String> searchKeys, Collection<OrganisationUnit> orgunits,
-        Boolean followup, Integer statusEnrollment, Integer min, Integer max )
-    {
-        return patientStore.getProgramStageInstances( searchKeys, orgunits, followup, null, null, statusEnrollment,
-            min, max );
-    }
-
-    @Override
-    public Collection<Patient> getPatientsByPhone( String phoneNumber, Integer min, Integer max )
-    {
-        return patientStore.getByPhoneNumber( phoneNumber, min, max );
-    }
-
-    @Override
-    public Grid getScheduledEventsReport( List<String> searchKeys, Collection<OrganisationUnit> orgunits,
-        Boolean followup, Integer statusEnrollment, Integer min, Integer max, I18n i18n )
-    {
-        String startDate = "";
-        String endDate = "";
-        for ( String searchKey : searchKeys )
-        {
-            String[] keys = searchKey.split( "_" );
-            if ( keys[0].equals( Patient.PREFIX_PROGRAM_EVENT_BY_STATUS ) )
-            {
-                startDate = keys[2];
-                endDate = keys[3];
-            }
-        }
-
-        Grid grid = new ListGrid();
-        grid.setTitle( i18n.getString( "activity_plan" ) );
-        if ( !startDate.isEmpty() && !endDate.isEmpty() )
-        {
-            grid.setSubtitle( i18n.getString( "from" ) + " " + startDate + " " + i18n.getString( "to" ) + " " + endDate );
-        }
-
-        grid.addHeader( new GridHeader( "patientid", true, true ) );
-        grid.addHeader( new GridHeader( i18n.getString( "first_name" ), false, true ) );
-        grid.addHeader( new GridHeader( i18n.getString( "middle_name" ), false, true ) );
-        grid.addHeader( new GridHeader( i18n.getString( "last_name" ), false, true ) );
-        grid.addHeader( new GridHeader( i18n.getString( "gender" ), false, true ) );
-        grid.addHeader( new GridHeader( i18n.getString( "phone_number" ), false, true ) );
-
-        Collection<PatientAttribute> patientAttributes = patientAttributeService
-            .getPatientAttributesByDisplayOnVisitSchedule( true );
-        for ( PatientAttribute patientAttribute : patientAttributes )
-        {
-            grid.addHeader( new GridHeader( patientAttribute.getDisplayName(), false, true ) );
-        }
-
-        grid.addHeader( new GridHeader( "programstageinstanceid", true, true ) );
-        grid.addHeader( new GridHeader( i18n.getString( "program_stage" ), false, true ) );
-        grid.addHeader( new GridHeader( i18n.getString( "due_date" ), false, true ) );
-
-        return patientStore.getPatientEventReport( grid, searchKeys, orgunits, followup, patientAttributes, null,
-            statusEnrollment, min, max );
-    }
-
-    @Override
-    public Grid getTrackingEventsReport( Program program, List<String> searchKeys,
-        Collection<OrganisationUnit> orgunits, Boolean followup, Integer statusEnrollment, I18n i18n )
-    {
-        String startDate = "";
-        String endDate = "";
-        for ( String searchKey : searchKeys )
-        {
-            String[] keys = searchKey.split( "_" );
-            if ( keys[0].equals( Patient.PREFIX_PROGRAM_EVENT_BY_STATUS ) )
-            {
-                startDate = keys[2];
-                endDate = keys[3];
-            }
-        }
-
-        Grid grid = new ListGrid();
-        grid.setTitle( i18n.getString( "program_tracking" ) );
-        if ( !startDate.isEmpty() && !endDate.isEmpty() )
-        {
-            grid.setSubtitle( i18n.getString( "from" ) + " " + startDate + " " + i18n.getString( "to" ) + " " + endDate );
-        }
-
-        grid.addHeader( new GridHeader( "patientid", true, true ) );
-        grid.addHeader( new GridHeader( i18n.getString( "first_name" ), true, true ) );
-        grid.addHeader( new GridHeader( i18n.getString( "middle_name" ), true, true ) );
-        grid.addHeader( new GridHeader( i18n.getString( "last_name" ), true, true ) );
-        grid.addHeader( new GridHeader( i18n.getString( "gender" ), true, true ) );
-        grid.addHeader( new GridHeader( i18n.getString( "phone_number" ), false, true ) );
-
-        Collection<PatientIdentifierType> patientIdentifierTypes = program.getIdentifierTypes();
-        
-        for ( PatientIdentifierType patientIdentifierType : patientIdentifierTypes )
-        {
-            grid.addHeader( new GridHeader( patientIdentifierType.getDisplayName(), false, true ) );
-        }
-        grid.addHeader( new GridHeader( "programstageinstanceid", true, true ) );
-        grid.addHeader( new GridHeader( i18n.getString( "program_stage" ), false, true ) );
-        grid.addHeader( new GridHeader( i18n.getString( "due_date" ), false, true ) );
-        grid.addHeader( new GridHeader( i18n.getString( "risk" ), false, true ) );
-
-        return patientStore.getPatientEventReport( grid, searchKeys, orgunits, followup, null, patientIdentifierTypes,
-            statusEnrollment, null, null );
-    }
-
-    @Override
-    public int validatePatient( Patient patient, Program program )
-    {
-        return patientStore.validate( patient, program );
-    }
+public class DefaultPatientService implements PatientService {
+	// -------------------------------------------------------------------------
+	// Dependencies
+	// -------------------------------------------------------------------------
+
+	private PatientStore patientStore;
+
+	public void setPatientStore(PatientStore patientStore) {
+		this.patientStore = patientStore;
+	}
+
+	private PatientIdentifierService patientIdentifierService;
+
+	public void setPatientIdentifierService(
+			PatientIdentifierService patientIdentifierService) {
+		this.patientIdentifierService = patientIdentifierService;
+	}
+
+	private PatientAttributeValueService patientAttributeValueService;
+
+	public void setPatientAttributeValueService(
+			PatientAttributeValueService patientAttributeValueService) {
+		this.patientAttributeValueService = patientAttributeValueService;
+	}
+
+	private PatientAttributeService patientAttributeService;
+
+	public void setPatientAttributeService(
+			PatientAttributeService patientAttributeService) {
+		this.patientAttributeService = patientAttributeService;
+	}
+
+	private PatientIdentifierTypeService patientIdentifierTypeService;
+
+	public void setPatientIdentifierTypeService(
+			PatientIdentifierTypeService patientIdentifierTypeService) {
+		this.patientIdentifierTypeService = patientIdentifierTypeService;
+	}
+
+	private RelationshipService relationshipService;
+
+	public void setRelationshipService(RelationshipService relationshipService) {
+		this.relationshipService = relationshipService;
+	}
+
+	private RelationshipTypeService relationshipTypeService;
+
+	public void setRelationshipTypeService(
+			RelationshipTypeService relationshipTypeService) {
+		this.relationshipTypeService = relationshipTypeService;
+	}
+
+	// -------------------------------------------------------------------------
+	// Implementation methods
+	// -------------------------------------------------------------------------
+
+	@Override
+	public int savePatient(Patient patient) {
+		return patientStore.save(patient);
+	}
+
+	@Override
+	public int createPatient(Patient patient, Integer representativeId,
+			Integer relationshipTypeId,
+			Set<PatientAttributeValue> patientAttributeValues) {
+		int id = savePatient(patient);
+
+		for (PatientAttributeValue pav : patientAttributeValues) {
+			patientAttributeValueService.savePatientAttributeValue(pav);
+			patient.getAttributeValues().add(pav);
+		}
+
+		// ---------------------------------------------------------------------
+		// If under age, save representative information
+		// ---------------------------------------------------------------------
+
+		if (representativeId != null) {
+			Patient representative = patientStore.get(representativeId);
+			if (representative != null) {
+				patient.setRepresentative(representative);
+
+				Relationship rel = new Relationship();
+				rel.setPatientA(representative);
+				rel.setPatientB(patient);
+
+				if (relationshipTypeId != null) {
+					RelationshipType relType = relationshipTypeService
+							.getRelationshipType(relationshipTypeId);
+					if (relType != null) {
+						rel.setRelationshipType(relType);
+						relationshipService.saveRelationship(rel);
+					}
+				}
+			}
+		}
+
+		updatePatient(patient); // Save patient to update associations
+
+		return id;
+	}
+
+	@Override
+	public void updatePatient(Patient patient) {
+		patientStore.update(patient);
+	}
+
+	@Override
+	public void deletePatient(Patient patient) {
+		patientStore.delete(patient);
+	}
+
+	@Override
+	public Patient getPatient(int id) {
+		return patientStore.get(id);
+	}
+
+	@Override
+	public Patient getPatient(String uid) {
+		return patientStore.getByUid(uid);
+	}
+
+	@Override
+	public Collection<Patient> getAllPatients() {
+		return patientStore.getAll();
+	}
+
+	@Override
+	public Collection<Patient> getPatientsForMobile(String searchText,
+			int orgUnitId) {
+		Set<Patient> patients = new HashSet<Patient>();
+		patients.addAll(getPatientsByPhone(searchText, 0, Integer.MAX_VALUE));
+		patients.addAll(getPatientsByPhone(searchText, 0, Integer.MAX_VALUE));
+
+		// if an org-unit has been selected, filter out every patient that has a
+		// different org-unit
+		if (orgUnitId != 0) {
+			Set<Patient> toRemoveList = new HashSet<Patient>();
+
+			for (Patient patient : patients) {
+				if (patient.getOrganisationUnit().getId() != orgUnitId) {
+					toRemoveList.add(patient);
+				}
+			}
+
+			patients.removeAll(toRemoveList);
+		}
+
+		return patients;
+	}
+
+	@Override
+	public Collection<Patient> getPatients(OrganisationUnit organisationUnit,
+			Integer min, Integer max) {
+		return patientStore.getByOrgUnit(organisationUnit, min, max);
+	}
+
+	@Override
+	public Collection<Patient> getPatients(Program program) {
+		return patientStore.getByProgram(program, 0, Integer.MAX_VALUE);
+	}
+
+	@Override
+	public Collection<Patient> getPatients(OrganisationUnit organisationUnit,
+			Program program) {
+		return patientStore.getByOrgUnitProgram(organisationUnit, program, 0,
+				Integer.MAX_VALUE);
+	}
+
+	@Override
+	public Collection<Patient> getPatient(Integer identifierTypeId,
+			Integer attributeId, String value) {
+		if (attributeId != null) {
+			PatientAttribute attribute = patientAttributeService
+					.getPatientAttribute(attributeId);
+			if (attribute != null) {
+				return patientAttributeValueService
+						.getPatient(attribute, value);
+			}
+		} else if (identifierTypeId != null) {
+			PatientIdentifierType identifierType = patientIdentifierTypeService
+					.getPatientIdentifierType(identifierTypeId);
+
+			if (identifierType != null) {
+				Patient p = patientIdentifierService.getPatient(identifierType,
+						value);
+				if (p != null) {
+					Set<Patient> set = new HashSet<Patient>();
+					set.add(p);
+					return set;
+				}
+			}
+		}
+
+		return null;
+	}
+
+	@Override
+	public Collection<Patient> sortPatientsByAttribute(
+			Collection<Patient> patients, PatientAttribute patientAttribute) {
+		Collection<Patient> sortedPatients = new ArrayList<Patient>();
+
+		// ---------------------------------------------------------------------
+		// Better to fetch all attribute values at once than fetching the
+		// required attribute value of each patient using loop
+		// ---------------------------------------------------------------------
+
+		Collection<PatientAttributeValue> patientAttributeValues = patientAttributeValueService
+				.getPatientAttributeValues(patients);
+
+		if (patientAttributeValues != null) {
+			for (PatientAttributeValue patientAttributeValue : patientAttributeValues) {
+				if (patientAttribute == patientAttributeValue
+						.getPatientAttribute()) {
+					sortedPatients.add(patientAttributeValue.getPatient());
+					patients.remove(patientAttributeValue.getPatient());
+				}
+			}
+		}
+
+		// ---------------------------------------------------------------------
+		// Make sure all patients are in the sorted list - because all
+		// patients might not have the sorting attribute/value
+		// ---------------------------------------------------------------------
+
+		sortedPatients.addAll(patients);
+
+		return sortedPatients;
+	}
+
+	@Override
+	public int countGetPatientsByOrgUnit(OrganisationUnit organisationUnit) {
+		return patientStore.countListPatientByOrgunit(organisationUnit);
+	}
+
+	@Override
+	public void updatePatient(Patient patient, Integer representativeId,
+			Integer relationshipTypeId,
+			List<PatientAttributeValue> valuesForSave,
+			List<PatientAttributeValue> valuesForUpdate,
+			Collection<PatientAttributeValue> valuesForDelete) {
+		patientStore.update(patient);
+
+		for (PatientAttributeValue av : valuesForSave) {
+			patientAttributeValueService.savePatientAttributeValue(av);
+		}
+
+		for (PatientAttributeValue av : valuesForUpdate) {
+			patientAttributeValueService.updatePatientAttributeValue(av);
+		}
+
+		for (PatientAttributeValue av : valuesForDelete) {
+			patientAttributeValueService.deletePatientAttributeValue(av);
+		}
+
+		if (shouldSaveRepresentativeInformation(patient, representativeId)) {
+			Patient representative = patientStore.get(representativeId);
+
+			if (representative != null) {
+				patient.setRepresentative(representative);
+
+				Relationship rel = new Relationship();
+				rel.setPatientA(representative);
+				rel.setPatientB(patient);
+
+				if (relationshipTypeId != null) {
+					RelationshipType relType = relationshipTypeService
+							.getRelationshipType(relationshipTypeId);
+					if (relType != null) {
+						rel.setRelationshipType(relType);
+						relationshipService.saveRelationship(rel);
+					}
+				}
+			}
+		}
+	}
+
+	private boolean shouldSaveRepresentativeInformation(Patient patient,
+			Integer representativeId) {
+		if (representativeId == null) {
+			return false;
+		}
+
+		return patient.getRepresentative() == null
+				|| !(patient.getRepresentative().getId() == representativeId);
+	}
+
+	@Override
+	public Collection<Patient> getPatients(OrganisationUnit organisationUnit,
+			Program program, Integer min, Integer max) {
+		return patientStore.getByOrgUnitProgram(organisationUnit, program, min,
+				max);
+	}
+
+	@Override
+	public int countGetPatientsByOrgUnitProgram(
+			OrganisationUnit organisationUnit, Program program) {
+		return patientStore.countGetPatientsByOrgUnitProgram(organisationUnit,
+				program);
+	}
+
+	@Override
+	public Object getObjectValue(String property, String value,
+			I18nFormat format) {
+		try {
+			Type type = Patient.class.getMethod(
+					"get" + StringUtils.capitalize(property)).getReturnType();
+
+			if (type == Integer.class || type == Integer.TYPE) {
+				return Integer.valueOf(value);
+			} else if (type.equals(Boolean.class) || type == Boolean.TYPE) {
+				return Boolean.valueOf(value);
+			} else if (type.equals(Date.class)) {
+				return format.parseDate(value.trim());
+			} else if (type.equals(Character.class) || type == Character.TYPE) {
+				return Character.valueOf(value.charAt(0));
+			}
+
+			return value;
+		} catch (Exception ex) {
+			ex.printStackTrace();
+		}
+
+		return null;
+	}
+
+	@Override
+	public Collection<Patient> getRepresentatives(Patient patient) {
+		return patientStore.getRepresentatives(patient);
+	}
+
+	@Override
+	public Collection<Patient> searchPatients(List<String> searchKeys,
+			Collection<OrganisationUnit> orgunits, Boolean followup,
+			Collection<PatientAttribute> patientAttributes,
+			Collection<PatientIdentifierType> identifierTypes,
+			Integer statusEnrollment, Integer min, Integer max) {
+		return patientStore.search(searchKeys, orgunits, followup,
+				patientAttributes, identifierTypes, statusEnrollment, min, max);
+	}
+
+	@Override
+	public int countSearchPatients(List<String> searchKeys,
+			Collection<OrganisationUnit> orgunits, Boolean followup,
+			Integer statusEnrollment) {
+		return patientStore.countSearch(searchKeys, orgunits, followup,
+				statusEnrollment);
+	}
+
+	@Override
+	public Collection<String> getPatientPhoneNumbers(List<String> searchKeys,
+			Collection<OrganisationUnit> orgunits, Boolean followup,
+			Integer statusEnrollment, Integer min, Integer max) {
+		Collection<Patient> patients = patientStore.search(searchKeys,
+				orgunits, followup, null, null, statusEnrollment, min, max);
+		Set<String> phoneNumbers = new HashSet<String>();
+
+		for (Patient patient : patients) {
+			Collection<PatientAttributeValue> attributeValues = patient
+					.getAttributeValues();
+			if (attributeValues != null) {
+				for (PatientAttributeValue attributeValue : attributeValues) {
+					if (attributeValue.getPatientAttribute().getValueType()
+							.equals(PatientAttribute.TYPE_PHONE_NUMBER)) {
+						phoneNumbers.add(attributeValue.getValue());
+					}
+				}
+			}
+		}
+
+		return phoneNumbers;
+	}
+
+	@Override
+	public List<Integer> getProgramStageInstances(List<String> searchKeys,
+			Collection<OrganisationUnit> orgunits, Boolean followup,
+			Integer statusEnrollment, Integer min, Integer max) {
+		return patientStore.getProgramStageInstances(searchKeys, orgunits,
+				followup, null, null, statusEnrollment, min, max);
+	}
+
+	@Override
+	public Collection<Patient> getPatientsByPhone(String phoneNumber,
+			Integer min, Integer max) {
+		return patientStore.getByPhoneNumber(phoneNumber, min, max);
+	}
+
+	@Override
+	public Grid getScheduledEventsReport(List<String> searchKeys,
+			Collection<OrganisationUnit> orgunits, Boolean followup,
+			Integer statusEnrollment, Integer min, Integer max, I18n i18n) {
+		String startDate = "";
+		String endDate = "";
+		for (String searchKey : searchKeys) {
+			String[] keys = searchKey.split("_");
+			if (keys[0].equals(Patient.PREFIX_PROGRAM_EVENT_BY_STATUS)) {
+				startDate = keys[2];
+				endDate = keys[3];
+			}
+		}
+
+		Grid grid = new ListGrid();
+		grid.setTitle(i18n.getString("activity_plan"));
+		if (!startDate.isEmpty() && !endDate.isEmpty()) {
+			grid.setSubtitle(i18n.getString("from") + " " + startDate + " "
+					+ i18n.getString("to") + " " + endDate);
+		}
+
+		grid.addHeader(new GridHeader("patientid", true, true));
+		grid.addHeader(new GridHeader(i18n.getString("first_name"), false, true));
+		grid.addHeader(new GridHeader(i18n.getString("middle_name"), false,
+				true));
+		grid.addHeader(new GridHeader(i18n.getString("last_name"), false, true));
+		grid.addHeader(new GridHeader(i18n.getString("gender"), false, true));
+		grid.addHeader(new GridHeader(i18n.getString("phone_number"), false,
+				true));
+
+		Collection<PatientAttribute> patientAttributes = patientAttributeService
+				.getPatientAttributesByDisplayOnVisitSchedule(true);
+		for (PatientAttribute patientAttribute : patientAttributes) {
+			grid.addHeader(new GridHeader(patientAttribute.getDisplayName(),
+					false, true));
+		}
+
+		grid.addHeader(new GridHeader("programstageinstanceid", true, true));
+		grid.addHeader(new GridHeader(i18n.getString("program_stage"), false,
+				true));
+		grid.addHeader(new GridHeader(i18n.getString("due_date"), false, true));
+
+		return patientStore.getPatientEventReport(grid, searchKeys, orgunits,
+				followup, patientAttributes, null, statusEnrollment, min, max);
+	}
+
+	@Override
+	public Grid getTrackingEventsReport(Program program,
+			List<String> searchKeys, Collection<OrganisationUnit> orgunits,
+			Boolean followup, Integer statusEnrollment, I18n i18n) {
+		String startDate = "";
+		String endDate = "";
+		for (String searchKey : searchKeys) {
+			String[] keys = searchKey.split("_");
+			if (keys[0].equals(Patient.PREFIX_PROGRAM_EVENT_BY_STATUS)) {
+				startDate = keys[2];
+				endDate = keys[3];
+			}
+		}
+
+		Grid grid = new ListGrid();
+		grid.setTitle(i18n.getString("program_tracking"));
+		if (!startDate.isEmpty() && !endDate.isEmpty()) {
+			grid.setSubtitle(i18n.getString("from") + " " + startDate + " "
+					+ i18n.getString("to") + " " + endDate);
+		}
+
+		grid.addHeader(new GridHeader("patientid", true, true));
+		grid.addHeader(new GridHeader(i18n.getString("first_name"), true, true));
+		grid.addHeader(new GridHeader(i18n.getString("middle_name"), true, true));
+		grid.addHeader(new GridHeader(i18n.getString("last_name"), true, true));
+		grid.addHeader(new GridHeader(i18n.getString("gender"), true, true));
+		grid.addHeader(new GridHeader(i18n.getString("phone_number"), false,
+				true));
+
+		Collection<PatientIdentifierType> patientIdentifierTypes = program
+				.getIdentifierTypes();
+
+		for (PatientIdentifierType patientIdentifierType : patientIdentifierTypes) {
+			grid.addHeader(new GridHeader(patientIdentifierType
+					.getDisplayName(), false, true));
+		}
+		grid.addHeader(new GridHeader("programstageinstanceid", true, true));
+		grid.addHeader(new GridHeader(i18n.getString("program_stage"), false,
+				true));
+		grid.addHeader(new GridHeader(i18n.getString("due_date"), false, true));
+		grid.addHeader(new GridHeader(i18n.getString("risk"), false, true));
+
+		return patientStore.getPatientEventReport(grid, searchKeys, orgunits,
+				followup, null, patientIdentifierTypes, statusEnrollment, null,
+				null);
+	}
+
+	@Override
+	public int validatePatient(Patient patient, Program program) {
+		return patientStore.validate(patient, program);
+	}
+
+	@Override
+	public Collection<Patient> getPatientsByAttributeValue(String searchText,
+			int patientAttributeId, Integer min, Integer max) {
+
+		return patientStore.getByPatientAttributeValue(searchText,
+				patientAttributeId, min, max);
+	}
+
+	@Override
+	public Collection<Patient> searchPatientsForMobile(String searchText,
+			int orgUnitId, int patientAttributeId) {
+		Set<Patient> patients = new HashSet<Patient>();
+
+		patients.addAll(getPatientsByAttributeValue(searchText,
+				patientAttributeId, 0, Integer.MAX_VALUE));
+
+		// if an org-unit has been selected, filter out every patient that has a
+		// different org-unit
+		if (orgUnitId != 0) {
+			Set<Patient> toRemoveList = new HashSet<Patient>();
+
+			for (Patient patient : patients) {
+				if (patient.getOrganisationUnit().getId() != orgUnitId) {
+					toRemoveList.add(patient);
+				}
+			}
+
+			patients.removeAll(toRemoveList);
+		}
+
+		return patients;
+	}
 
 }

=== modified file 'dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patient/hibernate/HibernatePatientStore.java'
--- dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patient/hibernate/HibernatePatientStore.java	2014-01-05 14:04:13 +0000
+++ dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patient/hibernate/HibernatePatientStore.java	2014-01-22 04:25:46 +0000
@@ -63,6 +63,7 @@
 import org.hisp.dhis.patient.PatientService;
 import org.hisp.dhis.patient.PatientStore;
 import org.hisp.dhis.patient.TrackedEntityQueryParams;
+import org.hisp.dhis.patientattributevalue.PatientAttributeValue;
 import org.hisp.dhis.period.Period;
 import org.hisp.dhis.program.Program;
 import org.hisp.dhis.program.ProgramInstance;
@@ -79,732 +80,770 @@
  * @author Abyot Asalefew Gizaw
  */
 @Transactional
-public class HibernatePatientStore
-    extends HibernateIdentifiableObjectStore<Patient>
-    implements PatientStore
-{
-    private static final Log log = LogFactory.getLog( HibernatePatientStore.class );
-
-    // -------------------------------------------------------------------------
-    // Dependencies
-    // -------------------------------------------------------------------------
-
-    private OrganisationUnitService organisationUnitService;
-
-    public void setOrganisationUnitService( OrganisationUnitService organisationUnitService )
-    {
-        this.organisationUnitService = organisationUnitService;
-    }
-
-    // -------------------------------------------------------------------------
-    // Implementation methods
-    // -------------------------------------------------------------------------
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public Collection<Patient> getByOrgUnit( OrganisationUnit organisationUnit, Integer min, Integer max )
-    {
-        String hql = "select p from Patient p where p.organisationUnit = :organisationUnit order by p.id DESC";
-
-        Query query = getQuery( hql );
-        query.setEntity( "organisationUnit", organisationUnit );
-
-        if ( min != null && max != null )
-        {
-            query.setFirstResult( min ).setMaxResults( max );
-        }
-
-        return query.list();
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public Collection<Patient> getByOrgUnitProgram( OrganisationUnit organisationUnit, Program program, Integer min,
-        Integer max )
-    {
-        String hql = "select pt from Patient pt inner join pt.programInstances pi "
-            + "where pt.organisationUnit = :organisationUnit " + "and pi.program = :program "
-            + "and pi.status = :status";
-
-        Query query = getQuery( hql );
-        query.setEntity( "organisationUnit", organisationUnit );
-        query.setEntity( "program", program );
-        query.setInteger( "status", ProgramInstance.STATUS_ACTIVE );
-
-        return query.list();
-    }
-
-    @SuppressWarnings( "unchecked" )
-    public List<Patient> query( TrackedEntityQueryParams params )
-    {
-        SqlHelper hlp = new SqlHelper();
-
-        String hql = "select pt from Patient pt left join pt.attributeValues av";
-
-        for ( QueryItem at : params.getAttributes() )
-        {
-            hql += " " + hlp.whereAnd();
-            hql += " (av.patientAttribute = :attr" + at.getItemId() + " and av.value = :filt" + at.getItemId() + ")";
-        }
-
-        Query query = getQuery( hql );
-
-        for ( QueryItem at : params.getAttributes() )
-        {
-            query.setEntity( "attr" + at.getItemId(), at.getItem() );
-            query.setString( "filt" + at.getItemId(), at.getFilter() );
-        }
-
-        return query.list();
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public Collection<Patient> getByProgram( Program program, Integer min, Integer max )
-    {
-        String hql = "select pt from Patient pt inner join pt.programInstances pi "
-            + "where pi.program = :program and pi.status = :status";
-
-        Query query = getQuery( hql );
-        query.setEntity( "program", program );
-        query.setInteger( "status", ProgramInstance.STATUS_ACTIVE );
-
-        return query.list();
-    }
-
-    @Override
-    public int countGetPatientsByName( String fullName )
-    {
-        fullName = fullName.toLowerCase();
-        String sql = "SELECT count(*) FROM patient where lower( name ) " + "like '%" + fullName + "%' ";
-
-        return jdbcTemplate.queryForObject( sql, Integer.class );
-    }
-
-    @Override
-    public int countListPatientByOrgunit( OrganisationUnit organisationUnit )
-    {
-        Query query = getQuery( "select count(p.id) from Patient p where p.organisationUnit.id=:orgUnitId " );
-
-        query.setParameter( "orgUnitId", organisationUnit.getId() );
-
-        Number rs = (Number) query.uniqueResult();
-
-        return rs != null ? rs.intValue() : 0;
-    }
-
-    @Override
-    public int countGetPatientsByOrgUnitProgram( OrganisationUnit organisationUnit, Program program )
-    {
-        String sql = "select count(p.patientid) from patient p join programinstance pi on p.patientid=pi.patientid "
-            + "where p.organisationunitid=" + organisationUnit.getId() + " and pi.programid=" + program.getId()
-            + " and pi.status=" + ProgramInstance.STATUS_ACTIVE;
-
-        return jdbcTemplate.queryForObject( sql, Integer.class );
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public Collection<Patient> getRepresentatives( Patient patient )
-    {
-        String hql = "select distinct p from Patient p where p.representative = :representative order by p.id DESC";
-
-        return getQuery( hql ).setEntity( "representative", patient ).list();
-    }
-
-    @Override
-    // TODO this method must be changed - cannot retrieve one by one
-    public Collection<Patient> search( List<String> searchKeys, Collection<OrganisationUnit> orgunits,
-        Boolean followup, Collection<PatientAttribute> patientAttributes,
-        Collection<PatientIdentifierType> identifierTypes, Integer statusEnrollment, Integer min, Integer max )
-    {
-        String sql = searchPatientSql( false, searchKeys, orgunits, followup, patientAttributes, identifierTypes,
-            statusEnrollment, min, max );
-        Collection<Patient> patients = new HashSet<Patient>();
-        try
-        {
-            patients = jdbcTemplate.query( sql, new RowMapper<Patient>()
-            {
-                public Patient mapRow( ResultSet rs, int rowNum )
-                    throws SQLException
-                {
-                    return get( rs.getInt( 1 ) );
-                }
-            } );
-        }
-        catch ( Exception ex )
-        {
-            ex.printStackTrace();
-        }
-        return patients;
-    }
-
-    @Override
-    public List<Integer> getProgramStageInstances( List<String> searchKeys, Collection<OrganisationUnit> orgunits,
-        Boolean followup, Collection<PatientAttribute> patientAttributes,
-        Collection<PatientIdentifierType> identifierTypes, Integer statusEnrollment, Integer min, Integer max )
-    {
-        String sql = searchPatientSql( false, searchKeys, orgunits, followup, patientAttributes, identifierTypes,
-            statusEnrollment, min, max );
-
-        List<Integer> programStageInstanceIds = new ArrayList<Integer>();
-        try
-        {
-            programStageInstanceIds = jdbcTemplate.query( sql, new RowMapper<Integer>()
-            {
-                public Integer mapRow( ResultSet rs, int rowNum )
-                    throws SQLException
-                {
-                    return rs.getInt( "programstageinstanceid" );
-                }
-            } );
-        }
-        catch ( Exception ex )
-        {
-            ex.printStackTrace();
-        }
-
-        return programStageInstanceIds;
-    }
-
-    public int countSearch( List<String> searchKeys, Collection<OrganisationUnit> orgunits, Boolean followup,
-        Integer statusEnrollment )
-    {
-        String sql = searchPatientSql( true, searchKeys, orgunits, followup, null, null, statusEnrollment, null, null );
-        return jdbcTemplate.queryForObject( sql, Integer.class );
-    }
-
-    @Override
-    public Grid getPatientEventReport( Grid grid, List<String> searchKeys, Collection<OrganisationUnit> orgunits,
-        Boolean followup, Collection<PatientAttribute> patientAttributes,
-        Collection<PatientIdentifierType> identifierTypes, Integer statusEnrollment, Integer min, Integer max )
-    {
-        String sql = searchPatientSql( false, searchKeys, orgunits, followup, patientAttributes, identifierTypes,
-            statusEnrollment, min, max );
-
-        SqlRowSet rowSet = jdbcTemplate.queryForRowSet( sql );
-
-        GridUtils.addRows( grid, rowSet );
-
-        return grid;
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public Collection<Patient> getByPhoneNumber( String phoneNumber, Integer min, Integer max )
-    {
-        Criteria criteria = getCriteria();
-        criteria.createAlias( "attributeValues", "attributeValue" );
-        criteria.createAlias( "attributeValue.patientAttribute", "patientAttribute" );
-        criteria.add( Restrictions.eq( "patientAttribute.valueType", PatientAttribute.TYPE_PHONE_NUMBER ) );
-        criteria.add( Restrictions.like( "attributeValue.value", phoneNumber ) );
-
-        if ( min != null && max != null )
-        {
-            criteria.setFirstResult( min );
-            criteria.setMaxResults( max );
-        }
-
-        return criteria.list();
-    }
-
-    @SuppressWarnings( "unchecked" )
-    public Collection<Integer> getRegistrationOrgunitIds( Date startDate, Date endDate )
-    {
-        Criteria criteria = getCriteria();
-        criteria.add( Restrictions.between( "registrationDate", startDate, endDate ) );
-        criteria.createAlias( "organisationUnit", "orgunit" );
-        criteria.setProjection( Projections.distinct( Projections.projectionList().add(
-            Projections.property( "orgunit.id" ), "orgunitid" ) ) );
-
-        return criteria.list();
-    }
-
-    public int validate( Patient patient, Program program )
-    {
-        if ( patient.getIdentifiers() != null && patient.getIdentifiers().size() > 0 )
-        {
-            Criteria criteria = getCriteria();
-            criteria.createAlias( "identifiers", "patientIdentifier" );
-            criteria.createAlias( "organisationUnit", "orgunit" );
-            criteria.createAlias( "programInstances", "programInstance" );
-            criteria.createAlias( "programInstance.program", "program" );
-
-            Disjunction disjunction = Restrictions.disjunction();
-
-            for ( PatientIdentifier identifier : patient.getIdentifiers() )
-            {
-                PatientIdentifierType patientIdentifierType = identifier.getIdentifierType();
-
-                Conjunction conjunction = Restrictions.conjunction();
-                conjunction.add( Restrictions.eq( "patientIdentifier.identifier", identifier.getIdentifier() ) );
-                conjunction.add( Restrictions.eq( "patientIdentifier.identifierType", patientIdentifierType ) );
-
-                if ( patient.getId() != 0 )
-                {
-                    conjunction.add( Restrictions.ne( "id", patient.getId() ) );
-                }
-
-                if ( patientIdentifierType.getType().equals( PatientIdentifierType.VALUE_TYPE_LOCAL_ID )
-                    && patientIdentifierType.getOrgunitScope() )
-                {
-                    conjunction.add( Restrictions.eq( "orgunit.id", patient.getOrganisationUnit().getId() ) );
-                }
-
-                if ( program != null
-                    && patientIdentifierType.getType().equals( PatientIdentifierType.VALUE_TYPE_LOCAL_ID )
-                    && patientIdentifierType.getProgramScope() )
-                {
-                    conjunction.add( Restrictions.eq( "program", program ) );
-                }
-
-                if ( patientIdentifierType.getType().equals( PatientIdentifierType.VALUE_TYPE_LOCAL_ID )
-                    && patientIdentifierType.getPeriodType() != null )
-                {
-                    Date currentDate = new Date();
-                    Period period = patientIdentifierType.getPeriodType().createPeriod( currentDate );
-                    conjunction
-                        .add( Restrictions.between( "enrollmentdate", period.getStartDate(), period.getEndDate() ) );
-                }
-
-                disjunction.add( conjunction );
-            }
-
-            criteria.add( disjunction );
-
-            Number rs = (Number) criteria.setProjection( Projections.rowCount() ).uniqueResult();
-
-            if ( rs != null && rs.intValue() > 0 )
-            {
-                return PatientService.ERROR_DUPLICATE_IDENTIFIER;
-            }
-        }
-
-        if ( program != null )
-        {
-            ValidationCriteria validationCriteria = program.isValid( patient );
-
-            if ( validationCriteria != null )
-            {
-                return PatientService.ERROR_ENROLLMENT;
-            }
-        }
-
-        return PatientService.ERROR_NONE;
-    }
-
-    // -------------------------------------------------------------------------
-    // Supportive methods TODO Remplement all this!
-    // -------------------------------------------------------------------------
-
-    private String searchPatientSql( boolean count, List<String> searchKeys, Collection<OrganisationUnit> orgunits,
-        Boolean followup, Collection<PatientAttribute> patientAttributes,
-        Collection<PatientIdentifierType> identifierTypes, Integer statusEnrollment, Integer min, Integer max )
-    {
-        String selector = count ? "count(*) " : "* ";
-        String sql = "select " + selector + " from ( select distinct p.patientid,";
-
-        if ( identifierTypes != null )
-        {
-            for ( PatientIdentifierType identifierType : identifierTypes )
-            {
-                sql += "(select identifier from patientidentifier where patientid=p.patientid and patientidentifiertypeid="
-                    + identifierType.getId() + " ) as " + PREFIX_IDENTIFIER_TYPE + "_" + identifierType.getId() + " ,";
-            }
-        }
-
-        if ( patientAttributes != null )
-        {
-            for ( PatientAttribute patientAttribute : patientAttributes )
-            {
-                sql += "(select value from patientattributevalue where patientid=p.patientid and patientattributeid="
-                    + patientAttribute.getId() + " ) as " + PREFIX_PATIENT_ATTRIBUTE + "_" + patientAttribute.getId()
-                    + " ,";
-            }
-        }
-
-        String patientWhere = "";
-        String patientOperator = " where ";
-        String patientGroupBy = " GROUP BY  p.patientid ";
-        String otherWhere = "";
-        String operator = " where ";
-        String orderBy = "";
-        boolean hasIdentifier = false;
-        boolean isSearchEvent = false;
-        boolean isPriorityEvent = false;
-        Collection<Integer> orgunitChilrenIds = null;
-
-        if ( orgunits != null )
-        {
-            orgunitChilrenIds = getOrgunitChildren( orgunits );
-        }
-
-        for ( String searchKey : searchKeys )
-        {
-            String[] keys = searchKey.split( "_" );
-
-            if ( keys.length <= 1 || keys[1] == null || keys[1].trim().isEmpty() || keys[1].equals( "null" ) )
-            {
-                continue;
-            }
-
-            String id = keys[1];
-            String value = "";
-
-            if ( keys.length >= 3 )
-            {
-                value = keys[2];
-            }
-
-            if ( keys[0].equals( PREFIX_IDENTIFIER_TYPE ) )
-            {
-
-                String[] keyValues = id.split( " " );
-                patientWhere += patientOperator + " (";
-                String opt = "";
-                for ( String v : keyValues )
-                {
-                    patientWhere += opt + " ( lower(pi.identifier) like '%" + v
-                        + "%' and pi.patientidentifiertypeid is not null ) ";
-                    opt = "or";
-                }
-
-                patientWhere += ")";
-                patientOperator = " and ";
-                hasIdentifier = true;
-            }
-            else if ( keys[0].equals( PREFIX_PATIENT_ATTRIBUTE ) )
-            {
-                sql += "(select value from patientattributevalue where patientid=p.patientid and patientattributeid="
-                    + id + " ) as " + PREFIX_PATIENT_ATTRIBUTE + "_" + id + ",";
-
-                String[] keyValues = value.split( " " );
-                otherWhere += operator + "(";
-                String opt = "";
-
-                for ( String v : keyValues )
-                {
-                    otherWhere += opt + " lower(" + PREFIX_PATIENT_ATTRIBUTE + "_" + id + ") like '%" + v + "%'";
-                    opt = "or";
-                }
-
-                otherWhere += ")";
-                operator = " and ";
-            }
-            else if ( keys[0].equals( PREFIX_PROGRAM ) )
-            {
-                sql += "(select programid from programinstance pgi where patientid=p.patientid and programid=" + id;
-
-                if ( statusEnrollment != null )
-                {
-                    sql += " and pgi.status=" + statusEnrollment;
-                }
-
-                sql += " limit 1 ) as " + PREFIX_PROGRAM + "_" + id + ",";
-                otherWhere += operator + PREFIX_PROGRAM + "_" + id + "=" + id;
-                operator = " and ";
-            }
-            else if ( keys[0].equals( PREFIX_PROGRAM_INSTANCE ) )
-            {
-                sql += "(select pi." + id + " from programinstance pi where patientid=p.patientid and pi.status=0 ";
-
-                if ( keys.length == 5 )
-                {
-                    sql += " and pi.programid=" + keys[4];
-                }
-                else
-                {
-                    sql += " limit 1 ";
-                }
-
-                sql += ") as " + PREFIX_PROGRAM_INSTANCE + "_" + id + ",";
-                otherWhere += operator + PREFIX_PROGRAM_INSTANCE + "_" + id + keys[2];
-                operator = " and ";
-            }
-            else if ( keys[0].equals( PREFIX_PROGRAM_EVENT_BY_STATUS ) )
-            {
-                isSearchEvent = true;
-                isPriorityEvent = Boolean.parseBoolean( keys[5] );
-                patientWhere += patientOperator + "pgi.patientid=p.patientid and ";
-                patientWhere += "pgi.programid=" + id + " and ";
-                patientWhere += "pgi.status=" + ProgramInstance.STATUS_ACTIVE;
-
-                String operatorStatus = "";
-                String condition = " and ( ";
-
-                for ( int index = 6; index < keys.length; index++ )
-                {
-                    int statusEvent = Integer.parseInt( keys[index] );
-                    switch ( statusEvent )
-                    {
-                    case ProgramStageInstance.COMPLETED_STATUS:
-                        patientWhere += condition + operatorStatus
-                            + "( psi.executiondate is not null and  psi.executiondate>='" + keys[2]
-                            + "' and psi.executiondate<='" + keys[3] + "' and psi.completed=true ";
-
-                        // get events by orgunit children
-                        if ( keys[4].equals( "-1" ) )
-                        {
-                            patientWhere += " and psi.organisationunitid in( "
-                                + TextUtils.getCommaDelimitedString( orgunitChilrenIds ) + " )";
-                        }
-
-                        // get events by selected orgunit
-                        else if ( !keys[4].equals( "0" ) )
-                        {
-                            patientWhere += " and psi.organisationunitid=" + getOrgUnitId( keys );
-                        }
-
-                        patientWhere += ")";
-                        operatorStatus = " OR ";
-                        condition = "";
-                        continue;
-                    case ProgramStageInstance.VISITED_STATUS:
-                        patientWhere += condition + operatorStatus
-                            + "( psi.executiondate is not null and psi.executiondate>='" + keys[2]
-                            + "' and psi.executiondate<='" + keys[3] + "' and psi.completed=false ";
-
-                        // get events by orgunit children
-                        if ( keys[4].equals( "-1" ) )
-                        {
-                            patientWhere += " and psi.organisationunitid in( "
-                                + TextUtils.getCommaDelimitedString( orgunitChilrenIds ) + " )";
-                        }
-
-                        // get events by selected orgunit
-                        else if ( !keys[4].equals( "0" ) )
-                        {
-                            patientWhere += " and psi.organisationunitid=" + getOrgUnitId( keys );
-                        }
-
-                        patientWhere += ")";
-                        operatorStatus = " OR ";
-                        condition = "";
-                        continue;
-                    case ProgramStageInstance.FUTURE_VISIT_STATUS:
-                        patientWhere += condition + operatorStatus + "( psi.executiondate is null and psi.duedate>='"
-                            + keys[2] + "' and psi.duedate<='" + keys[3]
-                            + "' and psi.status is not null and (DATE(now()) - DATE(psi.duedate) <= 0) ";
-
-                        // get events by orgunit children
-                        if ( keys[4].equals( "-1" ) )
-                        {
-                            patientWhere += " and p.organisationunitid in( "
-                                + TextUtils.getCommaDelimitedString( orgunitChilrenIds ) + " )";
-                        }
-
-                        // get events by selected orgunit
-                        else if ( !keys[4].equals( "0" ) )
-                        {
-                            patientWhere += " and p.organisationunitid=" + getOrgUnitId( keys );
-                        }
-
-                        patientWhere += ")";
-                        operatorStatus = " OR ";
-                        condition = "";
-                        continue;
-                    case ProgramStageInstance.LATE_VISIT_STATUS:
-                        patientWhere += condition + operatorStatus + "( psi.executiondate is null and  psi.duedate>='"
-                            + keys[2] + "' and psi.duedate<='" + keys[3]
-                            + "' and psi.status is not null and (DATE(now()) - DATE(psi.duedate) > 0) ";
-
-                        // get events by orgunit children
-                        if ( keys[4].equals( "-1" ) )
-                        {
-                            patientWhere += " and p.organisationunitid in( "
-                                + TextUtils.getCommaDelimitedString( orgunitChilrenIds ) + " )";
-                        }
-
-                        // get events by selected orgunit
-                        else if ( !keys[4].equals( "0" ) )
-                        {
-                            patientWhere += " and p.organisationunitid=" + getOrgUnitId( keys );
-                        }
-
-                        patientWhere += ")";
-                        operatorStatus = " OR ";
-                        condition = "";
-                        continue;
-                    case ProgramStageInstance.SKIPPED_STATUS:
-                        patientWhere += condition + operatorStatus + "( psi.status=5 and  psi.duedate>='" + keys[2]
-                            + "' and psi.duedate<='" + keys[3] + "' ";
-
-                        // get events by orgunit children
-                        if ( keys[4].equals( "-1" ) )
-                        {
-                            patientWhere += " and psi.organisationunitid in( "
-                                + TextUtils.getCommaDelimitedString( orgunitChilrenIds ) + " )";
-                        }
-
-                        // get events by selected orgunit
-                        else if ( !keys[4].equals( "0" ) )
-                        {
-                            patientWhere += " and p.organisationunitid=" + getOrgUnitId( keys );
-                        }
-                        patientWhere += ")";
-                        operatorStatus = " OR ";
-                        condition = "";
-                        continue;
-                    default:
-                        continue;
-                    }
-                }
-                if ( condition.isEmpty() )
-                {
-                    patientWhere += ")";
-                }
-
-                patientWhere += " and pgi.status=" + ProgramInstance.STATUS_ACTIVE + " ";
-                patientOperator = " and ";
-            }
-            else if ( keys[0].equals( PREFIX_PROGRAM_STAGE ) )
-            {
-                isSearchEvent = true;
-                patientWhere += patientOperator + "pgi.patientid=p.patientid and psi.programstageid=" + id + " and ";
-                patientWhere += "psi.duedate>='" + keys[3] + "' and psi.duedate<='" + keys[4] + "' and ";
-                patientWhere += "psi.organisationunitid = " + keys[5] + " and ";
-
-                int statusEvent = Integer.parseInt( keys[2] );
-                switch ( statusEvent )
-                {
-                case ProgramStageInstance.COMPLETED_STATUS:
-                    patientWhere += "psi.completed=true";
-                    break;
-                case ProgramStageInstance.VISITED_STATUS:
-                    patientWhere += "psi.executiondate is not null and psi.completed=false";
-                    break;
-                case ProgramStageInstance.FUTURE_VISIT_STATUS:
-                    patientWhere += "psi.executiondate is null and psi.duedate >= now()";
-                    break;
-                case ProgramStageInstance.LATE_VISIT_STATUS:
-                    patientWhere += "psi.executiondate is null and psi.duedate < now()";
-                    break;
-                default:
-                    break;
-                }
-
-                patientWhere += " and pgi.status=" + ProgramInstance.STATUS_ACTIVE + " ";
-                patientOperator = " and ";
-            }
-        }
-
-        if ( orgunits != null && !isSearchEvent )
-        {
-            sql += "(select organisationunitid from patient where patientid=p.patientid and organisationunitid in ( "
-                + TextUtils.getCommaDelimitedString( getOrganisationUnitIds( orgunits ) ) + " ) ) as orgunitid,";
-            otherWhere += operator + "orgunitid in ( "
-                + TextUtils.getCommaDelimitedString( getOrganisationUnitIds( orgunits ) ) + " ) ";
-        }
-
-        sql = sql.substring( 0, sql.length() - 1 ) + " "; // Removing last comma
-
-        String from = " from patient p ";
-
-        if ( isSearchEvent )
-        {
-            String subSQL = " , psi.programstageinstanceid as programstageinstanceid, pgs.name as programstagename, psi.duedate as duedate ";
-
-            if ( isPriorityEvent )
-            {
-                subSQL += ",pgi.followup ";
-                orderBy = " ORDER BY pgi.followup desc, p.patientid, duedate asc ";
-                patientGroupBy += ",pgi.followup ";
-            }
-            else
-            {
-                orderBy = " ORDER BY p.patientid, duedate asc ";
-            }
-
-            sql = sql + subSQL + from + " inner join programinstance pgi on " + " (pgi.patientid=p.patientid) "
-                + " inner join programstageinstance psi on (psi.programinstanceid=pgi.programinstanceid) "
-                + " inner join programstage pgs on (pgs.programstageid=psi.programstageid) ";
-
-            patientGroupBy += ",psi.programstageinstanceid, pgs.name, psi.duedate ";
-
-            from = " ";
-        }
-
-        if ( hasIdentifier )
-        {
-            sql += from + " left join patientidentifier pi on p.patientid=pi.patientid ";
-            from = " ";
-        }
-
-        sql += from + patientWhere;
-        if ( followup != null )
-        {
-            sql += " AND pgi.followup=" + followup;
-        }
-        if ( isSearchEvent )
-        {
-            sql += patientGroupBy;
-        }
-        sql += orderBy;
-        sql += " ) as searchresult";
-        sql += otherWhere;
-
-        if ( min != null && max != null )
-        {
-            sql += " limit " + max + " offset " + min;
-        }
-
-        log.info( "Search patient SQL: " + sql );
-
-        return sql;
-    }
-
-    private Integer getOrgUnitId( String[] keys )
-    {
-        Integer orgUnitId;
-        try
-        {
-            orgUnitId = Integer.parseInt( keys[4] );
-        }
-        catch ( NumberFormatException e )
-        {
-            // handle as uid
-            OrganisationUnit ou = organisationUnitService.getOrganisationUnit( keys[4] );
-            orgUnitId = ou.getId();
-        }
-        return orgUnitId;
-    }
-
-    private Collection<Integer> getOrgunitChildren( Collection<OrganisationUnit> orgunits )
-    {
-        Collection<Integer> orgUnitIds = new HashSet<Integer>();
-
-        if ( orgunits != null )
-        {
-            for ( OrganisationUnit orgunit : orgunits )
-            {
-                orgUnitIds
-                    .addAll( organisationUnitService.getOrganisationUnitHierarchy().getChildren( orgunit.getId() ) );
-                orgUnitIds.remove( orgunit.getId() );
-            }
-        }
-
-        if ( orgUnitIds.size() == 0 )
-        {
-            orgUnitIds.add( 0 );
-        }
-
-        return orgUnitIds;
-    }
-
-    private Collection<Integer> getOrganisationUnitIds( Collection<OrganisationUnit> orgunits )
-    {
-        Collection<Integer> orgUnitIds = new HashSet<Integer>();
-
-        for ( OrganisationUnit orgUnit : orgunits )
-        {
-            orgUnitIds.add( orgUnit.getId() );
-        }
-
-        if ( orgUnitIds.size() == 0 )
-        {
-            orgUnitIds.add( 0 );
-        }
-
-        return orgUnitIds;
-    }
+public class HibernatePatientStore extends
+		HibernateIdentifiableObjectStore<Patient> implements PatientStore {
+	private static final Log log = LogFactory
+			.getLog(HibernatePatientStore.class);
+
+	// -------------------------------------------------------------------------
+	// Dependencies
+	// -------------------------------------------------------------------------
+
+	private OrganisationUnitService organisationUnitService;
+
+	public void setOrganisationUnitService(
+			OrganisationUnitService organisationUnitService) {
+		this.organisationUnitService = organisationUnitService;
+	}
+
+	// -------------------------------------------------------------------------
+	// Implementation methods
+	// -------------------------------------------------------------------------
+
+	@Override
+	@SuppressWarnings("unchecked")
+	public Collection<Patient> getByOrgUnit(OrganisationUnit organisationUnit,
+			Integer min, Integer max) {
+		String hql = "select p from Patient p where p.organisationUnit = :organisationUnit order by p.id DESC";
+
+		Query query = getQuery(hql);
+		query.setEntity("organisationUnit", organisationUnit);
+
+		if (min != null && max != null) {
+			query.setFirstResult(min).setMaxResults(max);
+		}
+
+		return query.list();
+	}
+
+	@Override
+	@SuppressWarnings("unchecked")
+	public Collection<Patient> getByOrgUnitProgram(
+			OrganisationUnit organisationUnit, Program program, Integer min,
+			Integer max) {
+		String hql = "select pt from Patient pt inner join pt.programInstances pi "
+				+ "where pt.organisationUnit = :organisationUnit "
+				+ "and pi.program = :program " + "and pi.status = :status";
+
+		Query query = getQuery(hql);
+		query.setEntity("organisationUnit", organisationUnit);
+		query.setEntity("program", program);
+		query.setInteger("status", ProgramInstance.STATUS_ACTIVE);
+
+		return query.list();
+	}
+
+	@SuppressWarnings("unchecked")
+	public List<Patient> query(TrackedEntityQueryParams params) {
+		SqlHelper hlp = new SqlHelper();
+
+		String hql = "select pt from Patient pt left join pt.attributeValues av";
+
+		for (QueryItem at : params.getAttributes()) {
+			hql += " " + hlp.whereAnd();
+			hql += " (av.patientAttribute = :attr" + at.getItemId()
+					+ " and av.value = :filt" + at.getItemId() + ")";
+		}
+
+		Query query = getQuery(hql);
+
+		for (QueryItem at : params.getAttributes()) {
+			query.setEntity("attr" + at.getItemId(), at.getItem());
+			query.setString("filt" + at.getItemId(), at.getFilter());
+		}
+
+		return query.list();
+	}
+
+	@Override
+	@SuppressWarnings("unchecked")
+	public Collection<Patient> getByProgram(Program program, Integer min,
+			Integer max) {
+		String hql = "select pt from Patient pt inner join pt.programInstances pi "
+				+ "where pi.program = :program and pi.status = :status";
+
+		Query query = getQuery(hql);
+		query.setEntity("program", program);
+		query.setInteger("status", ProgramInstance.STATUS_ACTIVE);
+
+		return query.list();
+	}
+
+	@Override
+	public int countGetPatientsByName(String fullName) {
+		fullName = fullName.toLowerCase();
+		String sql = "SELECT count(*) FROM patient where lower( name ) "
+				+ "like '%" + fullName + "%' ";
+
+		return jdbcTemplate.queryForObject(sql, Integer.class);
+	}
+
+	@Override
+	public int countListPatientByOrgunit(OrganisationUnit organisationUnit) {
+		Query query = getQuery("select count(p.id) from Patient p where p.organisationUnit.id=:orgUnitId ");
+
+		query.setParameter("orgUnitId", organisationUnit.getId());
+
+		Number rs = (Number) query.uniqueResult();
+
+		return rs != null ? rs.intValue() : 0;
+	}
+
+	@Override
+	public int countGetPatientsByOrgUnitProgram(
+			OrganisationUnit organisationUnit, Program program) {
+		String sql = "select count(p.patientid) from patient p join programinstance pi on p.patientid=pi.patientid "
+				+ "where p.organisationunitid="
+				+ organisationUnit.getId()
+				+ " and pi.programid="
+				+ program.getId()
+				+ " and pi.status="
+				+ ProgramInstance.STATUS_ACTIVE;
+
+		return jdbcTemplate.queryForObject(sql, Integer.class);
+	}
+
+	@Override
+	@SuppressWarnings("unchecked")
+	public Collection<Patient> getRepresentatives(Patient patient) {
+		String hql = "select distinct p from Patient p where p.representative = :representative order by p.id DESC";
+
+		return getQuery(hql).setEntity("representative", patient).list();
+	}
+
+	@Override
+	// TODO this method must be changed - cannot retrieve one by one
+	public Collection<Patient> search(List<String> searchKeys,
+			Collection<OrganisationUnit> orgunits, Boolean followup,
+			Collection<PatientAttribute> patientAttributes,
+			Collection<PatientIdentifierType> identifierTypes,
+			Integer statusEnrollment, Integer min, Integer max) {
+		String sql = searchPatientSql(false, searchKeys, orgunits, followup,
+				patientAttributes, identifierTypes, statusEnrollment, min, max);
+		Collection<Patient> patients = new HashSet<Patient>();
+		try {
+			patients = jdbcTemplate.query(sql, new RowMapper<Patient>() {
+				public Patient mapRow(ResultSet rs, int rowNum)
+						throws SQLException {
+					return get(rs.getInt(1));
+				}
+			});
+		} catch (Exception ex) {
+			ex.printStackTrace();
+		}
+		return patients;
+	}
+
+	@Override
+	public List<Integer> getProgramStageInstances(List<String> searchKeys,
+			Collection<OrganisationUnit> orgunits, Boolean followup,
+			Collection<PatientAttribute> patientAttributes,
+			Collection<PatientIdentifierType> identifierTypes,
+			Integer statusEnrollment, Integer min, Integer max) {
+		String sql = searchPatientSql(false, searchKeys, orgunits, followup,
+				patientAttributes, identifierTypes, statusEnrollment, min, max);
+
+		List<Integer> programStageInstanceIds = new ArrayList<Integer>();
+		try {
+			programStageInstanceIds = jdbcTemplate.query(sql,
+					new RowMapper<Integer>() {
+						public Integer mapRow(ResultSet rs, int rowNum)
+								throws SQLException {
+							return rs.getInt("programstageinstanceid");
+						}
+					});
+		} catch (Exception ex) {
+			ex.printStackTrace();
+		}
+
+		return programStageInstanceIds;
+	}
+
+	public int countSearch(List<String> searchKeys,
+			Collection<OrganisationUnit> orgunits, Boolean followup,
+			Integer statusEnrollment) {
+		String sql = searchPatientSql(true, searchKeys, orgunits, followup,
+				null, null, statusEnrollment, null, null);
+		return jdbcTemplate.queryForObject(sql, Integer.class);
+	}
+
+	@Override
+	public Grid getPatientEventReport(Grid grid, List<String> searchKeys,
+			Collection<OrganisationUnit> orgunits, Boolean followup,
+			Collection<PatientAttribute> patientAttributes,
+			Collection<PatientIdentifierType> identifierTypes,
+			Integer statusEnrollment, Integer min, Integer max) {
+		String sql = searchPatientSql(false, searchKeys, orgunits, followup,
+				patientAttributes, identifierTypes, statusEnrollment, min, max);
+
+		SqlRowSet rowSet = jdbcTemplate.queryForRowSet(sql);
+
+		GridUtils.addRows(grid, rowSet);
+
+		return grid;
+	}
+
+	@Override
+	@SuppressWarnings("unchecked")
+	public Collection<Patient> getByPhoneNumber(String phoneNumber,
+			Integer min, Integer max) {
+		Criteria criteria = getCriteria();
+		criteria.createAlias("attributeValues", "attributeValue");
+		criteria.createAlias("attributeValue.patientAttribute",
+				"patientAttribute");
+		criteria.add(Restrictions.eq("patientAttribute.valueType",
+				PatientAttribute.TYPE_PHONE_NUMBER));
+		criteria.add(Restrictions.like("attributeValue.value", phoneNumber));
+
+		if (min != null && max != null) {
+			criteria.setFirstResult(min);
+			criteria.setMaxResults(max);
+		}
+
+		return criteria.list();
+	}
+
+	@SuppressWarnings("unchecked")
+	public Collection<Integer> getRegistrationOrgunitIds(Date startDate,
+			Date endDate) {
+		Criteria criteria = getCriteria();
+		criteria.add(Restrictions.between("registrationDate", startDate,
+				endDate));
+		criteria.createAlias("organisationUnit", "orgunit");
+		criteria.setProjection(Projections.distinct(Projections
+				.projectionList().add(Projections.property("orgunit.id"),
+						"orgunitid")));
+
+		return criteria.list();
+	}
+
+	public int validate(Patient patient, Program program) {
+		if (patient.getIdentifiers() != null
+				&& patient.getIdentifiers().size() > 0) {
+			Criteria criteria = getCriteria();
+			criteria.createAlias("identifiers", "patientIdentifier");
+			criteria.createAlias("organisationUnit", "orgunit");
+			criteria.createAlias("programInstances", "programInstance");
+			criteria.createAlias("programInstance.program", "program");
+
+			Disjunction disjunction = Restrictions.disjunction();
+
+			for (PatientIdentifier identifier : patient.getIdentifiers()) {
+				PatientIdentifierType patientIdentifierType = identifier
+						.getIdentifierType();
+
+				Conjunction conjunction = Restrictions.conjunction();
+				conjunction.add(Restrictions.eq("patientIdentifier.identifier",
+						identifier.getIdentifier()));
+				conjunction.add(Restrictions.eq(
+						"patientIdentifier.identifierType",
+						patientIdentifierType));
+
+				if (patient.getId() != 0) {
+					conjunction.add(Restrictions.ne("id", patient.getId()));
+				}
+
+				if (patientIdentifierType.getType().equals(
+						PatientIdentifierType.VALUE_TYPE_LOCAL_ID)
+						&& patientIdentifierType.getOrgunitScope()) {
+					conjunction.add(Restrictions.eq("orgunit.id", patient
+							.getOrganisationUnit().getId()));
+				}
+
+				if (program != null
+						&& patientIdentifierType.getType().equals(
+								PatientIdentifierType.VALUE_TYPE_LOCAL_ID)
+						&& patientIdentifierType.getProgramScope()) {
+					conjunction.add(Restrictions.eq("program", program));
+				}
+
+				if (patientIdentifierType.getType().equals(
+						PatientIdentifierType.VALUE_TYPE_LOCAL_ID)
+						&& patientIdentifierType.getPeriodType() != null) {
+					Date currentDate = new Date();
+					Period period = patientIdentifierType.getPeriodType()
+							.createPeriod(currentDate);
+					conjunction.add(Restrictions.between("enrollmentdate",
+							period.getStartDate(), period.getEndDate()));
+				}
+
+				disjunction.add(conjunction);
+			}
+
+			criteria.add(disjunction);
+
+			Number rs = (Number) criteria.setProjection(Projections.rowCount())
+					.uniqueResult();
+
+			if (rs != null && rs.intValue() > 0) {
+				return PatientService.ERROR_DUPLICATE_IDENTIFIER;
+			}
+		}
+
+		if (program != null) {
+			ValidationCriteria validationCriteria = program.isValid(patient);
+
+			if (validationCriteria != null) {
+				return PatientService.ERROR_ENROLLMENT;
+			}
+		}
+
+		return PatientService.ERROR_NONE;
+	}
+
+	// -------------------------------------------------------------------------
+	// Supportive methods TODO Remplement all this!
+	// -------------------------------------------------------------------------
+
+	private String searchPatientSql(boolean count, List<String> searchKeys,
+			Collection<OrganisationUnit> orgunits, Boolean followup,
+			Collection<PatientAttribute> patientAttributes,
+			Collection<PatientIdentifierType> identifierTypes,
+			Integer statusEnrollment, Integer min, Integer max) {
+		String selector = count ? "count(*) " : "* ";
+		String sql = "select " + selector
+				+ " from ( select distinct p.patientid,";
+
+		if (identifierTypes != null) {
+			for (PatientIdentifierType identifierType : identifierTypes) {
+				sql += "(select identifier from patientidentifier where patientid=p.patientid and patientidentifiertypeid="
+						+ identifierType.getId()
+						+ " ) as "
+						+ PREFIX_IDENTIFIER_TYPE
+						+ "_"
+						+ identifierType.getId()
+						+ " ,";
+			}
+		}
+
+		if (patientAttributes != null) {
+			for (PatientAttribute patientAttribute : patientAttributes) {
+				sql += "(select value from patientattributevalue where patientid=p.patientid and patientattributeid="
+						+ patientAttribute.getId()
+						+ " ) as "
+						+ PREFIX_PATIENT_ATTRIBUTE
+						+ "_"
+						+ patientAttribute.getId() + " ,";
+			}
+		}
+
+		String patientWhere = "";
+		String patientOperator = " where ";
+		String patientGroupBy = " GROUP BY  p.patientid ";
+		String otherWhere = "";
+		String operator = " where ";
+		String orderBy = "";
+		boolean hasIdentifier = false;
+		boolean isSearchEvent = false;
+		boolean isPriorityEvent = false;
+		Collection<Integer> orgunitChilrenIds = null;
+
+		if (orgunits != null) {
+			orgunitChilrenIds = getOrgunitChildren(orgunits);
+		}
+
+		for (String searchKey : searchKeys) {
+			String[] keys = searchKey.split("_");
+
+			if (keys.length <= 1 || keys[1] == null || keys[1].trim().isEmpty()
+					|| keys[1].equals("null")) {
+				continue;
+			}
+
+			String id = keys[1];
+			String value = "";
+
+			if (keys.length >= 3) {
+				value = keys[2];
+			}
+
+			if (keys[0].equals(PREFIX_IDENTIFIER_TYPE)) {
+
+				String[] keyValues = id.split(" ");
+				patientWhere += patientOperator + " (";
+				String opt = "";
+				for (String v : keyValues) {
+					patientWhere += opt
+							+ " ( lower(pi.identifier) like '%"
+							+ v
+							+ "%' and pi.patientidentifiertypeid is not null ) ";
+					opt = "or";
+				}
+
+				patientWhere += ")";
+				patientOperator = " and ";
+				hasIdentifier = true;
+			} else if (keys[0].equals(PREFIX_PATIENT_ATTRIBUTE)) {
+				sql += "(select value from patientattributevalue where patientid=p.patientid and patientattributeid="
+						+ id
+						+ " ) as "
+						+ PREFIX_PATIENT_ATTRIBUTE
+						+ "_"
+						+ id
+						+ ",";
+
+				String[] keyValues = value.split(" ");
+				otherWhere += operator + "(";
+				String opt = "";
+
+				for (String v : keyValues) {
+					otherWhere += opt + " lower(" + PREFIX_PATIENT_ATTRIBUTE
+							+ "_" + id + ") like '%" + v + "%'";
+					opt = "or";
+				}
+
+				otherWhere += ")";
+				operator = " and ";
+			} else if (keys[0].equals(PREFIX_PROGRAM)) {
+				sql += "(select programid from programinstance pgi where patientid=p.patientid and programid="
+						+ id;
+
+				if (statusEnrollment != null) {
+					sql += " and pgi.status=" + statusEnrollment;
+				}
+
+				sql += " limit 1 ) as " + PREFIX_PROGRAM + "_" + id + ",";
+				otherWhere += operator + PREFIX_PROGRAM + "_" + id + "=" + id;
+				operator = " and ";
+			} else if (keys[0].equals(PREFIX_PROGRAM_INSTANCE)) {
+				sql += "(select pi."
+						+ id
+						+ " from programinstance pi where patientid=p.patientid and pi.status=0 ";
+
+				if (keys.length == 5) {
+					sql += " and pi.programid=" + keys[4];
+				} else {
+					sql += " limit 1 ";
+				}
+
+				sql += ") as " + PREFIX_PROGRAM_INSTANCE + "_" + id + ",";
+				otherWhere += operator + PREFIX_PROGRAM_INSTANCE + "_" + id
+						+ keys[2];
+				operator = " and ";
+			} else if (keys[0].equals(PREFIX_PROGRAM_EVENT_BY_STATUS)) {
+				isSearchEvent = true;
+				isPriorityEvent = Boolean.parseBoolean(keys[5]);
+				patientWhere += patientOperator
+						+ "pgi.patientid=p.patientid and ";
+				patientWhere += "pgi.programid=" + id + " and ";
+				patientWhere += "pgi.status=" + ProgramInstance.STATUS_ACTIVE;
+
+				String operatorStatus = "";
+				String condition = " and ( ";
+
+				for (int index = 6; index < keys.length; index++) {
+					int statusEvent = Integer.parseInt(keys[index]);
+					switch (statusEvent) {
+					case ProgramStageInstance.COMPLETED_STATUS:
+						patientWhere += condition
+								+ operatorStatus
+								+ "( psi.executiondate is not null and  psi.executiondate>='"
+								+ keys[2] + "' and psi.executiondate<='"
+								+ keys[3] + "' and psi.completed=true ";
+
+						// get events by orgunit children
+						if (keys[4].equals("-1")) {
+							patientWhere += " and psi.organisationunitid in( "
+									+ TextUtils
+											.getCommaDelimitedString(orgunitChilrenIds)
+									+ " )";
+						}
+
+						// get events by selected orgunit
+						else if (!keys[4].equals("0")) {
+							patientWhere += " and psi.organisationunitid="
+									+ getOrgUnitId(keys);
+						}
+
+						patientWhere += ")";
+						operatorStatus = " OR ";
+						condition = "";
+						continue;
+					case ProgramStageInstance.VISITED_STATUS:
+						patientWhere += condition
+								+ operatorStatus
+								+ "( psi.executiondate is not null and psi.executiondate>='"
+								+ keys[2] + "' and psi.executiondate<='"
+								+ keys[3] + "' and psi.completed=false ";
+
+						// get events by orgunit children
+						if (keys[4].equals("-1")) {
+							patientWhere += " and psi.organisationunitid in( "
+									+ TextUtils
+											.getCommaDelimitedString(orgunitChilrenIds)
+									+ " )";
+						}
+
+						// get events by selected orgunit
+						else if (!keys[4].equals("0")) {
+							patientWhere += " and psi.organisationunitid="
+									+ getOrgUnitId(keys);
+						}
+
+						patientWhere += ")";
+						operatorStatus = " OR ";
+						condition = "";
+						continue;
+					case ProgramStageInstance.FUTURE_VISIT_STATUS:
+						patientWhere += condition
+								+ operatorStatus
+								+ "( psi.executiondate is null and psi.duedate>='"
+								+ keys[2]
+								+ "' and psi.duedate<='"
+								+ keys[3]
+								+ "' and psi.status is not null and (DATE(now()) - DATE(psi.duedate) <= 0) ";
+
+						// get events by orgunit children
+						if (keys[4].equals("-1")) {
+							patientWhere += " and p.organisationunitid in( "
+									+ TextUtils
+											.getCommaDelimitedString(orgunitChilrenIds)
+									+ " )";
+						}
+
+						// get events by selected orgunit
+						else if (!keys[4].equals("0")) {
+							patientWhere += " and p.organisationunitid="
+									+ getOrgUnitId(keys);
+						}
+
+						patientWhere += ")";
+						operatorStatus = " OR ";
+						condition = "";
+						continue;
+					case ProgramStageInstance.LATE_VISIT_STATUS:
+						patientWhere += condition
+								+ operatorStatus
+								+ "( psi.executiondate is null and  psi.duedate>='"
+								+ keys[2]
+								+ "' and psi.duedate<='"
+								+ keys[3]
+								+ "' and psi.status is not null and (DATE(now()) - DATE(psi.duedate) > 0) ";
+
+						// get events by orgunit children
+						if (keys[4].equals("-1")) {
+							patientWhere += " and p.organisationunitid in( "
+									+ TextUtils
+											.getCommaDelimitedString(orgunitChilrenIds)
+									+ " )";
+						}
+
+						// get events by selected orgunit
+						else if (!keys[4].equals("0")) {
+							patientWhere += " and p.organisationunitid="
+									+ getOrgUnitId(keys);
+						}
+
+						patientWhere += ")";
+						operatorStatus = " OR ";
+						condition = "";
+						continue;
+					case ProgramStageInstance.SKIPPED_STATUS:
+						patientWhere += condition + operatorStatus
+								+ "( psi.status=5 and  psi.duedate>='"
+								+ keys[2] + "' and psi.duedate<='" + keys[3]
+								+ "' ";
+
+						// get events by orgunit children
+						if (keys[4].equals("-1")) {
+							patientWhere += " and psi.organisationunitid in( "
+									+ TextUtils
+											.getCommaDelimitedString(orgunitChilrenIds)
+									+ " )";
+						}
+
+						// get events by selected orgunit
+						else if (!keys[4].equals("0")) {
+							patientWhere += " and p.organisationunitid="
+									+ getOrgUnitId(keys);
+						}
+						patientWhere += ")";
+						operatorStatus = " OR ";
+						condition = "";
+						continue;
+					default:
+						continue;
+					}
+				}
+				if (condition.isEmpty()) {
+					patientWhere += ")";
+				}
+
+				patientWhere += " and pgi.status="
+						+ ProgramInstance.STATUS_ACTIVE + " ";
+				patientOperator = " and ";
+			} else if (keys[0].equals(PREFIX_PROGRAM_STAGE)) {
+				isSearchEvent = true;
+				patientWhere += patientOperator
+						+ "pgi.patientid=p.patientid and psi.programstageid="
+						+ id + " and ";
+				patientWhere += "psi.duedate>='" + keys[3]
+						+ "' and psi.duedate<='" + keys[4] + "' and ";
+				patientWhere += "psi.organisationunitid = " + keys[5] + " and ";
+
+				int statusEvent = Integer.parseInt(keys[2]);
+				switch (statusEvent) {
+				case ProgramStageInstance.COMPLETED_STATUS:
+					patientWhere += "psi.completed=true";
+					break;
+				case ProgramStageInstance.VISITED_STATUS:
+					patientWhere += "psi.executiondate is not null and psi.completed=false";
+					break;
+				case ProgramStageInstance.FUTURE_VISIT_STATUS:
+					patientWhere += "psi.executiondate is null and psi.duedate >= now()";
+					break;
+				case ProgramStageInstance.LATE_VISIT_STATUS:
+					patientWhere += "psi.executiondate is null and psi.duedate < now()";
+					break;
+				default:
+					break;
+				}
+
+				patientWhere += " and pgi.status="
+						+ ProgramInstance.STATUS_ACTIVE + " ";
+				patientOperator = " and ";
+			}
+		}
+
+		if (orgunits != null && !isSearchEvent) {
+			sql += "(select organisationunitid from patient where patientid=p.patientid and organisationunitid in ( "
+					+ TextUtils
+							.getCommaDelimitedString(getOrganisationUnitIds(orgunits))
+					+ " ) ) as orgunitid,";
+			otherWhere += operator
+					+ "orgunitid in ( "
+					+ TextUtils
+							.getCommaDelimitedString(getOrganisationUnitIds(orgunits))
+					+ " ) ";
+		}
+
+		sql = sql.substring(0, sql.length() - 1) + " "; // Removing last comma
+
+		String from = " from patient p ";
+
+		if (isSearchEvent) {
+			String subSQL = " , psi.programstageinstanceid as programstageinstanceid, pgs.name as programstagename, psi.duedate as duedate ";
+
+			if (isPriorityEvent) {
+				subSQL += ",pgi.followup ";
+				orderBy = " ORDER BY pgi.followup desc, p.patientid, duedate asc ";
+				patientGroupBy += ",pgi.followup ";
+			} else {
+				orderBy = " ORDER BY p.patientid, duedate asc ";
+			}
+
+			sql = sql
+					+ subSQL
+					+ from
+					+ " inner join programinstance pgi on "
+					+ " (pgi.patientid=p.patientid) "
+					+ " inner join programstageinstance psi on (psi.programinstanceid=pgi.programinstanceid) "
+					+ " inner join programstage pgs on (pgs.programstageid=psi.programstageid) ";
+
+			patientGroupBy += ",psi.programstageinstanceid, pgs.name, psi.duedate ";
+
+			from = " ";
+		}
+
+		if (hasIdentifier) {
+			sql += from
+					+ " left join patientidentifier pi on p.patientid=pi.patientid ";
+			from = " ";
+		}
+
+		sql += from + patientWhere;
+		if (followup != null) {
+			sql += " AND pgi.followup=" + followup;
+		}
+		if (isSearchEvent) {
+			sql += patientGroupBy;
+		}
+		sql += orderBy;
+		sql += " ) as searchresult";
+		sql += otherWhere;
+
+		if (min != null && max != null) {
+			sql += " limit " + max + " offset " + min;
+		}
+
+		log.info("Search patient SQL: " + sql);
+
+		return sql;
+	}
+
+	private Integer getOrgUnitId(String[] keys) {
+		Integer orgUnitId;
+		try {
+			orgUnitId = Integer.parseInt(keys[4]);
+		} catch (NumberFormatException e) {
+			// handle as uid
+			OrganisationUnit ou = organisationUnitService
+					.getOrganisationUnit(keys[4]);
+			orgUnitId = ou.getId();
+		}
+		return orgUnitId;
+	}
+
+	private Collection<Integer> getOrgunitChildren(
+			Collection<OrganisationUnit> orgunits) {
+		Collection<Integer> orgUnitIds = new HashSet<Integer>();
+
+		if (orgunits != null) {
+			for (OrganisationUnit orgunit : orgunits) {
+				orgUnitIds.addAll(organisationUnitService
+						.getOrganisationUnitHierarchy().getChildren(
+								orgunit.getId()));
+				orgUnitIds.remove(orgunit.getId());
+			}
+		}
+
+		if (orgUnitIds.size() == 0) {
+			orgUnitIds.add(0);
+		}
+
+		return orgUnitIds;
+	}
+
+	private Collection<Integer> getOrganisationUnitIds(
+			Collection<OrganisationUnit> orgunits) {
+		Collection<Integer> orgUnitIds = new HashSet<Integer>();
+
+		for (OrganisationUnit orgUnit : orgunits) {
+			orgUnitIds.add(orgUnit.getId());
+		}
+
+		if (orgUnitIds.size() == 0) {
+			orgUnitIds.add(0);
+		}
+
+		return orgUnitIds;
+	}
+
+	@SuppressWarnings({ "unchecked" })
+	@Override
+	public Collection<Patient> getByPatientAttributeValue(String searchText,
+			int patientAttributeId, Integer min, Integer max) {
+
+		String hql = "FROM PatientAttributeValue pav WHERE lower (pav.value) LIKE lower ('%"
+				+ searchText
+				+ "%') AND pav.patientAttribute.id =:patientAttributeId";
+
+		Query query = getQuery(hql);
+
+		query.setInteger("patientAttributeId", patientAttributeId);
+
+		if (min != null && max != null) {
+			query.setFirstResult(min).setMaxResults(max);
+		}
+
+		List<Patient> patients = new ArrayList<Patient>();
+		Collection<PatientAttributeValue> patientAttributeValue = query.list();
+		for (PatientAttributeValue pv : patientAttributeValue) {
+			patients.add(pv.getPatient());
+		}
+
+		return patients;
+
+	}
+
 }
\ No newline at end of file

=== modified file 'dhis-2/dhis-web/dhis-web-light/src/main/java/org/hisp/dhis/light/namebaseddataentry/action/FindBeneficiarytAction.java'
--- dhis-2/dhis-web/dhis-web-light/src/main/java/org/hisp/dhis/light/namebaseddataentry/action/FindBeneficiarytAction.java	2013-12-16 15:45:17 +0000
+++ dhis-2/dhis-web/dhis-web-light/src/main/java/org/hisp/dhis/light/namebaseddataentry/action/FindBeneficiarytAction.java	2014-01-22 04:25:46 +0000
@@ -28,119 +28,144 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import com.opensymphony.xwork2.Action;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
 import org.hisp.dhis.patient.Patient;
 import org.hisp.dhis.patient.PatientService;
-
-import java.util.Collection;
-
-public class FindBeneficiarytAction
-    implements Action
-{
-    private static final String REDIRECT = "redirect";
-
-    // -------------------------------------------------------------------------
-    // Dependencies
-    // -------------------------------------------------------------------------
-
-    private PatientService patientService;
-
-    public void setPatientService( PatientService patientService )
-    {
-        this.patientService = patientService;
-    }
-
-    // -------------------------------------------------------------------------
-    // Input & Output
-    // -------------------------------------------------------------------------
-
-    private Collection<Patient> patients;
-
-    public Collection<Patient> getPatients()
-    {
-        return patients;
-    }
-
-    public void setPatients( Collection<Patient> patients )
-    {
-        this.patients = patients;
-    }
-
-    private String keyword;
-
-    public String getKeyword()
-    {
-        return keyword;
-    }
-
-    public void setKeyword( String keyword )
-    {
-        this.keyword = keyword;
-    }
-
-    private Integer organisationUnitId;
-
-    public Integer getOrganisationUnitId()
-    {
-        return organisationUnitId;
-    }
-
-    public void setOrganisationUnitId( Integer organisationUnitId )
-    {
-        this.organisationUnitId = organisationUnitId;
-    }
-
-    private Integer patientId;
-
-    public Integer getPatientId()
-    {
-        return patientId;
-    }
-
-    public void setPatientId( Integer patientId )
-    {
-        this.patientId = patientId;
-    }
-
-    // Use in search related patient
-
-    private Integer originalPatientId;
-
-    public void setOriginalPatientId( Integer originalPatientId )
-    {
-        this.originalPatientId = originalPatientId;
-    }
-
-    public Integer getOriginalPatientId()
-    {
-        return originalPatientId;
-    }
-
-    private Integer relationshipTypeId;
-
-    public Integer getRelationshipTypeId()
-    {
-        return relationshipTypeId;
-    }
-
-    public void setRelationshipTypeId( Integer relationshipTypeId )
-    {
-        this.relationshipTypeId = relationshipTypeId;
-    }
-
-    @Override
-    public String execute()
-        throws Exception
-    {   
-        patients = patientService.getPatientsForMobile( keyword, organisationUnitId );
-
-        if ( patients.size() == 1 )
-        {
-            Patient patient = patients.iterator().next();
-            patientId = patient.getId();
-            return REDIRECT;
-        }
-        return SUCCESS;
-    }
+import org.hisp.dhis.patientattributevalue.PatientAttributeValue;
+
+import com.opensymphony.xwork2.Action;
+
+public class FindBeneficiarytAction implements Action {
+	private static final String REDIRECT = "redirect";
+
+	// -------------------------------------------------------------------------
+	// Dependencies
+	// -------------------------------------------------------------------------
+
+	private PatientService patientService;
+
+	public void setPatientService(PatientService patientService) {
+		this.patientService = patientService;
+	}
+
+	// -------------------------------------------------------------------------
+	// Input & Output
+	// -------------------------------------------------------------------------
+
+	private Collection<Patient> patients;
+
+	public Collection<Patient> getPatients() {
+		return patients;
+	}
+
+	public void setPatients(Collection<Patient> patients) {
+		this.patients = patients;
+	}
+
+	private Set<PatientAttributeValue> pavSet;
+
+	public Set<PatientAttributeValue> getPavSet() {
+		return pavSet;
+	}
+
+	public void setPavSet(Set<PatientAttributeValue> pavSet) {
+		this.pavSet = pavSet;
+	}
+
+	private Set<PatientAttributeValue> patientAttributes;
+
+	public Set<PatientAttributeValue> getPatientAttributes() {
+		return patientAttributes;
+	}
+
+	public void setPatientAttributes(
+			Set<PatientAttributeValue> patientAttributes) {
+		this.patientAttributes = patientAttributes;
+	}
+
+	private String keyword;
+
+	public String getKeyword() {
+		return keyword;
+	}
+
+	public void setKeyword(String keyword) {
+		this.keyword = keyword;
+	}
+
+	private Integer organisationUnitId;
+
+	public Integer getOrganisationUnitId() {
+		return organisationUnitId;
+	}
+
+	public void setOrganisationUnitId(Integer organisationUnitId) {
+		this.organisationUnitId = organisationUnitId;
+	}
+
+	private Integer patientAttributeId;
+
+	public Integer getPatientAttributeId() {
+		return patientAttributeId;
+	}
+
+	public void setPatientAttributeId(Integer patientAttributeId) {
+		this.patientAttributeId = patientAttributeId;
+	}
+
+	private Integer patientId;
+
+	public Integer getPatientId() {
+		return patientId;
+	}
+
+	public void setPatientId(Integer patientId) {
+		this.patientId = patientId;
+	}
+
+	// Use in search related patient
+
+	private Integer originalPatientId;
+
+	public void setOriginalPatientId(Integer originalPatientId) {
+		this.originalPatientId = originalPatientId;
+	}
+
+	public Integer getOriginalPatientId() {
+		return originalPatientId;
+	}
+
+	private Integer relationshipTypeId;
+
+	public Integer getRelationshipTypeId() {
+		return relationshipTypeId;
+	}
+
+	public void setRelationshipTypeId(Integer relationshipTypeId) {
+		this.relationshipTypeId = relationshipTypeId;
+	}
+
+	@Override
+	public String execute() throws Exception {
+
+		patients = patientService.searchPatientsForMobile(keyword,
+				organisationUnitId, patientAttributeId);
+		pavSet = new HashSet<PatientAttributeValue>();
+
+		for (Patient p : patients) {
+			pavSet.addAll(p.getAttributeValues());
+		}
+
+		if (patients.size() == 1) {
+			Patient patient = patients.iterator().next();
+			patientId = patient.getId();
+
+			return REDIRECT;
+		}
+		return SUCCESS;
+	}
 
 }

=== modified file 'dhis-2/dhis-web/dhis-web-light/src/main/java/org/hisp/dhis/light/namebaseddataentry/action/GetFindBeneficiaryFormAction.java'
--- dhis-2/dhis-web/dhis-web-light/src/main/java/org/hisp/dhis/light/namebaseddataentry/action/GetFindBeneficiaryFormAction.java	2013-12-16 15:45:17 +0000
+++ dhis-2/dhis-web/dhis-web-light/src/main/java/org/hisp/dhis/light/namebaseddataentry/action/GetFindBeneficiaryFormAction.java	2014-01-22 04:25:46 +0000
@@ -34,119 +34,135 @@
 import java.util.List;
 import java.util.Set;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
+import org.hisp.dhis.patient.PatientAttribute;
+import org.hisp.dhis.patient.PatientAttributeService;
 import org.hisp.dhis.user.CurrentUserService;
 import org.hisp.dhis.user.User;
 
 import com.opensymphony.xwork2.Action;
 
-public class GetFindBeneficiaryFormAction
-    implements Action
-{
-    // -------------------------------------------------------------------------
-    // Dependencies
-    // -------------------------------------------------------------------------
-
-    private CurrentUserService currentUserService;
-
-    public void setCurrentUserService( CurrentUserService currentUserService )
-    {
-        this.currentUserService = currentUserService;
-    }
-
-    // -------------------------------------------------------------------------
-    // Input & Output
-    // -------------------------------------------------------------------------
-
-    private Integer orgUnitId;
-    
-    public Integer getOrgUnitId()
-    {
-        return orgUnitId;
-    }
-
-    public void setOrgUnitId( Integer orgUnitId )
-    {
-        this.orgUnitId = orgUnitId;
-    }
-
-    private Set<OrganisationUnit> organisationUnits;
-
-    public Set<OrganisationUnit> getOrganisationUnits()
-    {
-        return organisationUnits;
-    }
-
-    public void setOrganisationUnits( Set<OrganisationUnit> organisationUnits )
-    {
-        this.organisationUnits = organisationUnits;
-    }
-
-    private User user;
-
-    public User getUser()
-    {
-        return user;
-    }
-
-    public void setUser( User user )
-    {
-        this.user = user;
-    }
-
-    // use in find relation person
-
-    private Integer originalPatientId;
-
-    public Integer getOriginalPatientId()
-    {
-        return originalPatientId;
-    }
-
-    public void setOriginalPatientId( Integer originalPatientId )
-    {
-        this.originalPatientId = originalPatientId;
-    }
-
-    private Integer relationshipTypeId;
-
-    public Integer getRelationshipTypeId()
-    {
-        return relationshipTypeId;
-    }
-
-    public void setRelationshipTypeId( Integer relationshipTypeId )
-    {
-        this.relationshipTypeId = relationshipTypeId;
-    }
-
-    @Override
-    public String execute()
-        throws Exception
-    {
-        user = currentUserService.getCurrentUser();
-        Collection<OrganisationUnit> basicOrganisationUnits = currentUserService.getCurrentUser()
-            .getOrganisationUnits();
-        organisationUnits = new HashSet<OrganisationUnit>();
-
-        for ( OrganisationUnit organisationUnit : basicOrganisationUnits )
-        {
-            organisationUnits.addAll( this.getAllParentOrganisationUnits( organisationUnit ) );
-        }
-
-        return SUCCESS;
-    }
-
-    private Collection<? extends OrganisationUnit> getAllParentOrganisationUnits( OrganisationUnit organisationUnit )
-    {
-        List<OrganisationUnit> parents = new ArrayList<OrganisationUnit>();
-        parents.add( organisationUnit );
-
-        while ( organisationUnit.getParent() != null )
-        {
-            parents.add( organisationUnit.getParent() );
-            organisationUnit = organisationUnit.getParent();
-        }
-        return parents;
-    }
+public class GetFindBeneficiaryFormAction implements Action {
+	// -------------------------------------------------------------------------
+	// Dependencies
+	// -------------------------------------------------------------------------
+
+	private CurrentUserService currentUserService;
+
+	public void setCurrentUserService(CurrentUserService currentUserService) {
+		this.currentUserService = currentUserService;
+	}
+
+	private PatientAttributeService patientAttributeService;
+
+	public void setPatientAttributeService(
+			PatientAttributeService patientAttributeService) {
+		this.patientAttributeService = patientAttributeService;
+	}
+
+	// -------------------------------------------------------------------------
+	// Input & Output
+	// -------------------------------------------------------------------------
+
+	private Integer patientAttributeId;
+
+	public Integer getPatientAttributeId() {
+		return patientAttributeId;
+	}
+
+	public void setPatientAttributeId(Integer patientAttributeId) {
+		this.patientAttributeId = patientAttributeId;
+	}
+
+	private Integer orgUnitId;
+
+	public Integer getOrgUnitId() {
+		return orgUnitId;
+	}
+
+	public void setOrgUnitId(Integer orgUnitId) {
+		this.orgUnitId = orgUnitId;
+	}
+
+	private Collection<PatientAttribute> patientAttributes;
+
+	public Collection<PatientAttribute> getPatientAttributes() {
+		return patientAttributes;
+	}
+
+	public void setPatientAttributes(
+			Collection<PatientAttribute> patientAttributes) {
+		this.patientAttributes = patientAttributes;
+	}
+
+	private Set<OrganisationUnit> organisationUnits;
+
+	public Set<OrganisationUnit> getOrganisationUnits() {
+		return organisationUnits;
+	}
+
+	public void setOrganisationUnits(Set<OrganisationUnit> organisationUnits) {
+		this.organisationUnits = organisationUnits;
+	}
+
+	private User user;
+
+	public User getUser() {
+		return user;
+	}
+
+	public void setUser(User user) {
+		this.user = user;
+	}
+
+	// use in find relation person
+
+	private Integer originalPatientId;
+
+	public Integer getOriginalPatientId() {
+		return originalPatientId;
+	}
+
+	public void setOriginalPatientId(Integer originalPatientId) {
+		this.originalPatientId = originalPatientId;
+	}
+
+	private Integer relationshipTypeId;
+
+	public Integer getRelationshipTypeId() {
+		return relationshipTypeId;
+	}
+
+	public void setRelationshipTypeId(Integer relationshipTypeId) {
+		this.relationshipTypeId = relationshipTypeId;
+	}
+
+	@Override
+	public String execute() throws Exception {
+		user = currentUserService.getCurrentUser();
+		Collection<OrganisationUnit> basicOrganisationUnits = currentUserService
+				.getCurrentUser().getOrganisationUnits();
+		organisationUnits = new HashSet<OrganisationUnit>();
+
+		for (OrganisationUnit organisationUnit : basicOrganisationUnits) {
+			organisationUnits.addAll(this
+					.getAllParentOrganisationUnits(organisationUnit));
+		}
+
+		patientAttributes = patientAttributeService.getAllPatientAttributes();
+
+		return SUCCESS;
+	}
+
+	private Collection<? extends OrganisationUnit> getAllParentOrganisationUnits(
+			OrganisationUnit organisationUnit) {
+		List<OrganisationUnit> parents = new ArrayList<OrganisationUnit>();
+		parents.add(organisationUnit);
+
+		while (organisationUnit.getParent() != null) {
+			parents.add(organisationUnit.getParent());
+			organisationUnit = organisationUnit.getParent();
+		}
+		return parents;
+	}
 
 }

=== modified file 'dhis-2/dhis-web/dhis-web-light/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-web/dhis-web-light/src/main/resources/META-INF/dhis/beans.xml	2013-12-30 21:55:24 +0000
+++ dhis-2/dhis-web/dhis-web-light/src/main/resources/META-INF/dhis/beans.xml	2014-01-22 04:25:46 +0000
@@ -1,30 +1,35 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns="http://www.springframework.org/schema/beans"; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
-  xsi:schemaLocation="
+<beans xmlns="http://www.springframework.org/schema/beans";
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+	xsi:schemaLocation="
 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd";>
 
-    <!-- Utils / services -->
-
-    <bean id="org.hisp.dhis.light.utils.NamebasedUtils" class="org.hisp.dhis.light.utils.NamebasedUtilsImpl"
-        scope="prototype">
-        <property name="programService" ref="org.hisp.dhis.program.ProgramService" />
-        <property name="programStageService" ref="org.hisp.dhis.program.ProgramStageService" />
-    </bean>
-
-    <bean id="org.hisp.dhis.light.utils.FormUtils" class="org.hisp.dhis.light.utils.FormUtilsImpl"
-        scope="prototype">
-        <property name="organisationUnitService" ref="org.hisp.dhis.organisationunit.OrganisationUnitService" />
-        <property name="currentUserService" ref="org.hisp.dhis.user.CurrentUserService" />
-        <property name="dataValueService" ref="org.hisp.dhis.datavalue.DataValueService" />
-        <property name="dataSetService" ref="org.hisp.dhis.dataset.DataSetService" />
-        <property name="stdDevOutlierAnalysisService" ref="org.hisp.dhis.dataanalysis.StdDevOutlierAnalysisService" />
-        <property name="minMaxOutlierAnalysisService" ref="org.hisp.dhis.dataanalysis.MinMaxOutlierAnalysisService" />
-        <property name="systemSettingManager" ref="org.hisp.dhis.setting.SystemSettingManager" />
-        <property name="validationRuleService" ref="org.hisp.dhis.validation.ValidationRuleService" />
-        <property name="expressionService" ref="org.hisp.dhis.expression.ExpressionService" />
-    </bean>
-
-    <!-- Menu -->
+	<!-- Utils / services -->
+
+	<bean id="org.hisp.dhis.light.utils.NamebasedUtils" class="org.hisp.dhis.light.utils.NamebasedUtilsImpl"
+		scope="prototype">
+		<property name="programService" ref="org.hisp.dhis.program.ProgramService" />
+		<property name="programStageService" ref="org.hisp.dhis.program.ProgramStageService" />
+	</bean>
+
+	<bean id="org.hisp.dhis.light.utils.FormUtils" class="org.hisp.dhis.light.utils.FormUtilsImpl"
+		scope="prototype">
+		<property name="organisationUnitService"
+			ref="org.hisp.dhis.organisationunit.OrganisationUnitService" />
+		<property name="currentUserService" ref="org.hisp.dhis.user.CurrentUserService" />
+		<property name="dataValueService" ref="org.hisp.dhis.datavalue.DataValueService" />
+		<property name="dataSetService" ref="org.hisp.dhis.dataset.DataSetService" />
+		<property name="stdDevOutlierAnalysisService"
+			ref="org.hisp.dhis.dataanalysis.StdDevOutlierAnalysisService" />
+		<property name="minMaxOutlierAnalysisService"
+			ref="org.hisp.dhis.dataanalysis.MinMaxOutlierAnalysisService" />
+		<property name="systemSettingManager" ref="org.hisp.dhis.setting.SystemSettingManager" />
+		<property name="validationRuleService"
+			ref="org.hisp.dhis.validation.ValidationRuleService" />
+		<property name="expressionService" ref="org.hisp.dhis.expression.ExpressionService" />
+	</bean>
+
+	<!-- Menu -->
 
 	<bean id="org.hisp.dhis.light.action.NoAction" class="org.hisp.dhis.light.action.NoAction"
 		scope="prototype" />
@@ -38,30 +43,25 @@
 		<property name="periodService" ref="org.hisp.dhis.period.PeriodService" />
 		<property name="currentUserService" ref="org.hisp.dhis.user.CurrentUserService" />
 	</bean>
-	
+
 	<!-- Data entry -->
 
 	<bean id="org.hisp.dhis.light.dataentry.action.GetOrganisationUnitsAction"
 		class="org.hisp.dhis.light.dataentry.action.GetOrganisationUnitsAction"
 		scope="prototype">
-		<property name="formUtils"
-			ref="org.hisp.dhis.light.utils.FormUtils" />
+		<property name="formUtils" ref="org.hisp.dhis.light.utils.FormUtils" />
 	</bean>
 
 	<bean id="org.hisp.dhis.light.dataentry.action.GetDataSetsAction"
-		class="org.hisp.dhis.light.dataentry.action.GetDataSetsAction" 
-		scope="prototype">
-		<property name="formUtils"
-			ref="org.hisp.dhis.light.utils.FormUtils" />
+		class="org.hisp.dhis.light.dataentry.action.GetDataSetsAction" scope="prototype">
+		<property name="formUtils" ref="org.hisp.dhis.light.utils.FormUtils" />
 		<property name="organisationUnitService"
 			ref="org.hisp.dhis.organisationunit.OrganisationUnitService" />
 	</bean>
 
 	<bean id="org.hisp.dhis.light.dataentry.action.GetPeriodsAction"
-		class="org.hisp.dhis.light.dataentry.action.GetPeriodsAction" 
-		scope="prototype">
-		<property name="formUtils"
-			ref="org.hisp.dhis.light.utils.FormUtils" />
+		class="org.hisp.dhis.light.dataentry.action.GetPeriodsAction" scope="prototype">
+		<property name="formUtils" ref="org.hisp.dhis.light.utils.FormUtils" />
 		<property name="organisationUnitService"
 			ref="org.hisp.dhis.organisationunit.OrganisationUnitService" />
 		<property name="dataSetService" ref="org.hisp.dhis.dataset.DataSetService" />
@@ -76,15 +76,13 @@
 			ref="org.hisp.dhis.organisationunit.OrganisationUnitService" />
 		<property name="dataSetService" ref="org.hisp.dhis.dataset.DataSetService" />
 		<property name="periodService" ref="org.hisp.dhis.period.PeriodService" />
-		<property name="formUtils"
-			ref="org.hisp.dhis.light.utils.FormUtils" />
+		<property name="formUtils" ref="org.hisp.dhis.light.utils.FormUtils" />
 		<property name="registrationService"
 			ref="org.hisp.dhis.dataset.CompleteDataSetRegistrationService" />
 	</bean>
 
 	<bean id="org.hisp.dhis.light.dataentry.action.MarkComplete"
-		class="org.hisp.dhis.light.dataentry.action.MarkComplete" 
-		scope="prototype">
+		class="org.hisp.dhis.light.dataentry.action.MarkComplete" scope="prototype">
 		<property name="currentUserService" ref="org.hisp.dhis.user.CurrentUserService" />
 		<property name="organisationUnitService"
 			ref="org.hisp.dhis.organisationunit.OrganisationUnitService" />
@@ -93,10 +91,9 @@
 			ref="org.hisp.dhis.dataset.CompleteDataSetRegistrationService" />
 		<property name="periodService" ref="org.hisp.dhis.period.PeriodService" />
 	</bean>
-	
+
 	<bean id="org.hisp.dhis.light.dataentry.action.UndoCompleteAction"
-		class="org.hisp.dhis.light.dataentry.action.UndoCompleteAction" 
-		scope="prototype">
+		class="org.hisp.dhis.light.dataentry.action.UndoCompleteAction" scope="prototype">
 		<property name="organisationUnitService"
 			ref="org.hisp.dhis.organisationunit.OrganisationUnitService" />
 		<property name="dataSetService" ref="org.hisp.dhis.dataset.DataSetService" />
@@ -112,8 +109,7 @@
 			ref="org.hisp.dhis.organisationunit.OrganisationUnitService" />
 		<property name="dataSetService" ref="org.hisp.dhis.dataset.DataSetService" />
 		<property name="periodService" ref="org.hisp.dhis.period.PeriodService" />
-		<property name="formUtils"
-			ref="org.hisp.dhis.light.utils.FormUtils" />
+		<property name="formUtils" ref="org.hisp.dhis.light.utils.FormUtils" />
 	</bean>
 
 	<bean id="org.hisp.dhis.light.dataentry.action.SaveSectionFormAction"
@@ -130,8 +126,7 @@
 		<property name="registrationService"
 			ref="org.hisp.dhis.dataset.CompleteDataSetRegistrationService" />
 		<property name="periodService" ref="org.hisp.dhis.period.PeriodService" />
-		<property name="formUtils"
-			ref="org.hisp.dhis.light.utils.FormUtils" />
+		<property name="formUtils" ref="org.hisp.dhis.light.utils.FormUtils" />
 	</bean>
 
 	<!-- Namebased Data entry -->
@@ -146,7 +141,7 @@
 	<bean
 		id="org.hisp.dhis.light.namebaseddataentry.action.GetBeneficiaryListAction"
 		class="org.hisp.dhis.light.namebaseddataentry.action.GetBeneficiaryListAction"
-        scope="prototype">
+		scope="prototype">
 		<property name="organisationUnitService"
 			ref="org.hisp.dhis.organisationunit.OrganisationUnitService" />
 		<property name="activityReportingService"
@@ -161,7 +156,7 @@
 	<bean
 		id="org.hisp.dhis.light.namebaseddataentry.action.GetActivityListAction"
 		class="org.hisp.dhis.light.namebaseddataentry.action.GetActivityListAction"
-        scope="prototype">
+		scope="prototype">
 		<property name="organisationUnitService"
 			ref="org.hisp.dhis.organisationunit.OrganisationUnitService" />
 		<property name="activityReportingService"
@@ -171,26 +166,26 @@
 	<bean
 		id="org.hisp.dhis.light.namebaseddataentry.action.GetProgramStageSectionAction"
 		class="org.hisp.dhis.light.namebaseddataentry.action.GetProgramStageSectionAction"
-        scope="prototype">
+		scope="prototype">
 		<property name="util" ref="org.hisp.dhis.light.utils.NamebasedUtils" />
 		<property name="patientService" ref="org.hisp.dhis.patient.PatientService" />
 		<property name="programService" ref="org.hisp.dhis.program.ProgramService" />
 		<property name="programStageInstanceService"
-			ref="org.hisp.dhis.program.ProgramStageInstanceService" />	
+			ref="org.hisp.dhis.program.ProgramStageInstanceService" />
 	</bean>
-	
+
 	<bean
 		id="org.hisp.dhis.light.namebaseddataentry.action.MarkCompleteProgramStageAction"
 		class="org.hisp.dhis.light.namebaseddataentry.action.MarkCompleteProgramStageAction"
-        scope="prototype">
+		scope="prototype">
 		<property name="programStageInstanceService"
-			ref="org.hisp.dhis.program.ProgramStageInstanceService"/>
+			ref="org.hisp.dhis.program.ProgramStageInstanceService" />
 	</bean>
 
 	<bean
 		id="org.hisp.dhis.light.namebaseddataentry.action.GetProgramStageFormAction"
 		class="org.hisp.dhis.light.namebaseddataentry.action.GetProgramStageFormAction"
-        scope="prototype">
+		scope="prototype">
 		<property name="util" ref="org.hisp.dhis.light.utils.NamebasedUtils" />
 		<property name="programStageInstanceService"
 			ref="org.hisp.dhis.program.ProgramStageInstanceService" />
@@ -198,52 +193,62 @@
 			ref="org.hisp.dhis.patientdatavalue.PatientDataValueService" />
 		<property name="patientService" ref="org.hisp.dhis.patient.PatientService" />
 		<property name="programStageSectionService"
-			ref="org.hisp.dhis.program.ProgramStageSectionService"/>
-		<property name="userService"
-			ref="org.hisp.dhis.user.UserService"/>
+			ref="org.hisp.dhis.program.ProgramStageSectionService" />
+		<property name="userService" ref="org.hisp.dhis.user.UserService" />
 	</bean>
 
 	<bean
 		id="org.hisp.dhis.light.namebaseddataentry.action.SaveProgramStageFormAction"
 		class="org.hisp.dhis.light.namebaseddataentry.action.SaveProgramStageFormAction"
-        scope="prototype">
+		scope="prototype">
 		<property name="dataElementService" ref="org.hisp.dhis.dataelement.DataElementService" />
 		<property name="util" ref="org.hisp.dhis.light.utils.NamebasedUtils" />
 		<property name="patientService" ref="org.hisp.dhis.patient.PatientService" />
 		<property name="dataElementCategoryService"
 			ref="org.hisp.dhis.dataelement.DataElementCategoryService" />
 		<property name="programStageService" ref="org.hisp.dhis.program.ProgramStageService" />
-		<property name="programStageDataElementService" ref="org.hisp.dhis.program.ProgramStageDataElementService" />
-		<property name="programStageInstanceService" ref="org.hisp.dhis.program.ProgramStageInstanceService" />
-		<property name="programValidationService" ref="org.hisp.dhis.program.ProgramValidationService" />
-		<property name="programStageSectionService" ref="org.hisp.dhis.program.ProgramStageSectionService"/>
-		<property name="programExpressionService" ref="org.hisp.dhis.program.ProgramExpressionService" />
-		<property name="patientDataValueService" ref="org.hisp.dhis.patientdatavalue.PatientDataValueService" />
-		<property name="userService" ref="org.hisp.dhis.user.UserService"/>
-		<property name="organisationUnitService" ref="org.hisp.dhis.organisationunit.OrganisationUnitService"/>
+		<property name="programStageDataElementService"
+			ref="org.hisp.dhis.program.ProgramStageDataElementService" />
+		<property name="programStageInstanceService"
+			ref="org.hisp.dhis.program.ProgramStageInstanceService" />
+		<property name="programValidationService"
+			ref="org.hisp.dhis.program.ProgramValidationService" />
+		<property name="programStageSectionService"
+			ref="org.hisp.dhis.program.ProgramStageSectionService" />
+		<property name="programExpressionService"
+			ref="org.hisp.dhis.program.ProgramExpressionService" />
+		<property name="patientDataValueService"
+			ref="org.hisp.dhis.patientdatavalue.PatientDataValueService" />
+		<property name="userService" ref="org.hisp.dhis.user.UserService" />
+		<property name="organisationUnitService"
+			ref="org.hisp.dhis.organisationunit.OrganisationUnitService" />
 	</bean>
 
 	<bean
 		id="org.hisp.dhis.light.namebaseddataentry.action.GetBeneficiaryDetailAction"
 		class="org.hisp.dhis.light.namebaseddataentry.action.GetBeneficiaryDetailAction"
-        scope="prototype">
+		scope="prototype">
 		<property name="patientService" ref="org.hisp.dhis.patient.PatientService" />
 	</bean>
 
 	<bean
 		id="org.hisp.dhis.light.namebaseddataentry.action.GetFindBeneficiaryFormAction"
 		class="org.hisp.dhis.light.namebaseddataentry.action.GetFindBeneficiaryFormAction"
-        scope="prototype">
+		scope="prototype">
 		<property name="currentUserService" ref="org.hisp.dhis.user.CurrentUserService" />
+		<property name="patientAttributeService" ref="org.hisp.dhis.patient.PatientAttributeService" />
+		
 	</bean>
 
 	<bean
 		id="org.hisp.dhis.light.namebaseddataentry.action.FindBeneficiarytAction"
 		class="org.hisp.dhis.light.namebaseddataentry.action.FindBeneficiarytAction"
-        scope="prototype">
+		scope="prototype">
 		<property name="patientService" ref="org.hisp.dhis.patient.PatientService" />
 	</bean>
 
+
+
 	<bean
 		id="org.hisp.dhis.light.namebaseddataentry.action.GetPatientProgramListAction"
 		class="org.hisp.dhis.light.namebaseddataentry.action.GetPatientProgramListAction"
@@ -256,15 +261,17 @@
 		<property name="relationshipTypeService"
 			ref="org.hisp.dhis.relationship.RelationshipTypeService" />
 		<property name="util" ref="org.hisp.dhis.light.utils.NamebasedUtils" />
-		<property name="patientIdentifierService" ref="org.hisp.dhis.patient.PatientIdentifierService" />
+		<property name="patientIdentifierService"
+			ref="org.hisp.dhis.patient.PatientIdentifierService" />
 		<property name="currentUserService" ref="org.hisp.dhis.user.CurrentUserService" />
-		<property name="patientAttributeValueService" ref="org.hisp.dhis.patientattributevalue.PatientAttributeValueService" />
+		<property name="patientAttributeValueService"
+			ref="org.hisp.dhis.patientattributevalue.PatientAttributeValueService" />
 	</bean>
 
 	<bean
 		id="org.hisp.dhis.light.namebaseddataentry.action.GetProgramStageListAction"
 		class="org.hisp.dhis.light.namebaseddataentry.action.GetProgramStageListAction"
-        scope="prototype">
+		scope="prototype">
 		<property name="patientService" ref="org.hisp.dhis.patient.PatientService" />
 		<property name="programInstanceService" ref="org.hisp.dhis.program.ProgramInstanceService" />
 	</bean>
@@ -272,7 +279,7 @@
 	<bean
 		id="org.hisp.dhis.light.namebaseddataentry.action.GetRepeatableEventRegistrationFormAction"
 		class="org.hisp.dhis.light.namebaseddataentry.action.GetRepeatableEventRegistrationFormAction"
-        scope="prototype">
+		scope="prototype">
 		<property name="programStageService" ref="org.hisp.dhis.program.ProgramStageService" />
 		<property name="programInstanceService" ref="org.hisp.dhis.program.ProgramInstanceService" />
 	</bean>
@@ -280,7 +287,7 @@
 	<bean
 		id="org.hisp.dhis.light.namebaseddataentry.action.SaveRepeatableEventAction"
 		class="org.hisp.dhis.light.namebaseddataentry.action.SaveRepeatableEventAction"
-        scope="prototype">
+		scope="prototype">
 		<property name="programInstanceService" ref="org.hisp.dhis.program.ProgramInstanceService" />
 		<property name="programStageService" ref="org.hisp.dhis.program.ProgramStageService" />
 		<property name="programStageInstanceService"
@@ -290,7 +297,7 @@
 	<bean
 		id="org.hisp.dhis.light.namebaseddataentry.action.GetAddNewRelationshipFormAction"
 		class="org.hisp.dhis.light.namebaseddataentry.action.GetAddNewRelationshipFormAction"
-        scope="prototype">
+		scope="prototype">
 		<property name="relationshipTypeService"
 			ref="org.hisp.dhis.relationship.RelationshipTypeService" />
 		<property name="patientService" ref="org.hisp.dhis.patient.PatientService" />
@@ -310,7 +317,7 @@
 	<bean
 		id="org.hisp.dhis.light.namebaseddataentry.action.RegisterPatientLocationAction"
 		class="org.hisp.dhis.light.namebaseddataentry.action.RegisterPatientLocationAction"
-        scope="prototype">
+		scope="prototype">
 		<property name="patientService" ref="org.hisp.dhis.patient.PatientService" />
 		<property name="organisationUnitService"
 			ref="org.hisp.dhis.organisationunit.OrganisationUnitService" />
@@ -319,7 +326,7 @@
 	<bean
 		id="org.hisp.dhis.light.namebaseddataentry.action.GetPatientLocationFormAction"
 		class="org.hisp.dhis.light.namebaseddataentry.action.GetPatientLocationFormAction"
-        scope="prototype">
+		scope="prototype">
 		<property name="patientService" ref="org.hisp.dhis.patient.PatientService" />
 		<property name="currentUserService" ref="org.hisp.dhis.user.CurrentUserService" />
 	</bean>
@@ -411,8 +418,7 @@
 		<property name="programInstanceService" ref="org.hisp.dhis.program.ProgramInstanceService" />
 		<property name="programStageInstanceService"
 			ref="org.hisp.dhis.program.ProgramStageInstanceService" />
-		<property name="formUtils"
-			ref="org.hisp.dhis.light.utils.FormUtils" />
+		<property name="formUtils" ref="org.hisp.dhis.light.utils.FormUtils" />
 		<property name="patientAttributeValueService"
 			ref="org.hisp.dhis.patientattributevalue.PatientAttributeValueService" />
 		<property name="patientAttributeOptionService"
@@ -454,7 +460,7 @@
 			ref="org.hisp.dhis.program.ProgramStageInstanceService" />
 		<property name="programInstanceService" ref="org.hisp.dhis.program.ProgramInstanceService" />
 		<property name="patientService" ref="org.hisp.dhis.patient.PatientService" />
-		<property name="userService" ref="org.hisp.dhis.user.UserService"/>	
+		<property name="userService" ref="org.hisp.dhis.user.UserService" />
 	</bean>
 
 	<bean id="org.hisp.dhis.light.singleevent.action.SaveSingleEventAction"
@@ -473,16 +479,16 @@
 		<property name="dataElementService" ref="org.hisp.dhis.dataelement.DataElementService" />
 		<property name="programStageDataElementService"
 			ref="org.hisp.dhis.program.ProgramStageDataElementService" />
-		<property name="userService" ref="org.hisp.dhis.user.UserService"/>
+		<property name="userService" ref="org.hisp.dhis.user.UserService" />
 	</bean>
 
 	<bean
 		id="org.hisp.dhis.light.singleevent.action.FindSingleEventOptionSetAction"
 		class="org.hisp.dhis.light.singleevent.action.FindSingleEventOptionSetAction"
-        scope="prototype">
+		scope="prototype">
 		<property name="dataElementService" ref="org.hisp.dhis.dataelement.DataElementService" />
 	</bean>
-	
+
 	<!-- Dashboard -->
 
 	<bean id="org.hisp.dhis.light.dashboard.action.ProvideContentAction"
@@ -513,8 +519,7 @@
 	<!-- Settings -->
 
 	<bean id="org.hisp.dhis.light.settings.action.GetSettingsAction"
-		class="org.hisp.dhis.light.settings.action.GetSettingsAction" 
-		scope="prototype">
+		class="org.hisp.dhis.light.settings.action.GetSettingsAction" scope="prototype">
 		<property name="resourceBundleManager"
 			ref="org.hisp.dhis.i18n.resourcebundle.ResourceBundleManager" />
 		<property name="localeManager" ref="org.hisp.dhis.i18n.locale.LocaleManager" />
@@ -532,60 +537,57 @@
 	<!-- Messages -->
 
 	<bean id="org.hisp.dhis.light.message.action.GetMessagesAction"
-		class="org.hisp.dhis.light.message.action.GetMessagesAction" 
-		scope="prototype">
+		class="org.hisp.dhis.light.message.action.GetMessagesAction" scope="prototype">
 		<property name="messageService" ref="org.hisp.dhis.message.MessageService" />
 	</bean>
 
 	<bean id="org.hisp.dhis.light.message.action.GetMessageAction"
-		class="org.hisp.dhis.light.message.action.GetMessageAction" 
-		scope="prototype">
+		class="org.hisp.dhis.light.message.action.GetMessageAction" scope="prototype">
 		<property name="messageService" ref="org.hisp.dhis.message.MessageService" />
 		<property name="currentUserService" ref="org.hisp.dhis.user.CurrentUserService" />
 	</bean>
 
 	<bean id="org.hisp.dhis.light.message.action.SendReplyAction"
-		class="org.hisp.dhis.light.message.action.SendReplyAction" 
-		scope="prototype">
+		class="org.hisp.dhis.light.message.action.SendReplyAction" scope="prototype">
 		<property name="messageService" ref="org.hisp.dhis.message.MessageService" />
 	</bean>
 
 	<bean id="org.hisp.dhis.light.message.action.SendFeedbackAction"
-		class="org.hisp.dhis.light.message.action.SendFeedbackAction" 
-		scope="prototype">
+		class="org.hisp.dhis.light.message.action.SendFeedbackAction" scope="prototype">
 		<property name="messageService" ref="org.hisp.dhis.message.MessageService" />
 	</bean>
-	
+
 	<!-- Anonymous -->
-	
-	<bean
-		id="org.hisp.dhis.light.anonymous.action.SearchOrgUnitAction"
+
+	<bean id="org.hisp.dhis.light.anonymous.action.SearchOrgUnitAction"
 		class="org.hisp.dhis.light.anonymous.action.SearchOrgUnitAction"
 		scope="prototype">
 		<property name="currentUserService" ref="org.hisp.dhis.user.CurrentUserService" />
-		<property name="organisationUnitService" ref="org.hisp.dhis.organisationunit.OrganisationUnitService" />
+		<property name="organisationUnitService"
+			ref="org.hisp.dhis.organisationunit.OrganisationUnitService" />
 	</bean>
-	
+
 	<bean
 		id="org.hisp.dhis.light.anonymous.action.GetAllAnonymousProgramAction"
 		class="org.hisp.dhis.light.anonymous.action.GetAllAnonymousProgramAction"
 		scope="prototype">
 		<property name="programService" ref="org.hisp.dhis.program.ProgramService" />
-		<property name="orgUnitService" ref="org.hisp.dhis.organisationunit.OrganisationUnitService" />
+		<property name="orgUnitService"
+			ref="org.hisp.dhis.organisationunit.OrganisationUnitService" />
 	</bean>
 
 	<bean id="org.hisp.dhis.light.anonymous.action.ShowAnonymousFormAction"
 		class="org.hisp.dhis.light.anonymous.action.ShowAnonymousFormAction"
 		scope="prototype">
 		<property name="programService" ref="org.hisp.dhis.program.ProgramService" />
-		<property name="userService" ref="org.hisp.dhis.user.UserService"/>
+		<property name="userService" ref="org.hisp.dhis.user.UserService" />
 	</bean>
 
 	<bean id="org.hisp.dhis.light.anonymous.action.SaveAnonymousProgramAction"
 		class="org.hisp.dhis.light.anonymous.action.SaveAnonymousProgramAction"
 		scope="prototype">
 		<property name="orgUnitService"
-			ref="org.hisp.dhis.organisationunit.OrganisationUnitService" />	
+			ref="org.hisp.dhis.organisationunit.OrganisationUnitService" />
 		<property name="programService" ref="org.hisp.dhis.program.ProgramService" />
 		<property name="util" ref="org.hisp.dhis.light.utils.NamebasedUtils" />
 		<property name="dataElementService" ref="org.hisp.dhis.dataelement.DataElementService" />
@@ -596,22 +598,20 @@
 			ref="org.hisp.dhis.patientdatavalue.PatientDataValueService" />
 		<property name="programStageDataElementService"
 			ref="org.hisp.dhis.program.ProgramStageDataElementService" />
-		<property name="userService" ref="org.hisp.dhis.user.UserService"/>	
+		<property name="userService" ref="org.hisp.dhis.user.UserService" />
 	</bean>
 
 	<bean
 		id="org.hisp.dhis.light.namebaseddataentry.action.DeleteRelationshipAction"
 		class="org.hisp.dhis.light.namebaseddataentry.action.DeleteRelationshipAction"
-        scope="prototype">
+		scope="prototype">
 		<property name="patientService" ref="org.hisp.dhis.patient.PatientService" />
 		<property name="relationshipService"
 			ref="org.hisp.dhis.relationship.RelationshipService" />
 	</bean>
-	
-	<bean
-		id="org.hisp.dhis.light.messaging.action.FindUserAction"
-		class="org.hisp.dhis.light.messaging.action.FindUserAction"
-        scope="prototype">
+
+	<bean id="org.hisp.dhis.light.messaging.action.FindUserAction"
+		class="org.hisp.dhis.light.messaging.action.FindUserAction" scope="prototype">
 		<property name="userService" ref="org.hisp.dhis.user.UserService" />
 	</bean>
 </beans>

=== modified file 'dhis-2/dhis-web/dhis-web-light/src/main/resources/org/hisp/dhis/light/i18n_module.properties'
--- dhis-2/dhis-web/dhis-web-light/src/main/resources/org/hisp/dhis/light/i18n_module.properties	2013-11-09 16:08:46 +0000
+++ dhis-2/dhis-web/dhis-web-light/src/main/resources/org/hisp/dhis/light/i18n_module.properties	2014-01-22 04:25:46 +0000
@@ -132,4 +132,5 @@
 search_user=Search user by name
 last_recipients=Last recipients
 search_orgunit=Search Organisation Unit
-date_of_birth_hint=*Approximated: enter age. Declared or Verified: enter date in format [yyyy-mm-dd]
\ No newline at end of file
+date_of_birth_hint=*Approximated: enter age. Declared or Verified: enter date in format [yyyy-mm-dd]
+select_attribute=Select attribute
\ No newline at end of file

=== modified file 'dhis-2/dhis-web/dhis-web-light/src/main/resources/struts.xml'
--- dhis-2/dhis-web/dhis-web-light/src/main/resources/struts.xml	2013-11-08 11:59:56 +0000
+++ dhis-2/dhis-web/dhis-web-light/src/main/resources/struts.xml	2014-01-22 04:25:46 +0000
@@ -188,6 +188,7 @@
       <param name="page">/dhis-web-light/namebased/findBeneficiaryForm.vm</param>
 	   <param name="requiredAuthorities">F_PATIENT_SEARCH</param>
     </action>
+    
 
     <action name="showFindRelatedPatientForm"
         class="org.hisp.dhis.light.namebaseddataentry.action.GetFindBeneficiaryFormAction">

=== modified file 'dhis-2/dhis-web/dhis-web-light/src/main/webapp/dhis-web-light/namebased/beneficiaryList.vm'
--- dhis-2/dhis-web/dhis-web-light/src/main/webapp/dhis-web-light/namebased/beneficiaryList.vm	2013-09-16 17:07:25 +0000
+++ dhis-2/dhis-web/dhis-web-light/src/main/webapp/dhis-web-light/namebased/beneficiaryList.vm	2014-01-22 04:25:46 +0000
@@ -2,8 +2,10 @@
 
 <p>
 <ul>
-#foreach( $patient in $patients )
-	<li><a href="showPatientProgramList.action?patientId=$patient.getId()">$!encoder.htmlEncode( ${patient.name} )</a></li>
+#foreach( $pav in $pavSet )
+	#if($pav.getPatientAttribute().getDisplayInListNoProgram()== true)
+<li><a href="showPatientProgramList.action?patientId=$pav.getPatient().getId()">$!encoder.htmlEncode( ${pav.value} )</a></li>
+#end	
 #end
 </ul>
 </p>

=== modified file 'dhis-2/dhis-web/dhis-web-light/src/main/webapp/dhis-web-light/namebased/findBeneficiaryForm.vm'
--- dhis-2/dhis-web/dhis-web-light/src/main/webapp/dhis-web-light/namebased/findBeneficiaryForm.vm	2012-10-24 09:02:06 +0000
+++ dhis-2/dhis-web/dhis-web-light/src/main/webapp/dhis-web-light/namebased/findBeneficiaryForm.vm	2014-01-22 04:25:46 +0000
@@ -11,7 +11,13 @@
 <div class="header-box" align="center">
 <input type="hidden" name="orgUnitId" value="$orgUnitId"/>	
 	<p style="text-align: left;">
-		<label>$i18n.getString( "search_by_name_or_id" )</label>
+		
+		<select name="patientAttributeId">
+			<option value="0">$i18n.getString( "select_attribute" )</option>
+			#foreach($patientAttribute in $patientAttributes)
+				<option value="$patientAttribute.getId()">$patientAttribute.getName()</option>
+			#end
+		</select>
 		#if( $validationMap.get( "keyword" ) )
            	<br /><span style="color: #990000;"> $i18n.getString($validationMap.get( "fullName" ))</span>
      	#end