← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 4240: Add advanced search patients function (Patient module)

 

------------------------------------------------------------
revno: 4240
committer: Tran Chau <tran.hispvietnam@xxxxxxxxx>
branch nick: dhis2
timestamp: Tue 2011-08-02 16:12:51 +0700
message:
  Add advanced search patients function (Patient module)
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/patient/Patient.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/patientattributevalue/PatientAttributeValueService.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/patientattributevalue/PatientAttributeValueStore.java
  dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patientattributevalue/DefaultPatientAttributeValueService.java
  dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patientattributevalue/hibernate/HibernatePatientAttributeValueStore.java
  dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/paging/ActionPagingSupport.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/patient/SearchPatientAction.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/javascript/patient.js
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/listPatient.vm
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/selectPatient.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/Patient.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/patient/Patient.java	2011-05-05 21:14:56 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/patient/Patient.java	2011-08-02 09:12:51 +0000
@@ -362,7 +362,6 @@
         {
             return "( < 1 yr )";
         }
-
         else
         {
             return "( " + age + " yr )";

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/patientattributevalue/PatientAttributeValueService.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/patientattributevalue/PatientAttributeValueService.java	2011-07-27 03:07:45 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/patientattributevalue/PatientAttributeValueService.java	2011-08-02 09:12:51 +0000
@@ -27,6 +27,7 @@
 package org.hisp.dhis.patientattributevalue;
 
 import java.util.Collection;
+import java.util.List;
 import java.util.Map;
 
 import org.hisp.dhis.patient.Patient;
@@ -64,7 +65,7 @@
     Map<Integer, Collection<PatientAttributeValue>> getPatientAttributeValueMapForPatients( Collection<Patient> patients );
     
     Map<Integer, PatientAttributeValue> getPatientAttributeValueMapForPatients( Collection<Patient> patients, PatientAttribute patientAttribute );
-
+    
     Collection<PatientAttributeValue> searchPatientAttributeValue( PatientAttribute patientAttribute, String searchText );   
 
     void copyPatientAttributeValues( Patient source, Patient destination );
@@ -74,9 +75,13 @@
     Collection<Patient> getPatient( PatientAttribute attribute, String value );
     
     Collection<Patient> searchPatients( PatientAttribute patientAttribute, String searchText, int min, int max);
-    
+        
     Collection<Patient> searchPatients( PatientAttribute patientAttribute, String searchText );
-    
+
+    Collection<Patient> searchPatients( List<Integer> patientAttributeIds, List<String> searchTexts, int min, int max);
+
     int countSearchPatientAttributeValue(  PatientAttribute patientAttribute, String searchText );
     
+    int countSearchPatients( List<Integer> patientAttributeIds, List<String> searchTexts );
+    
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/patientattributevalue/PatientAttributeValueStore.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/patientattributevalue/PatientAttributeValueStore.java	2010-10-29 05:24:41 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/patientattributevalue/PatientAttributeValueStore.java	2011-08-02 09:12:51 +0000
@@ -27,6 +27,8 @@
 package org.hisp.dhis.patientattributevalue;
 
 import java.util.Collection;
+import java.util.List;
+import java.util.Map;
 
 import org.hisp.dhis.common.GenericStore;
 import org.hisp.dhis.patient.Patient;
@@ -66,5 +68,9 @@
     
     Collection<Patient> searchPatients( PatientAttribute patientAttribute, String searchText );
 
+    Collection<Patient> searchPatients( List<Integer> patientAttributeIds, List<String> searchTexts, int min, int max);
+
     int countSearchPatientAttributeValue(  PatientAttribute patientAttribute, String searchText );
+    
+    int countSearchPatients( List<Integer> patientAttributeIds, List<String> searchTexts );
 }

=== modified file 'dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patientattributevalue/DefaultPatientAttributeValueService.java'
--- dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patientattributevalue/DefaultPatientAttributeValueService.java	2011-07-27 03:07:45 +0000
+++ dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patientattributevalue/DefaultPatientAttributeValueService.java	2011-08-02 09:12:51 +0000
@@ -29,6 +29,7 @@
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.SortedMap;
@@ -228,4 +229,15 @@
     {
         return patientAttributeValueStore.searchPatients( patientAttribute, searchText );
     }
+
+    public Collection<Patient> searchPatients( List<Integer> patientAttributeIds, List<String> searchTexts, int min,
+        int max )
+    {
+        return patientAttributeValueStore.searchPatients( patientAttributeIds, searchTexts, min, max );
+    }
+
+    public int countSearchPatients( List<Integer> patientAttributeIds, List<String> searchTexts )
+    {
+        return patientAttributeValueStore.countSearchPatients( patientAttributeIds, searchTexts );
+    }
 }

