← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 12267: Add function to confifure default registration/enrolment forms

 

------------------------------------------------------------
revno: 12267
committer: Tran Chau <tran.hispvietnam@xxxxxxxxx>
branch nick: dhis2
timestamp: Fri 2013-09-27 11:43:25 +0700
message:
  Add function to confifure default registration/enrolment forms
added:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramPatientProperty.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramPatientPropertyService.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramPatientPropertyStore.java
  dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/DefaultProgramPatientPropertyService.java
  dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/hibernate/HibernateProgramPatientPropertyStore.java
  dhis-2/dhis-services/dhis-service-patient/src/main/resources/org/hisp/dhis/program/hibernate/ProgramPatientProperty.hbm.xml
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/Program.java
  dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/DefaultEventAnalyticsService.java
  dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcEventAnalyticsTableManager.java
  dhis-2/dhis-services/dhis-service-mobile/src/main/java/org/hisp/dhis/mobile/service/ActivityReportingServiceImpl.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/startup/TableAlteror.java
  dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/DefaultProgramInstanceService.java
  dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/ProgramDeletionHandler.java
  dhis-2/dhis-services/dhis-service-patient/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-services/dhis-service-patient/src/main/resources/org/hisp/dhis/program/hibernate/Program.hbm.xml
  dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/caseentry/GetDataRecordsAction.java
  dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/caseentry/ShowEventWithRegistrationFormAction.java
  dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/GetPatientAction.java
  dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/PatientDashboardAction.java
  dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/ProgramEnrollmentAction.java
  dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/SaveIdentifierAndAttributeAction.java
  dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/SearchPatientAction.java
  dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/ShowAddPatientFormAction.java
  dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/ShowAddRelationshipPatientAction.java
  dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/report/LoadDataElementsAction.java
  dhis-2/dhis-web/dhis-web-caseentry/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-web/dhis-web-caseentry/src/main/webapp/dhis-web-caseentry/dataentryRecords.vm
  dhis-2/dhis-web/dhis-web-caseentry/src/main/webapp/dhis-web-caseentry/defaultPatientForm.vm
  dhis-2/dhis-web/dhis-web-caseentry/src/main/webapp/dhis-web-caseentry/patientForm.vm
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/caseaggregation/GetParamsByProgramAction.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/dataentryform/ViewPatientRegistrationFormAction.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/program/AddProgramAction.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/program/ShowAddProgramFormAction.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/program/ShowUpdateProgramFormAction.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/program/UpdateProgramAction.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/resources/org/hisp/dhis/patient/i18n_module.properties
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/addProgramForm.vm
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/index.vm
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/javascript/program.js
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/menu.vm
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/programList.vm
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/updateProgramForm.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/program/Program.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/Program.java	2013-09-23 03:15:40 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/Program.java	2013-09-27 04:43:25 +0000
@@ -28,12 +28,10 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonView;
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
 
 import org.apache.commons.lang.StringUtils;
 import org.hisp.dhis.common.BaseIdentifiableObject;
@@ -44,17 +42,17 @@
 import org.hisp.dhis.organisationunit.OrganisationUnit;
 import org.hisp.dhis.organisationunit.OrganisationUnitGroup;
 import org.hisp.dhis.patient.Patient;
-import org.hisp.dhis.patient.PatientAttribute;
-import org.hisp.dhis.patient.PatientIdentifierType;
 import org.hisp.dhis.patient.PatientReminder;
 import org.hisp.dhis.relationship.RelationshipType;
 import org.hisp.dhis.user.UserAuthorityGroup;
 import org.hisp.dhis.validation.ValidationCriteria;
 
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonView;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
 
 /**
  * @author Abyot Asalefew
@@ -77,6 +75,14 @@
 
     public static final int SINGLE_EVENT_WITHOUT_REGISTRATION = 3;
 
+    public static final String SEPARATE_CHARACTOR = "_";
+
+    public static final String PREFIX_IDENTIFIER_TYPE = "iden";
+
+    public static final String PREFIX_ATTRIBUTE = "attr";
+    
+    public static final String PREFIX_PROPERTY = "prop";
+
     private String description;
 
     private Integer version;
@@ -107,10 +113,6 @@
 
     private Boolean ignoreOverdueEvents = false;
 
-    private List<PatientIdentifierType> patientIdentifierTypes;
-
-    private List<PatientAttribute> patientAttributes;
-
     private Set<UserAuthorityGroup> userRoles = new HashSet<UserAuthorityGroup>();
 
     private Boolean onlyEnrollOnce = false;
@@ -143,9 +145,11 @@
     private Boolean relationshipFromA;
 
     private Program relatedProgram;
-    
+
     private Boolean dataEntryMethod = false;
 
+    private Set<ProgramPatientProperty> programPatientProperties;
+
     // -------------------------------------------------------------------------
     // Constructors
     // -------------------------------------------------------------------------
@@ -367,36 +371,6 @@
         this.patientValidationCriteria = patientValidationCriteria;
     }
 
-    @JsonProperty( value = "identifierTypes" )
-    @JsonSerialize( contentAs = BaseIdentifiableObject.class )
-    @JsonView( { DetailedView.class, ExportView.class } )
-    @JacksonXmlElementWrapper( localName = "identifierTypes", namespace = DxfNamespaces.DXF_2_0 )
-    @JacksonXmlProperty( localName = "identifierType", namespace = DxfNamespaces.DXF_2_0 )
-    public List<PatientIdentifierType> getPatientIdentifierTypes()
-    {
-        return patientIdentifierTypes;
-    }
-
-    public void setPatientIdentifierTypes( List<PatientIdentifierType> patientIdentifierTypes )
-    {
-        this.patientIdentifierTypes = patientIdentifierTypes;
-    }
-
-    @JsonProperty( value = "attributes" )
-    @JsonSerialize( contentAs = BaseIdentifiableObject.class )
-    @JsonView( { DetailedView.class, ExportView.class } )
-    @JacksonXmlElementWrapper( localName = "attributes", namespace = DxfNamespaces.DXF_2_0 )
-    @JacksonXmlProperty( localName = "attribute", namespace = DxfNamespaces.DXF_2_0 )
-    public List<PatientAttribute> getPatientAttributes()
-    {
-        return patientAttributes;
-    }
-
-    public void setPatientAttributes( List<PatientAttribute> patientAttributes )
-    {
-        this.patientAttributes = patientAttributes;
-    }
-
     @JsonProperty
     @JsonView( { DetailedView.class, ExportView.class } )
     @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
@@ -633,4 +607,14 @@
         this.dataEntryMethod = dataEntryMethod;
     }
 
+    public Set<ProgramPatientProperty> getProgramPatientProperties()
+    {
+        return programPatientProperties;
+    }
+
+    public void setProgramPatientProperties( Set<ProgramPatientProperty> programPatientProperties )
+    {
+        this.programPatientProperties = programPatientProperties;
+    }
+
 }

=== added file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramPatientProperty.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramPatientProperty.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramPatientProperty.java	2013-09-27 04:43:25 +0000
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2004-2013, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright notice, this
+ *   list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the HISP project nor the names of its contributors may
+ *   be used to endorse or promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.hisp.dhis.program;
+
+import java.io.Serializable;
+
+import org.hisp.dhis.patient.PatientAttribute;
+import org.hisp.dhis.patient.PatientIdentifierType;
+
+/**
+ * @author Chau Thu Tran
+ * 
+ * @version $ ProgramPatientProperty.java Sep 20, 2013 10:39:33 AM $
+ */
+public class ProgramPatientProperty
+    implements Serializable
+{
+    private static final long serialVersionUID = 8089655298024075223L;
+
+    private int id;
+
+    private Program program;
+
+    private PatientIdentifierType patientIdentifierType;
+
+    private PatientAttribute patientAttribute;
+
+    private String propertyName;
+
+    private String defaultValue;
+
+    private boolean hidden;
+
+    private int sortOrder;
+
+    // -------------------------------------------------------------------------
+    // Constructors
+    // -------------------------------------------------------------------------
+
+    public ProgramPatientProperty()
+    {
+
+    }
+
+    public ProgramPatientProperty( Program program, String propertyName, String defaultValue, boolean hidden,
+        int sortOrder )
+    {
+        this.program = program;
+        this.propertyName = propertyName;
+        this.defaultValue = defaultValue;
+        this.hidden = hidden;
+    }
+
+    public ProgramPatientProperty( Program program, PatientIdentifierType patientIdentifierType, String defaultValue,
+        boolean hidden, int sortOrder )
+    {
+        this.program = program;
+        this.patientIdentifierType = patientIdentifierType;
+        this.defaultValue = defaultValue;
+        this.hidden = hidden;
+    }
+
+    public ProgramPatientProperty( Program prorgam, PatientAttribute patientAttribute, String defaultValue,
+        boolean hidden, int sortOrder )
+    {
+        this.program = prorgam;
+        this.patientAttribute = patientAttribute;
+        this.hidden = hidden;
+        this.defaultValue = defaultValue;
+    }
+
+    // -------------------------------------------------------------------------
+    // Logic
+    // -------------------------------------------------------------------------
+
+    @Override
+    public int hashCode()
+    {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((patientAttribute == null) ? 0 : patientAttribute.hashCode());
+        result = prime * result + ((patientIdentifierType == null) ? 0 : patientIdentifierType.hashCode());
+        result = prime * result + ((program == null) ? 0 : program.hashCode());
+        result = prime * result + ((propertyName == null) ? 0 : propertyName.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals( Object obj )
+    {
+        if ( this == obj )
+            return true;
+        if ( obj == null )
+            return false;
+        if ( getClass() != obj.getClass() )
+            return false;
+        ProgramPatientProperty other = (ProgramPatientProperty) obj;
+        if ( patientAttribute == null )
+        {
+            if ( other.patientAttribute != null )
+                return false;
+        }
+        else if ( !patientAttribute.equals( other.patientAttribute ) )
+            return false;
+        if ( patientIdentifierType == null )
+        {
+            if ( other.patientIdentifierType != null )
+                return false;
+        }
+        else if ( !patientIdentifierType.equals( other.patientIdentifierType ) )
+            return false;
+        if ( program == null )
+        {
+            if ( other.program != null )
+                return false;
+        }
+        else if ( !program.equals( other.program ) )
+            return false;
+        if ( propertyName == null )
+        {
+            if ( other.propertyName != null )
+                return false;
+        }
+        else if ( !propertyName.equals( other.propertyName ) )
+            return false;
+        return true;
+    }
+
+    // -------------------------------------------------------------------------
+    // Getters and setters
+    // -------------------------------------------------------------------------
+
+    public Program getProgram()
+    {
+        return program;
+    }
+
+    public void setProgram( Program program )
+    {
+        this.program = program;
+    }
+
+    public PatientAttribute getPatientAttribute()
+    {
+        return patientAttribute;
+    }
+
+    public void setPatientAttribute( PatientAttribute patientAttribute )
+    {
+        this.patientAttribute = patientAttribute;
+    }
+
+    public boolean isHidden()
+    {
+        return hidden;
+    }
+
+    public void setHidden( boolean hidden )
+    {
+        this.hidden = hidden;
+    }
+
+    public String getDefaultValue()
+    {
+        return defaultValue;
+    }
+
+    public void setDefaultValue( String defaultValue )
+    {
+        this.defaultValue = defaultValue;
+    }
+
+    public PatientIdentifierType getPatientIdentifierType()
+    {
+        return patientIdentifierType;
+    }
+
+    public void setPatientIdentifierType( PatientIdentifierType patientIdentifierType )
+    {
+        this.patientIdentifierType = patientIdentifierType;
+    }
+
+    public String getPropertyName()
+    {
+        return propertyName;
+    }
+
+    public void setPropertyName( String propertyName )
+    {
+        this.propertyName = propertyName;
+    }
+
+    public int getId()
+    {
+        return id;
+    }
+
+    public void setId( int id )
+    {
+        this.id = id;
+    }
+
+    public int getSortOrder()
+    {
+        return sortOrder;
+    }
+
+    public void setSortOrder( int sortOrder )
+    {
+        this.sortOrder = sortOrder;
+    }
+
+    public boolean isAttribute()
+    {
+        return (patientAttribute != null) ? true : false;
+    }
+
+    public boolean isIdentifierType()
+    {
+        return (patientIdentifierType != null) ? true : false;
+    }
+
+    public boolean isProperty()
+    {
+        return (propertyName != null) ? true : false;
+    }
+
+}

=== added file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramPatientPropertyService.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramPatientPropertyService.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramPatientPropertyService.java	2013-09-27 04:43:25 +0000
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2004-2013, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright notice, this
+ *   list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the HISP project nor the names of its contributors may
+ *   be used to endorse or promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.hisp.dhis.program;
+
+import java.util.Collection;
+
+import org.hisp.dhis.patient.PatientAttribute;
+import org.hisp.dhis.patient.PatientIdentifierType;
+
+/**
+ * @author Chau Thu Tran
+ * 
+ * @version $ ProgramPatientPropertyService.java Sep 26, 2013 4:18:09 PM $
+ */
+public interface ProgramPatientPropertyService
+{
+    String ID = ProgramStageInstanceService.class.getName();
+
+    void addProgramPatientProperty( ProgramPatientProperty programPatientProperty );
+
+    void updateProgramPatientProperty( ProgramPatientProperty programPatientProperty );
+
+    void deleteProgramPatientProperty( ProgramPatientProperty programPatientProperty );
+
+    // Patient-Identifiers
+
+    ProgramPatientProperty getProgramPatientProperty( Program program, PatientIdentifierType patientIdentifierType );
+
+    Collection<ProgramPatientProperty> getProgramPatientIdentifierTypes( Program program );
+
+    Collection<PatientIdentifierType> getPatientIdentifierTypes( Program program );
+
+    // Patient-Attributes
+
+    ProgramPatientProperty getProgramPatientProperty( Program program, PatientAttribute patientAttribute );
+
+    Collection<ProgramPatientProperty> getProgramPatientAttributes( Program program );
+
+    Collection<PatientAttribute> getPatientAttributes( Program program );
+
+    // Fixed-attributes
+
+    ProgramPatientProperty getProgramPatientProperty( Program program, String propertyName );
+
+    Collection<ProgramPatientProperty> getProgramPatientProperties( Program program );
+
+    Collection<String> getPatientProperties( Program program );
+
+}

=== added file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramPatientPropertyStore.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramPatientPropertyStore.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramPatientPropertyStore.java	2013-09-27 04:43:25 +0000
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2004-2013, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright notice, this
+ *   list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the HISP project nor the names of its contributors may
+ *   be used to endorse or promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.hisp.dhis.program;
+
+import java.util.Collection;
+
+import org.hisp.dhis.patient.PatientAttribute;
+import org.hisp.dhis.patient.PatientIdentifierType;
+
+/**
+ * @author Chau Thu Tran
+ * 
+ * @version $ ProgramPatientPropertyStore.java Sep 26, 2013 4:27:34 PM $
+ */
+public interface ProgramPatientPropertyStore
+{
+    String ID = ProgramPatientPropertyStore.class.getName();
+
+    void save( ProgramPatientProperty patientAttribute );
+
+    void update( ProgramPatientProperty patientAttribute );
+
+    void delete( ProgramPatientProperty patientAttribute );
+
+    ProgramPatientProperty get( Program program, PatientIdentifierType patientIdentifierType );
+    
+    ProgramPatientProperty get( Program program, PatientAttribute patientAttribute );
+    
+    
+    ProgramPatientProperty get( Program program, String propertyName );
+    
+    Collection<ProgramPatientProperty> getProgramPatientIdentifierTypes( Program program );
+    
+    Collection<ProgramPatientProperty> getProgramPatientAttributes( Program program );
+    
+    Collection<ProgramPatientProperty> getProgramPatientProperties( Program program );
+    
+    
+    Collection<PatientIdentifierType> getPatientIdentifierTypes( Program program );
+    
+    Collection<PatientAttribute> getPatientAttributes( Program program );
+    
+    Collection<String> getPatientProperties( Program program );
+}

=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/DefaultEventAnalyticsService.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/DefaultEventAnalyticsService.java	2013-09-25 09:18:11 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/DefaultEventAnalyticsService.java	2013-09-27 04:43:25 +0000
@@ -56,6 +56,7 @@
 import org.hisp.dhis.patient.PatientIdentifierType;
 import org.hisp.dhis.patient.PatientIdentifierTypeService;
 import org.hisp.dhis.program.Program;
+import org.hisp.dhis.program.ProgramPatientProperty;
 import org.hisp.dhis.program.ProgramService;
 import org.hisp.dhis.program.ProgramStage;
 import org.hisp.dhis.program.ProgramStageService;
@@ -70,31 +71,37 @@
     implements EventAnalyticsService
 {
     private static final String ITEM_EVENT = "psi";
+
     private static final String ITEM_PROGRAM_STAGE = "ps";
+
     private static final String ITEM_EXECUTION_DATE = "executiondate";
+
     private static final String ITEM_ORG_UNIT = "ou";
+
     private static final String ITEM_ORG_UNIT_NAME = "ouname";
+
     private static final String ITEM_GENDER = "gender";
+
     private static final String ITEM_ISDEAD = "isdead";
-    
+
     @Autowired
     private ProgramService programService;
-    
+
     @Autowired
     private ProgramStageService programStageService;
 
     @Autowired
     private DataElementService dataElementService;
-    
+
     @Autowired
     private PatientAttributeService attributeService;
 
     @Autowired
     private PatientIdentifierTypeService identifierTypeService;
-    
+
     @Autowired
     private OrganisationUnitService organisationUnitService;
-    
+
     @Autowired
     private EventAnalyticsManager analyticsManager;
 
@@ -102,12 +109,13 @@
     // EventAnalyticsService implementation
     // -------------------------------------------------------------------------
 
-    //TODO order the event analytics tables up front to avoid default sorting in queries
-    
+    // TODO order the event analytics tables up front to avoid default sorting
+    // in queries
+
     public Grid getEvents( EventQueryParams params )
     {
         Grid grid = new ListGrid();
-                
+
         grid.addHeader( new GridHeader( "Event", ITEM_EVENT ) );
         grid.addHeader( new GridHeader( "Program stage", ITEM_PROGRAM_STAGE ) );
         grid.addHeader( new GridHeader( "Execution date", ITEM_EXECUTION_DATE ) );
@@ -121,7 +129,7 @@
         for ( QueryItem queryItem : params.getItems() )
         {
             IdentifiableObject item = queryItem.getItem();
-            
+
             grid.addHeader( new GridHeader( item.getName(), item.getUid() ) );
         }
 
@@ -130,24 +138,24 @@
         // ---------------------------------------------------------------------
 
         List<EventQueryParams> queries = EventQueryPlanner.planQuery( params );
-        
+
         int count = 0;
-        
+
         for ( EventQueryParams query : queries )
         {
             if ( params.isPaging() )
             {
                 count += analyticsManager.getEventCount( query );
             }
-            
+
             analyticsManager.getEvents( query, grid );
         }
-        
+
         // ---------------------------------------------------------------------
         // Meta-data
         // ---------------------------------------------------------------------
 
-        Map<Object, Object> metaData = new HashMap<Object, Object>();        
+        Map<Object, Object> metaData = new HashMap<Object, Object>();
         metaData.put( AnalyticsService.NAMES_META_KEY, getUidNameMap( params ) );
 
         if ( params.isPaging() )
@@ -155,34 +163,34 @@
             Pager pager = new Pager( params.getPageWithDefault(), count, params.getPageSizeWithDefault() );
             metaData.put( AnalyticsService.PAGER_META_KEY, pager );
         }
-        
+
         grid.setMetaData( metaData );
-        
+
         return grid;
     }
-    
-    public EventQueryParams getFromUrl( String program, String stage, String startDate, String endDate, String ou, String ouMode,
-        Set<String> item, Set<String> asc, Set<String> desc, Integer page, Integer pageSize )
+
+    public EventQueryParams getFromUrl( String program, String stage, String startDate, String endDate, String ou,
+        String ouMode, Set<String> item, Set<String> asc, Set<String> desc, Integer page, Integer pageSize )
     {
         EventQueryParams params = new EventQueryParams();
-        
+
         Program pr = programService.getProgram( program );
-        
+
         if ( pr == null )
         {
             throw new IllegalQueryException( "Program does not exist: " + program );
         }
-        
+
         ProgramStage ps = programStageService.getProgramStage( stage );
-        
+
         if ( stage != null && !stage.isEmpty() && ps == null )
         {
             throw new IllegalQueryException( "Program stage is specified but does not exist: " + stage );
         }
-        
+
         Date start = null;
         Date end = null;
-        
+
         try
         {
             start = DateUtils.getMediumDate( startDate );
@@ -192,17 +200,17 @@
         {
             throw new IllegalQueryException( "Start date or end date is invalid: " + startDate + " - " + endDate );
         }
-        
+
         if ( start == null || end == null )
         {
             throw new IllegalQueryException( "Start date or end date is invalid: " + startDate + " - " + endDate );
         }
-        
+
         if ( start.after( end ) )
         {
             throw new IllegalQueryException( "Start date is after end date: " + startDate + " - " + endDate );
         }
-        
+
         if ( item != null )
         {
             for ( String it : item )
@@ -214,17 +222,17 @@
                 else if ( it != null ) // Filter
                 {
                     String[] split = it.split( OPTION_SEP );
-                    
+
                     if ( split == null || split.length != 3 )
                     {
                         throw new IllegalQueryException( "Item filter has invalid format: " + it );
                     }
-                    
+
                     params.getItems().add( new QueryItem( getItem( split[0], pr ), split[1], split[2] ) );
                 }
             }
         }
-        
+
         if ( asc != null )
         {
             for ( String sort : asc )
@@ -240,118 +248,129 @@
                 params.getDesc().add( getSortItem( sort, pr ) );
             }
         }
-        
+
         if ( ou != null )
         {
             String[] split = ou.split( OPTION_SEP );
-            
+
             for ( String ouId : split )
             {
                 OrganisationUnit orgUnit = organisationUnitService.getOrganisationUnit( ouId );
-                
+
                 if ( orgUnit != null )
                 {
                     orgUnit.setLevel( organisationUnitService.getLevelOfOrganisationUnit( orgUnit.getId() ) );
-                    
+
                     params.getOrganisationUnits().add( orgUnit );
                 }
             }
         }
-        
+
         if ( params.getOrganisationUnits().isEmpty() )
         {
             throw new IllegalQueryException( "At least one organisation unit must be specified" );
         }
-        
+
         if ( page != null && page <= 0 )
         {
             throw new IllegalQueryException( "Page number must be positive: " + page );
         }
-        
+
         if ( pageSize != null && pageSize < 0 )
         {
             throw new IllegalQueryException( "Page size must be zero or positive: " + pageSize );
         }
-        
+
         params.setProgram( pr );
         params.setProgramStage( ps );
         params.setStartDate( start );
         params.setEndDate( end );
         params.setOrganisationUnitMode( ouMode );
         params.setPage( page );
-        
+
         if ( pageSize != null )
         {
             params.setPageSize( pageSize );
         }
-        
+
         return params;
     }
 
     // -------------------------------------------------------------------------
     // Supportive methods
     // -------------------------------------------------------------------------
-    
+
     private Map<String, String> getUidNameMap( EventQueryParams params )
     {
         Map<String, String> map = new HashMap<String, String>();
-        
+
         Program program = params.getProgram();
         ProgramStage stage = params.getProgramStage();
-        
+
         map.put( program.getUid(), program.getName() );
-        
+
         if ( stage != null )
         {
             map.put( stage.getUid(), stage.getName() );
         }
-        
+
         return map;
     }
-    
+
     private String getSortItem( String item, Program program )
     {
         if ( !ITEM_EXECUTION_DATE.equals( item ) && getItem( item, program ) == null )
         {
             throw new IllegalQueryException( "Descending sort item is invalid: " + item );
         }
-        
+
         return item;
     }
-    
+
     private IdentifiableObject getItem( String item, Program program )
     {
         if ( ITEM_GENDER.equalsIgnoreCase( item ) )
         {
             return new BaseIdentifiableObject( ITEM_GENDER, ITEM_GENDER, ITEM_GENDER );
         }
-        
+
         if ( ITEM_ISDEAD.equalsIgnoreCase( item ) )
         {
             return new BaseIdentifiableObject( ITEM_ISDEAD, ITEM_ISDEAD, ITEM_ISDEAD );
         }
-        
+
         DataElement de = dataElementService.getDataElement( item );
-        
+
         if ( de != null && program.getAllDataElements().contains( de ) )
         {
             return de;
         }
-        
+
         PatientAttribute at = attributeService.getPatientAttribute( item );
-        
-        if ( at != null && program.getPatientAttributes().contains( at ) )
+
+        if ( at != null )
         {
-            return at;
+            for ( ProgramPatientProperty programPatientProperty : program.getProgramPatientProperties() )
+            {
+                if ( programPatientProperty.isIdentifierType()
+                    && at.equals( programPatientProperty.getPatientAttribute() ) )
+                {
+                    return at;
+                }
+            }
         }
-        
+
         PatientIdentifierType it = identifierTypeService.getPatientIdentifierType( item );
-        
-        if ( it != null && program.getPatientIdentifierTypes().contains( it ) )
+
+        if ( it != null )
         {
-            return it;
+            for ( ProgramPatientProperty programPatientProperty : program.getProgramPatientProperties() )
+            {
+                if ( programPatientProperty.isAttribute() && at.equals( programPatientProperty.getPatientIdentifierType() ) )
+                    return at;
+            }
         }
-        
-        throw new IllegalQueryException( "Item identifier does not reference any item part of the program: " + item );           
+
+        throw new IllegalQueryException( "Item identifier does not reference any item part of the program: " + item );
     }
 }

=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcEventAnalyticsTableManager.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcEventAnalyticsTableManager.java	2013-09-24 09:29:24 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcEventAnalyticsTableManager.java	2013-09-27 04:43:25 +0000
@@ -44,6 +44,7 @@
 import org.hisp.dhis.period.Period;
 import org.hisp.dhis.period.PeriodType;
 import org.hisp.dhis.program.Program;
+import org.hisp.dhis.program.ProgramPatientProperty;
 import org.hisp.dhis.program.ProgramService;
 import org.hisp.dhis.system.util.DateUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -60,80 +61,80 @@
 {
     @Autowired
     private ProgramService programService;
-        
+
     // -------------------------------------------------------------------------
     // Implementation
     // -------------------------------------------------------------------------
-    
+
     @Override
     @Transactional
     public List<AnalyticsTable> getTables( Date earliest, Date latest )
     {
         String baseName = getTableName();
-        
+
         List<Period> periods = PartitionUtils.getPeriods( earliest, latest );
 
         List<AnalyticsTable> tables = new ArrayList<AnalyticsTable>();
-        
+
         for ( Period period : periods )
         {
             for ( Program program : programService.getAllPrograms() )
             {
                 AnalyticsTable table = new AnalyticsTable( baseName, null, period, program );
                 List<String[]> dimensionColumns = getDimensionColumns( table );
-                table.setDimensionColumns( dimensionColumns );                
+                table.setDimensionColumns( dimensionColumns );
                 tables.add( table );
             }
         }
-        
+
         return tables;
-    }    
-    
+    }
+
     public boolean validState()
     {
         return jdbcTemplate.queryForRowSet( "select dataelementid from patientdatavalue limit 1" ).next();
     }
-    
+
     public String getTableName()
     {
         return "analytics_event";
     }
-    
+
     public void createTable( AnalyticsTable table )
     {
         final String tableName = table.getTempTableName();
-        
+
         final String sqlDrop = "drop table " + tableName;
-        
+
         executeSilently( sqlDrop );
-        
+
         String sqlCreate = "create table " + tableName + " (";
-        
+
         for ( String[] col : getDimensionColumns( table ) )
         {
             sqlCreate += col[0] + " " + col[1] + ",";
         }
-        
+
         sqlCreate = removeLast( sqlCreate, 1 ) + ")";
-        
+
         log.info( "Create SQL: " + sqlCreate );
-        
+
         executeSilently( sqlCreate );
     }
-    
+
     @Async
     @Override
     public Future<?> populateTableAsync( ConcurrentLinkedQueue<AnalyticsTable> tables )
     {
-        taskLoop : while ( true )
+        taskLoop: while ( true )
         {
             AnalyticsTable table = tables.poll();
-                
+
             if ( table == null )
             {
                 break taskLoop;
             }
-            
+
             final String start = DateUtils.getMediumDateString( table.getPeriod().getStartDate() );
             final String end = DateUtils.getMediumDateString( table.getPeriod().getEndDate() );
 
@@ -143,44 +144,41 @@
             {
                 sql += col[0] + ",";
             }
-            
+
             sql = removeLast( sql, 1 ) + ") select ";
 
             for ( String[] col : getDimensionColumns( table ) )
             {
                 sql += col[2] + ",";
             }
-            
+
             sql = removeLast( sql, 1 ) + " ";
-            
-            sql += 
-                "from programstageinstance psi " +
-                "left join programinstance pi on psi.programinstanceid=pi.programinstanceid " +
-                "left join programstage ps on psi.programstageid=ps.programstageid " +
-                "left join program pr on pi.programid=pr.programid " +
-                "left join patient pa on pi.patientid=pa.patientid " +
-                "left join organisationunit ou on psi.organisationunitid=ou.organisationunitid " +
-                "left join _orgunitstructure ous on psi.organisationunitid=ous.organisationunitid " +
-                "left join _dateperiodstructure dps on psi.executiondate=dps.dateperiod " +
-                "where psi.executiondate >= '" + start + "' " +
-                "and psi.executiondate <= '" + end + "' " +
-                "and pr.programid=" + table.getProgram().getId() + ";";
-
-            log.info( "Populate SQL: "+ sql );
-            
+
+            sql += "from programstageinstance psi "
+                + "left join programinstance pi on psi.programinstanceid=pi.programinstanceid "
+                + "left join programstage ps on psi.programstageid=ps.programstageid "
+                + "left join program pr on pi.programid=pr.programid "
+                + "left join patient pa on pi.patientid=pa.patientid "
+                + "left join organisationunit ou on psi.organisationunitid=ou.organisationunitid "
+                + "left join _orgunitstructure ous on psi.organisationunitid=ous.organisationunitid "
+                + "left join _dateperiodstructure dps on psi.executiondate=dps.dateperiod "
+                + "where psi.executiondate >= '" + start + "' " + "and psi.executiondate <= '" + end + "' "
+                + "and pr.programid=" + table.getProgram().getId() + ";";
+
+            log.info( "Populate SQL: " + sql );
+
             jdbcTemplate.execute( sql );
         }
-    
+
         return null;
     }
-    
+
     public List<String[]> getDimensionColumns( AnalyticsTable table )
     {
         List<String[]> columns = new ArrayList<String[]>();
 
-        Collection<OrganisationUnitLevel> levels =
-            organisationUnitService.getOrganisationUnitLevels();
-        
+        Collection<OrganisationUnitLevel> levels = organisationUnitService.getOrganisationUnitLevels();
+
         for ( OrganisationUnitLevel level : levels )
         {
             String column = PREFIX_ORGUNITLEVEL + level.getLevel();
@@ -189,70 +187,76 @@
         }
 
         List<PeriodType> periodTypes = PeriodType.getAvailablePeriodTypes();
-        
+
         for ( PeriodType periodType : periodTypes )
         {
             String column = periodType.getName().toLowerCase();
             String[] col = { column, "character varying(10)", "dps." + column };
             columns.add( col );
         }
-        
+
         for ( DataElement dataElement : table.getProgram().getAllDataElements() )
         {
-            String select = "(select value from patientdatavalue where programstageinstanceid=" +
-                "psi.programstageinstanceid and dataelementid=" + dataElement.getId() + ") as " + dataElement.getUid();
-            
+            String select = "(select value from patientdatavalue where programstageinstanceid="
+                + "psi.programstageinstanceid and dataelementid=" + dataElement.getId() + ") as "
+                + dataElement.getUid();
+
             String[] col = { dataElement.getUid(), "character varying(255)", select };
             columns.add( col );
         }
-        
-        for ( PatientAttribute attribute : table.getProgram().getPatientAttributes() )
-        {
-            String select = "(select value from patientattributevalue where patientid=pi.patientid and " +
-                "patientattributeid=" + attribute.getId() + ") as " + attribute.getUid();
-            
-            String[] col = { attribute.getUid(), "character varying(255)", select };
-            columns.add( col );
-        }
-        
-        for ( PatientIdentifierType identifierType : table.getProgram().getPatientIdentifierTypes() )
-        {
-            String select = "(select identifier from patientidentifier where patientid=pi.patientid and " +
-                "patientidentifiertypeid=" + identifierType.getId() + ") as " + identifierType.getUid();
-            
-            String[] col = { identifierType.getUid() + "character varying(31)", select };
-            columns.add( col );
+
+        for ( ProgramPatientProperty programPatientProperty : table.getProgram().getProgramPatientProperties() )
+        {
+            if ( programPatientProperty.isAttribute() )
+            {
+                PatientAttribute attribute = programPatientProperty.getPatientAttribute();
+                String select = "(select value from patientattributevalue where patientid=pi.patientid and "
+                    + "patientattributeid=" + attribute.getId() + ") as " + attribute.getUid();
+
+                String[] col = { attribute.getUid(), "character varying(255)", select };
+                columns.add( col );
+            }
+            if( programPatientProperty.isIdentifierType())
+            {
+                PatientIdentifierType identifierType = programPatientProperty.getPatientIdentifierType();
+                String select = "(select identifier from patientidentifier where patientid=pi.patientid and "
+                    + "patientidentifiertypeid=" + identifierType.getId() + ") as " + identifierType.getUid();
+
+                String[] col = { identifierType.getUid() + "character varying(31)", select };
+                columns.add( col );
+            }
         }
         
         String[] gender = { "gender", "character varying(5)", "pa.gender" };
-        String[] isdead = { "isdead", "boolean", "pa.isdead" };            
+        String[] isdead = { "isdead", "boolean", "pa.isdead" };
         String[] psi = { "psi", "character(11) not null", "psi.uid" };
         String[] ps = { "ps", "character(11) not null", "ps.uid" };
         String[] ed = { "executiondate", "date", "psi.executiondate" };
         String[] ou = { "ou", "character(11) not null", "ou.uid" };
         String[] oun = { "ouname", "character varying(160) not null", "ou.name" };
-        
+
         columns.addAll( Arrays.asList( gender, isdead, psi, ps, ed, ou, oun ) );
-        
+
         return columns;
     }
-    
+
     public Date getEarliestData()
     {
         final String sql = "select min(pdv.timestamp) from patientdatavalue pdv";
-        
+
         return jdbcTemplate.queryForObject( sql, Date.class );
     }
 
     public Date getLatestData()
     {
         final String sql = "select max(pdv.timestamp) from patientdatavalue pdv";
-        
+
         return jdbcTemplate.queryForObject( sql, Date.class );
     }
-    
+
     @Async
-    public Future<?> applyAggregationLevels( ConcurrentLinkedQueue<AnalyticsTable> tables, Collection<String> dataElements, int aggregationLevel )
+    public Future<?> applyAggregationLevels( ConcurrentLinkedQueue<AnalyticsTable> tables,
+        Collection<String> dataElements, int aggregationLevel )
     {
         return null; // Not relevant
     }

=== modified file 'dhis-2/dhis-services/dhis-service-mobile/src/main/java/org/hisp/dhis/mobile/service/ActivityReportingServiceImpl.java'
--- dhis-2/dhis-services/dhis-service-mobile/src/main/java/org/hisp/dhis/mobile/service/ActivityReportingServiceImpl.java	2013-09-24 04:07:07 +0000
+++ dhis-2/dhis-services/dhis-service-mobile/src/main/java/org/hisp/dhis/mobile/service/ActivityReportingServiceImpl.java	2013-09-27 04:43:25 +0000
@@ -77,6 +77,7 @@
 import org.hisp.dhis.program.Program;
 import org.hisp.dhis.program.ProgramInstance;
 import org.hisp.dhis.program.ProgramInstanceService;
+import org.hisp.dhis.program.ProgramPatientProperty;
 import org.hisp.dhis.program.ProgramService;
 import org.hisp.dhis.program.ProgramStage;
 import org.hisp.dhis.program.ProgramStageDataElement;
@@ -1664,7 +1665,13 @@
         Collection<Program> programs = programService.getAllPrograms();
         for ( Program program : programs )
         {
-            patientIdentifierTypes.removeAll( program.getPatientIdentifierTypes() );
+            for ( ProgramPatientProperty programPatientProperty : program.getProgramPatientProperties() )
+            {
+                if ( programPatientProperty.isIdentifierType() )
+                {
+                    patientIdentifierTypes.remove( programPatientProperty.getPatientIdentifierType() );
+                }
+            }
         }
         return patientIdentifierTypes;
     }
@@ -1674,7 +1681,13 @@
         if ( programId != null && !programId.trim().equals( "" ) )
         {
             Program program = programService.getProgram( Integer.parseInt( programId ) );
-            patientAttributes = program.getPatientAttributes();
+            for ( ProgramPatientProperty programPatientProperty : program.getProgramPatientProperties() )
+            {
+                if ( programPatientProperty.isAttribute() )
+                {
+                    patientAttributes.add( programPatientProperty.getPatientAttribute() );
+                }
+            }
         }
         else
         {
@@ -1689,7 +1702,13 @@
         if ( programId != null && !programId.trim().equals( "" ) )
         {
             Program program = programService.getProgram( Integer.parseInt( programId ) );
-            patientIdentifierTypes = program.getPatientIdentifierTypes();
+            for ( ProgramPatientProperty programPatientProperty : program.getProgramPatientProperties() )
+            {
+                if ( programPatientProperty.isIdentifierType() )
+                {
+                    patientIdentifierTypes.add( programPatientProperty.getPatientIdentifierType() );
+                }
+            }
         }
         else
         {

=== 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	2013-09-23 08:00:15 +0000
+++ dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patient/DefaultPatientService.java	2013-09-27 04:43:25 +0000
@@ -28,6 +28,14 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
 import org.apache.commons.lang.StringUtils;
 import org.hisp.dhis.common.Grid;
 import org.hisp.dhis.common.GridHeader;
@@ -37,6 +45,7 @@
 import org.hisp.dhis.patientattributevalue.PatientAttributeValue;
 import org.hisp.dhis.patientattributevalue.PatientAttributeValueService;
 import org.hisp.dhis.program.Program;
+import org.hisp.dhis.program.ProgramPatientProperty;
 import org.hisp.dhis.relationship.Relationship;
 import org.hisp.dhis.relationship.RelationshipService;
 import org.hisp.dhis.relationship.RelationshipType;
@@ -44,14 +53,6 @@
 import org.hisp.dhis.system.grid.ListGrid;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
 /**
  * @author Abyot Asalefew Gizaw
  * @version $Id$
@@ -260,7 +261,7 @@
     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( patientIdentifierService.getPatientsByIdentifier( searchText, 0, Integer.MAX_VALUE ) );
         patients.addAll( getPatientsByNames( searchText, null, null ) );
         patients.addAll( getPatientsByPhone( searchText, null, null ) );
 
@@ -671,10 +672,15 @@
         grid.addHeader( new GridHeader( i18n.getString( "gender" ), true, true ) );
         grid.addHeader( new GridHeader( i18n.getString( "phone_number" ), false, true ) );
 
-        Collection<PatientIdentifierType> patientIdentifierTypes = program.getPatientIdentifierTypes();
-        for ( PatientIdentifierType patientIdentifierType : patientIdentifierTypes )
+        Collection<ProgramPatientProperty> programPatientIdentifierTypes = program.getProgramPatientProperties();
+        Collection<PatientIdentifierType> patientIdentifierTypes = new HashSet<PatientIdentifierType>();
+        for ( ProgramPatientProperty programPatientIdentifierType : programPatientIdentifierTypes )
         {
-            grid.addHeader( new GridHeader( patientIdentifierType.getDisplayName(), false, true ) );
+            if ( programPatientIdentifierType.isIdentifierType() )
+            {
+                grid.addHeader( new GridHeader( programPatientIdentifierType.getPatientIdentifierType()
+                    .getDisplayName(), false, true ) );
+            }
         }
         grid.addHeader( new GridHeader( "programstageinstanceid", true, true ) );
         grid.addHeader( new GridHeader( i18n.getString( "program_stage" ), false, true ) );
@@ -683,7 +689,6 @@
 
         return patientStore.getPatientEventReport( grid, searchKeys, orgunits, followup, null, patientIdentifierTypes,
             null, null );
-
     }
 
     @Override

=== modified file 'dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patient/startup/TableAlteror.java'
--- dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patient/startup/TableAlteror.java	2013-09-23 04:29:22 +0000
+++ dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patient/startup/TableAlteror.java	2013-09-27 04:43:25 +0000
@@ -382,6 +382,11 @@
         executeSql( "ALTER TABLE programinstance DROP COLUMN completed" );
     }
 
+    private void updateProgramPatientProperties()
+    {
+        
+    }
+    
     private int executeSql( String sql )
     {
         try

=== modified file 'dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/DefaultProgramInstanceService.java'
--- dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/DefaultProgramInstanceService.java	2013-09-23 12:07:14 +0000
+++ dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/DefaultProgramInstanceService.java	2013-09-27 04:43:25 +0000
@@ -338,13 +338,17 @@
 
         for ( Program program : programs )
         {
-            Collection<PatientAttribute> atttributes = program.getPatientAttributes();
+            Collection<ProgramPatientProperty> programAtttributes = program.getProgramPatientProperties();
             while ( iterAttribute.hasNext() )
             {
                 PatientAttributeValue attributeValue = iterAttribute.next();
-                if ( !atttributes.contains( attributeValue.getPatientAttribute() ) )
+                for ( ProgramPatientProperty programAtttribute : programAtttributes )
                 {
-                    iterAttribute.remove();
+                    if ( programAtttribute.isAttribute()
+                        && !programAtttribute.getPatientAttribute().equals( attributeValue.getPatientAttribute() ) )
+                    {
+                        iterAttribute.remove();
+                    }
                 }
             }
         }
@@ -371,13 +375,17 @@
 
         for ( Program program : programs )
         {
-            Collection<PatientIdentifierType> identifierTypes = program.getPatientIdentifierTypes();
+            Collection<ProgramPatientProperty> identifierTypes = program.getProgramPatientProperties();
             while ( iterIdentifier.hasNext() )
             {
-                PatientIdentifier identifier = iterIdentifier.next();
-                if ( !identifierTypes.contains( identifier.getIdentifierType() ) )
+                for ( ProgramPatientProperty identifierType : identifierTypes )
                 {
-                    iterIdentifier.remove();
+                    if ( identifierType.isIdentifierType()
+                        && !identifierType.getPatientIdentifierType()
+                            .equals( iterIdentifier.next().getIdentifierType() ) )
+                    {
+                        iterIdentifier.remove();
+                    }
                 }
             }
         }
@@ -452,28 +460,33 @@
 
         Patient patient = programInstance.getPatient();
 
-        Collection<PatientIdentifierType> identifierTypes = programInstance.getProgram().getPatientIdentifierTypes();
+        Collection<ProgramPatientProperty> programPatientProperties = programInstance.getProgram()
+            .getProgramPatientProperties();
 
         Collection<PatientIdentifier> identifiers = patient.getIdentifiers();
 
-        if ( identifierTypes != null && identifiers.size() > 0 )
+        if ( programPatientProperties != null && programPatientProperties.size() > 0 )
         {
-            for ( PatientIdentifierType identifierType : identifierTypes )
+            for ( ProgramPatientProperty programIdentifierType : programPatientProperties )
             {
-                for ( PatientIdentifier identifier : identifiers )
+                if ( programIdentifierType.isIdentifierType() )
                 {
-                    if ( identifier.getIdentifierType() != null
-                        && identifier.getIdentifierType().equals( identifierType ) )
-                    {
-                        grid.addRow();
-                        grid.addValue( identifierType.getDisplayName() );
-                        grid.addValue( identifier.getIdentifier() );
-                    }
-                    else if ( identifier.getIdentifierType() == null )
-                    {
-                        grid.addRow();
-                        grid.addValue( i18n.getString( "system_identifier" ) );
-                        grid.addValue( identifier.getIdentifier() );
+                    for ( PatientIdentifier identifier : identifiers )
+                    {
+
+                        if ( identifier.getIdentifierType() != null
+                            && identifier.getIdentifierType().equals( programIdentifierType.getPatientIdentifierType() ) )
+                        {
+                            grid.addRow();
+                            grid.addValue( programIdentifierType.getPatientIdentifierType().getDisplayName() );
+                            grid.addValue( identifier.getIdentifier() );
+                        }
+                        else if ( identifier.getIdentifierType() == null )
+                        {
+                            grid.addRow();
+                            grid.addValue( i18n.getString( "system_identifier" ) );
+                            grid.addValue( identifier.getIdentifier() );
+                        }
                     }
                 }
             }
@@ -481,16 +494,18 @@
 
         // Get patient-attribute-values which belong to the program
 
-        Collection<PatientAttribute> attrtibutes = programInstance.getProgram().getPatientAttributes();
-        for ( PatientAttribute attrtibute : attrtibutes )
+        for ( ProgramPatientProperty programAttrtibute : programPatientProperties )
         {
-            PatientAttributeValue attributeValue = patientAttributeValueService.getPatientAttributeValue( patient,
-                attrtibute );
-            if ( attributeValue != null )
+            if ( programAttrtibute.isAttribute() )
             {
-                grid.addRow();
-                grid.addValue( attrtibute.getDisplayName() );
-                grid.addValue( attributeValue.getValue() );
+                PatientAttributeValue attributeValue = patientAttributeValueService.getPatientAttributeValue( patient,
+                    programAttrtibute.getPatientAttribute() );
+                if ( attributeValue != null )
+                {
+                    grid.addRow();
+                    grid.addValue( programAttrtibute.getPatientAttribute().getDisplayName() );
+                    grid.addValue( attributeValue.getValue() );
+                }
             }
         }
 

=== added file 'dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/DefaultProgramPatientPropertyService.java'
--- dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/DefaultProgramPatientPropertyService.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/DefaultProgramPatientPropertyService.java	2013-09-27 04:43:25 +0000
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2004-2013, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright notice, this
+ *   list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the HISP project nor the names of its contributors may
+ *   be used to endorse or promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.hisp.dhis.program;
+
+import java.util.Collection;
+
+import org.hisp.dhis.patient.PatientAttribute;
+import org.hisp.dhis.patient.PatientIdentifierType;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * @author Chau Thu Tran
+ * 
+ * @version $ DefaultProgramPatientPropertyService.java Sep 26, 2013 4:30:49 PM
+ *          $
+ */
+@Transactional
+public class DefaultProgramPatientPropertyService
+    implements ProgramPatientPropertyService
+{
+    // -------------------------------------------------------------------------
+    // Dependencies
+    // -------------------------------------------------------------------------
+
+    private ProgramPatientPropertyStore programPatientPropertyStore;
+
+    public void setProgramPatientPropertyStore( ProgramPatientPropertyStore programPatientPropertyStore )
+    {
+        this.programPatientPropertyStore = programPatientPropertyStore;
+    }
+
+    // -------------------------------------------------------------------------
+    // Implementation methods
+    // -------------------------------------------------------------------------
+
+    @Override
+    public void addProgramPatientProperty( ProgramPatientProperty programPatientProperty )
+    {
+        programPatientPropertyStore.save( programPatientProperty );
+    }
+
+    @Override
+    public void deleteProgramPatientProperty( ProgramPatientProperty programPatientProperty )
+    {
+        programPatientPropertyStore.delete( programPatientProperty );
+    }
+
+    @Override
+    public void updateProgramPatientProperty( ProgramPatientProperty programPatientProperty )
+    {
+        programPatientPropertyStore.update( programPatientProperty );
+    }
+
+    @Override
+    public ProgramPatientProperty getProgramPatientProperty( Program program,
+        PatientIdentifierType patientIdentifierType )
+    {
+        return programPatientPropertyStore.get( program, patientIdentifierType );
+    }
+
+    @Override
+    public Collection<ProgramPatientProperty> getProgramPatientIdentifierTypes( Program program )
+    {
+        return programPatientPropertyStore.getProgramPatientIdentifierTypes( program );
+    }
+
+    @Override
+    public Collection<PatientIdentifierType> getPatientIdentifierTypes( Program program )
+    {
+        return programPatientPropertyStore.getPatientIdentifierTypes( program );
+    }
+
+    @Override
+    public ProgramPatientProperty getProgramPatientProperty( Program program, PatientAttribute patientAttribute )
+    {
+        return programPatientPropertyStore.get( program, patientAttribute );
+    }
+
+    @Override
+    public Collection<PatientAttribute> getPatientAttributes( Program program )
+    {
+        return programPatientPropertyStore.getPatientAttributes( program );
+    }
+
+    @Override
+    public ProgramPatientProperty getProgramPatientProperty( Program program, String propertyName )
+    {
+        return programPatientPropertyStore.get( program, propertyName );
+    }
+
+    @Override
+    public Collection<ProgramPatientProperty> getProgramPatientProperties( Program program )
+    {
+        return programPatientPropertyStore.getProgramPatientProperties( program );
+    }
+
+    @Override
+    public Collection<String> getPatientProperties( Program program )
+    {
+        return programPatientPropertyStore.getPatientProperties( program );
+    }
+
+    @Override
+    public Collection<ProgramPatientProperty> getProgramPatientAttributes( Program program )
+    {
+        return programPatientPropertyStore.getProgramPatientAttributes( program );
+    }
+
+}

=== modified file 'dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/ProgramDeletionHandler.java'
--- dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/ProgramDeletionHandler.java	2013-08-23 16:05:01 +0000
+++ dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/ProgramDeletionHandler.java	2013-09-27 04:43:25 +0000
@@ -75,7 +75,7 @@
             programService.updateProgram( program );
         }
     }