=== modified file 'dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patientattributevalue/hibernate/HibernatePatientAttributeValueStore.java'
--- dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patientattributevalue/hibernate/HibernatePatientAttributeValueStore.java	2011-04-07 08:21:36 +0000
+++ dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patientattributevalue/hibernate/HibernatePatientAttributeValueStore.java	2011-08-02 09:12:51 +0000
@@ -27,6 +27,8 @@
 package org.hisp.dhis.patientattributevalue.hibernate;
 
 import java.util.Collection;
+import java.util.List;
+import java.util.Map;
 
 import org.hibernate.Query;
 import org.hibernate.criterion.Projections;
@@ -132,9 +134,9 @@
     public Collection<Patient> searchPatients( PatientAttribute patientAttribute, String searchText, int min, int max )
     {
         return getCriteria( Restrictions.eq( "patientAttribute", patientAttribute ),
-            Restrictions.ilike( "value", "%" + searchText + "%" ) )
-            .setProjection(Projections.distinct(Projections.property( "patient") ))
-            .setFirstResult( min ).setMaxResults( max ).list();
+            Restrictions.ilike( "value", "%" + searchText + "%" ) ).setProjection(
+            Projections.distinct( Projections.property( "patient" ) ) ).setFirstResult( min ).setMaxResults( max )
+            .list();
 
     }
 
@@ -149,4 +151,110 @@
 
         return query.list();
     }
+
+    @SuppressWarnings( "unchecked" )
+    public Collection<Patient> searchPatients( List<Integer> patientAttributeIds, List<String> searchTexts, int min,
+        int max )
+    {
+        String hql = "SELECT pav.patient FROM PatientAttributeValue as pav WHERE pav.patient in ";
+        String end = "";
+
+        int index = 0;
+        for ( Integer patientAttributeId : patientAttributeIds )
+        {
+            end += ")";
+
+            hql += createHQL( patientAttributeId, searchTexts.get( index ), index, patientAttributeIds.size() );
+
+            index++;
+        }
+
+        hql += " ORDER BY pav.value ASC";
+
+        Query query = getQuery( hql + end ).setFirstResult( min ).setMaxResults( max );
+
+        return query.list();
+    }
+
+    public int countSearchPatients( List<Integer> patientAttributeIds, List<String> searchTexts )
+    {
+        String hql = "SELECT COUNT( pav.patient ) FROM PatientAttributeValue as pav WHERE pav.patient in ";
+        String end = "";
+
+        int index = 0;
+        for ( Integer patientAttributeId : patientAttributeIds )
+        {
+            end += ")";
+
+            hql += createHQL( patientAttributeId, searchTexts.get( index ), index, patientAttributeIds.size() );
+
+            index++;
+        }
+
+        Query query = getQuery( hql + end );
+
+        Number rs = (Number) query.uniqueResult();
+
+        return (rs != null) ? rs.intValue() : 0;
+    }
+
+    // -------------------------------------------------------------------------
+    // Supportive methods
+    // -------------------------------------------------------------------------
+    
+    private String createHQL( Integer patientAttributeId, String searchText, int index, int noCondition )
+    {
+        String hql = "";
+        boolean isSearchByAttribute = true;
+
+        // ---------------------------------------------------------------------
+        // search patients by name or identifier
+        // ---------------------------------------------------------------------
+        if ( patientAttributeId == null )
+        {
+            hql += " ( SELECT p" + index + " FROM Patient as p" + index + " JOIN p" + index
+                + ".identifiers as identifier" + index + " " + "WHERE  lower(identifier" + index
+                + ".identifier) LIKE lower('%" + searchText + "%') " + "OR lower(p" + index
+                + ".firstName) LIKE lower('%" + searchText + "%') " + "OR lower(p" + index
+                + ".middleName) LIKE lower('%" + searchText + "%') " + "OR lower(p" + index
+                + ".lastName) LIKE lower('%" + searchText + "%') ";
+
+            isSearchByAttribute = false;
+        }
+        // -----------------------------------------------------------------
+        // search patients by program
+        // -----------------------------------------------------------------
+        else if ( patientAttributeId == 0 )
+        {
+            hql += " ( SELECT p" + index + " FROM Patient AS p" + index + " " + " JOIN p" + index
+                + ".programs AS program" + index + " WHERE program" + index + ".id=" + searchText;
+
+            isSearchByAttribute = false;
+        }
+        // -----------------------------------------------------------------
+        // search patients by attribute
+        // -----------------------------------------------------------------
+        else
+        {
+            hql += " ( SELECT pav" + index + ".patient FROM PatientAttributeValue as pav" + index + " " + "WHERE pav"
+                + index + ".patientAttribute.id=" + patientAttributeId + " AND lower(pav" + index
+                + ".value) LIKE lower('%" + searchText + "%') ";
+        }
+
+        if ( index < noCondition - 1 )
+        {
+
+            if ( isSearchByAttribute )
+            {
+                hql += " AND pav" + index + ".patient in ";
+            }
+            else
+            {
+                hql += " AND p" + index + " in ";
+            }
+        }
+
+        return hql;
+
+    }
 }