-    
+
     @Override
     public void deletePatientIdentifierType( PatientIdentifierType patientIdentifierType )
     {
@@ -83,11 +83,18 @@
 
         for ( Program program : programs )
         {
-            program.getPatientIdentifierTypes().clear();
-            programService.updateProgram( program );
+            for ( ProgramPatientProperty programPatientIdentifierType : program
+                .getProgramPatientProperties() )
+            {
+                if ( programPatientIdentifierType.getPatientIdentifierType().equals( patientIdentifierType ) )
+                {
+                    program.getProgramPatientProperties().remove( programPatientIdentifierType );
+                    programService.updateProgram( program );
+                }
+            }
         }
     }
-    
+
     @Override
     public void deletePatientAttribute( PatientAttribute patientAttribute )
     {
@@ -95,18 +102,25 @@
 
         for ( Program program : programs )
         {
-            program.getPatientAttributes().clear();
-            programService.updateProgram( program );
+            for ( ProgramPatientProperty programPatientAttribute : program
+                .getProgramPatientProperties())
+            {
+                if ( programPatientAttribute.getPatientAttribute().equals( patientAttribute ) )
+                {
+                    program.getProgramPatientProperties().remove( programPatientAttribute );
+                    programService.updateProgram( program );
+                }
+            }
         }
     }
-    
+
     @Override
     public void deleteOrganisationUnit( OrganisationUnit unit )
     {
-        //TODO improve performance
-        
+        // TODO improve performance
+
         Collection<Program> programs = programService.getAllPrograms();
-        
+
         for ( Program program : programs )
         {
             if ( program.getOrganisationUnits().remove( unit ) )

=== added file 'dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/hibernate/HibernateProgramPatientPropertyStore.java'
--- dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/hibernate/HibernateProgramPatientPropertyStore.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/hibernate/HibernateProgramPatientPropertyStore.java	2013-09-27 04:43:25 +0000
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2004-2013, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright notice, this
+ *   list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the HISP project nor the names of its contributors may
+ *   be used to endorse or promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.hisp.dhis.program.hibernate;
+
+import java.util.Collection;
+
+import org.hibernate.Criteria;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.criterion.Projections;
+import org.hibernate.criterion.Restrictions;
+import org.hisp.dhis.patient.PatientAttribute;
+import org.hisp.dhis.patient.PatientIdentifierType;
+import org.hisp.dhis.program.Program;
+import org.hisp.dhis.program.ProgramPatientProperty;
+import org.hisp.dhis.program.ProgramPatientPropertyStore;
+
+/**
+ * @author Chau Thu Tran
+ * 
+ * @version $ HibernateProgramPatientPropertyStore.java Sep 26, 2013 16:51:42 PM
+ *          $
+ */
+public class HibernateProgramPatientPropertyStore
+    implements ProgramPatientPropertyStore
+{
+    // -------------------------------------------------------------------------
+    // Dependencies
+    // -------------------------------------------------------------------------
+
+    private SessionFactory sessionFactory;
+
+    public void setSessionFactory( SessionFactory sessionFactory )
+    {
+        this.sessionFactory = sessionFactory;
+    }
+
+    // -------------------------------------------------------------------------
+    // Basic ProgramPatientAttribute
+    // -------------------------------------------------------------------------
+
+    @Override
+    public void save( ProgramPatientProperty programPatientAttribute )
+    {
+        Session session = sessionFactory.getCurrentSession();
+
+        session.save( programPatientAttribute );
+    }
+
+    @Override
+    public void update( ProgramPatientProperty programPatientAttribute )
+    {
+        Session session = sessionFactory.getCurrentSession();
+
+        session.update( programPatientAttribute );
+    }
+
+    @Override
+    public void delete( ProgramPatientProperty programPatientAttribute )
+    {
+        Session session = sessionFactory.getCurrentSession();
+
+        session.delete( programPatientAttribute );
+    }
+
+    @Override
+    public ProgramPatientProperty get( Program program, PatientAttribute patientAttribute )
+    {
+        Session session = sessionFactory.getCurrentSession();
+
+        Criteria criteria = session.createCriteria( ProgramPatientProperty.class );
+        criteria.add( Restrictions.eq( "program", program ) );
+        criteria.add( Restrictions.isNotNull( "patientAttribute" ) );
+        criteria.add( Restrictions.eq( "patientAttribute", patientAttribute ) );
+
+        return (ProgramPatientProperty) criteria.uniqueResult();
+    }
+
+    @Override
+    public ProgramPatientProperty get( Program program, PatientIdentifierType patientIdentifierType )
+    {
+        Session session = sessionFactory.getCurrentSession();
+
+        Criteria criteria = session.createCriteria( ProgramPatientProperty.class );
+        criteria.add( Restrictions.eq( "program", program ) );
+        criteria.add( Restrictions.isNotNull( "patientIdentifierType" ) );
+        criteria.add( Restrictions.eq( "patientIdentifierType", patientIdentifierType ) );
+
+        return (ProgramPatientProperty) criteria.uniqueResult();
+    }
+
+    @Override
+    public ProgramPatientProperty get( Program program, String propertyName )
+    {
+        Session session = sessionFactory.getCurrentSession();
+
+        Criteria criteria = session.createCriteria( ProgramPatientProperty.class );
+        criteria.add( Restrictions.eq( "program", program ) );
+        criteria.add( Restrictions.isNotNull( "propertyName" ) );
+        criteria.add( Restrictions.eq( "propertyName", propertyName ) );
+
+        return (ProgramPatientProperty) criteria.uniqueResult();
+    }
+
+    @SuppressWarnings( "unchecked" )
+    @Override
+    public Collection<ProgramPatientProperty> getProgramPatientIdentifierTypes( Program program )
+    {
+        Session session = sessionFactory.getCurrentSession();
+
+        Criteria criteria = session.createCriteria( ProgramPatientProperty.class );
+        criteria.add( Restrictions.eq( "program", program ) );
+        criteria.add( Restrictions.isNotNull( "patientIdentifierType" ) );
+
+        return criteria.list();
+    }
+
+    @SuppressWarnings( "unchecked" )
+    @Override
+    public Collection<ProgramPatientProperty> getProgramPatientAttributes( Program program )
+    {
+        Session session = sessionFactory.getCurrentSession();
+
+        Criteria criteria = session.createCriteria( ProgramPatientProperty.class );
+        criteria.add( Restrictions.eq( "program", program ) );
+        criteria.add( Restrictions.isNotNull( "patientAttribute" ) );
+
+        return criteria.list();
+    }
+
+    @SuppressWarnings( "unchecked" )
+    @Override
+    public Collection<ProgramPatientProperty> getProgramPatientProperties( Program program )
+    {
+        Session session = sessionFactory.getCurrentSession();
+
+        Criteria criteria = session.createCriteria( ProgramPatientProperty.class );
+        criteria.add( Restrictions.eq( "program", program ) );
+        criteria.add( Restrictions.isNotNull( "propertyName" ) );
+
+        return criteria.list();
+    }
+
+    @SuppressWarnings( "unchecked" )
+    @Override
+    public Collection<PatientIdentifierType> getPatientIdentifierTypes( Program program )
+    {
+        Session session = sessionFactory.getCurrentSession();
+        Criteria criteria = session.createCriteria( ProgramPatientProperty.class );
+        criteria.add( Restrictions.eq( "program", program ) );
+        criteria.add( Restrictions.isNotNull( "patientIdentifierType" ) );
+        criteria.setProjection( Projections.property( "patientIdentifierType" ) );
+
+        return criteria.list();
+    }
+
+    @SuppressWarnings( "unchecked" )
+    @Override
+    public Collection<PatientAttribute> getPatientAttributes( Program program )
+    {
+        Session session = sessionFactory.getCurrentSession();
+        Criteria criteria = session.createCriteria( ProgramPatientProperty.class );
+        criteria.add( Restrictions.eq( "program", program ) );
+        criteria.add( Restrictions.isNotNull( "patientAttribute" ) );
+        criteria.setProjection( Projections.property( "patientAttribute" ) );
+
+        return criteria.list();
+    }
+
+    @SuppressWarnings( "unchecked" )
+    @Override
+    public Collection<String> getPatientProperties( Program program )
+    {
+        Session session = sessionFactory.getCurrentSession();
+        Criteria criteria = session.createCriteria( ProgramPatientProperty.class );
+        criteria.add( Restrictions.eq( "program", program ) );
+        criteria.add( Restrictions.isNotNull( "patientProperty" ) );
+        criteria.setProjection( Projections.property( "patientProperty" ) );
+
+        return criteria.list();
+    }
+
+}

=== modified file 'dhis-2/dhis-services/dhis-service-patient/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-services/dhis-service-patient/src/main/resources/META-INF/dhis/beans.xml	2013-09-19 05:24:04 +0000
+++ dhis-2/dhis-services/dhis-service-patient/src/main/resources/META-INF/dhis/beans.xml	2013-09-27 04:43:25 +0000
@@ -6,6 +6,11 @@
 
 	<!-- Store definitions -->
 
+	<bean id="org.hisp.dhis.program.ProgramPatientPropertyStore"
+		class="org.hisp.dhis.program.hibernate.HibernateProgramPatientPropertyStore">
+		<property name="sessionFactory" ref="sessionFactory" />
+	</bean>
+
 	<bean id="org.hisp.dhis.program.ProgramIndicatorStore"
 		class="org.hisp.dhis.program.hibernate.HibernateProgramIndicatorStore">
 		<property name="clazz" value="org.hisp.dhis.program.ProgramIndicator" />
@@ -144,6 +149,12 @@
 
 	<!-- Service definitions -->
 
+	<bean id="org.hisp.dhis.program.ProgramPatientPropertyService"
+		class="org.hisp.dhis.program.DefaultProgramPatientPropertyService">
+		<property name="programPatientPropertyStore"
+			ref="org.hisp.dhis.program.ProgramPatientPropertyStore" />
+	</bean>
+
 	<bean id="org.hisp.dhis.program.ProgramDataEntryService" class="org.hisp.dhis.program.DefaultProgramDataEntryService">
 		<property name="dataElementService" ref="org.hisp.dhis.dataelement.DataElementService" />
 		<property name="programStageInstanceService"

=== modified file 'dhis-2/dhis-services/dhis-service-patient/src/main/resources/org/hisp/dhis/program/hibernate/Program.hbm.xml'
--- dhis-2/dhis-services/dhis-service-patient/src/main/resources/org/hisp/dhis/program/hibernate/Program.hbm.xml	2013-09-16 09:47:59 +0000
+++ dhis-2/dhis-services/dhis-service-patient/src/main/resources/org/hisp/dhis/program/hibernate/Program.hbm.xml	2013-09-27 04:43:25 +0000
@@ -11,7 +11,8 @@
 		<id name="id" column="programid">
 			<generator class="native" />
 		</id>
-    &identifiableProperties;
+    	
+    	&identifiableProperties;
 
 		<property name="name" column="name" not-null="true" length="230" />
 
@@ -46,19 +47,6 @@
 
 		<property name="onlyEnrollOnce" />
 
-		<list name="patientIdentifierTypes" table="program_patientIdentifierTypes">
-			<key column="programid" foreign-key="fk_program_patientIdentifierTypes_programid" />
-			<list-index column="sort_order" base="0" />
-			<many-to-many column="patientidentifiertypeid"
-				class="org.hisp.dhis.patient.PatientIdentifierType" foreign-key="fk_program_patientIdentifierTypes_patientidentifiertypeid" />
-		</list>
-
-		<list name="patientAttributes" table="program_patientAttributes">
-			<key column="programid" foreign-key="fk_program_patientAttributes_programid" />
-			<list-index column="sort_order" base="0" />
-			<many-to-many column="patientattributeid"
-				class="org.hisp.dhis.patient.PatientAttribute" foreign-key="fk_program_patientAttributes_patientattributeid" />
-		</list>
 		<property name="ignoreOverdueEvents" />
 
 		<set name="userRoles" table="program_userroles">
@@ -88,7 +76,7 @@
 		<property name="selectEnrollmentDatesInFuture" />
 
 		<property name="selectIncidentDatesInFuture" />
-		
+
 		<property name="relationshipText" />
 
 		<many-to-one name="relationshipType"
@@ -96,11 +84,17 @@
 			foreign-key="fk_program_relationshipid" />
 
 		<property name="relationshipFromA" />
-		
+
 		<many-to-one name="relatedProgram" class="org.hisp.dhis.program.Program"
 			column="relatedprogramid" foreign-key="fk_program_relatedprogram" />
-			
+
 		<property name="dataEntryMethod" />
+		
+		<set name="programPatientProperties" order-by="sortOrder">
+			<key column="programid" />
+			<one-to-many class="org.hisp.dhis.program.ProgramPatientProperty" />
+		</set>
+		
 
 		<!-- Access properties -->
 

=== added file 'dhis-2/dhis-services/dhis-service-patient/src/main/resources/org/hisp/dhis/program/hibernate/ProgramPatientProperty.hbm.xml'
--- dhis-2/dhis-services/dhis-service-patient/src/main/resources/org/hisp/dhis/program/hibernate/ProgramPatientProperty.hbm.xml	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-patient/src/main/resources/org/hisp/dhis/program/hibernate/ProgramPatientProperty.hbm.xml	2013-09-27 04:43:25 +0000
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+  "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+  "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd";>
+
+<hibernate-mapping>
+	<class name="org.hisp.dhis.program.ProgramPatientProperty" table="programpatientproperty">
+
+		<id name="id" column="programpatientpropertyid">
+			<generator class="native" />
+		</id>
+
+		<many-to-one name="program" class="org.hisp.dhis.program.Program"
+			column="programid" foreign-key="fk_programpatientproperty_programid" />
+
+		<many-to-one name="patientAttribute" class="org.hisp.dhis.patient.PatientAttribute"
+			column="patientattributeid" foreign-key="fk_programpatientproperty_patientattributeid" />
+
+		<many-to-one name="patientIdentifierType"
+			class="org.hisp.dhis.patient.PatientIdentifierType" column="patientidentifiertypeid"
+			foreign-key="fk_programpatientproperty_patientidentifiertypeid" />
+
+		<property name="propertyName" />
+		
+		<property name="defaultValue" />
+
+		<property name="hidden" />
+		
+		<property name="sortOrder" />
+
+	</class>
+</hibernate-mapping>

=== modified file 'dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/caseentry/GetDataRecordsAction.java'
--- dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/caseentry/GetDataRecordsAction.java	2013-08-23 16:05:01 +0000
+++ dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/caseentry/GetDataRecordsAction.java	2013-09-27 04:43:25 +0000
@@ -51,6 +51,7 @@
 import org.hisp.dhis.patientattributevalue.PatientAttributeValueService;
 import org.hisp.dhis.program.Program;
 import org.hisp.dhis.program.ProgramInstance;
+import org.hisp.dhis.program.ProgramPatientPropertyService;
 import org.hisp.dhis.program.ProgramService;
 import org.hisp.dhis.program.ProgramStageInstance;
 import org.hisp.dhis.program.ProgramStageInstanceService;
@@ -104,6 +105,13 @@
         this.patientAttributeValueService = patientAttributeValueService;
     }
 
+    private ProgramPatientPropertyService programPatientPropertyService;
+    
+    public void setProgramPatientPropertyService( ProgramPatientPropertyService programPatientPropertyService )
+    {
+        this.programPatientPropertyService = programPatientPropertyService;
+    }
+
     private I18n i18n;
 
     public void setI18n( I18n i18n )
@@ -157,9 +165,9 @@
         return programStageInstances;
     }
 
-    private List<PatientIdentifierType> identifierTypes;
+    private Collection<PatientIdentifierType> identifierTypes;
 
-    public List<PatientIdentifierType> getIdentifierTypes()
+    public Collection<PatientIdentifierType> getIdentifierTypes()
     {
         return identifierTypes;
     }
@@ -229,7 +237,7 @@
         {
             program = programService.getProgram( programId );
 
-            identifierTypes = program.getPatientIdentifierTypes();
+            identifierTypes = programPatientPropertyService.getPatientIdentifierTypes( program );
         }
 
         if ( searchTexts.size() > 0 )

=== modified file 'dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/caseentry/ShowEventWithRegistrationFormAction.java'
--- dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/caseentry/ShowEventWithRegistrationFormAction.java	2013-09-03 06:39:59 +0000
+++ dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/caseentry/ShowEventWithRegistrationFormAction.java	2013-09-27 04:43:25 +0000
@@ -51,6 +51,7 @@
 import org.hisp.dhis.patient.comparator.PatientAttributeGroupSortOrderComparator;
 import org.hisp.dhis.program.Program;
 import org.hisp.dhis.program.ProgramDataEntryService;
+import org.hisp.dhis.program.ProgramPatientProperty;
 import org.hisp.dhis.program.ProgramService;
 import org.hisp.dhis.program.ProgramStage;
 import org.hisp.dhis.program.ProgramStageDataElement;
@@ -187,8 +188,17 @@
             programs.remove( program );
             for ( Program p : programs )
             {
-                identifierTypes.removeAll( p.getPatientIdentifierTypes() );
-                patientAttributesInProgram.addAll( p.getPatientAttributes() );
+                for ( ProgramPatientProperty programPatientProperty : p.getProgramPatientProperties() )
+                {
+                    if ( programPatientProperty.isIdentifierType() )
+                    {
+                        identifierTypes.remove( programPatientProperty.getPatientIdentifierType() );
+                    }
+                    else if ( programPatientProperty.isAttribute() )
+                    {
+                        patientAttributesInProgram.remove( programPatientProperty.getPatientAttribute() );
+                    }
+                }
             }
 
             attributeGroups = new ArrayList<PatientAttributeGroup>(

=== modified file 'dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/GetPatientAction.java'
--- dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/GetPatientAction.java	2013-09-11 16:02:06 +0000
+++ dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/GetPatientAction.java	2013-09-27 04:43:25 +0000
@@ -30,7 +30,6 @@
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -40,8 +39,6 @@
 import org.hisp.dhis.i18n.I18nFormat;
 import org.hisp.dhis.patient.Patient;
 import org.hisp.dhis.patient.PatientAttribute;
-import org.hisp.dhis.patient.PatientAttributeGroup;
-import org.hisp.dhis.patient.PatientAttributeGroupService;
 import org.hisp.dhis.patient.PatientAttributeService;
 import org.hisp.dhis.patient.PatientIdentifier;
 import org.hisp.dhis.patient.PatientIdentifierType;
@@ -49,12 +46,12 @@
 import org.hisp.dhis.patient.PatientRegistrationForm;
 import org.hisp.dhis.patient.PatientRegistrationFormService;
 import org.hisp.dhis.patient.PatientService;
-import org.hisp.dhis.patient.comparator.PatientAttributeGroupSortOrderComparator;
 import org.hisp.dhis.patientattributevalue.PatientAttributeValue;
 import org.hisp.dhis.patientattributevalue.PatientAttributeValueService;
 import org.hisp.dhis.program.Program;
 import org.hisp.dhis.program.ProgramInstance;
 import org.hisp.dhis.program.ProgramInstanceService;
+import org.hisp.dhis.program.ProgramPatientPropertyService;
 import org.hisp.dhis.program.ProgramService;
 import org.hisp.dhis.relationship.Relationship;
 import org.hisp.dhis.relationship.RelationshipService;
@@ -91,10 +88,10 @@
 
     private ProgramInstanceService programInstanceService;
 
-    private PatientAttributeGroupService attributeGroupService;
-
     private PatientAttributeService attributeService;
 
+    private ProgramPatientPropertyService programPatientPropertyService;
+
     private I18n i18n;
 
     private I18nFormat format;
@@ -113,18 +110,10 @@
 
     private Map<Integer, String> patientAttributeValueMap = new HashMap<Integer, String>();
 
-    private Collection<PatientAttribute> noGroupAttributes = new HashSet<PatientAttribute>();
-
-    private List<PatientAttributeGroup> attributeGroups;
-
-    private Collection<PatientIdentifierType> identifierTypes;
+    private Collection<PatientIdentifierType> identifierTypes = new HashSet<PatientIdentifierType>();
 
     private Map<Integer, String> identiferMap;
 
-    private String childContactName;
-
-    private String childContactType;
-
     private String systemIdentifier;
 
     private Relationship relationship;
@@ -171,6 +160,11 @@
         return attributesMap;
     }
 
+    public void setProgramPatientPropertyService( ProgramPatientPropertyService programPatientPropertyService )
+    {
+        this.programPatientPropertyService = programPatientPropertyService;
+    }
+
     // -------------------------------------------------------------------------
     // Action implementation
     // -------------------------------------------------------------------------
@@ -233,104 +227,74 @@
 
         List<PatientAttribute> attributes = new ArrayList<PatientAttribute>();
 
-        if ( customRegistrationForm == null )
-        {
-            attributeGroups = new ArrayList<PatientAttributeGroup>(
-                attributeGroupService.getAllPatientAttributeGroups() );
-            Collections.sort( attributeGroups, new PatientAttributeGroupSortOrderComparator() );
-
-            if ( program == null )
-            {
-                identifierTypes = patientIdentifierTypeService.getAllPatientIdentifierTypes();
-                attributes = new ArrayList<PatientAttribute>( attributeService.getAllPatientAttributes() );
-                Collection<Program> programs = programService.getAllPrograms();
-                for ( Program p : programs )
+        if ( customRegistrationForm == null && program == null )
+        {
+            identifierTypes = patientIdentifierTypeService.getAllPatientIdentifierTypes();
+            attributes = new ArrayList<PatientAttribute>( attributeService.getAllPatientAttributes() );
+            Collection<Program> programs = programService.getAllPrograms();
+            for ( Program p : programs )
+            {
+                identifierTypes.removeAll( programPatientPropertyService.getPatientIdentifierTypes( p ) );
+                attributes.removeAll( programPatientPropertyService.getPatientAttributes( p ) );
+            }
+        }
+
+        // -------------------------------------------------------------------------
+        // Get data
+        // -------------------------------------------------------------------------
+
+        identiferMap = new HashMap<Integer, String>();
+
+        PatientIdentifierType idType = null;
+        Patient representative = patient.getRepresentative();
+        relationship = relationshipService.getRelationship( representative, patient );
+
+        if ( patient.isUnderAge() && representative != null )
+        {
+            for ( PatientIdentifier representativeIdentifier : representative.getIdentifiers() )
+            {
+                if ( representativeIdentifier.getIdentifierType() != null
+                    && representativeIdentifier.getIdentifierType().isRelated() )
                 {
-                    identifierTypes.removeAll( p.getPatientIdentifierTypes() );
-                    attributes.removeAll( p.getPatientAttributes() );
+                    identiferMap.put( representativeIdentifier.getIdentifierType().getId(),
+                        representativeIdentifier.getIdentifier() );
                 }
             }
+        }
+
+        for ( PatientIdentifier identifier : patient.getIdentifiers() )
+        {
+            idType = identifier.getIdentifierType();
+
+            if ( idType != null )
+            {
+                identiferMap.put( identifier.getIdentifierType().getId(), identifier.getIdentifier() );
+            }
+        }
+
+        // -------------------------------------------------------------------------
+        // Get patient-attribute values
+        // -------------------------------------------------------------------------
+
+        Collection<PatientAttributeValue> patientAttributeValues = patientAttributeValueService
+            .getPatientAttributeValues( patient );
+
+        for ( PatientAttributeValue patientAttributeValue : patientAttributeValues )
+        {
+            if ( PatientAttribute.TYPE_COMBO.equalsIgnoreCase( patientAttributeValue.getPatientAttribute()
+                .getValueType() ) )
+            {
+                patientAttributeValueMap.put( patientAttributeValue.getPatientAttribute().getId(),
+                    patientAttributeValue.getPatientAttributeOption().getName() );
+            }
             else
             {
-                identifierTypes = program.getPatientIdentifierTypes();
-                attributes = program.getPatientAttributes();
-            }
-
-            for ( PatientAttribute attribute : attributes )
-            {
-                PatientAttributeGroup patientAttributeGroup = attribute.getPatientAttributeGroup();
-                String groupName = (patientAttributeGroup == null) ? "" : patientAttributeGroup.getDisplayName();
-                if ( attributesMap.containsKey( groupName ) )
-                {
-                    List<PatientAttribute> attrs = attributesMap.get( groupName );
-                    attrs.add( attribute );
-                }
-                else
-                {
-                    List<PatientAttribute> attrs = new ArrayList<PatientAttribute>();
-                    attrs.add( attribute );
-                    attributesMap.put( groupName, attrs );
-                }
-            }
-
-            // -------------------------------------------------------------------------
-            // Get data
-            // -------------------------------------------------------------------------
-
-            identiferMap = new HashMap<Integer, String>();
-
-            PatientIdentifierType idType = null;
-            Patient representative = patient.getRepresentative();
-            relationship = relationshipService.getRelationship( representative, patient );
-
-            if ( patient.isUnderAge() && representative != null )
-            {
-                for ( PatientIdentifier representativeIdentifier : representative.getIdentifiers() )
-                {
-                    if ( representativeIdentifier.getIdentifierType() != null
-                        && representativeIdentifier.getIdentifierType().isRelated() )
-                    {
-                        identiferMap.put( representativeIdentifier.getIdentifierType().getId(),
-                            representativeIdentifier.getIdentifier() );
-                    }
-                }
-            }
-
-            for ( PatientIdentifier identifier : patient.getIdentifiers() )
-            {
-                idType = identifier.getIdentifierType();
-
-                if ( idType != null )
-                {
-                    identiferMap.put( identifier.getIdentifierType().getId(), identifier.getIdentifier() );
-                }
-            }
-
-            // -------------------------------------------------------------------------
-            // Get patient-attribute values
-            // -------------------------------------------------------------------------
-
-            Collection<PatientAttributeValue> patientAttributeValues = patientAttributeValueService
-                .getPatientAttributeValues( patient );
-
-            for ( PatientAttributeValue patientAttributeValue : patientAttributeValues )
-            {
-                if ( PatientAttribute.TYPE_COMBO.equalsIgnoreCase( patientAttributeValue.getPatientAttribute()
-                    .getValueType() ) )
-                {
-                    patientAttributeValueMap.put( patientAttributeValue.getPatientAttribute().getId(),
-                        patientAttributeValue.getPatientAttributeOption().getName() );
-                }
-                else
-                {
-                    patientAttributeValueMap.put( patientAttributeValue.getPatientAttribute().getId(),
-                        patientAttributeValue.getValue() );
-                }
+                patientAttributeValueMap.put( patientAttributeValue.getPatientAttribute().getId(),
+                    patientAttributeValue.getValue() );
             }
         }
 
         return SUCCESS;
-
     }
 
     // -----------------------------------------------------------------------------
@@ -342,11 +306,6 @@
         this.patientRegistrationFormService = patientRegistrationFormService;
     }
 
-    public void setAttributeGroupService( PatientAttributeGroupService attributeGroupService )
-    {
-        this.attributeGroupService = attributeGroupService;
-    }
-
     public void setI18n( I18n i18n )
     {
         this.i18n = i18n;
@@ -432,16 +391,6 @@
         return patientAttributeValueMap;
     }
 
-    public Collection<PatientAttribute> getNoGroupAttributes()
-    {
-        return noGroupAttributes;
-    }
-
-    public List<PatientAttributeGroup> getAttributeGroups()
-    {
-        return attributeGroups;
-    }
-
     public Collection<PatientIdentifierType> getIdentifierTypes()
     {
         return identifierTypes;
@@ -452,16 +401,6 @@
         return identiferMap;
     }
 
-    public String getChildContactName()
-    {
-        return childContactName;
-    }
-
-    public String getChildContactType()
-    {
-        return childContactType;
-    }
-
     public String getSystemIdentifier()
     {
         return systemIdentifier;

=== modified file 'dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/PatientDashboardAction.java'
--- dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/PatientDashboardAction.java	2013-09-17 09:47:21 +0000
+++ dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/PatientDashboardAction.java	2013-09-27 04:43:25 +0000
@@ -41,7 +41,6 @@
 import org.hisp.dhis.patient.PatientAudit;
 import org.hisp.dhis.patient.PatientAuditService;
 import org.hisp.dhis.patient.PatientIdentifier;
-import org.hisp.dhis.patient.PatientIdentifierType;
 import org.hisp.dhis.patient.PatientService;
 import org.hisp.dhis.patientattributevalue.PatientAttributeValue;
 import org.hisp.dhis.patientattributevalue.PatientAttributeValueService;
@@ -50,6 +49,7 @@
 import org.hisp.dhis.program.ProgramIndicatorService;
 import org.hisp.dhis.program.ProgramInstance;
 import org.hisp.dhis.program.ProgramInstanceService;
+import org.hisp.dhis.program.ProgramPatientProperty;
 import org.hisp.dhis.program.ProgramService;
 import org.hisp.dhis.relationship.Relationship;
 import org.hisp.dhis.relationship.RelationshipService;
@@ -84,7 +84,7 @@
     private ProgramIndicatorService programIndicatorService;
 
     private PatientAttributeValueService patientAttributeValueService;
-    
+
     // -------------------------------------------------------------------------
     // Input && Output
     // -------------------------------------------------------------------------
@@ -224,7 +224,7 @@
         relationships = relationshipService.getRelationshipsForPatient( patient );
 
         Collection<ProgramInstance> programInstances = programInstanceService.getProgramInstances( patient );
-        
+
         // ---------------------------------------------------------------------
         // Get patient-attribute-values
         // ---------------------------------------------------------------------
@@ -235,12 +235,16 @@
 
         for ( Program program : programs )
         {
-            Collection<PatientAttribute> atttributes = program.getPatientAttributes();
+            Collection<ProgramPatientProperty> programAtttributes = program.getProgramPatientProperties();
             for ( PatientAttributeValue attributeValue : _attributeValues )
             {
-                if ( atttributes.contains( attributeValue.getPatientAttribute() ) )
+                for ( ProgramPatientProperty programAtttribute : programAtttributes )
                 {
-                    attributeValues.add( attributeValue );
+                    if ( programAtttribute.isAttribute()
+                        && programAtttribute.getPatientAttribute().equals( attributeValue.getPatientAttribute() ) )
+                    {
+                        attributeValues.add( attributeValue );
+                    }
                 }
             }
         }
@@ -254,15 +258,20 @@
 
         for ( Program program : programs )
         {
-            Collection<PatientIdentifierType> identifierTypes = program.getPatientIdentifierTypes();
+            Collection<ProgramPatientProperty> programIdentifierTypes = program.getProgramPatientProperties();
             for ( PatientIdentifier identifier : _identifiers )
             {
-                if ( !identifierTypes.contains( identifier.getIdentifierType() ) )
+                for ( ProgramPatientProperty programIdentifierType : programIdentifierTypes )
                 {
-                    identifiers.add( identifier );
+                    if ( programIdentifierType.isIdentifierType()
+                        && programIdentifierType.getPatientIdentifierType().equals( identifier.getIdentifierType() ) )
+                    {
+                        identifiers.add( identifier );
+                    }
                 }
             }
         }
+
         // ---------------------------------------------------------------------
         // Get program enrollment
         // ---------------------------------------------------------------------

=== modified file 'dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/ProgramEnrollmentAction.java'
--- dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/ProgramEnrollmentAction.java	2013-09-18 06:54:48 +0000
+++ dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/ProgramEnrollmentAction.java	2013-09-27 04:43:25 +0000
@@ -48,6 +48,7 @@
 import org.hisp.dhis.program.Program;
 import org.hisp.dhis.program.ProgramInstance;
 import org.hisp.dhis.program.ProgramInstanceService;
+import org.hisp.dhis.program.ProgramPatientPropertyService;
 import org.hisp.dhis.program.ProgramStageInstance;
 import org.hisp.dhis.program.comparator.ProgramStageInstanceVisitDateComparator;
 
@@ -71,6 +72,8 @@
 
     private SelectedStateManager selectedStateManager;
 
+    private ProgramPatientPropertyService programPatientPropertyService;
+
     // -------------------------------------------------------------------------
     // Input/Output
     // -------------------------------------------------------------------------
@@ -81,7 +84,7 @@
 
     private List<ProgramStageInstance> programStageInstances = new ArrayList<ProgramStageInstance>();
 
-    private List<PatientIdentifierType> identifierTypes;
+    private List<PatientIdentifierType> identifierTypes = new ArrayList<PatientIdentifierType>();
 
     private Collection<PatientAttribute> noGroupAttributes = new HashSet<PatientAttribute>();
 
@@ -91,7 +94,7 @@
 
     private Boolean hasDataEntry;
 
-    private List<PatientAttribute> patientAttributes;
+    private List<PatientAttribute> patientAttributes = new ArrayList<PatientAttribute>();
 
     private ProgramInstance programInstance;
 
@@ -99,6 +102,11 @@
     // Getters/Setters
     // -------------------------------------------------------------------------
 
+    public void setProgramPatientPropertyService( ProgramPatientPropertyService programPatientPropertyService )
+    {
+        this.programPatientPropertyService = programPatientPropertyService;
+    }
+
     public void setSelectedStateManager( SelectedStateManager selectedStateManager )
     {
         this.selectedStateManager = selectedStateManager;
@@ -190,7 +198,7 @@
 
         loadIdentifierTypes( programInstance );
 
-        loadPatientAttributes( programInstance );
+        loadPatientAttributes( programInstance.getProgram() );
 
         hasDataEntry = showDataEntry( orgunit, programInstance.getProgram(), programInstance );
 
@@ -207,7 +215,13 @@
         // Load identifier types of the selected program
         // ---------------------------------------------------------------------
 
-        identifierTypes = programInstance.getProgram().getPatientIdentifierTypes();
+        Collection<PatientIdentifierType> idenTypes = programPatientPropertyService
+            .getPatientIdentifierTypes( programInstance.getProgram() );
+        if ( idenTypes != null )
+        {
+            identifierTypes.addAll( idenTypes );
+        }
+
         identiferMap = new HashMap<Integer, String>();
 
         if ( identifierTypes != null && identifierTypes.size() > 0 )
@@ -222,26 +236,28 @@
         }
     }
 
-    private void loadPatientAttributes( ProgramInstance programInstance )
+    private void loadPatientAttributes( Program program )
     {
         // ---------------------------------------------------------------------
         // Load patient-attributes of the selected program
         // ---------------------------------------------------------------------
 
-        patientAttributes = programInstance.getProgram().getPatientAttributes();
-
-        if ( patientAttributes != null )
-        {
-            Collection<PatientAttributeValue> patientAttributeValues = patientAttributeValueService
-                .getPatientAttributeValues( programInstance.getPatient() );
-
-            for ( PatientAttributeValue patientAttributeValue : patientAttributeValues )
+        Collection<PatientAttribute> attrTypes = programPatientPropertyService.getPatientAttributes( program );
+        if ( attrTypes != null )
+        {
+            patientAttributes.addAll( attrTypes );
+
+        }
+
+        Collection<PatientAttributeValue> patientAttributeValues = patientAttributeValueService
+            .getPatientAttributeValues( programInstance.getPatient() );
+
+        for ( PatientAttributeValue patientAttributeValue : patientAttributeValues )
+        {
+            if ( patientAttributes.contains( patientAttributeValue.getPatientAttribute() ) )
             {
-                if ( patientAttributes.contains( patientAttributeValue.getPatientAttribute() ) )
-                {
-                    patientAttributeValueMap.put( patientAttributeValue.getPatientAttribute().getId(),
-                        patientAttributeValue.getValue() );
-                }
+                patientAttributeValueMap.put( patientAttributeValue.getPatientAttribute().getId(),
+                    patientAttributeValue.getValue() );
             }
         }
     }

=== modified file 'dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/SaveIdentifierAndAttributeAction.java'
--- dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/SaveIdentifierAndAttributeAction.java	2013-09-19 06:06:15 +0000
+++ dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/SaveIdentifierAndAttributeAction.java	2013-09-27 04:43:25 +0000
@@ -47,6 +47,7 @@
 import org.hisp.dhis.patientattributevalue.PatientAttributeValue;
 import org.hisp.dhis.patientattributevalue.PatientAttributeValueService;
 import org.hisp.dhis.program.Program;
+import org.hisp.dhis.program.ProgramPatientProperty;
 import org.hisp.dhis.program.ProgramService;
 
 import com.opensymphony.xwork2.Action;
@@ -173,40 +174,45 @@
 
         String value = null;
 
-        Collection<PatientIdentifierType> identifierTypes = program.getPatientIdentifierTypes();
+        Collection<ProgramPatientProperty> programPatientProperties = program.getProgramPatientProperties();
 
         PatientIdentifier identifier = null;
 
-        if ( identifierTypes != null )
+        if ( programPatientProperties != null )
         {
-            for ( PatientIdentifierType identifierType : identifierTypes )
+            for ( ProgramPatientProperty programPatientProperty : programPatientProperties )
             {
-                value = request.getParameter( AddPatientAction.PREFIX_IDENTIFIER + identifierType.getId() );
-
-                identifier = patientIdentifierService.getPatientIdentifier( identifierType, patient );
-
-                if ( StringUtils.isNotBlank( value ) )
-                {
-                    value = value.trim();
-
-                    if ( identifier == null )
-                    {
-                        identifier = new PatientIdentifier();
-                        identifier.setIdentifierType( identifierType );
-                        identifier.setPatient( patient );
-                        identifier.setIdentifier( value );
-                        patient.getIdentifiers().add( identifier );
-                    }
-                    else
-                    {
-                        identifier.setIdentifier( value );
-                        patient.getIdentifiers().add( identifier );
-                    }
-                }
-                else if ( identifier != null )
-                {
-                    patient.getIdentifiers().remove( identifier );
-                    patientIdentifierService.deletePatientIdentifier( identifier );
+                if ( programPatientProperty.isIdentifierType() )
+                {
+                    PatientIdentifierType identifierType = programPatientProperty.getPatientIdentifierType();
+
+                    value = request.getParameter( AddPatientAction.PREFIX_IDENTIFIER + identifierType.getId() );
+
+                    identifier = patientIdentifierService.getPatientIdentifier( identifierType, patient );
+
+                    if ( StringUtils.isNotBlank( value ) )
+                    {
+                        value = value.trim();
+
+                        if ( identifier == null )
+                        {
+                            identifier = new PatientIdentifier();
+                            identifier.setIdentifierType( identifierType );
+                            identifier.setPatient( patient );
+                            identifier.setIdentifier( value );
+                            patient.getIdentifiers().add( identifier );
+                        }
+                        else
+                        {
+                            identifier.setIdentifier( value );
+                            patient.getIdentifiers().add( identifier );
+                        }
+                    }
+                    else if ( identifier != null )
+                    {
+                        patient.getIdentifiers().remove( identifier );
+                        patientIdentifierService.deletePatientIdentifier( identifier );
+                    }
                 }
             }
         }

=== modified file 'dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/SearchPatientAction.java'
--- dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/SearchPatientAction.java	2013-09-09 18:25:50 +0000
+++ dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/SearchPatientAction.java	2013-09-27 04:43:25 +0000
@@ -42,6 +42,7 @@
 import org.hisp.dhis.patient.PatientIdentifierType;
 import org.hisp.dhis.patient.PatientService;
 import org.hisp.dhis.program.Program;
+import org.hisp.dhis.program.ProgramPatientPropertyService;
 import org.hisp.dhis.program.ProgramService;
 import org.hisp.dhis.user.CurrentUserService;
 
@@ -64,6 +65,8 @@
 
     private CurrentUserService currentUserService;
 
+    private ProgramPatientPropertyService programPatientPropertyService;
+
     // -------------------------------------------------------------------------
     // Input/output
     // -------------------------------------------------------------------------
@@ -82,6 +85,11 @@
     // Getters && Setters
     // -------------------------------------------------------------------------
 
+    public void setProgramPatientPropertyService( ProgramPatientPropertyService programPatientPropertyService )
+    {
+        this.programPatientPropertyService = programPatientPropertyService;
+    }
+
     public void setCurrentUserService( CurrentUserService currentUserService )
     {
         this.currentUserService = currentUserService;
@@ -214,8 +222,8 @@
             {
                 for ( Integer programId : programIds )
                 {
-                    Program progam = programService.getProgram( programId );
-                    identifierTypes.addAll( progam.getPatientIdentifierTypes() );
+                    Program program = programService.getProgram( programId );
+                    identifierTypes.addAll( programPatientPropertyService.getPatientIdentifierTypes( program ) );
                 }
             }
         }

=== modified file 'dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/ShowAddPatientFormAction.java'
--- dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/ShowAddPatientFormAction.java	2013-09-11 16:02:06 +0000
+++ dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/ShowAddPatientFormAction.java	2013-09-27 04:43:25 +0000
@@ -30,8 +30,8 @@
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 
@@ -40,16 +40,13 @@
 import org.hisp.dhis.organisationunit.OrganisationUnit;
 import org.hisp.dhis.ouwt.manager.OrganisationUnitSelectionManager;
 import org.hisp.dhis.patient.PatientAttribute;
-import org.hisp.dhis.patient.PatientAttributeGroup;
-import org.hisp.dhis.patient.PatientAttributeGroupService;
 import org.hisp.dhis.patient.PatientAttributeService;
 import org.hisp.dhis.patient.PatientIdentifierType;
 import org.hisp.dhis.patient.PatientIdentifierTypeService;
 import org.hisp.dhis.patient.PatientRegistrationForm;
 import org.hisp.dhis.patient.PatientRegistrationFormService;
-import org.hisp.dhis.patient.PatientService;
-import org.hisp.dhis.patient.comparator.PatientAttributeGroupSortOrderComparator;
 import org.hisp.dhis.program.Program;
+import org.hisp.dhis.program.ProgramPatientPropertyService;
 import org.hisp.dhis.program.ProgramService;
 import org.hisp.dhis.user.User;
 
@@ -101,18 +98,11 @@
         this.attributeService = attributeService;
     }
 
-    private PatientService patientService;
-
-    public void setPatientService( PatientService patientService )
-    {
-        this.patientService = patientService;
-    }
-
-    private PatientAttributeGroupService attributeGroupService;
-
-    public void setAttributeGroupService( PatientAttributeGroupService attributeGroupService )
-    {
-        this.attributeGroupService = attributeGroupService;
+    private ProgramPatientPropertyService programPatientPropertyService;
+
+    public void setProgramPatientPropertyService( ProgramPatientPropertyService programPatientPropertyService )
+    {
+        this.programPatientPropertyService = programPatientPropertyService;
     }
 
     private I18n i18n;
@@ -166,20 +156,13 @@
         return healthWorkers;
     }
 
-    private Collection<PatientIdentifierType> identifierTypes;
+    private Collection<PatientIdentifierType> identifierTypes = new HashSet<PatientIdentifierType>();
 
     public Collection<PatientIdentifierType> getIdentifierTypes()
     {
         return identifierTypes;
     }
 
-    private Map<String, List<PatientAttribute>> attributesMap = new HashMap<String, List<PatientAttribute>>();
-
-    public Map<String, List<PatientAttribute>> getAttributesMap()
-    {
-        return attributesMap;
-    }
-
     private OrganisationUnit organisationUnit;
 
     public OrganisationUnit getOrganisationUnit()
@@ -208,27 +191,6 @@
         return program;
     }
 