=== modified file 'dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/paging/ActionPagingSupport.java'
--- dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/paging/ActionPagingSupport.java	2011-05-05 21:15:45 +0000
+++ dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/paging/ActionPagingSupport.java	2011-08-02 09:12:51 +0000
@@ -103,8 +103,11 @@
             String paramName = paramNames.nextElement();
             if ( !paramName.equalsIgnoreCase( "pageSize" ) && !paramName.equalsIgnoreCase( "currentPage" ) )
             {
-                String value = request.getParameter( paramName );
-                baseLink += paramName + "=" + value + "&";
+                String[] values = request.getParameterValues( paramName );
+                for( int i=0; i<values.length; i++ )
+                {
+                    baseLink += paramName + "=" + values[i] + "&";
+                }
             }
         }
 

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/patient/SearchPatientAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/patient/SearchPatientAction.java	2011-07-20 09:15:06 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/patient/SearchPatientAction.java	2011-08-02 09:12:51 +0000
@@ -30,6 +30,7 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import org.hisp.dhis.organisationunit.OrganisationUnit;
@@ -41,8 +42,6 @@
 import org.hisp.dhis.patient.state.SelectedStateManager;
 import org.hisp.dhis.patientattributevalue.PatientAttributeValue;
 import org.hisp.dhis.patientattributevalue.PatientAttributeValueService;