-    private List<PatientAttributeGroup> attributeGroups;
-
-    public List<PatientAttributeGroup> getAttributeGroups()
-    {
-        return attributeGroups;
-    }
-
-    private String orgunitCountIdentifier;
-
-    public String getOrgunitCountIdentifier()
-    {
-        return orgunitCountIdentifier;
-    }
-
-    private PatientRegistrationForm patientRegistrationForm;
-
-    public PatientRegistrationForm getPatientRegistrationForm()
-    {
-        return patientRegistrationForm;
-    }
-
     private Program relatedProgram;
 
     public Program getRelatedProgram()
@@ -247,7 +209,8 @@
 
         if ( programId == null )
         {
-            patientRegistrationForm = patientRegistrationFormService.getCommonPatientRegistrationForm();
+            PatientRegistrationForm patientRegistrationForm = patientRegistrationFormService
+                .getCommonPatientRegistrationForm();
 
             if ( patientRegistrationForm != null && patientRegistrationForm.getDataEntryForm() != null )
             {
@@ -259,7 +222,8 @@
         else
         {
             program = programService.getProgram( programId );
-            patientRegistrationForm = patientRegistrationFormService.getPatientRegistrationForm( program );
+            PatientRegistrationForm patientRegistrationForm = patientRegistrationFormService
+                .getPatientRegistrationForm( program );
 
             if ( patientRegistrationForm != null && patientRegistrationForm.getDataEntryForm() != null )
             {
@@ -271,50 +235,18 @@
 
         List<PatientAttribute> attributes = new ArrayList<PatientAttribute>();
 
-        if ( customRegistrationForm == null )
+        if ( customRegistrationForm == null && program == null )
         {
-            attributeGroups = new ArrayList<PatientAttributeGroup>(
-                attributeGroupService.getAllPatientAttributeGroups() );
-            Collections.sort( attributeGroups, new PatientAttributeGroupSortOrderComparator() );
-
-            if ( program == null )
-            {
-                identifierTypes = patientIdentifierTypeService.getAllPatientIdentifierTypes();
-                attributes = new ArrayList<PatientAttribute>( attributeService.getAllPatientAttributes() );
-                Collection<Program> programs = programService.getAllPrograms();
-                for ( Program p : programs )
-                {
-                    identifierTypes.removeAll( p.getPatientIdentifierTypes() );
-                    attributes.removeAll( p.getPatientAttributes() );
-                }
-            }
-            else
-            {
-                identifierTypes = program.getPatientIdentifierTypes();
-                attributes = program.getPatientAttributes();
-            }
-
-            for ( PatientAttribute attribute : attributes )
-            {
-                PatientAttributeGroup patientAttributeGroup = attribute.getPatientAttributeGroup();
-                String groupName = (patientAttributeGroup == null) ? "" : patientAttributeGroup.getDisplayName();
-                if ( attributesMap.containsKey( groupName ) )
-                {
-                    List<PatientAttribute> attrs = attributesMap.get( groupName );
-                    attrs.add( attribute );
-                }
-                else
-                {
-                    List<PatientAttribute> attrs = new ArrayList<PatientAttribute>();
-                    attrs.add( attribute );
-                    attributesMap.put( groupName, attrs );
-                }
-            }
-
+            identifierTypes = patientIdentifierTypeService.getAllPatientIdentifierTypes();
+            attributes = new ArrayList<PatientAttribute>( attributeService.getAllPatientAttributes() );
+            Collection<Program> programs = programService.getAllPrograms();
+            for ( Program p : programs )
+            {
+                identifierTypes.removeAll( programPatientPropertyService.getPatientIdentifierTypes( p ) );
+                attributes.removeAll( programPatientPropertyService.getPatientAttributes( p ) );
+            }
         }
 
-        orgunitCountIdentifier = generateOrgunitIdentifier( organisationUnit );
-
         if ( relatedProgramId != null )
         {
             relatedProgram = programService.getProgram( relatedProgramId );
@@ -322,29 +254,4 @@
 
         return SUCCESS;
     }
-
-    private String generateOrgunitIdentifier( OrganisationUnit organisationUnit )
-    {
-        String value = organisationUnit.getCode();
-        value = (value == null) ? "" : value;
-
-        int totalPatient = patientService.countGetPatientsByOrgUnit( organisationUnit );
-        if ( totalPatient < 10 )
-        {
-            value += "000" + totalPatient;
-        }
-        else if ( totalPatient < 100 )
-        {
-            value += "00" + totalPatient;
-        }
-        else if ( totalPatient < 1000 )
-        {
-            value += "0" + totalPatient;
-        }
-        else
-        {
-            value += totalPatient;
-        }
-        return value;
-    }
 }

=== modified file 'dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/ShowAddRelationshipPatientAction.java'
--- dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/ShowAddRelationshipPatientAction.java	2013-08-23 16:05:01 +0000
+++ dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/patient/ShowAddRelationshipPatientAction.java	2013-09-27 04:43:25 +0000
@@ -48,6 +48,7 @@
 import org.hisp.dhis.patientattributevalue.PatientAttributeValue;
 import org.hisp.dhis.patientattributevalue.PatientAttributeValueService;
 import org.hisp.dhis.program.Program;
+import org.hisp.dhis.program.ProgramPatientPropertyService;
 import org.hisp.dhis.program.ProgramService;
 import org.hisp.dhis.relationship.RelationshipType;
 import org.hisp.dhis.relationship.RelationshipTypeService;
@@ -81,6 +82,8 @@
 
     private OrganisationUnitSelectionManager selectionManager;
 
+    private ProgramPatientPropertyService programPatientPropertyService;
+
     // -------------------------------------------------------------------------
     // Input/Output
     // -------------------------------------------------------------------------
@@ -124,8 +127,8 @@
 
         for ( Program program : programs )
         {
-            identifierTypes.removeAll( program.getPatientIdentifierTypes() );
-            patientAttributes.removeAll( program.getPatientAttributes() );
+            identifierTypes.removeAll( programPatientPropertyService.getPatientIdentifierTypes( program ) );
+            patientAttributes.remove( programPatientPropertyService.getPatientAttributes( program ) );
         }
 
         for ( PatientAttribute patientAttribute : patientAttributes )
@@ -192,6 +195,11 @@
     // Getter/Setter
     // -------------------------------------------------------------------------
 
+    public void setProgramPatientPropertyService( ProgramPatientPropertyService programPatientPropertyService )
+    {
+        this.programPatientPropertyService = programPatientPropertyService;
+    }
+
     public void setSelectionManager( OrganisationUnitSelectionManager selectionManager )
     {
         this.selectionManager = selectionManager;

=== modified file 'dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/report/LoadDataElementsAction.java'
--- dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/report/LoadDataElementsAction.java	2013-09-25 07:00:33 +0000
+++ dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/report/LoadDataElementsAction.java	2013-09-27 04:43:25 +0000
@@ -36,6 +36,7 @@
 import org.hisp.dhis.patient.PatientIdentifierType;
 import org.hisp.dhis.patient.PatientIdentifierTypeService;
 import org.hisp.dhis.program.Program;
+import org.hisp.dhis.program.ProgramPatientPropertyService;
 import org.hisp.dhis.program.ProgramService;
 import org.hisp.dhis.program.ProgramStage;
 import org.hisp.dhis.program.ProgramStageDataElement;
@@ -92,6 +93,13 @@
         this.attributeService = attributeService;
     }
 
+    private ProgramPatientPropertyService programPatientPropertyService;
+
+    public void setProgramPatientPropertyService( ProgramPatientPropertyService programPatientPropertyService )
+    {
+        this.programPatientPropertyService = programPatientPropertyService;
+    }
+
     // -------------------------------------------------------------------------
     // Input/output
     // -------------------------------------------------------------------------
@@ -164,11 +172,11 @@
 
             for ( Program _program : programs )
             {
-                identifierTypes.removeAll( _program.getPatientIdentifierTypes() );
-                patientAttributes.removeAll( _program.getPatientAttributes() );
+                identifierTypes.removeAll( programPatientPropertyService.getPatientIdentifierTypes( _program ) );
+                patientAttributes.remove( programPatientPropertyService.getPatientAttributes( _program ) );
             }
         }
-        
+
         return SUCCESS;
     }
 }

=== modified file 'dhis-2/dhis-web/dhis-web-caseentry/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-web/dhis-web-caseentry/src/main/resources/META-INF/dhis/beans.xml	2013-09-23 04:29:22 +0000
+++ dhis-2/dhis-web/dhis-web-caseentry/src/main/resources/META-INF/dhis/beans.xml	2013-09-27 04:43:25 +0000
@@ -31,6 +31,9 @@
 		<property name="patientService" ref="org.hisp.dhis.patient.PatientService" />
 		<property name="programService" ref="org.hisp.dhis.program.ProgramService" />
 		<property name="currentUserService" ref="org.hisp.dhis.user.CurrentUserService" />
+		<property name="selectionTreeManager" ref="org.hisp.dhis.oust.manager.SelectionTreeManager" />
+		<property name="programPatientPropertyService"
+			ref="org.hisp.dhis.program.ProgramPatientPropertyService" />
 	</bean>
 
 	<bean
@@ -218,6 +221,8 @@
 			ref="org.hisp.dhis.patient.PatientAttributeService" />
 		<property name="patientAttributeValueService"
 			ref="org.hisp.dhis.patientattributevalue.PatientAttributeValueService" />
+		<property name="programPatientPropertyService"
+			ref="org.hisp.dhis.program.ProgramPatientPropertyService" />
 	</bean>
 
 	<!-- Single-event DataEntry -->
@@ -462,9 +467,8 @@
 		<property name="patientRegistrationFormService"
 			ref="org.hisp.dhis.patient.PatientRegistrationFormService" />
 		<property name="programInstanceService" ref="org.hisp.dhis.program.ProgramInstanceService" />
-		<property name="attributeGroupService">
-			<ref bean="org.hisp.dhis.patient.PatientAttributeGroupService" />
-		</property>
+		<property name="programPatientPropertyService"
+			ref="org.hisp.dhis.program.ProgramPatientPropertyService" />
 	</bean>
 
 	<bean id="org.hisp.dhis.caseentry.action.patient.AddPatientAction"
@@ -521,7 +525,6 @@
 	<bean id="org.hisp.dhis.caseentry.action.patient.ShowAddPatientFormAction"
 		class="org.hisp.dhis.caseentry.action.patient.ShowAddPatientFormAction"
 		scope="prototype">
-		<property name="patientService" ref="org.hisp.dhis.patient.PatientService" />
 		<property name="selectionManager"
 			ref="org.hisp.dhis.ouwt.manager.OrganisationUnitSelectionManager" />
 		<property name="attributeService">
@@ -536,9 +539,8 @@
 		<property name="patientRegistrationFormService">
 			<ref bean="org.hisp.dhis.patient.PatientRegistrationFormService" />
 		</property>
-		<property name="attributeGroupService">
-			<ref bean="org.hisp.dhis.patient.PatientAttributeGroupService" />
-		</property>
+		<property name="programPatientPropertyService"
+			ref="org.hisp.dhis.program.ProgramPatientPropertyService" />
 	</bean>
 
 	<bean id="org.hisp.dhis.caseentry.action.patient.ValidatePatientAction"
@@ -656,6 +658,9 @@
 			ref="org.hisp.dhis.patientattributevalue.PatientAttributeValueService" />
 		<property name="selectedStateManager"
 			ref="org.hisp.dhis.caseentry.state.SelectedStateManager" />
+		<property name="programPatientPropertyService"
+			ref="org.hisp.dhis.program.ProgramPatientPropertyService" />
+			
 	</bean>
 
 	<bean
@@ -834,6 +839,8 @@
 		<property name="programService" ref="org.hisp.dhis.program.ProgramService" />
 		<property name="selectionManager"
 			ref="org.hisp.dhis.ouwt.manager.OrganisationUnitSelectionManager" />
+		<property name="programPatientPropertyService"
+			ref="org.hisp.dhis.program.ProgramPatientPropertyService" />
 	</bean>
 
 	<bean
@@ -908,6 +915,8 @@
 			ref="org.hisp.dhis.patient.PatientIdentifierTypeService" />
 		<property name="attributeService"
 			ref="org.hisp.dhis.patient.PatientAttributeService" />
+		<property name="programPatientPropertyService"
+			ref="org.hisp.dhis.program.ProgramPatientPropertyService" />
 	</bean>
 
 	<bean

=== modified file 'dhis-2/dhis-web/dhis-web-caseentry/src/main/webapp/dhis-web-caseentry/dataentryRecords.vm'
--- dhis-2/dhis-web/dhis-web-caseentry/src/main/webapp/dhis-web-caseentry/dataentryRecords.vm	2013-09-23 03:15:40 +0000
+++ dhis-2/dhis-web/dhis-web-caseentry/src/main/webapp/dhis-web-caseentry/dataentryRecords.vm	2013-09-27 04:43:25 +0000
@@ -61,9 +61,9 @@
 			#if( $auth.hasAccess( "dhis-web-caseentry", "accessPatientAttributes" ) )
 			<td><a href="javascript:isDashboard=false;showPatientDashboardForm( '$patient.id' )">
 				#set($value="")
-				#foreach( $identifierType in $identifierTypes)
+				#foreach( $programIdentifierType in $identifierTypes)
 					#foreach( $identifier in $patient.identifiers)
-						#if($identifier.identifierType.id==$identifierType.id)
+						#if($identifier.identifierType.id==$programIdentifierType.patientIdentifierType.id)
 							#set($value=$identifier.identifier)
 						#end
 					#end

=== modified file 'dhis-2/dhis-web/dhis-web-caseentry/src/main/webapp/dhis-web-caseentry/defaultPatientForm.vm'
--- dhis-2/dhis-web/dhis-web-caseentry/src/main/webapp/dhis-web-caseentry/defaultPatientForm.vm	2013-09-23 03:15:40 +0000
+++ dhis-2/dhis-web/dhis-web-caseentry/src/main/webapp/dhis-web-caseentry/defaultPatientForm.vm	2013-09-27 04:43:25 +0000
@@ -1,214 +1,225 @@
 
-#if($patientRegistrationForm.fixedAttributes.contains( 'registrationDate' ))
-	<tr id='registrationDateTR'>
-		<td class='text-column'><label for="registration_date">$i18n.getString( "registration_date" ) <em title="$i18n.getString( 'required' )" class="required">*</em></label></td>
-		<td class="input-column" colspan='2'>
-			<input type="text" id="registrationDate" name="registrationDate" class="{validate:{required:true}}" value='$!format.formatDate($!patient.registrationDate)'/>
-		</td>		
-	</tr>
-#end
-
-<tr>
-	<th colspan="2" class="heading-column">$i18n.getString( "demographics" )</th>
-</tr>
-
-#if($patientRegistrationForm.fixedAttributes.contains( 'fullName' ))
-	<tr>
-		<td class='text-column'><label for="fullName">$i18n.getString( "full_name" ) <em title="$i18n.getString( "required" )" class="required">*</em></label></td>
-		<td class="input-column"><input type="text" id="fullName" name="fullName" value="$!patient.name" class="{validate:{required:true, rangelength:[3,50]}}"></td>
-	</tr>
-#end
-
-#if($patientRegistrationForm.fixedAttributes.contains( 'gender' ))
-	<tr>
-		<td class='text-column'><label for="gender">$i18n.getString( "gender" ) <em title="$i18n.getString( "required" )" class="required">*</em></label></td>
-		<td class="input-column">
-			<select id="gender" name="gender">
-				<option value="M" #if( $!patient.gender == 'M' ) selected="selected" #end>$i18n.getString( "male" )</option>
-				<option value="F" #if( $!patient.gender == 'F' ) selected="selected" #end>$i18n.getString( "female" )</option>
-				<option value="T" #if( $!patient.gender == 'T' ) selected="selected" #end>$i18n.getString( "transgender" )</option>
-			</select>
-		</td>					
-	</tr>
-#end
-
-<tr>
-	<td class='text-column' ><label for="birthDate">$i18n.getString( "date_of_birth" ) <em title="$i18n.getString( 'required' )" class="required">*</em></label></td>
-	<td class="input-column">
-		<select id='dobType' name="dobType" style='width:120px' onchange='dobTypeOnChange("patientForm")' >
-			<option value="V" #if($patient.dobType=='V') selected #end >$i18n.getString( "verified" )</option>
-			<option value="D" #if($patient.dobType=='D') selected #end >$i18n.getString( "declared" )</option>
-			<option value="A" #if($patient.dobType=='A') selected #end >$i18n.getString( "approximated" )</option>
-		</select>
-		#if($patientRegistrationForm.fixedAttributes.contains( 'birthDate' ))
-			<input type="text" id="birthDate" name="birthDate" value='$!format.formatDate($!patient.birthDate)' style='width:136px;' />
-		#else
-			<input type="text" id="age" name="age" placeholder="$i18n.getString('enter_age_in_years')" value='$!patient.getIntegerValueOfAge()' class="{validate:{number:true}}" style='width:136px;' />
-		#end
-	</td>
-</tr>
-
-<tr>
-	<td></td>
-	<td class="input-column">
-		<input id="memberValidator" class="hidden {validate:{required:true}}"/>
-	</td>
-</tr>
-	
-#if($patientRegistrationForm.fixedAttributes.contains( 'phoneNumber' ))
-	<tr>
-		<td class='text-column'><label for="phoneNumber">$i18n.getString( "phone_number" )</label></td>
-		<td class="input-column">
-			<input type="text" id="phoneNumber" name="phoneNumber" class="{validate:{phone:true}}"/>
-			<input type="button" value='+' style='width:20px;' onclick='addPhoneNumberField("$!phoneNumberAreaCode");' />
-		</td>
-	</tr>
-#end
-
-#if($patientRegistrationForm.fixedAttributes.contains( 'healthWorker' ))
-	<tr>
-		<td class='text-column'><label for="healthWorker">$i18n.getString( "health_worker" )</label></td>
-		<td class="input-column">
-			<select id="healthWorkerId" name="healthWorkerId">
-				<option value="">[$i18n.getString("please_select")]</option>
-				#foreach( $healthWorker in $healthWorkers)
-					<option value="$healthWorker.id" #if($patient.healthWorker.id == $healthWorker.id) selected #end>$healthWorker.name</option>
+#set($programPatientProperties = $program.programPatientProperties)
+#if($programPatientProperties.size() > 0 )
+	<tr>
+		<th colspan="2" class="heading-column">$i18n.getString( "demographics" )</th>
+	</tr>
+#end
+
+#foreach ($programPatientProperty in $programPatientProperties)
+	#if( $programPatientProperty.isProperty()=='true')
+
+		#if( $programPatientProperty.propertyName == 'registrationDate')
+			<tr id='registrationDateTR'>
+				<td class='text-column'><label for="registration_date">$i18n.getString( "registration_date" ) <em title="$i18n.getString( 'required' )" class="required">*</em></label></td>
+				<td class="input-column" colspan='2'>
+					<input type="text" id="registrationDate" name="registrationDate" class="{validate:{required:true}}" value='$!format.formatDate($!patient.registrationDate)'/>
+				</td>		
+			</tr>
+		#end
+		
+		#if($programPatientProperty.propertyName == 'fullName' )
+			<tr>
+				<td class='text-column'><label for="fullName">$i18n.getString( "full_name" ) <em title="$i18n.getString( "required" )" class="required">*</em></label></td>
+				<td class="input-column"><input type="text" id="fullName" name="fullName" value="$!patient.name" class="{validate:{required:true, rangelength:[3,50]}}"></td>
+			</tr>
+		#end
+
+		#if($programPatientProperty.propertyName == 'gender' )
+			<tr>
+				<td class='text-column'><label for="gender">$i18n.getString( "gender" ) <em title="$i18n.getString( "required" )" class="required">*</em></label></td>
+				<td class="input-column">
+					<select id="gender" name="gender">
+						<option value="M" #if( $!patient.gender == 'M' ) selected="selected" #end>$i18n.getString( "male" )</option>
+						<option value="F" #if( $!patient.gender == 'F' ) selected="selected" #end>$i18n.getString( "female" )</option>
+						<option value="T" #if( $!patient.gender == 'T' ) selected="selected" #end>$i18n.getString( "transgender" )</option>
+					</select>
+				</td>					
+			</tr>
+		#end
+
+		#if($programPatientProperty.propertyName == 'birthDate' )
+		<tr>
+			<td class='text-column' ><label for="birthDate">$i18n.getString( "date_of_birth" ) <em title="$i18n.getString( 'required' )" class="required">*</em></label></td>
+			<td class="input-column">
+				<select id='dobType' name="dobType" style='width:120px' onchange='dobTypeOnChange("patientForm")' >
+					<option value="V" #if($patient.dobType=='V') selected #end >$i18n.getString( "verified" )</option>
+					<option value="D" #if($patient.dobType=='D') selected #end >$i18n.getString( "declared" )</option>
+					<option value="A" #if($patient.dobType=='A') selected #end >$i18n.getString( "approximated" )</option>
+				</select>
+				#if($patientRegistrationForm.fixedAttributes.contains( 'birthDate' ))
+					<input type="text" id="birthDate" name="birthDate" value='$!format.formatDate($!patient.birthDate)' style='width:136px;' />
+				#else
+					<input type="text" id="age" name="age" placeholder="$i18n.getString('enter_age_in_years')" value='$!patient.getIntegerValueOfAge()' class="{validate:{number:true}}" style='width:136px;' />
 				#end
-			</select>
-		</td>
-	</tr>
-#end
-
-<!-- UNDERAGE -->
-
-#if($!patient.underAge)
-	#set( $representative = $!patient.representative ) 
-	<tr id="representativeFormDiv" name="representativeFormDiv">
-		<td class='text-column'>$i18n.getString("guardian")</td>
-		<td> 
-			$!patient.representative.name <img src="../images/information.png" alt="$i18n.getString( 'show_details' )" onclick='showRepresentativeInfo()' class='img-button'>
-		</td>
-	</tr>
-#else
-	<tr id="underAgeDiv" name="underAgeDiv">
-		<td class='text-column'>$i18n.getString("has_guardian")</td>
-		<td>
-			<input type="checkbox" name="underAge" id="underAge" onclick="toggleUnderAge(this);" value="true" #if($!patient.underAge == "true") checked="checked" #end/>
-		</td>
-	</tr>
-#end
-
-<!-- DEAD -->
-#if($patientRegistrationForm.fixedAttributes.contains( 'isDead' ))
-	<tr id="deathCheckboxTR">
-		<td class='text-column'>$i18n.getString("is_dead")</td>
-		<td>
-			<input type="checkbox" name="isDead" id="isDead" value="true" #if($!patient.isDead) checked="checked" #end onchange='isDeathOnChange();'/>
-		</td>
-	</tr>
-#end
-
-#if($patientRegistrationForm.fixedAttributes.contains( 'deathDate' ))
-	<tr id='deathDateTR' #if($!patient.isDead) #else class="hidden" #end>
-		<td class='text-column'><label for="deathDate">$i18n.getString("death_date")</label></td>
-		<td class="input-column">
-			<input type="text" name="deathDate" id="deathDate" #if($!patient.deathDate) value="$format.formatDate( $!patient.deathDate )" #end>
-		</td>
-	</tr>
-#end
-
-<tr>
-	<td></td>
-	<td><input type="button" class='button' id='checkDuplicateBtn' name='checkDuplicateBtn' value="$i18n.getString('check_duplicate')" /></td>
-</tr>
-
-<tr><td>&nbsp;</td></tr>
-#set($identifierTypes = $patientRegistrationForm.identifierTypes)
-#if( $identifierTypes.size() > 0)
+			</td>
+		</tr>
+		#end
+		
+		#if($programPatientProperty.propertyName == 'phoneNumber' )
+			<tr>
+				<td class='text-column'><label for="phoneNumber">$i18n.getString( "phone_number" )</label></td>
+				<td class="input-column">
+					<input type="text" id="phoneNumber" name="phoneNumber" class="{validate:{phone:true}}"/>
+					<input type="button" value='+' style='width:20px;' onclick='addPhoneNumberField("$!phoneNumberAreaCode");' />
+				</td>
+			</tr>
+		#end
+
+		#if($programPatientProperty.propertyName == 'healthWorker' )
+			<tr>
+				<td class='text-column'><label for="healthWorker">$i18n.getString( "health_worker" )</label></td>
+				<td class="input-column">
+					<select id="healthWorkerId" name="healthWorkerId">
+						<option value="">[$i18n.getString("please_select")]</option>
+						#foreach( $healthWorker in $healthWorkers)
+							<option value="$healthWorker.id" #if($patient.healthWorker.id == $healthWorker.id) selected #end>$healthWorker.name</option>
+						#end
+					</select>
+				</td>
+			</tr>
+		#end
+
+		<!-- UNDERAGE -->
+
+		#if($!patient.underAge)
+			#set( $representative = $!patient.representative ) 
+			<tr id="representativeFormDiv" name="representativeFormDiv">
+				<td class='text-column'>$i18n.getString("guardian")</td>
+				<td> 
+					$!patient.representative.name <img src="../images/information.png" alt="$i18n.getString( 'show_details' )" onclick='showRepresentativeInfo()' class='img-button'>
+				</td>
+			</tr>
+		#elseif($!patient)
+			<tr id="underAgeDiv" name="underAgeDiv">
+				<td class='text-column'>$i18n.getString("has_guardian")</td>
+				<td>
+					<input type="checkbox" name="underAge" id="underAge" onclick="toggleUnderAge(this);" value="true" #if($!patient.underAge == "true") checked="checked" #end/>
+				</td>
+			</tr>
+		#end
+
+		<!-- DEAD -->
+		#if($programPatientProperty.propertyName == 'isDead' )
+			<tr id="deathCheckboxTR">
+				<td class='text-column'>$i18n.getString("is_dead")</td>
+				<td>
+					<input type="checkbox" name="isDead" id="isDead" value="true" #if($!patient.isDead) checked="checked" #end onchange='isDeathOnChange();'/>
+				</td>
+			</tr>
+		#end
+
+		#if($programPatientProperty.propertyName == 'deathDate' )
+			<tr id='deathDateTR' #if($!patient.isDead) #else class="hidden" #end>
+				<td class='text-column'><label for="deathDate">$i18n.getString("death_date")</label></td>
+				<td class="input-column">
+					<input type="text" name="deathDate" id="deathDate" #if($!patient.deathDate) value="$format.formatDate( $!patient.deathDate )" #end>
+				</td>
+			</tr>
+		#end
+
 	<!--IDENTIFIERS -->
-	<tr><th colspan="2" class="heading-column">$i18n.getString("patient_details")</th></tr>
-	#foreach ($identifierType in $identifierTypes)
-		#if( $identifierType.program )
+	#elseif( $programPatientProperty.isIdentifierType())
+		<tr><th colspan="2" class="heading-column">$i18n.getString("patient_details")</th></tr>
+		#set( $identifierType = $programPatientProperty.patientIdentifierType)
+		#set( $identifier = '' )
+		#set( $identifier = $identiferMap.get( $identifierType.id ) )
+		#if( $!identifier &&  $identifier != '' )
+		#elseif($!patient)
 		#else
-			#set( $identifier = '' )
-			#set( $identifier = $identiferMap.get( $identifierType.id ) )
-			#if($identifierType.type=='orgunitCount' && $!orgunitCountIdentifier)
-				#set( $identifier = $!orgunitCountIdentifier )
-			#end
-		
-			<tr> 
-				<td class='text-column'><label>$encoder.htmlEncode($identifierType.displayName) #if($identifierType.mandatory) <em title="$i18n.getString( "required" )" class="required">*</em> #end</label></td>
-				<td class="input-column">
-					<input type="text" id="iden$identifierType.id" name="iden$identifierType.id" value="$!identifier" data="{related:$identifierType.related}" #if($identifierType.related && $!patient.underAge) disabled="disabled" #end class="{validate:{required:$identifierType.mandatory, #if($!identifierType.noChars) maxlength:$identifierType.noChars, #end #if($identifierType.type=='number') number:true #elseif($!identifierType.type=='letter') lettersonly:true #end }}" />
-				</td>	
-			</tr>
+			#set( $identifier = $programPatientProperty.defaultValue )
 		#end
-	#end
-#end
-
-<!-- ATTRIBUTES IN GROUPS -->
-	
-	
-#foreach($attribute in $$patientRegistrationForm.dynamicAttributes )
-	#if( $attribute )
+		<tr #if($programPatientProperty.hidden=='true') class='hidden' #end > 
+			<td class='text-column' ><label>$encoder.htmlEncode($identifierType.displayName) #if($identifierType.mandatory) <em title="$i18n.getString( "required" )" class="required">*</em> #end</label></td>
+			<td class="input-column">
+				<input type="text" id="iden$identifierType.id" name="iden$identifierType.id" value="$!identifier" 
+					data="{related:$identifierType.related}" 
+					#if($identifierType.related && $!patient.underAge) disabled="disabled" #end 
+					class="{validate:{required:$identifierType.mandatory, 
+						#if($!identifierType.noChars) maxlength:$identifierType.noChars, #end 
+						#if($identifierType.type=='number') 
+							number:true 
+						#elseif($!identifierType.type=='letter') 
+							lettersonly:true 
+						#end 
+						}}" />
+			</td>	
+		</tr>
+		
+	<!-- ATTRIBUTES IN GROUPS -->
+	#elseif( $programPatientProperty.isAttribute())
+		#set($attribute = $programPatientProperty.patientAttribute)
+		
 		#set($value = "")
 		#set($value = $patientAttributeValueMap.get($attribute.id))
-		<tr>
+		#if( $!value && $value != '')
+		#elseif($!patient)
+		#else
+			#set( $value = $programAttribute.defaultValue )
+		#end
+		
+		#set($hidden = "")
+		#if($programPatientProperty.hidden=='true')
+			#set($hidden = "hidden")
+		#end
+		<tr class='$hidden'>
 			<td class='text-column'><label>$encoder.htmlEncode($attribute.displayName) #if($attribute.mandatory) <em title="$i18n.getString( 'required' )" class="required">*</em> #end</label></td>
 			<td class="input-column">
 				#if( $attribute.valueType == "bool" )
-					<select id="attr$attribute.id" name="attr$attribute.id" inherit="$!attribute.inherit"> 
+					<select id="attr$attribute.id" name="attr$attribute.id" inherit="$!attribute.inherit" 
+						class="{validate:{required:$identifierType.mandatory}}" > 
 						<option value="" selected="selected">[$i18n.getString( "please_select" )]</option>
 						<option value="true" #if($value=='true') selected #end>$i18n.getString( "yes" )</option>
 						<option value="false" #if($value=='false') selected #end>$i18n.getString( "no" )</option>
 					</select>                
 				#elseif( $attribute.valueType == "trueOnly" )
-					<input type='checkbox' value="true" id="attr$attribute.id" name="attr$attribute.id" inherit="$!attribute.inherit" #if($value=='true') checked #end> 
+					<input type='checkbox' value="true" id="attr$attribute.id" name="attr$attribute.id" inherit="$!attribute.inherit" 
+						#if($value=='true') checked #end class="{validate:{required:$identifierType.mandatory}} " > 
 				#elseif( $attribute.valueType == "date" )
 					<input type="text" id="attr$attribute.id" name="attr$attribute.id" inherit="$!attribute.inherit" value='$value' class=' #validate( "default"  $attribute.mandatory )'/>
 					<script type="text/javascript">
 						datePickerValid( 'attr$attribute.id', false, false );
 					</script>                    
 				#elseif( $attribute.valueType == "combo" )  
-					<select  id="attr$attribute.id"  name="attr$attribute.id" inherit="$!attribute.inherit" class='#validate( "default"  $attribute.mandatory )'>
+					<select  id="attr$attribute.id"  name="attr$attribute.id" inherit="$!attribute.inherit" 
+						class="{validate:{required:$identifierType.mandatory}} " >
 						<option value="">[$i18n.getString( "please_select" )]</option>
 						#foreach ($option in $attribute.attributeOptions )
 							<option value="$option.id" #if("$value"=="$option.name") selected #end>$option.name</option>
 						#end
 					</select>
 				#else
-					<input type="text" id="attr$attribute.id" name="attr$attribute.id" inherit="$!attribute.inherit" value='$value' class="{validate:{required:$attribute.mandatory #if($attribute.valueType=='NUMBER'),number:true #end }}" />
+					<input type="text" id="attr$attribute.id" name="attr$attribute.id" inherit="$!attribute.inherit" value='$value' 
+						class="{validate:{required:$attribute.mandatory #if($attribute.valueType=='NUMBER'),number:true #end }} " />
 				#end
 			</td>		
 		</tr>
 	#end
 #end
-	
+
 <!-- PROGRAM ENROLLMENT -->
 
-#if($!program)
-	<tr><td>&nbsp;</td></tr>
-	<tr><th colspan="2" class="heading-column">$i18n.getString( "program_enrollment" )</th></tr>
-	<tr>
-		<tr>
-		<td class='text-column'><label for="enrollmentDate">$encoder.htmlEncode($program.dateOfEnrollmentDescription) <em title="$i18n.getString( "required" )" class="required">*</em></label></td>
-		<td colspan='2' class='input-column'><input type="text" id="enrollmentDate" name="enrollmentDate" class="{validate:{required:true}}"></td>
+<tr><td>&nbsp;</td></tr>
+<tr><th colspan="2" class="heading-column">$i18n.getString( "program_enrollment" )</th></tr>
+<tr>
+	<tr>
+	<td class='text-column'><label for="enrollmentDate">$encoder.htmlEncode($program.dateOfEnrollmentDescription) <em title="$i18n.getString( "required" )" class="required">*</em></label></td>
+	<td colspan='2' class='input-column'><input type="text" id="enrollmentDate" name="enrollmentDate" class="{validate:{required:true}}"></td>
+</tr>
+#if($!program.displayIncidentDate=='true')
+	<tr>
+		<td class='text-column'><label for="dateOfIncident">$encoder.htmlEncode($program.dateOfIncidentDescription) <em title="$i18n.getString( "required" )" class="required">*</em></label></td>
+		<td colspan='2' class='input-column'><input type="text" id="dateOfIncident" name="dateOfIncident"  class="{validate:{required:true}}"></td>
 	</tr>
-	#if($!program.displayIncidentDate=='true')
-		<tr>
-			<td class='text-column'><label for="dateOfIncident">$encoder.htmlEncode($program.dateOfIncidentDescription) <em title="$i18n.getString( "required" )" class="required">*</em></label></td>
-			<td colspan='2' class='input-column'><input type="text" id="dateOfIncident" name="dateOfIncident"  class="{validate:{required:true}}"></td>
-		</tr>
-		<script>
-			#if($program.selectEnrollmentDatesInFuture=='true' || $program.selectIncidentDatesInFuture=='true'  )
-				datePickerInRange( 'dateOfIncident' , 'enrollmentDate', false, true );
-			#else
-				datePickerInRangeValid( 'dateOfIncident' , 'enrollmentDate', false, true );
-			#end
-		</script>
-	#else
-		<script>datePickerValid( 'enrollmentDate', true );</script>
-	#end
+	<script>
+		#if($program.selectEnrollmentDatesInFuture=='true' || $program.selectIncidentDatesInFuture=='true'  )
+			datePickerInRange( 'dateOfIncident' , 'enrollmentDate', false, true );
+		#else
+			datePickerInRangeValid( 'dateOfIncident' , 'enrollmentDate', false, true );
+		#end
+	</script>
+#else
+	<script>datePickerValid( 'enrollmentDate', true );</script>
 #end
 
 <script>

=== modified file 'dhis-2/dhis-web/dhis-web-caseentry/src/main/webapp/dhis-web-caseentry/patientForm.vm'
--- dhis-2/dhis-web/dhis-web-caseentry/src/main/webapp/dhis-web-caseentry/patientForm.vm	2013-09-23 03:15:40 +0000
+++ dhis-2/dhis-web/dhis-web-caseentry/src/main/webapp/dhis-web-caseentry/patientForm.vm	2013-09-27 04:43:25 +0000
@@ -4,7 +4,7 @@
 
 #if($!customRegistrationForm)
 	$customRegistrationForm
-#elseif($!patientRegistrationForm)
+#elseif($!program)
 	#parse( "/dhis-web-caseentry/defaultPatientForm.vm" )
 #else
 	## Macro for generating the jQuery validation rules 
@@ -125,141 +125,66 @@
 
 	<tr><td>&nbsp;</td></tr>
 
-#if( $identifierTypes.size() > 0)
-	<!--IDENTIFIERS -->
-	<tr><th colspan="2" class="heading-column">$i18n.getString("patient_identifiers")</th></tr>
-	#foreach ($identifierType in $identifierTypes)
-		#if( $identifierType.program )
-		#else
-			#set( $identifier = '' )
-			#set( $identifier = $identiferMap.get( $identifierType.id ) )
-			#if($identifierType.type=='orgunitCount' && $!orgunitCountIdentifier)
-				#set( $identifier = $!orgunitCountIdentifier )
-			#end
-		
-			<tr name='idenFields'> 
-				<td class='text-column'><label>$encoder.htmlEncode($identifierType.displayName) #if($identifierType.mandatory) <em title="$i18n.getString( "required" )" class="required">*</em> #end</label></td>
-				<td class="input-column">
-					<input type="text" id="iden$identifierType.id" name="iden$identifierType.id" value="$!identifier" data="{related:$identifierType.related}" #if($identifierType.related && $!patient.underAge) disabled="disabled" #end 
-						class="{validate:{required:$identifierType.mandatory, #if($!identifierType.noChars) maxlength:$identifierType.noChars, #end #if($identifierType.type=='number') number:true #elseif($!identifierType.type=='letter') lettersonly:true #end }}" 
-						#if($identifierType.type=='orgunitCount') readonly #end />
-				</td>	
-			</tr>
-		#end
-	#end
-#end
-
-	<!-- ATTRIBUTES IN GROUPS -->
-	
-	#foreach ($attributeGroup in $attributeGroups )
-		#set($attributes = $attributesMap.get($attributeGroup.displayName))
-		<tr><td>&nbsp;</td></tr>
-		<tr><th colspan="2" class="heading-column">$attributeGroup.displayName</th></tr>
-		#foreach($attribute in $attributes )
-			#if( $attribute )
-				#set($value = "")
-				#set($value = $patientAttributeValueMap.get($attribute.id))
-				<tr name='attributesFields'>
-					<td class='text-column'><label>$encoder.htmlEncode($attribute.displayName) #if($attribute.mandatory) <em title="$i18n.getString( 'required' )" class="required">*</em> #end</label></td>
+	#if( $identifierTypes.size() > 0)
+		<!--IDENTIFIERS -->
+		<tr><th colspan="2" class="heading-column">$i18n.getString("patient_identifiers")</th></tr>
+		#foreach ($identifierType in $identifierTypes)
+			#if( $identifierType.program )
+			#else
+				#set( $identifier = '' )
+				#set( $identifier = $identiferMap.get( $identifierType.id ) )
+				#if($identifierType.type=='orgunitCount' && $!orgunitCountIdentifier)
+					#set( $identifier = $!orgunitCountIdentifier )
+				#end
+			
+				<tr name='idenFields'> 
+					<td class='text-column'><label>$encoder.htmlEncode($identifierType.displayName) #if($identifierType.mandatory) <em title="$i18n.getString( "required" )" class="required">*</em> #end</label></td>
 					<td class="input-column">
-						#if( $attribute.valueType == "bool" )
-							<select id="attr$attribute.id" name="attr$attribute.id" inherit="$!attribute.inherit"> 
-								<option value="" selected="selected">[$i18n.getString( "please_select" )]</option>
-								<option value="true" #if($value=='true') selected #end>$i18n.getString( "yes" )</option>
-								<option value="false" #if($value=='false') selected #end>$i18n.getString( "no" )</option>
-							</select>                
-						#elseif( $attribute.valueType == "trueOnly" )
-							<input type='checkbox' value="true" id="attr$attribute.id" name="attr$attribute.id" inherit="$!attribute.inherit" #if($value=='true') checked #end> 
-						#elseif( $attribute.valueType == "date" )
-							<input type="text" id="attr$attribute.id" name="attr$attribute.id" inherit="$!attribute.inherit" value='$value' class=' #validate( "default"  $attribute.mandatory )'/>
-							<script type="text/javascript">
-								datePickerValid( 'attr$attribute.id', false, false );
-							</script>                    
-						#elseif( $attribute.valueType == "combo" )  
-							<select  id="attr$attribute.id"  name="attr$attribute.id" inherit="$!attribute.inherit" class='#validate( "default"  $attribute.mandatory )'>
-								<option value="">[$i18n.getString( "please_select" )]</option>
-								#foreach ($option in $attribute.attributeOptions )
-									<option value="$option.id" #if("$value"=="$option.name") selected #end>$option.name</option>
-								#end
-							</select>
-						#else
-							<input type="text" id="attr$attribute.id" name="attr$attribute.id" inherit="$!attribute.inherit" value='$value' class="{validate:{required:$attribute.mandatory #if($attribute.valueType=='NUMBER'),number:true #end }}" />
-						#end
-					</td>		
+						<input type="text" id="iden$identifierType.id" name="iden$identifierType.id" value="$!identifier" data="{related:$identifierType.related}" #if($identifierType.related && $!patient.underAge) disabled="disabled" #end 
+							class="{validate:{required:$identifierType.mandatory, #if($!identifierType.noChars) maxlength:$identifierType.noChars, #end #if($identifierType.type=='number') number:true #elseif($!identifierType.type=='letter') lettersonly:true #end }}" 
+							#if($identifierType.type=='orgunitCount') readonly #end />
+					</td>	
 				</tr>
 			#end
 		#end
 	#end
 
-	<tr><td>&nbsp;</td></tr>
-
-	<!-- ATTRIBUTES NOT IN GROUPS -->
-	#set($attributes = $attributesMap.get(""))
-	#if ($!attributes) 
-		<tr><th colspan="2" class="heading-column">$i18n.getString( "other_details" )</th></tr>
-		#foreach($attribute in $attributes )
-			#set( $attributeValue = "" )
-			#set( $attributeValue = $!patientAttributeValueMap.get( $attribute.id ) )
-			#if( $attribute.valueType != 'calculated')
+	<!-- ATTRIBUTES IN GROUPS -->
+	
+	#foreach($attribute in $attributes )
+		#if( $attribute )
+			#set($value = "")
+			#set($value = $patientAttributeValueMap.get($attribute.id))
 			<tr name='attributesFields'>
-				<td class='text-column'><label>$encoder.htmlEncode($attribute.displayName) #if($attribute.mandatory) <em title="$i18n.getString( "required" )" class="required">*</em> #end</label></td>
+				<td class='text-column'><label>$encoder.htmlEncode($attribute.displayName) #if($attribute.mandatory) <em title="$i18n.getString( 'required' )" class="required">*</em> #end</label></td>
 				<td class="input-column">
 					#if( $attribute.valueType == "bool" )
-						<select id="attr$attribute.id"  name="attr$attribute.id" inherit="$!attribute.inherit">              
-							<option value="">[$i18n.getString( "please_select" )]</option>
-							<option value="true" #if( $attributeValue ) selected="selected" #end>$i18n.getString( "yes" )</option>
-							<option value="false" #if( !$attributeValue ) selected="selected" #end>$i18n.getString( "no" )</option>
+						<select id="attr$attribute.id" name="attr$attribute.id" inherit="$!attribute.inherit"> 
+							<option value="" selected="selected">[$i18n.getString( "please_select" )]</option>
+							<option value="true" #if($value=='true') selected #end>$i18n.getString( "yes" )</option>
+							<option value="false" #if($value=='false') selected #end>$i18n.getString( "no" )</option>
 						</select>                
 					#elseif( $attribute.valueType == "trueOnly" )
 						<input type='checkbox' value="true" id="attr$attribute.id" name="attr$attribute.id" inherit="$!attribute.inherit" #if($value=='true') checked #end> 
 					#elseif( $attribute.valueType == "date" )
-						<input type="text" id="attr$attribute.id" name="attr$attribute.id" inherit="$!attribute.inherit" value="$!attributeValue" class=' #validate( "default"  $attribute.mandatory )'>
+						<input type="text" id="attr$attribute.id" name="attr$attribute.id" inherit="$!attribute.inherit" value='$value' class=' #validate( "default"  $attribute.mandatory )'/>
 						<script type="text/javascript">
 							datePickerValid( 'attr$attribute.id', false, false );
 						</script>                    
-					#elseif( $attribute.valueType == "combo" )
-						<select  id="attr$attribute.id"  name="attr$attribute.id" inherit="$!attribute.inherit" class=' #validate( "default"  $attribute.mandatory )' >
-							 <option value="">[$i18n.getString( "please_select" )]</option>
-						#foreach ($option in $attribute.attributeOptions )
-							<option value="$option.id" #if($attributeValue == $option.name) selected="selected" #end>$option.name</option>
-						#end
+					#elseif( $attribute.valueType == "combo" )  
+						<select  id="attr$attribute.id"  name="attr$attribute.id" inherit="$!attribute.inherit" class='#validate( "default"  $attribute.mandatory )'>
+							<option value="">[$i18n.getString( "please_select" )]</option>
+							#foreach ($option in $attribute.attributeOptions )
+								<option value="$option.id" #if("$value"=="$option.name") selected #end>$option.name</option>
+							#end
 						</select>