-import org.hisp.dhis.program.Program;
-import org.hisp.dhis.program.ProgramService;
 
 /**
  * @author Abyot Asalefew Gizaw
@@ -64,25 +63,19 @@
 
     private PatientService patientService;
 
+    private PatientAttributeValueService patientAttributeValueService;
+
     private PatientAttributeService patientAttributeService;
 
-    private PatientAttributeValueService patientAttributeValueService;
-
-    private ProgramService programService;
-
     // -------------------------------------------------------------------------
     // Input
     // -------------------------------------------------------------------------
 
-    private String searchText;
+    private List<String> searchText = new ArrayList<String>();
 
     private Boolean listAll;
 
-    private Integer searchingAttributeId;
-
-    private Integer sortPatientAttributeId;
-
-    private Integer programId;
+    private List<Integer> searchingAttributeId = new ArrayList<Integer>();
 
     // -------------------------------------------------------------------------
     // Output
@@ -92,15 +85,11 @@
 
     private Collection<Patient> patients = new ArrayList<Patient>();
 
-    private Map<Integer, String> mapPatientPatientAttr = new HashMap<Integer, String>();
+    private Map<String, String> mapPatientPatientAttr = new HashMap<String, String>();
 
     private Map<Integer, String> mapPatientOrgunit = new HashMap<Integer, String>();
 
-    private PatientAttribute sortingPatientAttribute = null;
-
-    private PatientAttribute searchingPatientAttribute = null;
-
-    private Program program;
+    private List<PatientAttribute> patientAttributes = new ArrayList<PatientAttribute>();
 
     // -------------------------------------------------------------------------
     // Getters/Setters
@@ -111,9 +100,9 @@
         this.selectedStateManager = selectedStateManager;
     }
 
-    public void setProgramService( ProgramService programService )
+    public void setPatientAttributeService( PatientAttributeService patientAttributeService )
     {
-        this.programService = programService;
+        this.patientAttributeService = patientAttributeService;
     }
 
     public void setPatientService( PatientService patientService )
@@ -121,22 +110,22 @@
         this.patientService = patientService;
     }
 
+    public List<PatientAttribute> getPatientAttributes()
+    {
+        return patientAttributes;
+    }
+
     public Map<Integer, String> getMapPatientOrgunit()
     {
         return mapPatientOrgunit;
     }
 
-    public void setPatientAttributeService( PatientAttributeService patientAttributeService )
-    {
-        this.patientAttributeService = patientAttributeService;
-    }
-
     public void setPatientAttributeValueService( PatientAttributeValueService patientAttributeValueService )
     {
         this.patientAttributeValueService = patientAttributeValueService;
     }
 
-    public void setSearchText( String searchText )
+    public void setSearchText( List<String> searchText )
     {
         this.searchText = searchText;
     }
@@ -146,26 +135,11 @@
         this.listAll = listAll;
     }
 
-    public void setProgramId( Integer programId )
-    {
-        this.programId = programId;
-    }
-
-    public void setSearchingAttributeId( Integer searchingAttributeId )
+    public void setSearchingAttributeId( List<Integer> searchingAttributeId )
     {
         this.searchingAttributeId = searchingAttributeId;
     }
 
-    public String getSearchText()
-    {
-        return searchText;
-    }
-
-    public Program getProgram()
-    {
-        return program;
-    }
-
     public Collection<Patient> getPatients()
     {
         return patients;
@@ -176,12 +150,7 @@
         return total;
     }
 
-    public void setSortPatientAttributeId( Integer sortPatientAttributeId )
-    {
-        this.sortPatientAttributeId = sortPatientAttributeId;
-    }
-
-    public Map<Integer, String> getMapPatientPatientAttr()
+    public Map<String, String> getMapPatientPatientAttr()
     {
         return mapPatientPatientAttr;
     }
@@ -195,141 +164,30 @@
     {
         OrganisationUnit organisationUnit = selectedStateManager.getSelectedOrganisationUnit();
 
-        setParamsToSearch();
-
         // ---------------------------------------------------------------------
-        // Get all of patient into the selected organisation unit
+        // Get all of patients into the selected organisation unit
         // ---------------------------------------------------------------------
 
         if ( listAll != null && listAll )
         {
-            selectedStateManager.clearSearchingAttributeId();
-            selectedStateManager.clearSortingAttributeId();
-            selectedStateManager.clearSearchText();
-            selectedStateManager.clearSelectedProgram();
-            selectedStateManager.setListAll( listAll );
-
-            listAllPatient( organisationUnit, sortingPatientAttribute );
-
-            return SUCCESS;
-        }
-
-        // ---------------------------------------------------------------------
-        // Get patients by the selected program
-        // ---------------------------------------------------------------------
-
-        if ( searchingAttributeId != null && searchingAttributeId == 0 && programId != null )
-        {
-            program = programService.getProgram( programId );
-
-            if ( sortPatientAttributeId != null )
-            {
-                selectedStateManager.setSortingAttributeId( sortPatientAttributeId );
-            }
-            else
-            {
-                selectedStateManager.clearSortingAttributeId();
-            }
-            selectedStateManager.setSelectedProgram( program );
-            selectedStateManager.setSearchingAttributeId( searchingAttributeId );
-
-            searchPatientByProgram( organisationUnit, program, sortingPatientAttribute );
-
-            return SUCCESS;
-        }
-
-        // ---------------------------------------------------------------------
-        // Get patients by searchingAttributeId and searchText
-        // and sort result by sortingAttributeId
-        // ---------------------------------------------------------------------
-
-        if ( searchingPatientAttribute != null && searchText != null )
-        {
-
-            selectedStateManager.clearListAll();
-            selectedStateManager.setSearchingAttributeId( searchingAttributeId );
-            if ( sortPatientAttributeId != null )
-            {
-                selectedStateManager.setSortingAttributeId( sortPatientAttributeId );
-            }
-            else
-            {
-                selectedStateManager.clearSortingAttributeId();
-            }
-
-            if ( programId != null )
-            {
-                selectedStateManager.clearSortingAttributeId();
-            }
-            selectedStateManager.setSearchText( searchText );
-
-            searchPatientByAttribute( searchingPatientAttribute, searchText, sortingPatientAttribute );
-
-            return SUCCESS;
-        }
-
-        if ( searchingPatientAttribute == null && searchText != null )
-        {
-            selectedStateManager.clearListAll();
-            selectedStateManager.clearSearchingAttributeId();
-
-            if ( sortPatientAttributeId != null )
-            {
-                selectedStateManager.setSortingAttributeId( sortPatientAttributeId );
-            }
-            else
-            {
-                selectedStateManager.clearSortingAttributeId();
-            }
-
-            if ( programId != null )
-            {
-                selectedStateManager.clearSortingAttributeId();
-            }
-            selectedStateManager.setSearchText( searchText );
-
-            searchPatientByAttribute( searchText, sortingPatientAttribute );
-
-            return SUCCESS;
-        }
-
-        // ---------------------------------------------------------------------
-        // Search patients by values into section
-        // ---------------------------------------------------------------------
-
-        listAll = selectedStateManager.getListAll();
-        searchingAttributeId = selectedStateManager.getSearchingAttributeId();
-        sortPatientAttributeId = selectedStateManager.getSortAttributeId();
-        searchText = selectedStateManager.getSearchText();
-        program = selectedStateManager.getSelectedProgram();
-
-        setParamsToSearch();
-
-        if ( listAll )
-        {
-            listAllPatient( organisationUnit, sortingPatientAttribute );
-
-            return SUCCESS;
-
-        }
-
-        if ( searchingAttributeId != null && searchingAttributeId == 0 && program != null )
-        {
-            searchPatientByProgram( organisationUnit, program, sortingPatientAttribute );
-            return SUCCESS;
-        }
-
-        if ( searchingAttributeId != null && searchText != null )
-        {
-            searchPatientByAttribute( searchText, sortingPatientAttribute );
-            return SUCCESS;
-        }
-
-        if ( searchingAttributeId == null && searchText != null )
-        {
-            searchPatientByAttribute( searchText, sortingPatientAttribute );
-            return SUCCESS;
-        }
+            listAllPatient( organisationUnit );
+
+            return SUCCESS;
+        }
+
+        // ---------------------------------------------------------------------
+        // Search patients by attributes
+        // ---------------------------------------------------------------------
+
+        for ( Integer attributeId : searchingAttributeId )
+        {
+            if ( attributeId != null && attributeId != 0 )
+            {
+                patientAttributes.add( patientAttributeService.getPatientAttribute( attributeId ) );
+            }
+        }
+
+        searchPatientByAttributes( searchingAttributeId, searchText );
 
         return SUCCESS;
 
@@ -339,148 +197,35 @@
     // Supporting methods
     // -------------------------------------------------------------------------
 
-    private void setParamsToSearch()
-    {
-        // ---------------------------------------------------------------------
-        // Get sorting patient-attribute
-        // ---------------------------------------------------------------------
-
-        if ( sortPatientAttributeId != null )
-        {
-            sortingPatientAttribute = patientAttributeService.getPatientAttribute( sortPatientAttributeId );
-        }
-
-        // ---------------------------------------------------------------------
-        // Get and searching patient-attribute
-        // ---------------------------------------------------------------------
-
-        if ( searchingAttributeId != null )
-        {
-            searchingPatientAttribute = patientAttributeService.getPatientAttribute( searchingAttributeId );
-        }
-    }
-
-    private void listAllPatient( OrganisationUnit organisationUnit, PatientAttribute sortingPatientAttribute )
+    private void listAllPatient( OrganisationUnit organisationUnit )
     {
         total = patientService.countGetPatientsByOrgUnit( organisationUnit );
         this.paging = createPaging( total );
 
         patients = new ArrayList<Patient>( patientService.getPatients( organisationUnit, paging.getStartPos(), paging
             .getPageSize() ) );
-        
-        if ( patients != null && patients.size() > 0 && sortingPatientAttribute != null )
-        {
-            for ( Patient patient : patients )
-            {
-                PatientAttributeValue attributeValue = patientAttributeValueService.getPatientAttributeValue( patient,
-                    sortingPatientAttribute );
-                String value = (attributeValue == null) ? "" : attributeValue.getValue();
-
-                mapPatientPatientAttr.put( patient.getId(), value );
-            }
-            
-            patients = patientService.sortPatientsByAttribute( patients, sortingPatientAttribute );
-        }
-    }
-
-    private void searchPatientByProgram( OrganisationUnit organisationUnit, Program program,
-        PatientAttribute sortingPatientAttribute )
-    {
-        total = patientService.countGetPatientsByOrgUnitProgram( organisationUnit, program );
-        this.paging = createPaging( total );
-
-        patients = new ArrayList<Patient>( patientService.getPatients( organisationUnit, program, paging.getStartPos(),
-            paging.getPageSize() ) );
-
-        if ( patients != null && patients.size() > 0 && sortingPatientAttribute != null )
-        {
-            for ( Patient patient : patients )
-            {
-                PatientAttributeValue attributeValue = patientAttributeValueService.getPatientAttributeValue( patient,
-                    sortingPatientAttribute );
-                String value = (attributeValue == null) ? "" : attributeValue.getValue();
-
-                mapPatientPatientAttr.put( patient.getId(), value );
-            }
-            
-            patients = patientService.sortPatientsByAttribute( patients, sortingPatientAttribute );
-        }
-    }
-
-    private void searchPatientByAttribute( PatientAttribute searchingPatientAttribute, String searchText,
-        PatientAttribute sortingPatientAttribute )
-    {
-        total = patientAttributeValueService.countSearchPatientAttributeValue( searchingPatientAttribute, searchText );
-        this.paging = createPaging( total );
-
-        patients = patientAttributeValueService.searchPatients( searchingPatientAttribute, searchText, paging
-            .getStartPos(), paging.getPageSize() );
-
-        if ( patients != null && patients.size() > 0 )
-        {
-            if ( sortingPatientAttribute != null )
-            {
-                patients = patientService.sortPatientsByAttribute( patients, sortingPatientAttribute );
-            }
-
-            for ( Patient patient : patients )
-            {
-                mapPatientOrgunit.put( patient.getId(), getHierarchyOrgunit( patient.getOrganisationUnit() ) );
-
-                if ( sortingPatientAttribute != null )
-                {
-                    PatientAttributeValue attributeValue = patientAttributeValueService.getPatientAttributeValue(
-                        patient, sortingPatientAttribute );
-                    String value = (attributeValue == null) ? "" : attributeValue.getValue();
-
-                    mapPatientPatientAttr.put( patient.getId(), value );
-                }
-            }
-        }
-
-    }
-
-    private void searchPatientByAttribute( String searchText, PatientAttribute sortingPatientAttribute )
-    {
-        int index = searchText.indexOf( ' ' );
-
-        if ( index != -1 && index == searchText.lastIndexOf( ' ' ) )
-        {
-            String[] keys = searchText.split( " " );
-            searchText = keys[0] + "  " + keys[1];
-        }
-
-        total = patientService.countGetPatients( searchText );
-        this.paging = createPaging( total );
-
-        patients = patientService.getPatients( searchText, paging.getStartPos(), paging.getPageSize() );
-
-        if ( patients != null && patients.size() > 0 )
-        {
-            if ( sortingPatientAttribute != null )
-            {
-                patients = patientService.sortPatientsByAttribute( patients, sortingPatientAttribute );
-            }
-            for ( Patient patient : patients )
-            {
-                // -------------------------------------------------------------
-                // Get hierarchy organisation unit
-                // -------------------------------------------------------------
-
-                mapPatientOrgunit.put( patient.getId(), getHierarchyOrgunit( patient.getOrganisationUnit() ) );
-
-                // -------------------------------------------------------------
-                // Sort patients
-                // -------------------------------------------------------------
-
-                if ( sortingPatientAttribute != null )
-                {
-                    PatientAttributeValue attributeValue = patientAttributeValueService.getPatientAttributeValue(
-                        patient, sortingPatientAttribute );
-                    String value = (attributeValue == null) ? "" : attributeValue.getValue();
-
-                    mapPatientPatientAttr.put( patient.getId(), value );
-                }
+    }
+
+    private void searchPatientByAttributes( List<Integer> searchingAttributeId, List<String> searchText )
+    {
+        total = patientAttributeValueService.countSearchPatients( searchingAttributeId, searchText );
+
+        this.paging = createPaging( total );
+
+        patients = patientAttributeValueService.searchPatients( searchingAttributeId, searchText, paging.getStartPos(),
+            paging.getPageSize() );
+
+        Collection<PatientAttributeValue> attributeValues = patientAttributeValueService
+            .getPatientAttributeValues( patients );
+
+        for ( Patient patient : patients )
+        {
+            mapPatientOrgunit.put( patient.getId(), getHierarchyOrgunit( patient.getOrganisationUnit() ) );
+
+            for ( PatientAttributeValue attributeValue : attributeValues )
+            {
+                mapPatientPatientAttr.put( patient.getId() + "-" + attributeValue.getPatientAttribute().getId(),
+                    attributeValue.getValue() );
             }
         }
     }

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/META-INF/dhis/beans.xml	2011-08-01 18:58:07 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/META-INF/dhis/beans.xml	2011-08-02 09:12:51 +0000
@@ -342,7 +342,6 @@
 			ref="org.hisp.dhis.patientattributevalue.PatientAttributeValueService" />
 		<property name="patientAttributeService"
 			ref="org.hisp.dhis.patient.PatientAttributeService" />
-		<property name="programService" ref="org.hisp.dhis.program.ProgramService" />
 	</bean>
 
 	<bean id="org.hisp.dhis.patient.action.patient.GetPatientAction"

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/javascript/patient.js'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/javascript/patient.js	2011-08-01 02:39:52 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/javascript/patient.js	2011-08-02 09:12:51 +0000
@@ -26,13 +26,14 @@
 					{
 					}, 
 					function( json ) 
-					{    
-						clearListById('programId');
-						addOptionById( 'programId', "0", i18n_select_program );
+					{   
+						programComboBox = '<select id="searchText" name="searchText" style="width:20.2em" >';
+						
 						for ( i in json.programs ) 
 						{
-							addOptionById( 'programId', json.programs[i].id, json.programs[i].name );
+							programComboBox += '<option value=' + json.programs[i].id + '>' + json.programs[i].name + '</option>';
 						} 
+						programComboBox += '</select>';
 						
 						showById('searchPatientDiv');
 						enable('listPatientBtn');
@@ -55,21 +56,19 @@
 // Search patients by selected attribute
 //------------------------------------------------------------------------------
 
-
-function searchingAttributeOnChange()
-{
-	var value = byId('searchingAttributeId').value;
+function searchingAttributeOnChange( this_ )
+{	
+	var container = jQuery(this_).parent().parent().attr('id');
+	var attributeId = jQuery('#' + container+ ' [id=searchingAttributeId]').val(); 
+	var element = $('#' + container+ ' [id=searchText]');
 	
-	if(value == '0')
+	if( attributeId == '0' )
 	{
-		byId('programId').style.display = 'block';
-		byId('searchText').style.display = 'none';
+		element.replaceWith( programComboBox );
 	}
 	else
 	{
-		byId('searchText').style.display = 'block';
-		byId('programId').style.display = 'none';
-		byId('programId').selectedIndex = 0;
+		element.replaceWith( searchTextBox );
 	}
 }
 
@@ -125,23 +124,22 @@
 	
 	if( getFieldValue('searchText') == '' )
 	{
-		$('#listPatientDiv').html( "<i style='color:red'>" + i18n_specify_a_search_criteria + "</i>" );
-		showById( 'listPatientDiv' );
+		showWarningMessage( i18n_specify_a_search_criteria );
 		return;
 	}
 	
 	contentDiv = 'listPatientDiv';
 	$( "#loaderDiv" ).show();
-	$('#listPatientDiv').load("searchPatient.action", 
-		{
-			searchText: getFieldValue('searchText'), 
-			searchingAttributeId: getFieldValue('searchingAttributeId'), 
-			sortPatientAttributeId: getFieldValue('sortPatientAttributeId'), 
-			programId: getFieldValue('programId') 
-		}
-		, function(){
-			showById('listPatientDiv');
-			$( "#loaderDiv" ).hide();
+	$.ajax({
+		url: 'searchPatient.action',
+		type:"POST",
+		data: getParamsForDiv('searchPatientDiv'),
+		success: function( html ){
+				statusSearching = 1;
+				setInnerHTML( 'listPatientDiv', html );
+				showById('listPatientDiv');
+				$( "#loaderDiv" ).hide();
+			}
 		});
 }
 
@@ -507,7 +505,6 @@
 		});
 }
 
-
 function validateProgramEnrollment()
 {	
 	$.ajax({
@@ -695,22 +692,23 @@
 
 function loadPatientList()
 {
-	$.ajaxSettings.cache = false;
-
-	hideById('listPatientDiv');
 	hideById('addPatientDiv');
 	hideById('updatePatientDiv');
 	hideById('enrollmentDiv');
 	hideById('listRelationshipDiv');
 	hideById('addRelationshipDiv');
 	
-	jQuery('#listPatientDiv').load("searchPatient.action", {}
-		, function(){
-			showById('selectDiv');
-			showById('searchPatientDiv');
-			showById('listPatientDiv');
-			$( "#loaderDiv" ).hide();
-		});
+	showById('selectDiv');
+	showById('searchPatientDiv');
+	
+	if( statusSearching == 0)
+	{
+		loadAllPatients();
+	}
+	else if( statusSearching == 1 )
+	{
+		searchPatients();
+	}
 }
 
 // -----------------------------------------------------------------------------
@@ -730,6 +728,7 @@
 			sortPatientAttributeId: getFieldValue('sortPatientAttributeId')
 		},
 		function(){
+			statusSearching = 0;
 			showById('listPatientDiv');
 			jQuery('#loaderDiv').hide();
 		});
@@ -876,3 +875,22 @@
 	return n_body && (!n_result || (n_result > n_body)) ? n_body : n_result;
 }
 
+// -----------------------------------------------------------------------------
+// Advanced search
+// -----------------------------------------------------------------------------
+
+function addAttributeOption()
+{
+	var rowId = 'advSearchBox' + jQuery('#advancedSearchTB select[name=searchingAttributeId]').length + 1;
+	var contend  = '<td>' + getInnerHTML('searchingAttributeIdTD') + '</td>'
+		contend += '<td>' + searchTextBox ;
+		contend += '<input type="button" value="-" onclick="removeAttributeOption(' + "'" + rowId + "'" + ');"></td>';
+		contend = '<tr id="' + rowId + '">' + contend + '</tr>';
+	$('#advancedSearchTB > tbody:last').append( contend );
+}	
+
+function removeAttributeOption( rowId )
+{
+	jQuery( '#' + rowId ).remove();
+}		
+

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/listPatient.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/listPatient.vm	2011-08-01 02:39:52 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/listPatient.vm	2011-08-02 09:12:51 +0000
@@ -27,9 +27,9 @@
     <td>    
       <table class="listTable" id="patientList" width='100%'>               
           <col width="30"/>
-            #if($mapPatientPatientAttr.size()!=0)
-                <col/>
-            #end
+			#foreach( $attribute in $patientAttributes )
+				<col/>
+			#end
           <col/>
           <col/>
           <col/>
@@ -44,12 +44,8 @@
 		  <thead>
 			<tr>
 				<th>#</th>
-				#if($mapPatientPatientAttr.size()!=0)
-					<th id="patientAttributeName"></th>
-					<script>
-						var selectedAttr = byId("sortPatientAttributeId");
-						byId('patientAttributeName').innerHTML = selectedAttr.options[selectedAttr.selectedIndex].text;
-					</script>
+				#foreach( $attribute in $patientAttributes )
+					<th id="patientAttributeName">$attribute.name</th>
 				#end
 				<th>$i18n.getString( "first_name" )</th>
 				<th>$i18n.getString( "middle_name" )</th>
@@ -67,17 +63,16 @@
           <tbody id="list">	
 		  #set( $mark = false )
           #foreach( $patient in $patients )
-          	<tr id="tr${patient.id}" #alternate( $mark )>
+          	<tr id="tr${patient.id}" #alternate($mark) >
 				
 				<td>
 					#set( $nr = ( ( $paging.getCurrentPage() - 1  ) * $paging.pageSize ) + $velocityCount )
 					$nr
 				</td>
 				
-				#if($!mapPatientPatientAttr.size()!=0)
-				<td>
-					$!mapPatientPatientAttr.get( $patient.id )
-				</td>
+				#foreach( $attribute in $patientAttributes )
+					#set ( $key = $patient.id + '-' + $attribute.id )
+					<td>$mapPatientPatientAttr.get($key)</td>
 				#end
 					
 				<td>$!patient.firstName</td>

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/selectPatient.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/selectPatient.vm	2011-08-01 02:39:52 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/selectPatient.vm	2011-08-02 09:12:51 +0000
@@ -23,38 +23,29 @@
 </div>
 
 <div id='searchPatientDiv' style='display:none'>
-	<table>	
-		<tr>	       
-			<td>
-			  <select id="searchingAttributeId" name="searchingAttributeId" style="min-width:20.2em"  #if( $patientAttributes.size() == 0 ) disabled="disabled" #end onchange="searchingAttributeOnChange()">
-				<option value="">$i18n.getString( "search_by_name_identifier" )</option>
-				<option value="0">$i18n.getString( "search_by_program" )</option>
-					#foreach( $attribute in $patientAttributes )
-						<option value="$attribute.id" >$encoder.htmlEncode( $attribute.name )</option>
-					#end
-			  </select> 
-			  <em title="$i18n.getString( "required" )" class="required">*</em></label>
-			</td>		
-			<td>
-				<input type="text" id="searchText" name="searchText" maxlength="30" style="width:20em" value="$!searchText" onkeyup='searchPatientsOnKeyUp( event );'>
-				<select id="programId" name='programId' style="display:none; width:20.2em" ></select>
-			</td>		
-			<td><input type="button" value='$i18n.getString( "search" )' onclick='searchPatients();'></td>
-			<td>&nbsp;</td>
-			<td><input type="button" value='$i18n.getString( "add_new" )' onclick="showAddPatientForm();"></td>
-		</tr>
-		
-		<tr>
-			<td></td>
-			<td>
-			<select id="sortPatientAttributeId" name="sortPatientAttributeId" maxlength="30" style="width:20.2em" onchange="sortPatients();">
-					<option value="" selected >[ $i18n.getString( "sort_by" ) ]</option>
-					#foreach( $patientAttribute in $patientAttributes )
-						<option value="$patientAttribute.id" >$encoder.htmlEncode( $patientAttribute.name )</option>
-					#end
-				</select>
-			</td>
-		</tr>
+	<table id='advancedSearchTB'>	
+		<tbody>
+			<tr id='advSearchBox0'>	       
+				<td id='searchingAttributeIdTD'>
+				  <select id="searchingAttributeId" name="searchingAttributeId" style="width:20.2em"  #if( $patientAttributes.size() == 0 ) disabled="disabled" #end onchange="searchingAttributeOnChange(this)">
+					<option value="">$i18n.getString( "search_by_name_identifier" )</option>
+					<option value="0">$i18n.getString( "search_by_program" )</option>
+						#foreach( $attribute in $patientAttributes )
+							<option value="$attribute.id" >$encoder.htmlEncode( $attribute.name )</option>
+						#end
+				  </select> 
+				  <em title="$i18n.getString( "required" )" class="required">*</em></label>
+				</td>		
+				<td>
+					<input type="text" id="searchText" name="searchText" maxlength="30" style="width:20em" value="$!searchText" onkeyup='searchPatientsOnKeyUp( event );'>
+					<input type="button" value='+' onclick='addAttributeOption();'>
+				</td>	
+				<td></td>
+				<td><input type="button" value='$i18n.getString( "search" )' onclick='searchPatients();'></td>
+				<td>&nbsp;</td>
+				<td><input type="button" value='$i18n.getString( "add_new" )' onclick="showAddPatientForm();"></td>
+			</tr>
+		</tbody>
 	</table>
 </div>
 
@@ -108,8 +99,18 @@
 	var i18n_search_result = '$encoder.jsEscape( $i18n.getString( "search_result" ) , "'")';
 	var i18n_duplicated_patient_list = '$encoder.jsEscape( $i18n.getString( "duplicated_patient_list" ) , "'")';
 	var i18n_duplicate_warning = '$encoder.jsEscape( $i18n.getString( "duplicate_warning" ) , "'")';
+	var i18n_search_by_name_identifier = '$encoder.jsEscape( $i18n.getString( "search_by_name_identifier" ) , "'")';
+	var i18n_search_by_program = '$encoder.jsEscape( $i18n.getString( "search_by_program" ) , "'")';
+	
 	var checkedDuplicate = false;
-	
+	// -1: no search anything
+	//  0: show list all patient
+	//  1: search with conditions
+	var statusSearching = -1;
 	isAjax = true;
 	contentDiv = '';
+	
+	var programComboBox = '';
+	var searchTextBox = '<input type="text" id="searchText" name="searchText" maxlength="30" style="width:20em" onkeyup="searchPatientsOnKeyUp( event );">';
+	
 </script>
\ No newline at end of file