-					#else  
-						<input type="text"  id="attr$attribute.id" name="attr$attribute.id" inherit="$!attribute.inherit" value="$!attributeValue" class="{validate:{required:$attribute.mandatory #if($!attribute.noChars),maxlength:$attribute.noChars #end #if($attribute.valueType=='NUMBER'),number:true #end }}" >
+					#else
+						<input type="text" id="attr$attribute.id" name="attr$attribute.id" inherit="$!attribute.inherit" value='$value' class="{validate:{required:$attribute.mandatory #if($attribute.valueType=='NUMBER'),number:true #end }}" />
 					#end
 				</td>		
 			</tr>
-			#end
-		#end
-	#end
-	
-	<!-- PROGRAM ENROLLMENT -->
-	
-	#if($!program)
-		<tr><td>&nbsp;</td></tr>
-		<tr><th colspan="2" class="heading-column">$i18n.getString( "program_enrollment" )</th></tr>
-		<tr>
-			<tr>
-			<td class='text-column'><label for="enrollmentDate">$encoder.htmlEncode($program.dateOfEnrollmentDescription) <em title="$i18n.getString( "required" )" class="required">*</em></label></td>
-			<td colspan='2' class='input-column'><input type="text" id="enrollmentDate" name="enrollmentDate" class="{validate:{required:true}}"></td>
-		</tr>
-		#if($!program.displayIncidentDate=='true')
-			<tr>
-				<td class='text-column'><label for="dateOfIncident">$encoder.htmlEncode($program.dateOfIncidentDescription) <em title="$i18n.getString( "required" )" class="required">*</em></label></td>
-				<td colspan='2' class='input-column'><input type="text" id="dateOfIncident" name="dateOfIncident"  class="{validate:{required:true}}"></td>
-			</tr>
-			<script>
-				#if($program.selectEnrollmentDatesInFuture=='true' || $program.selectIncidentDatesInFuture=='true' )
-					datePickerInRange( 'dateOfIncident' , 'enrollmentDate', false, true );
-				#else
-					datePickerInRangeValid( 'dateOfIncident' , 'enrollmentDate', false, true );
-				#end
-			</script>
-		#else
-			<script>datePickerValid( 'enrollmentDate', true );</script>
-		#end
-	#end
-
+		#end
+	#end
 #end
 
 <script>

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/caseaggregation/GetParamsByProgramAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/caseaggregation/GetParamsByProgramAction.java	2013-08-23 16:05:01 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/caseaggregation/GetParamsByProgramAction.java	2013-09-27 04:43:25 +0000
@@ -36,6 +36,7 @@
 import org.hisp.dhis.patient.PatientAttribute;
 import org.hisp.dhis.patient.PatientAttributeService;
 import org.hisp.dhis.program.Program;
+import org.hisp.dhis.program.ProgramPatientPropertyService;
 import org.hisp.dhis.program.ProgramService;
 import org.hisp.dhis.program.ProgramStage;
 
@@ -68,6 +69,13 @@
         this.attributeService = attributeService;
     }
 
+    private ProgramPatientPropertyService programPatientPropertyService;
+
+    public void setProgramPatientPropertyService( ProgramPatientPropertyService programPatientPropertyService )
+    {
+        this.programPatientPropertyService = programPatientPropertyService;
+    }
+
     // -------------------------------------------------------------------------
     // Input & Output
     // -------------------------------------------------------------------------
@@ -107,13 +115,13 @@
 
             Collection<Program> programs = programService.getAllPrograms();
             programs.remove( program );
-            
+
             for ( Program _program : programs )
             {
-                patientAttributes.remove( _program.getPatientAttributes() );
+                patientAttributes.removeAll( programPatientPropertyService.getPatientAttributes( _program ) );
             }
         }
-        
+
         return SUCCESS;
     }
 }

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/dataentryform/ViewPatientRegistrationFormAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/dataentryform/ViewPatientRegistrationFormAction.java	2013-09-11 16:02:06 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/dataentryform/ViewPatientRegistrationFormAction.java	2013-09-27 04:43:25 +0000
@@ -40,6 +40,7 @@
 import org.hisp.dhis.patient.PatientRegistrationForm;
 import org.hisp.dhis.patient.PatientRegistrationFormService;
 import org.hisp.dhis.program.Program;
+import org.hisp.dhis.program.ProgramPatientPropertyService;
 import org.hisp.dhis.program.ProgramService;
 import org.hisp.dhis.setting.SystemSettingManager;
 import org.hisp.dhis.user.UserSettingService;
@@ -100,6 +101,13 @@
         this.userSettingService = userSettingService;
     }
 
+    private ProgramPatientPropertyService programPatientPropertyService;
+
+    public void setProgramPatientPropertyService( ProgramPatientPropertyService programPatientPropertyService )
+    {
+        this.programPatientPropertyService = programPatientPropertyService;
+    }
+
     // -------------------------------------------------------------------------
     // Getters & Setters
     // -------------------------------------------------------------------------
@@ -172,18 +180,20 @@
             attributes = patientAttributeService.getAllPatientAttributes();
             for ( Program p : programs )
             {
-                identifierTypes.remove( p.getPatientIdentifierTypes() );
-                attributes.remove( p.getPatientAttributes() );
+                identifierTypes.removeAll( programPatientPropertyService.getPatientIdentifierTypes( p ) );
+                attributes.removeAll( programPatientPropertyService.getPatientAttributes( p ) );
             }
         }
         else
         {
             program = programService.getProgram( programId );
-            identifierTypes = program.getPatientIdentifierTypes();
-            attributes = program.getPatientAttributes();
+            
+            identifierTypes.addAll( programPatientPropertyService.getPatientIdentifierTypes( program ) );
+            attributes.addAll( programPatientPropertyService.getPatientAttributes( program ) );
+            
             registrationForm = patientRegistrationFormService.getPatientRegistrationForm( program );
         }
-        
+
         // ---------------------------------------------------------------------
         // Get images
         // ---------------------------------------------------------------------

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/program/AddProgramAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/program/AddProgramAction.java	2013-09-16 09:47:59 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/program/AddProgramAction.java	2013-09-27 04:43:25 +0000
@@ -34,7 +34,6 @@
 import java.util.List;
 import java.util.Set;
 
-import org.hisp.dhis.patient.Patient;
 import org.hisp.dhis.patient.PatientAttribute;
 import org.hisp.dhis.patient.PatientAttributeService;
 import org.hisp.dhis.patient.PatientIdentifierType;
@@ -43,6 +42,8 @@
 import org.hisp.dhis.program.Program;
 import org.hisp.dhis.program.ProgramInstance;
 import org.hisp.dhis.program.ProgramInstanceService;
+import org.hisp.dhis.program.ProgramPatientProperty;
+import org.hisp.dhis.program.ProgramPatientPropertyService;
 import org.hisp.dhis.program.ProgramService;
 import org.hisp.dhis.program.ProgramStage;
 import org.hisp.dhis.program.ProgramStageService;
@@ -117,10 +118,31 @@
         this.relationshipTypeService = relationshipTypeService;
     }
 
+    private ProgramPatientPropertyService programPatientPropertyService;
+
+    public void setProgramPatientPropertyService( ProgramPatientPropertyService programPatientPropertyService )
+    {
+        this.programPatientPropertyService = programPatientPropertyService;
+    }
+
     // -------------------------------------------------------------------------
     // Input/Output
     // -------------------------------------------------------------------------
 
+    private List<Boolean> hiddens;
+
+    public void setHiddens( List<Boolean> hiddens )
+    {
+        this.hiddens = hiddens;
+    }
+
+    private List<String> defaultValues;
+
+    public void setDefaultValues( List<String> defaultValues )
+    {
+        this.defaultValues = defaultValues;
+    }
+
     private String name;
 
     public void setName( String name )
@@ -367,37 +389,10 @@
         program.setRelationshipFromA( relationshipFromA );
         program.setRelationshipText( relationshipText );
 
-        List<PatientIdentifierType> identifierTypes = new ArrayList<PatientIdentifierType>();
-        List<PatientAttribute> patientAttributes = new ArrayList<PatientAttribute>();
-        int index = 0;
-        for ( String selectedPropertyId : selectedPropertyIds )
-        {
-            String[] ids = selectedPropertyId.split( "_" );
-
-            if ( ids[0].equals( Patient.PREFIX_IDENTIFIER_TYPE ) )
-            {
-                PatientIdentifierType identifierType = patientIdentifierTypeService.getPatientIdentifierType( Integer
-                    .parseInt( ids[1] ) );
-
-                identifierType.setPersonDisplayName( personDisplayNames.get( index ) );
-                patientIdentifierTypeService.updatePatientIdentifierType( identifierType );
-
-                identifierTypes.add( identifierType );
-            }
-            else if ( ids[0].equals( Patient.PREFIX_PATIENT_ATTRIBUTE ) )
-            {
-                PatientAttribute patientAttribute = patientAttributeService.getPatientAttribute( Integer
-                    .parseInt( ids[1] ) );
-                patientAttributes.add( patientAttribute );
-            }
-
-            index++;
-        }
-
-        program.setPatientIdentifierTypes( identifierTypes );
-        program.setPatientAttributes( patientAttributes );
-
-        // Template messasges
+        // ---------------------------------------------------------------------
+        // Template messages
+        // ---------------------------------------------------------------------
+
         Set<PatientReminder> patientReminders = new HashSet<PatientReminder>();
         for ( int i = 0; i < daysAllowedSendMessages.size(); i++ )
         {
@@ -420,7 +415,54 @@
         }
         program.setPatientReminders( patientReminders );
 
-        programService.saveProgram( program );
+        int id = programService.saveProgram( program );
+        program.setId( id );
+
+        // ---------------------------------------------------------------------
+        // Create Program - Identifier-typse and Attributes association
+        // ---------------------------------------------------------------------
+
+        int index = 0;
+
+        for ( String patientProperty : selectedPropertyIds )
+        {
+            String[] property = patientProperty.split( Program.SEPARATE_CHARACTOR );
+            if ( property[0].equals( Program.PREFIX_IDENTIFIER_TYPE ) )
+            {
+                PatientIdentifierType identifierType = patientIdentifierTypeService.getPatientIdentifierType( Integer
+                    .parseInt( property[1] ) );
+                identifierType.setPersonDisplayName( personDisplayNames.get( index ) );
+                patientIdentifierTypeService.updatePatientIdentifierType( identifierType );
+
+                ProgramPatientProperty programPatientProperty = new ProgramPatientProperty( program, identifierType,
+                    defaultValues.get( index ), hiddens.get( index ), index );
+
+                programPatientPropertyService.addProgramPatientProperty( programPatientProperty );
+            }
+            else if ( property[0].equals( Program.PREFIX_ATTRIBUTE ) )
+            {
+                PatientAttribute patientAttribute = patientAttributeService.getPatientAttribute( Integer
+                    .parseInt( property[1] ) );
+
+                ProgramPatientProperty programPatientProperty = new ProgramPatientProperty( program,
+                    patientAttribute, defaultValues.get( index ), hiddens.get( index ), index );
+
+                programPatientPropertyService.addProgramPatientProperty( programPatientProperty );
+            }
+            else if ( property[0].equals( Program.PREFIX_PROPERTY ) )
+            {
+                ProgramPatientProperty programPatientProperty = new ProgramPatientProperty( program, property[1],
+                    defaultValues.get( index ), hiddens.get( index ), index );
+
+                programPatientPropertyService.addProgramPatientProperty( programPatientProperty );
+            }
+
+            index++;
+        }
+        
+        // ---------------------------------------------------------------------
+        // Create program-stage for single event program autocalically
+        // ---------------------------------------------------------------------
 
         if ( program.getType().equals( Program.SINGLE_EVENT_WITH_REGISTRATION )
             || program.getType().equals( Program.SINGLE_EVENT_WITHOUT_REGISTRATION ) )

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/program/ShowAddProgramFormAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/program/ShowAddProgramFormAction.java	2013-09-11 16:02:06 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/program/ShowAddProgramFormAction.java	2013-09-27 04:43:25 +0000
@@ -31,7 +31,6 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.List;
 
 import org.hisp.dhis.common.comparator.IdentifiableObjectNameComparator;
@@ -40,6 +39,7 @@
 import org.hisp.dhis.patient.PatientIdentifierType;
 import org.hisp.dhis.patient.PatientIdentifierTypeService;
 import org.hisp.dhis.program.Program;
+import org.hisp.dhis.program.ProgramPatientPropertyService;
 import org.hisp.dhis.program.ProgramService;
 import org.hisp.dhis.relationship.RelationshipType;
 import org.hisp.dhis.relationship.RelationshipTypeService;
@@ -94,6 +94,13 @@
         this.relationshipTypeService = relationshipTypeService;
     }
 
+    private ProgramPatientPropertyService programPatientPropertyService;
+
+    public void setProgramPatientPropertyService( ProgramPatientPropertyService programPatientPropertyService )
+    {
+        this.programPatientPropertyService = programPatientPropertyService;
+    }
+
     // -------------------------------------------------------------------------
     // Output
     // -------------------------------------------------------------------------
@@ -142,22 +149,21 @@
 
         programs = new ArrayList<Program>( programService.getAllPrograms() );
         Collections.sort( programs, IdentifiableObjectNameComparator.INSTANCE );
-       
-      
+
+        availableIdentifierTypes = patientIdentifierTypeService.getAllPatientIdentifierTypes();
         availableAttributes = patientAttributeService.getAllPatientAttributes();
- 
-        availableIdentifierTypes = patientIdentifierTypeService.getAllPatientIdentifierTypes();
+
         for ( Program p : programs )
         {
-            availableIdentifierTypes
-                .removeAll( new HashSet<PatientIdentifierType>( p.getPatientIdentifierTypes() ) );
+            availableIdentifierTypes.removeAll( programPatientPropertyService.getPatientIdentifierTypes( p ) );
+            availableAttributes.removeAll( programPatientPropertyService.getPatientAttributes( p ) );
         }
-        
+
         userGroups = new ArrayList<UserGroup>( userGroupService.getAllUserGroups() );
-        
-        relationshipTypes = new ArrayList<RelationshipType>(relationshipTypeService.getAllRelationshipTypes());
+
+        relationshipTypes = new ArrayList<RelationshipType>( relationshipTypeService.getAllRelationshipTypes() );
         Collections.sort( relationshipTypes, IdentifiableObjectNameComparator.INSTANCE );
-        
+
         return SUCCESS;
     }
 }

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/program/ShowUpdateProgramFormAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/program/ShowUpdateProgramFormAction.java	2013-09-11 16:02:06 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/program/ShowUpdateProgramFormAction.java	2013-09-27 04:43:25 +0000
@@ -31,7 +31,6 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.List;
 
 import org.hisp.dhis.common.comparator.IdentifiableObjectNameComparator;
@@ -42,6 +41,7 @@
 import org.hisp.dhis.patient.PatientIdentifierType;
 import org.hisp.dhis.patient.PatientIdentifierTypeService;
 import org.hisp.dhis.program.Program;
+import org.hisp.dhis.program.ProgramPatientPropertyService;
 import org.hisp.dhis.program.ProgramService;
 import org.hisp.dhis.relationship.RelationshipType;
 import org.hisp.dhis.relationship.RelationshipTypeService;
@@ -96,6 +96,13 @@
         this.relationshipTypeService = relationshipTypeService;
     }
 
+    private ProgramPatientPropertyService programPatientPropertyService;
+
+    public void setProgramPatientPropertyService( ProgramPatientPropertyService programPatientPropertyService )
+    {
+        this.programPatientPropertyService = programPatientPropertyService;
+    }
+
     // -------------------------------------------------------------------------
     // Input/Output
     // -------------------------------------------------------------------------
@@ -202,18 +209,19 @@
         program = programService.getProgram( id );
 
         availableIdentifierTypes = patientIdentifierTypeService.getAllPatientIdentifierTypes();
-
         availableAttributes = patientAttributeService.getAllPatientAttributes();
-        availableAttributes.removeAll( new HashSet<PatientAttribute>( program.getPatientAttributes() ) );
-        
+
         programs = new ArrayList<Program>( programService.getAllPrograms() );
 
         for ( Program p : programs )
         {
-            availableIdentifierTypes
-                .removeAll( new HashSet<PatientIdentifierType>( p.getPatientIdentifierTypes() ) );
+            Collection<PatientIdentifierType> identifierTypes = programPatientPropertyService
+                .getPatientIdentifierTypes( p );
+            availableIdentifierTypes.removeAll( identifierTypes );
+
+            Collection<PatientAttribute> atttributes = programPatientPropertyService.getPatientAttributes( p );
+            availableAttributes.removeAll( atttributes );
         }
-
         userGroups = new ArrayList<UserGroup>( userGroupService.getAllUserGroups() );
 
         programs.remove( program );

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/program/UpdateProgramAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/program/UpdateProgramAction.java	2013-09-16 09:47:59 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/program/UpdateProgramAction.java	2013-09-27 04:43:25 +0000
@@ -29,17 +29,19 @@
  */
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
-import org.hisp.dhis.patient.Patient;
 import org.hisp.dhis.patient.PatientAttribute;
 import org.hisp.dhis.patient.PatientAttributeService;
 import org.hisp.dhis.patient.PatientIdentifierType;
 import org.hisp.dhis.patient.PatientIdentifierTypeService;
 import org.hisp.dhis.patient.PatientReminder;
 import org.hisp.dhis.program.Program;
+import org.hisp.dhis.program.ProgramPatientProperty;
+import org.hisp.dhis.program.ProgramPatientPropertyService;
 import org.hisp.dhis.program.ProgramService;
 import org.hisp.dhis.relationship.RelationshipType;
 import org.hisp.dhis.relationship.RelationshipTypeService;
@@ -94,6 +96,13 @@
         this.relationshipTypeService = relationshipTypeService;
     }
 
+    private ProgramPatientPropertyService programPatientPropertyService;
+
+    public void setProgramPatientPropertyService( ProgramPatientPropertyService programPatientPropertyService )
+    {
+        this.programPatientPropertyService = programPatientPropertyService;
+    }
+
     // -------------------------------------------------------------------------
     // Input/Output
     // -------------------------------------------------------------------------
@@ -166,13 +175,6 @@
         this.displayIncidentDate = displayIncidentDate;
     }
 
-    private List<String> selectedPropertyIds = new ArrayList<String>();
-
-    public void setSelectedPropertyIds( List<String> selectedPropertyIds )
-    {
-        this.selectedPropertyIds = selectedPropertyIds;
-    }
-
     private List<Boolean> personDisplayNames = new ArrayList<Boolean>();
 
     public void setPersonDisplayNames( List<Boolean> personDisplayNames )
@@ -334,6 +336,27 @@
         this.dataEntryMethod = dataEntryMethod;
     }
 
+    private List<String> selectedPropertyIds = new ArrayList<String>();
+
+    public void setSelectedPropertyIds( List<String> selectedPropertyIds )
+    {
+        this.selectedPropertyIds = selectedPropertyIds;
+    }
+
+    private List<Boolean> hiddens;
+
+    public void setHiddens( List<Boolean> hiddens )
+    {
+        this.hiddens = hiddens;
+    }
+
+    private List<String> defaultValues;
+
+    public void setDefaultValues( List<String> defaultValues )
+    {
+        this.defaultValues = defaultValues;
+    }
+
     // -------------------------------------------------------------------------
     // Action implementation
     // -------------------------------------------------------------------------
@@ -393,36 +416,10 @@
         program.setRelationshipFromA( relationshipFromA );
         program.setRelationshipText( relationshipText );
 
-        List<PatientIdentifierType> identifierTypes = new ArrayList<PatientIdentifierType>();
-        List<PatientAttribute> patientAttributes = new ArrayList<PatientAttribute>();
-        int index = 0;
-        for ( String selectedPropertyId : selectedPropertyIds )
-        {
-            String[] ids = selectedPropertyId.split( "_" );
-
-            if ( ids[0].equals( Patient.PREFIX_IDENTIFIER_TYPE ) )
-            {
-                PatientIdentifierType identifierType = patientIdentifierTypeService.getPatientIdentifierType( Integer
-                    .parseInt( ids[1] ) );
-
-                identifierType.setPersonDisplayName( personDisplayNames.get( index ) );
-                patientIdentifierTypeService.updatePatientIdentifierType( identifierType );
-
-                identifierTypes.add( identifierType );
-            }
-            else if ( ids[0].equals( Patient.PREFIX_PATIENT_ATTRIBUTE ) )
-            {
-                PatientAttribute patientAttribute = patientAttributeService.getPatientAttribute( Integer
-                    .parseInt( ids[1] ) );
-                patientAttributes.add( patientAttribute );
-            }
-            index++;
-        }
-
-        program.setPatientIdentifierTypes( identifierTypes );
-        program.setPatientAttributes( patientAttributes );
-
-        // Template messasges
+        // ---------------------------------------------------------------------
+        // Template messages
+        // ---------------------------------------------------------------------
+
         Set<PatientReminder> patientReminders = new HashSet<PatientReminder>();
         for ( int i = 0; i < daysAllowedSendMessages.size(); i++ )
         {
@@ -455,6 +452,102 @@
 
         programService.updateProgram( program );
 
+        // ---------------------------------------------------------------------
+        // Create Program - Identifier-typse and Attributes association
+        // ---------------------------------------------------------------------
+
+        int index = 0;
+
+        Collection<ProgramPatientProperty> removeProgramProperties = program.getProgramPatientProperties();
+
+        for ( String patientProperty : selectedPropertyIds )
+        {
+            String[] property = patientProperty.split( Program.SEPARATE_CHARACTOR );
+          
+            if ( property[0].equals( Program.PREFIX_IDENTIFIER_TYPE ) )
+            {
+                PatientIdentifierType identifierType = patientIdentifierTypeService.getPatientIdentifierType( Integer
+                    .parseInt( property[1] ) );
+                identifierType.setPersonDisplayName( personDisplayNames.get( index ) );
+                patientIdentifierTypeService.updatePatientIdentifierType( identifierType );
+
+                ProgramPatientProperty programPatientProperty = programPatientPropertyService
+                    .getProgramPatientProperty( program, identifierType );
+
+                if ( programPatientProperty == null )
+                {
+                    programPatientProperty = new ProgramPatientProperty( program, identifierType,
+                        defaultValues.get( index ), hiddens.get( index ), index );
+
+                    programPatientPropertyService.addProgramPatientProperty( programPatientProperty );
+                }
+                else
+                {
+                    programPatientProperty.setProgram( program );
+                    programPatientProperty.setHidden( hiddens.get( index ) );
+                    programPatientProperty.setDefaultValue( defaultValues.get( index ) );
+                    programPatientProperty.setSortOrder( index );
+                    programPatientPropertyService.updateProgramPatientProperty( programPatientProperty );
+
+                    removeProgramProperties.remove( programPatientProperty );
+                }
+            }
+            else if ( property[0].equals( Program.PREFIX_ATTRIBUTE ) )
+            {
+                PatientAttribute patientAttribute = patientAttributeService.getPatientAttribute( Integer
+                    .parseInt( property[1] ) );
+
+                ProgramPatientProperty programPatientProperty = programPatientPropertyService
+                    .getProgramPatientProperty( program, patientAttribute );
+
+                if ( programPatientProperty == null )
+                {
+                    programPatientProperty = new ProgramPatientProperty( program, patientAttribute,
+                        defaultValues.get( index ), hiddens.get( index ), index );
+
+                    programPatientPropertyService.addProgramPatientProperty( programPatientProperty );
+                }
+                else
+                {
+                    programPatientProperty.setProgram( program );
+                    programPatientProperty.setHidden( hiddens.get( index ) );
+                    programPatientProperty.setDefaultValue( defaultValues.get( index ) );
+                    programPatientProperty.setSortOrder( index );
+                    programPatientPropertyService.updateProgramPatientProperty( programPatientProperty );
+
+                    removeProgramProperties.remove( programPatientProperty );
+                }
+            }
+            else if ( property[0].equals( Program.PREFIX_PROPERTY ) )
+            {
+                ProgramPatientProperty programPatientProperty = programPatientPropertyService
+                    .getProgramPatientProperty( program, property[1] );
+                
+                if ( programPatientProperty == null )
+                {
+                    programPatientProperty = new ProgramPatientProperty( program, property[1],
+                        defaultValues.get( index ), hiddens.get( index ), index );
+                    programPatientPropertyService.addProgramPatientProperty( programPatientProperty );
+                }
+                else
+                {
+                    programPatientProperty.setProgram( program );
+                    programPatientProperty.setHidden( hiddens.get( index ) );
+                    programPatientProperty.setDefaultValue( defaultValues.get( index ) );
+                    programPatientProperty.setSortOrder( index );
+                    programPatientPropertyService.updateProgramPatientProperty( programPatientProperty );
+
+                    removeProgramProperties.remove( programPatientProperty );
+                }
+            }
+
+            index++;
+        }
+
+        for ( ProgramPatientProperty programProperty : removeProgramProperties )
+        {
+            programPatientPropertyService.deleteProgramPatientProperty( programProperty );
+        }
         return SUCCESS;
     }
 }

=== 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	2013-09-17 06:08:16 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/META-INF/dhis/beans.xml	2013-09-27 04:43:25 +0000
@@ -182,6 +182,8 @@
 		<property name="userGroupService" ref="org.hisp.dhis.user.UserGroupService" />
 		<property name="relationshipTypeService"
 			ref="org.hisp.dhis.relationship.RelationshipTypeService" />
+		<property name="programPatientPropertyService"
+			ref="org.hisp.dhis.program.ProgramPatientPropertyService" />
 	</bean>
 
 	<bean id="org.hisp.dhis.patient.action.program.GetProgramListAction"
@@ -225,6 +227,8 @@
 		<property name="userGroupService" ref="org.hisp.dhis.user.UserGroupService" />
 		<property name="relationshipTypeService"
 			ref="org.hisp.dhis.relationship.RelationshipTypeService" />
+		<property name="programPatientPropertyService"
+			ref="org.hisp.dhis.program.ProgramPatientPropertyService" />
 	</bean>
 
 	<bean
@@ -239,7 +243,10 @@
 		<property name="userGroupService" ref="org.hisp.dhis.user.UserGroupService" />
 		<property name="relationshipTypeService"
 			ref="org.hisp.dhis.relationship.RelationshipTypeService" />
+		<property name="programPatientPropertyService"
+			ref="org.hisp.dhis.program.ProgramPatientPropertyService" />
 	</bean>
+
 	<bean id="org.hisp.dhis.patient.action.program.UpdateProgramAction"
 		class="org.hisp.dhis.patient.action.program.UpdateProgramAction"
 		scope="prototype">
@@ -251,6 +258,8 @@
 		<property name="userGroupService" ref="org.hisp.dhis.user.UserGroupService" />
 		<property name="relationshipTypeService"
 			ref="org.hisp.dhis.relationship.RelationshipTypeService" />
+		<property name="programPatientPropertyService"
+			ref="org.hisp.dhis.program.ProgramPatientPropertyService" />
 	</bean>
 
 	<bean id="org.hisp.dhis.patient.action.program.ValidateProgramAction"
@@ -638,6 +647,8 @@
 		<property name="userSettingService">
 			<ref bean="org.hisp.dhis.user.UserSettingService" />
 		</property>
+		<property name="programPatientPropertyService"
+			ref="org.hisp.dhis.program.ProgramPatientPropertyService" />
 	</bean>
 
 	<bean
@@ -833,6 +844,8 @@
 		<property name="programService" ref="org.hisp.dhis.program.ProgramService" />
 		<property name="attributeService"
 			ref="org.hisp.dhis.patient.PatientAttributeService" />
+		<property name="programPatientPropertyService"
+			ref="org.hisp.dhis.program.ProgramPatientPropertyService" />
 	</bean>
 
 	<bean

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/org/hisp/dhis/patient/i18n_module.properties'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/org/hisp/dhis/patient/i18n_module.properties	2013-09-23 07:25:48 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/org/hisp/dhis/patient/i18n_module.properties	2013-09-27 04:43:25 +0000
@@ -482,4 +482,6 @@
 the_properties_to_open_data_entry_form_after_enrolment_is_active_in_the_stage = The properties to open data entry form after enrolment is active in the stage
 add_relative = Add relative
 who_is_the_new_relative_to_the_existing_person = Who is the new relative to the existing person?
-program_for_new_relative_to_be_enrolled_in = Program for new relative to be enrolled in
\ No newline at end of file
+program_for_new_relative_to_be_enrolled_in = Program for new relative to be enrolled in
+default_value = Default value
+hidden = Hidden
\ No newline at end of file

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/addProgramForm.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/addProgramForm.vm	2013-09-19 03:16:23 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/addProgramForm.vm	2013-09-27 04:43:25 +0000
@@ -64,14 +64,27 @@
 		
 		var selectedPropertyIds = jQuery( "#selectedPropertyIds" );
 		selectedPropertyIds.empty();
+		
 		var personDisplayNames = jQuery( "#personDisplayNames" );
 		personDisplayNames.empty();
 		
+		var defaultValues = jQuery( "#defaultValues" );
+		defaultValues.empty();
+		
+		var hiddens = jQuery( "#hiddens" );
+		hiddens.empty();
+		
 		if(getFieldValue('type')!=3){
 			jQuery("#selectedList").find("tr").each( function( i, item ){ 
 				
 				selectedPropertyIds.append( "<option value='" + item.id + "' selected='true'>" + item.id + "</option>" );
 				
+				var defaultValue = jQuery( item ).find( "input[name='defaultValue']:first").attr('value');
+				defaultValues.append( "<option value='" + defaultValue + "' selected='true'>" + defaultValue + "</option>" );
+				
+				checked = jQuery( item ).find( "input[name='hidden']:first").attr('checked') ? true : false;
+				hiddens.append( "<option value='" + checked + "' selected='true'>" + checked + "</option>" );
+						
 				var displayed = jQuery( item ).find( "input[name='displayed']:first");
 				var checked = displayed.attr('checked') ? true : false;
 				personDisplayNames.append( "<option value='" + checked + "' selected='true'>" + checked + "</option>" );
@@ -258,6 +271,8 @@
 		<th></th>
 		<th>$i18n.getString( "select_identifiers_and_attributes" )							
 			<select style='display:none;' multiple id="selectedPropertyIds" name="selectedPropertyIds" ></select>
+			<select style='display:none;' multiple id="hiddens" name="hiddens" ></select>
+			<select style='display:none;' multiple id="defaultValues" name="defaultValues" ></select>
 			<select style='display:none;' multiple id="personDisplayNames" name="personDisplayNames" ></select>
 		</th>
 	  </tr>
@@ -265,6 +280,16 @@
 	<tr>
 		<td>
 			<select style="width:100%;" size="15" multiple id="availablePropertyIds" name="availablePropertyIds" ondblclick="selectProperties();">
+				<option value="prop_registrationDate">$i18n.getString('registration_date')</option>
+				<option value="prop_fullName">$i18n.getString('full_name')</option>
+				<option value="prop_gender">$i18n.getString('gender')</option>
+				<option value="prop_dobType">$i18n.getString('dob_type')</option>
+				<option value="prop_birthDate">$i18n.getString('birth_date')</option>
+				<option value="prop_age">$i18n.getString('age_years')</option>
+				<option value="prop_phoneNumber">$i18n.getString('phone_number')</option>
+				<option value="prop_deathDate">$i18n.getString('death_date')</option>
+				<option value="prop_isDead">$i18n.getString('is_dead')</option>
+				<option value="prop_healthWorker">$i18n.getString('health_worker')</option>
 				#foreach( $identifier in $availableIdentifierTypes )
 					<option value="iden_$identifier.id">$identifier.displayName</option>
 				#end
@@ -289,6 +314,8 @@
 					<thead>
 						<tr>
 							<th>$i18n.getString( "identifiers_and_attributes" )</th>
+							<th style="width:20px;">$i18n.getString( "default_value" )</th>
+							<th style="width:20px;">$i18n.getString( "hidden" )</th>
 							<th>$i18n.getString( "displayed_in_list" )</th>
 					</thead>
 					<tbody id="selectedList"></tbody>

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/index.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/index.vm	2013-08-16 12:29:21 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/index.vm	2013-09-27 04:43:25 +0000
@@ -6,7 +6,7 @@
     #introListImgItem( "patientAttributeGroup.action" "patient_attribute_group" "patient" )
     #introListImgItem( "patientIdentifierType.action" "patient_identifier_type" "patient" )
     #introListImgItem( "relationshipType.action" "relationship_type" "patient" )
-    #introListImgItem( "patientRegistrationForm.action" "patient_registration_form" "pivottable" )
+    <!-- #introListImgItem( "patientRegistrationForm.action" "patient_registration_form" "pivottable" ) -->
     #introListImgItem( "program.action" "program" "program" )
     #introListImgItem( "caseAggregation.action" "patient_aggregation_query_builder" "caseaggregationmapping" )
 	#introListImgItem( "validationCriteria.action" "validation_criteria" "validationrule" )

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/javascript/program.js'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/javascript/program.js	2013-09-16 09:47:59 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/javascript/program.js	2013-09-27 04:43:25 +0000
@@ -137,7 +137,9 @@
 	jQuery("#availablePropertyIds").children().each(function(i, item){
 		if( item.selected ){
 			html = "<tr class='selected' id='" + item.value + "' ondblclick='unSelectProperties( this )'><td onmousedown='select(event,this)'>" + item.text + "</td>";
-			html += "<td align='center'><input type='checkbox' name='displayed' value='" + item.value + "'";
+			html += "<td align='center'><input type='textbox' name='defaultValue' /></td>";
+			html += "<td align='center'><input type='checkbox' name='hidden' /></td>";
+			html += "<td align='center'><input type='checkbox' name='displayed' ";
 			if( item.value.match("^attr_")=="attr_" )
 			{
 				html += " style='display:none' ";
@@ -159,7 +161,9 @@
 	var selectedList = jQuery("#selectedList");
 	jQuery("#availablePropertyIds").children().each(function(i, item){
 		html = "<tr class='selected' id='" + item.value + "' ondblclick='unSelectDataElement( this )'><td onmousedown='select(this)'>" + item.text + "</td>";
-		html += "<td align='center'><input type='checkbox' name='displayed' value='" + item.value + "'";
+		html += "<td align='center'><input type='textbox' name='defaultValue' /></td>";
+		html += "<td align='center'><input type='checkbox' name='hidden' /></td>";
+		html += "<td align='center'><input type='checkbox' name='displayed' ";
 		if( item.value.match("^attr_")=="attr_" )
 		{
 			html += " style='display:none' ";

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/menu.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/menu.vm	2013-05-24 09:10:42 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/menu.vm	2013-09-27 04:43:25 +0000
@@ -5,7 +5,7 @@
 	<li><a href="patientAttributeGroup.action">$i18n.getString( "patient_attribute_group" )</a></li>
 	<li><a href="patientIdentifierType.action">$i18n.getString( "patient_identifier_type" )</a></li>
 	<li><a href="relationshipType.action">$i18n.getString( "relationship_type" )</a></li>
-	<li><a href="patientRegistrationForm.action">$i18n.getString( "patient_registration_form" )</a></li>
+	<!-- <li><a href="patientRegistrationForm.action">$i18n.getString( "patient_registration_form" )</a></li> -->
 </ul>
 
 <h2>$i18n.getString( "programs" )</h2>

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/programList.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/programList.vm	2013-09-24 15:35:46 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/programList.vm	2013-09-27 04:43:25 +0000
@@ -46,7 +46,7 @@
 					  #end
 					  
 					  #if( $auth.hasAccess( "dhis-web-maintenance-patient", "programIndicator" ) && $program.type !='3' )
-						<a href="programIndicator.action?programId=$program.id" title="$i18n.getString( 'program_indicator_management_form' )"><img src="../images/indicator.png" ></a>
+						<a href="programIndicator.action?programId=$program.id" title="$i18n.getString( 'program_indicator_management_form' )"><img src="images/program_indicator.png" ></a>
 					  #else
 						<img src="images/program_indicator_disabled.png">
 					  #end

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/updateProgramForm.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/updateProgramForm.vm	2013-09-23 04:33:12 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/updateProgramForm.vm	2013-09-27 04:43:25 +0000
@@ -65,16 +65,33 @@
 					userGroup.append( "<option value='" + item.value + "' selected='true'>" + item.value + "</option>" );
 				});
 				
+				// Identifier-types && Attributes
+				
 				var selectedPropertyIds = jQuery( "#selectedPropertyIds" );
 				selectedPropertyIds.empty();
+				
 				var personDisplayNames = jQuery( "#personDisplayNames" );
 				personDisplayNames.empty();
+				
+				var defaultValues = jQuery( "#defaultValues" );
+				defaultValues.empty();
+				
+				var hiddens = jQuery( "#hiddens" );
+				hiddens.empty();
+				
 				if(getFieldValue('type')!=3){
 					jQuery("#selectedList").find("tr").each( function( i, item ){ 
 						selectedPropertyIds.append( "<option value='" + item.id + "' selected='true'>" + item.id + "</option>" );
+						
 						var displayed = jQuery( item ).find( "input[name='displayed']:first");
 						var checked = displayed.attr('checked') ? true : false;
 						personDisplayNames.append( "<option value='" + checked + "' selected='true'>" + checked + "</option>" );
+						
+						var defaultValue = jQuery( item ).find( "input[name='defaultValue']:first").attr('value');
+						defaultValues.append( "<option value='" + defaultValue + "' selected='true'>" + defaultValue + "</option>" );
+						
+						checked = jQuery( item ).find( "input[name='hidden']:first").attr('checked') ? true : false;
+						hiddens.append( "<option value='" + checked + "' selected='true'>" + checked + "</option>" );
 					});
 				};
 			});
@@ -82,7 +99,7 @@
 });
 
 </script>
-
+		
 <h3>$i18n.getString( "edit_program" )</h3>
 
 <form id="updateProgramForm" name="updateProgramForm" action="updateProgram.action" method="post" onsubmit="selectAllById('selectedPropertyIds');" >
@@ -91,7 +108,7 @@
   <select id='datesToCompare' name="datesToCompare" multiple="multiple" class="hidden"></select>
   <select id='sendTo' name="sendTo" multiple="multiple" class="hidden"></select>
   <select id='whenToSend' name="whenToSend" multiple="multiple" class="hidden"></select>
-	<select id='messageType' name="messageType" multiple="multiple" class="hidden"></select>
+  <select id='messageType' name="messageType" multiple="multiple" class="hidden"></select>
   <select id='userGroup' name="userGroup" multiple="multiple" class="hidden"></select>
 
   <input type="hidden" id="id" name="id" value="$program.id">
@@ -270,6 +287,8 @@
 			<th></th>
 			<th>$i18n.getString( "select_identifiers_and_attributes" )							
 				<select style='display:none;' multiple id="selectedPropertyIds" name="selectedPropertyIds" ></select>
+				<select style='display:none;' multiple id="hiddens" name="hiddens" ></select>
+				<select style='display:none;' multiple id="defaultValues" name="defaultValues" ></select>
 				<select style='display:none;' multiple id="personDisplayNames" name="personDisplayNames" ></select>
 			</th>
 		  </tr>
@@ -278,12 +297,89 @@
 		<tr>
 			<td>
 				<select size="15" style="width:100%;" multiple id="availablePropertyIds" name="availablePropertyIds" ondblclick="selectProperties();" #if( $program.type=='3' ) disabled #end>
-					#foreach( $identifier in $availableIdentifierTypes )
-						<option value="iden_$identifier.id">$identifier.displayName</option>
-					#end
-					#foreach( $attribute in $availableAttributes )
-						<option value="attr_$attribute.id">$attribute.displayName</option>
-					#end
+					#set($hasRegistrationDate = false)
+				#set($hasFullName = false)
+				#set($hasGender = false)
+				#set($hasDobType = false)
+				#set($hasBirthDate = false)
+				#set($hasAge = false)
+				#set($hasPhoneNumber = false)
+				#set($hasDeathDate = false)
+				#set($hasIsDead = false) 
+				#set($hasHealthWorker = false)
+				#foreach( $programPatientProperty in $program.programPatientProperties ) 
+					#if( $programPatientProperty.isProperty() )
+						#set($fixedAttribute = $programPatientProperty.propertyName)
+						#if($fixedAttribute =='registrationDate')
+							#set($hasRegistrationDate = true)
+						#end
+						#if($fixedAttribute=='fullName')
+							#set($hasFullName = true)
+						#end
+						#if($fixedAttribute=='gender')
+							#set($hasGender = true)
+						#end
+						#if($fixedAttribute=='dobType')
+							#set($hasDobType = true)
+						#end
+						#if($fixedAttribute=='birthDate')
+							#set($hasBirthDate = true)
+						#end
+						#if($fixedAttribute=='age')
+							#set($hasAge = true)
+						#end
+						#if($fixedAttribute=='phoneNumber')
+							#set($hasPhoneNumber = true)
+						#end
+						#if($fixedAttribute=='deathDate')
+							#set($hasDeathDate = true)
+						#end
+						#if($fixedAttribute=='isDead')
+							#set($hasIsDead = true)
+						#end
+						#if($fixedAttribute=='healthWorker')
+							#set($hasHealthWorker = true)
+						#end
+					#end
+				#end
+				
+				#if($hasRegistrationDate==false)
+					<option value="prop_registrationDate">$i18n.getString('registration_date')</option>
+				#end
+				#if($hasFullName==false)
+					<option value="prop_fullName">$i18n.getString('full_name')</option>
+				#end
+				#if($hasGender==false)
+					<option value="prop_gender">$i18n.getString('gender')</option>
+				#end
+				#if($hasDobType==false)
+					<option value="prop_dobType">$i18n.getString('dob_type')</option>
+				#end
+				#if($hasBirthDate==false)
+					<option value="prop_birthDate">$i18n.getString('birth_date')</option>
+				#end
+				#if($hasAge==false)
+					<option value="prop_age">$i18n.getString('age_years')</option>
+				#end
+				#if($hasPhoneNumber==false)
+					<option value="prop_phoneNumber">$i18n.getString('phone_number')</option>
+				#end
+				#if($hasDeathDate==false)
+					<option value="prop_deathDate">$i18n.getString('death_date')</option>
+				#end
+				#if($hasIsDead==false)
+					<option value="prop_isDead">$i18n.getString('is_dead')</option>
+				#end
+				#if($hasHealthWorker==false)
+					<option value="prop_healthWorker">$i18n.getString('health_worker')</option>
+				#end
+				
+				#foreach( $identifier in $availableIdentifierTypes )
+					<option value="iden_$identifier.id">$identifier.displayName</option>
+				#end
+				#foreach( $attribute in $availableAttributes )
+					<option value="attr_$attribute.id">$attribute.displayName</option>
+				#end
 				</select>
 			</td>
 			<td style="text-align:center">
@@ -302,20 +398,34 @@
 						<thead>
 							<tr>
 								<th style="width:180px;">$i18n.getString( "identifiers_and_attributes" )</th>
+								<th style="width:20px;">$i18n.getString( "default_value" )</th>
+								<th style="width:20px;">$i18n.getString( "hidden" )</th>
 								<th style="width:20px;">$i18n.getString( "displayed_in_list" )</th>
 						</thead>
-						<tbody id="selectedList" #if($program.type==3) style="display:none;" #end>
-							#foreach( $identifier in $program.patientIdentifierTypes )
-								<tr ondblclick="unSelectProperties( this )" id="iden_$identifier.id">
-									<td onmousedown="select(event, this)">$encoder.htmlEncode( $identifier.name )</td>
-									<td align="center"><input type="checkbox" name="displayed" value="iden_$identifier.id" #if($identifier.personDisplayName == true ) checked #end #if($program.type==3) disabled #end /></td>
-								</tr>
-							#end
-							#foreach( $attribute in $program.patientAttributes )
-								<tr ondblclick="unSelectProperties( this )" id="attr_$attribute.id">
-									<td onmousedown="select(event, this)">$encoder.htmlEncode( $attribute.name )</td>
-									<td align="center"><input type="checkbox" name="displayed" style='display:none' /></td>
-								</tr>
+						<tbody id="selectedList" #if($program.type==3) style="display:none;" #end> 
+							#foreach( $programPatientProperty in $program.programPatientProperties )
+								#if($programPatientProperty.isIdentifierType())
+								<tr ondblclick="unSelectProperties( this )" id="iden_$programPatientProperty.patientIdentifierType.id">
+									<td onmousedown="select(event, this)">$encoder.htmlEncode( $programPatientProperty.patientIdentifierType.displayName )</td>
+									<td align="center"><input type="textbox" name="defaultValue" value="$!programPatientProperty.defaultValue" /></td>
+									<td align="center"><input type="checkbox" name="hidden" #if($programPatientProperty.hidden == 'true' ) checked #end #if($program.type==3) disabled #end /></td>
+									<td align="center"><input type="checkbox" name="displayed" #if($programPatientProperty.patientIdentifierType.personDisplayName == true ) checked #end #if($program.type==3) disabled #end /></td>
+								</tr>
+								#elseif( $programPatientProperty.isAttribute())
+								<tr ondblclick="unSelectProperties( this )" id="attr_$programPatientProperty.patientAttribute.id">
+									<td onmousedown="select(event, this)">$encoder.htmlEncode( $programPatientProperty.patientAttribute.displayName )</td>
+									<td align="center"><input type="textbox" name="defaultValue" value="$!programPatientProperty.defaultValue" /></td>
+									<td align="center"><input type="checkbox" name="hidden" #if($programPatientProperty.hidden == 'true' ) checked #end #if($program.type==3) disabled #end /></td>
+									<td align="center"><input type="checkbox" name="displayed" style='display:none' /></td>
+								</tr>
+								#else
+								<tr ondblclick="unSelectProperties( this )" id="prop_$programPatientProperty.propertyName">
+									<td onmousedown="select(event, this)">$i18n.getString( $programPatientProperty.propertyName )</td>
+									<td align="center"><input type="textbox" name="defaultValue" value="$!programPatientProperty.defaultValue" /></td>
+									<td align="center"><input type="checkbox" name="hidden" #if($programPatientProperty.hidden == 'true' ) checked #end #if($program.type==3) disabled #end /></td>
+									<td align="center"><input type="checkbox" name="displayed" style='display:none' /></td>
+								</tr>
+								#end
 							#end
 						</tbody>
 					</table>