← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 14008: Add UI for CategoryOptionGroup object in data dictionary web module.

 

------------------------------------------------------------
revno: 14008
committer: Tran Chau <tran.hispvietnam@xxxxxxxxx>
branch nick: dhis2
timestamp: Thu 2014-02-13 16:51:36 +0700
message:
  Add UI for CategoryOptionGroup object in data dictionary web module.
added:
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataelement/DefaultCategoryOptionGroupService.java
  dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/ajax/jsonCategoryOptionGroup.vm
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup/
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup/AddCategoryOptionGroupAction.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup/GetCategoryOptionGroupAction.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup/GetCategoryOptionGroupListAction.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup/RemoveCategoryOptionGroupAction.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup/ShowAddCategoryOptionGroupAction.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup/ShowUpdateCategoryOptionGroupAction.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup/UpdateCategoryOptionGroupAction.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup/ValidateCategoryOptionGroupAction.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/addCategoryOptionGroupForm.vm
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/categoryOptionGroup.vm
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/javascript/categoryOptionGroup.js
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/multidimensional/addConceptForm.vm
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/multidimensional/concept.vm
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/multidimensional/updateConceptForm.vm
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/updateCategoryOptionGroupForm.vm
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/CategoryOptionGroup.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/CategoryOptionGroupService.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityAttributeService.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityAttributeStore.java
  dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/trackedentity/DefaultTrackedEntityAttributeService.java
  dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/deletion/DeletionHandler.java
  dhis-2/dhis-web/dhis-web-caseentry/src/main/webapp/dhis-web-caseentry/javascript/commons.js
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/resources/org/hisp/dhis/dd/i18n_module.properties
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/resources/struts.xml
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/index.vm
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/menu.vm
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-program/src/main/java/org/hisp/dhis/trackedentity/action/trackedentityattribute/GetAttributeListAction.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-program/src/main/resources/org/hisp/dhis/trackedentity/i18n_module.properties


--
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/dataelement/CategoryOptionGroup.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/CategoryOptionGroup.java	2014-02-12 10:52:22 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/CategoryOptionGroup.java	2014-02-13 09:51:36 +0000
@@ -38,15 +38,15 @@
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
 
 /**
-* @author Lars Helge Overland
-*/
-@JacksonXmlRootElement(localName = "categoryOptionGroup", namespace = DxfNamespaces.DXF_2_0)
+ * @author Lars Helge Overland
+ */
+@JacksonXmlRootElement( localName = "categoryOptionGroup", namespace = DxfNamespaces.DXF_2_0 )
 public class CategoryOptionGroup
     extends BaseNameableObject
 {
     @Scanned
     private Set<DataElementCategoryOption> members = new HashSet<DataElementCategoryOption>();
-    
+
     private CategoryOptionGroupSet groupSet;
 
     // -------------------------------------------------------------------------
@@ -85,4 +85,19 @@
     {
         this.groupSet = groupSet;
     }
+
+    // -------------------------------------------------------------------------
+    // Logic
+    // -------------------------------------------------------------------------
+
+    public void addCategoryOption( DataElementCategoryOption categoryOption )
+    {
+        members.add( categoryOption );
+    }
+
+    public void removeCategoryOption( DataElementCategoryOption categoryOption )
+    {
+        members.remove( categoryOption );
+    }
+
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/CategoryOptionGroupService.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/CategoryOptionGroupService.java	2014-02-12 10:52:22 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/CategoryOptionGroupService.java	2014-02-13 09:51:36 +0000
@@ -1,6 +1,150 @@
 package org.hisp.dhis.dataelement;
 
+/*
+ * 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.
+ */
+
+import java.util.Collection;
+
 public interface CategoryOptionGroupService
 {
-
+    String ID = CategoryOptionGroupService.class.getName();
+
+    /**
+     * Adds an {@link CategoryOptionGroup}
+     * 
+     * @param categoryOptionGroup The to CategoryOptionGroup add.
+     * 
+     * @return A generated unique id of the added {@link CategoryOptionGroup} .
+     */
+    int addCategoryOptionGroup( CategoryOptionGroup categoryOptionGroup );
+
+    /**
+     * Deletes a {@link CategoryOptionGroup}.
+     * 
+     * @param categoryOptionGroup the CategoryOptionGroup to delete.
+     */
+    void deleteCategoryOptionGroup( CategoryOptionGroup categoryOptionGroup );
+
+    /**
+     * Updates an {@link CategoryOptionGroup}.
+     * 
+     * @param categoryOptionGroup the CategoryOptionGroup to update.
+     */
+    void updateCategoryOptionGroup( CategoryOptionGroup categoryOptionGroup );
+
+    /**
+     * Returns a {@link CategoryOptionGroup}.
+     * 
+     * @param id the id of the CategoryOptionGroup to return.
+     * 
+     * @return the CategoryOptionGroup with the given id
+     */
+    CategoryOptionGroup getCategoryOptionGroup( int id );
+
+    /**
+     * Returns the {@link CategoryOptionGroup} with the given UID.
+     * 
+     * @param uid the UID.
+     * @return the CategoryOptionGroup with the given UID, or null if no match.
+     */
+    CategoryOptionGroup getCategoryOptionGroupByUid( String uid );
+
+    /**
+     * Returns a {@link CategoryOptionGroup} with a given name.
+     * 
+     * @param name the name of the CategoryOptionGroup to return.
+     * 
+     * @return the CategoryOptionGroup with the given name, or null if no match.
+     */
+    CategoryOptionGroup getCategoryOptionGroupByName( String name );
+
+    /**
+     * Returns a {@link CategoryOptionGroup} with a given name.
+     * 
+     * @param shortName the code of the CategoryOptionGroup to return.
+     * 
+     * @return the CategoryOptionGroup with the given code, or null if no
+     *         match.
+     */
+    CategoryOptionGroup getCategoryOptionGroupByCode( String code );
+
+    /**
+     * Returns a {@link CategoryOptionGroup} with a given name.
+     * 
+     * @param shortName the shortName of the CategoryOptionGroup to return.
+     * 
+     * @return the CategoryOptionGroup with the given shortName, or null if no
+     *         match.
+     */
+    CategoryOptionGroup getCategoryOptionGroupByShortName( String shortName );
+
+    /**
+     * Returns all {@link CategoryOptionGroup}
+     * 
+     * @return a collection of all CategoryOptionGroup, or an empty collection
+     *         if there are no CategoryOptionGroups.
+     */
+    Collection<CategoryOptionGroup> getAllCategoryOptionGroups();
+
+    /**
+     * Returns {@link CategoryOptionGroup} list with paging
+     * 
+     * @param name Keyword for searching by name
+     * @param first
+     * @param max
+     * @return a collection of all CategoryOptionGroup, or an empty collection
+     *         if there are no CategoryOptionGroups.
+     */
+    Collection<CategoryOptionGroup> getCategoryOptionGroupsBetweenByName( String name, int first, int max );
+
+    /**
+     * Returns The number of all CategoryOptionGroup available
+     * 
+     */
+    int getCategoryOptionGroupCount();
+
+    /**
+     * Returns {@link CategoryOptionGroup} list with paging
+     * 
+     * @param first
+     * @param max
+     * @return a collection of all CategoryOptionGroup, or an empty collection
+     *         if there are no CategoryOptionGroups.
+     */
+    Collection<CategoryOptionGroup> getCategoryOptionGroupsBetween( int first, int max );
+
+    /**
+     * Returns The number of CategoryOptionGroups with the key searched
+     * 
+     * @param name Keyword for searching by name
+     * 
+     * @return A number
+     * 
+     */
+    int getCategoryOptionGroupCountByName( String name );
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityAttributeService.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityAttributeService.java	2014-02-07 20:25:49 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityAttributeService.java	2014-02-13 09:51:36 +0000
@@ -43,7 +43,8 @@
      * 
      * @param attribute The to TrackedEntityAttribute add.
      * 
-     * @return A generated unique id of the added {@link TrackedEntityAttribute}.
+     * @return A generated unique id of the added {@link TrackedEntityAttribute}
+     *         .
      */
     int saveTrackedEntityAttribute( TrackedEntityAttribute attribute );
 
@@ -74,7 +75,8 @@
      * Returns the {@link TrackedEntityAttribute} with the given UID.
      * 
      * @param uid the UID.
-     * @return the TrackedEntityAttribute with the given UID, or null if no match.
+     * @return the TrackedEntityAttribute with the given UID, or null if no
+     *         match.
      */
     TrackedEntityAttribute getTrackedEntityAttribute( String uid );
 
@@ -83,15 +85,16 @@
      * 
      * @param name the name of the TrackedEntityAttribute to return.
      * 
-     * @return the TrackedEntityAttribute with the given name, or null if no match.
+     * @return the TrackedEntityAttribute with the given name, or null if no
+     *         match.
      */
     TrackedEntityAttribute getTrackedEntityAttributeByName( String name );
 
     /**
      * Returns all {@link TrackedEntityAttribute}
      * 
-     * @return a collection of all TrackedEntityAttribute, or an empty collection if
-     *         there are no TrackedEntityAttributes.
+     * @return a collection of all TrackedEntityAttribute, or an empty
+     *         collection if there are no TrackedEntityAttributes.
      */
     Collection<TrackedEntityAttribute> getAllTrackedEntityAttributes();
 
@@ -139,7 +142,8 @@
      * 
      * @return List of attributes
      */
-    Collection<TrackedEntityAttribute> getTrackedEntityAttributesByDisplayOnVisitSchedule( boolean displayOnVisitSchedule );
+    Collection<TrackedEntityAttribute> getTrackedEntityAttributesByDisplayOnVisitSchedule(
+        boolean displayOnVisitSchedule );
 
     /**
      * Get attributes which are displayed in visit schedule
@@ -159,4 +163,40 @@
      */
     Collection<TrackedEntityAttribute> getTrackedEntityAttributesDisplayedInList( boolean displayInListNoProgram );
 
+    /**
+     * Returns {@link TrackedEntityAttribute} list with paging
+     * 
+     * @param name Keyword for searching by name
+     * @param min
+     * @param max
+     * @return a collection of all TrackedEntityAttribute, or an empty
+     *         collection if there are no TrackedEntityAttributes.
+     */
+    Collection<TrackedEntityAttribute> getTrackedEntityAttributesBetweenByName( String name, int min, int max );
+
+    /**
+     * Returns The number of all TrackedEntityAttribute available
+     * 
+     */
+    int getTrackedEntityAttributeCount();
+
+    /**
+     * Returns {@link TrackedEntityAttribute} list with paging
+     * 
+     * @param min
+     * @param max
+     * @return a collection of all TrackedEntityAttribute, or an empty
+     *         collection if there are no TrackedEntityAttributes.
+     */
+    Collection<TrackedEntityAttribute> getTrackedEntityAttributesBetween( int min, int max );
+
+    /**
+     * Returns The number of TrackedEntityAttributes with the key searched
+     * 
+     * @param name Keyword for searching by name
+     * 
+     * @return A number
+     * 
+     */
+    int getTrackedEntityAttributeCountByName( String name );
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityAttributeStore.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityAttributeStore.java	2014-02-07 20:25:49 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityAttributeStore.java	2014-02-13 09:51:36 +0000
@@ -81,17 +81,20 @@
 
     /**
      * Get attributes which are displayed in visit schedule
+     * 
      * @param displayOnVisitSchedule True/False value
      * 
-     * @return List of  attributes
+     * @return List of attributes
      */
     Collection<TrackedEntityAttribute> getByDisplayOnVisitSchedule( boolean displayOnVisitSchedule );
 
     /**
      * Get attributes which are displayed in visit schedule
+     * 
      * @param displayInListNoProgram True/False value
      * 
      * @return List of attributes
      */
     Collection<TrackedEntityAttribute> getDisplayedInList( boolean displayInListNoProgram );
+
 }

=== added file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataelement/DefaultCategoryOptionGroupService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataelement/DefaultCategoryOptionGroupService.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataelement/DefaultCategoryOptionGroupService.java	2014-02-13 09:51:36 +0000
@@ -0,0 +1,158 @@
+/*
+ * 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.dataelement;
+
+import static org.hisp.dhis.i18n.I18nUtils.i18n;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.hisp.dhis.common.GenericIdentifiableObjectStore;
+import org.hisp.dhis.i18n.I18nService;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * @author Chau Thu Tran
+ * 
+ * @version $ DefaultCategoryOptionGroupService.java Feb 12, 2014 11:38:43 PM $
+ */
+@Transactional
+public class DefaultCategoryOptionGroupService
+    implements CategoryOptionGroupService
+{
+    // -------------------------------------------------------------------------
+    // Dependencies
+    // -------------------------------------------------------------------------
+
+    private GenericIdentifiableObjectStore<CategoryOptionGroup> categoryOptionGroupStore;
+
+    public void setCategoryOptionGroupStore(
+        GenericIdentifiableObjectStore<CategoryOptionGroup> categoryOptionGroupStore )
+    {
+        this.categoryOptionGroupStore = categoryOptionGroupStore;
+    }
+
+    private I18nService i18nService;
+
+    public void setI18nService( I18nService service )
+    {
+        i18nService = service;
+    }
+
+    // -------------------------------------------------------------------------
+    // CategoryOptionGroup
+    // -------------------------------------------------------------------------
+
+    @Override
+    public int addCategoryOptionGroup( CategoryOptionGroup categoryOptionGroup )
+    {
+        return categoryOptionGroupStore.save( categoryOptionGroup );
+    }
+
+    @Override
+    public void deleteCategoryOptionGroup( CategoryOptionGroup categoryOptionGroup )
+    {
+        categoryOptionGroupStore.delete( categoryOptionGroup );
+    }
+
+    @Override
+    public void updateCategoryOptionGroup( CategoryOptionGroup categoryOptionGroup )
+    {
+        categoryOptionGroupStore.update( categoryOptionGroup );
+    }
+
+    @Override
+    public CategoryOptionGroup getCategoryOptionGroup( int id )
+    {
+        return i18n( i18nService, categoryOptionGroupStore.get( id ) );
+    }
+
+    @Override
+    public CategoryOptionGroup getCategoryOptionGroupByUid( String uid )
+    {
+        return i18n( i18nService, categoryOptionGroupStore.getByUid( uid ) );
+    }
+
+    @Override
+    public CategoryOptionGroup getCategoryOptionGroupByName( String name )
+    {
+        return i18n( i18nService, categoryOptionGroupStore.getByName( name ) );
+    }
+
+    @Override
+    public Collection<CategoryOptionGroup> getAllCategoryOptionGroups()
+    {
+        return i18n( i18nService, categoryOptionGroupStore.getAll() );
+    }
+
+    @Override
+    public Collection<CategoryOptionGroup> getCategoryOptionGroupsBetweenByName( String name, int first, int max )
+    {
+        return i18n( i18nService, categoryOptionGroupStore.getAllLikeNameOrderedName( name, first, max ) );
+    }
+
+    @Override
+    public int getCategoryOptionGroupCount()
+    {
+        return categoryOptionGroupStore.getCount();
+    }
+
+    @Override
+    public Collection<CategoryOptionGroup> getCategoryOptionGroupsBetween( int first, int max )
+    {
+        return i18n( i18nService, categoryOptionGroupStore.getAllOrderedName( first, max ) );
+    }
+
+    @Override
+    public int getCategoryOptionGroupCountByName( String name )
+    {
+        return categoryOptionGroupStore.getCountLikeName( name );
+    }
+
+    @Override
+    public CategoryOptionGroup getCategoryOptionGroupByShortName( String shortName )
+    {
+        List<CategoryOptionGroup> categoryOptionGroups = new ArrayList<CategoryOptionGroup>(
+            categoryOptionGroupStore.getAllLikeShortName( shortName ) );
+
+        if ( categoryOptionGroups.isEmpty() )
+        {
+            return null;
+        }
+
+        return i18n( i18nService, categoryOptionGroups.get( 0 ) );
+    }
+
+    @Override
+    public CategoryOptionGroup getCategoryOptionGroupByCode( String code )
+    {
+        return i18n( i18nService, categoryOptionGroupStore.getByCode( code ) );
+    }
+
+}

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/beans.xml	2014-02-12 16:09:47 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/beans.xml	2014-02-13 09:51:36 +0000
@@ -626,6 +626,11 @@
     <property name="optionStore" ref="org.hisp.dhis.option.OptionStore" />
     <property name="i18nService" ref="org.hisp.dhis.i18n.I18nService" />
   </bean>
+  
+  <bean id="org.hisp.dhis.dataelement.CategoryOptionGroupService" class="org.hisp.dhis.dataelement.DefaultCategoryOptionGroupService">
+    <property name="categoryOptionGroupStore" ref="org.hisp.dhis.dataelement.CategoryOptionGroupStore" />
+    <property name="i18nService" ref="org.hisp.dhis.i18n.I18nService" />
+  </bean>
 
   <bean id="org.hisp.dhis.mapping.MappingService" class="org.hisp.dhis.mapping.DefaultMappingService">
     <property name="mapStore" ref="org.hisp.dhis.mapping.MapStore" />

=== modified file 'dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/trackedentity/DefaultTrackedEntityAttributeService.java'
--- dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/trackedentity/DefaultTrackedEntityAttributeService.java	2014-02-07 20:25:49 +0000
+++ dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/trackedentity/DefaultTrackedEntityAttributeService.java	2014-02-13 09:51:36 +0000
@@ -151,4 +151,24 @@
         return attributeStore.getDisplayedInList( displayInListNoProgram );
     }
 
+    public Collection<TrackedEntityAttribute> getTrackedEntityAttributesBetweenByName( String name, int min, int max )
+    {
+        return attributeStore.getAllLikeNameOrderedName( name, min, max );
+    }
+
+    public int getTrackedEntityAttributeCount()
+    {
+        return attributeStore.getCount();
+    }
+
+    public Collection<TrackedEntityAttribute> getTrackedEntityAttributesBetween( int min, int max )
+    {
+        return attributeStore.getAllOrderedName( min, max );
+    }
+
+    public int getTrackedEntityAttributeCountByName( String name )
+    {
+        return attributeStore.getCountEqNameNoAcl( name );
+    }
+
 }

=== modified file 'dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/deletion/DeletionHandler.java'
--- dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/deletion/DeletionHandler.java	2014-02-07 20:25:49 +0000
+++ dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/deletion/DeletionHandler.java	2014-02-13 09:51:36 +0000
@@ -81,11 +81,11 @@
 import org.hisp.dhis.report.Report;
 import org.hisp.dhis.reporttable.ReportTable;
 import org.hisp.dhis.sqlview.SqlView;
-import org.hisp.dhis.trackedentity.TrackedEntityInstance;
 import org.hisp.dhis.trackedentity.TrackedEntityAttribute;
 import org.hisp.dhis.trackedentity.TrackedEntityAttributeGroup;
 import org.hisp.dhis.trackedentity.TrackedEntityAudit;
 import org.hisp.dhis.trackedentity.TrackedEntityForm;
+import org.hisp.dhis.trackedentity.TrackedEntityInstance;
 import org.hisp.dhis.trackedentityattributevalue.TrackedEntityAttributeValue;
 import org.hisp.dhis.trackedentitydatavalue.TrackedEntityDataValue;
 import org.hisp.dhis.user.User;

=== modified file 'dhis-2/dhis-web/dhis-web-caseentry/src/main/webapp/dhis-web-caseentry/javascript/commons.js'
--- dhis-2/dhis-web/dhis-web-caseentry/src/main/webapp/dhis-web-caseentry/javascript/commons.js	2014-02-12 10:18:42 +0000
+++ dhis-2/dhis-web/dhis-web-caseentry/src/main/webapp/dhis-web-caseentry/javascript/commons.js	2014-02-13 09:51:36 +0000
@@ -388,7 +388,6 @@
 			id:programIdAddEntityInstance,
 			entityInstanceId: getFieldValue('entityInstanceId')
 		}, function( json )  {
-			
 			removeAttributeOption('advSearchBox0');			
 			var attributeList = jQuery( '#searchObjectId');	
 				

=== added file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/ajax/jsonCategoryOptionGroup.vm'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/ajax/jsonCategoryOptionGroup.vm	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/ajax/jsonCategoryOptionGroup.vm	2014-02-13 09:51:36 +0000
@@ -0,0 +1,9 @@
+{ "categoryOptionGroup": 
+  {
+    "id": $!{categoryOptionGroup.id},
+    "name": "$!encoder.jsonEncode( ${categoryOptionGroup.displayName} )",
+	"shortName": "$!encoder.jsonEncode( ${categoryOptionGroup.displayShortName} )",
+	"code": "$!encoder.jsonEncode( ${categoryOptionGroup.code} )",
+    "memberCount": "$categoryOptionGroup.members.size()"
+  } 
+}

=== added directory 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup'
=== added file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup/AddCategoryOptionGroupAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup/AddCategoryOptionGroupAction.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup/AddCategoryOptionGroupAction.java	2014-02-13 09:51:36 +0000
@@ -0,0 +1,113 @@
+/*
+ * 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.dd.action.categoryoptiongroup;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.hisp.dhis.dataelement.CategoryOptionGroup;
+import org.hisp.dhis.dataelement.CategoryOptionGroupService;
+import org.hisp.dhis.dataelement.DataElementCategoryService;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.opensymphony.xwork2.Action;
+
+/**
+ * @author Chau Thu Tran
+ * 
+ * @version $ AddCategoryOptionGroupAction.java Feb 12, 2014 11:20:01 PM $
+ */
+public class AddCategoryOptionGroupAction
+    implements Action
+{
+    // -------------------------------------------------------------------------
+    // Dependencies
+    // -------------------------------------------------------------------------
+
+    @Autowired
+    private CategoryOptionGroupService categoryOptionGroupService;
+
+    @Autowired
+    private DataElementCategoryService dataElementCategoryService;
+
+    // -------------------------------------------------------------------------
+    // Input
+    // -------------------------------------------------------------------------
+
+    private String name;
+
+    public void setName( String name )
+    {
+        this.name = name;
+    }
+
+    private String shortName;
+
+    public void setShortName( String shortName )
+    {
+        this.shortName = shortName;
+    }
+
+    private String code;
+
+    public void setCode( String code )
+    {
+        this.code = code;
+    }
+
+    private Set<String> groupMembers = new HashSet<String>();
+
+    public void setGroupMembers( Set<String> groupMembers )
+    {
+        this.groupMembers = groupMembers;
+    }
+
+    // -------------------------------------------------------------------------
+    // Action implementation
+    // -------------------------------------------------------------------------
+
+    @Override
+    public String execute()
+        throws Exception
+    {
+        CategoryOptionGroup categoryOptionGroup = new CategoryOptionGroup( name );
+        categoryOptionGroup.setShortName( shortName );
+        categoryOptionGroup.setCode( code );
+
+        for ( String id : groupMembers )
+        {
+            categoryOptionGroup.addCategoryOption( dataElementCategoryService.getDataElementCategoryOption( Integer
+                .parseInt( id ) ) );
+        }
+
+        categoryOptionGroupService.addCategoryOptionGroup( categoryOptionGroup );
+
+        return SUCCESS;
+    }
+
+}

=== added file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup/GetCategoryOptionGroupAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup/GetCategoryOptionGroupAction.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup/GetCategoryOptionGroupAction.java	2014-02-13 09:51:36 +0000
@@ -0,0 +1,82 @@
+/*
+ * 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.dd.action.categoryoptiongroup;
+
+import org.hisp.dhis.dataelement.CategoryOptionGroup;
+import org.hisp.dhis.dataelement.CategoryOptionGroupService;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.opensymphony.xwork2.Action;
+
+/**
+ * @author Chau Thu Tran
+ * 
+ * @version $ GetCategoryOptionGroupAction.java Feb 12, 2014 11:27:01 PM $
+ */
+public class GetCategoryOptionGroupAction
+    implements Action
+{
+    // -------------------------------------------------------------------------
+    // Dependencies
+    // -------------------------------------------------------------------------
+
+    @Autowired
+    private CategoryOptionGroupService categoryOptionGroupService;
+
+    // -------------------------------------------------------------------------
+    // Input
+    // -------------------------------------------------------------------------
+
+    private int id;
+
+    public void setId( int id )
+    {
+        this.id = id;
+    }
+
+    private CategoryOptionGroup categoryOptionGroup;
+
+    public CategoryOptionGroup getCategoryOptionGroup()
+    {
+        return categoryOptionGroup;
+    }
+
+    // -------------------------------------------------------------------------
+    // Action implementation
+    // -------------------------------------------------------------------------
+
+    @Override
+    public String execute()
+        throws Exception
+    {
+        categoryOptionGroup = categoryOptionGroupService.getCategoryOptionGroup( id );
+        
+        return SUCCESS;
+    }
+
+}

=== added file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup/GetCategoryOptionGroupListAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup/GetCategoryOptionGroupListAction.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup/GetCategoryOptionGroupListAction.java	2014-02-13 09:51:36 +0000
@@ -0,0 +1,109 @@
+/*
+ * 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.dd.action.categoryoptiongroup;
+
+import static org.apache.commons.lang.StringUtils.isNotBlank;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.hisp.dhis.common.comparator.IdentifiableObjectNameComparator;
+import org.hisp.dhis.dataelement.CategoryOptionGroup;
+import org.hisp.dhis.dataelement.CategoryOptionGroupService;
+import org.hisp.dhis.paging.ActionPagingSupport;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * @author Chau Thu Tran
+ * 
+ * @version $ GetCategoryOptionGroupListAction.java Feb 12, 2014 11:27:01 PM $
+ */
+public class GetCategoryOptionGroupListAction
+    extends ActionPagingSupport<CategoryOptionGroup>
+{
+    // -------------------------------------------------------------------------
+    // Dependencies
+    // -------------------------------------------------------------------------
+
+    @Autowired
+    private CategoryOptionGroupService categoryOptionGroupService;
+
+    // -------------------------------------------------------------------------
+    // Input
+    // -------------------------------------------------------------------------
+
+    private String key;
+
+    public String getKey()
+    {
+        return key;
+    }
+
+    public void setKey( String key )
+    {
+        this.key = key;
+    }
+
+    private List<CategoryOptionGroup> categoryOptionGroups = new ArrayList<CategoryOptionGroup>();;
+
+    public List<CategoryOptionGroup> getCategoryOptionGroups()
+    {
+        return categoryOptionGroups;
+    }
+
+    // -------------------------------------------------------------------------
+    // Action implementation
+    // -------------------------------------------------------------------------
+
+    @Override
+    public String execute()
+        throws Exception
+    {
+        if ( isNotBlank( key ) ) // Filter on key only if set
+        {
+            this.paging = createPaging( categoryOptionGroupService.getCategoryOptionGroupCountByName( key ) );
+
+            categoryOptionGroups = new ArrayList<CategoryOptionGroup>(
+                categoryOptionGroupService.getCategoryOptionGroupsBetweenByName( key, paging.getStartPos(),
+                    paging.getPageSize() ) );
+        }
+        else
+        {
+            this.paging = createPaging( categoryOptionGroupService.getCategoryOptionGroupCount() );
+
+            categoryOptionGroups = new ArrayList<CategoryOptionGroup>( categoryOptionGroupService.getCategoryOptionGroupsBetween(
+                paging.getStartPos(), paging.getPageSize() ) );
+        }
+
+        Collections.sort( categoryOptionGroups, IdentifiableObjectNameComparator.INSTANCE );
+
+        return SUCCESS;
+    }
+
+}

=== added file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup/RemoveCategoryOptionGroupAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup/RemoveCategoryOptionGroupAction.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup/RemoveCategoryOptionGroupAction.java	2014-02-13 09:51:36 +0000
@@ -0,0 +1,77 @@
+/*
+ * 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.dd.action.categoryoptiongroup;
+
+import org.hisp.dhis.dataelement.CategoryOptionGroup;
+import org.hisp.dhis.dataelement.CategoryOptionGroupService;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.opensymphony.xwork2.Action;
+
+/**
+ * @author Chau Thu Tran
+ * 
+ * @version $ RemoveCategoryOptionGroupAction.java Feb 12, 2014 11:27:01 PM $
+ */
+public class RemoveCategoryOptionGroupAction
+    implements Action
+{
+    // -------------------------------------------------------------------------
+    // Dependencies
+    // -------------------------------------------------------------------------
+
+    @Autowired
+    private CategoryOptionGroupService categoryOptionGroupService;
+
+    // -------------------------------------------------------------------------
+    // Input
+    // -------------------------------------------------------------------------
+
+    private int id;
+
+    public void setId( int id )
+    {
+        this.id = id;
+    }
+
+    // -------------------------------------------------------------------------
+    // Action implementation
+    // -------------------------------------------------------------------------
+
+    @Override
+    public String execute()
+        throws Exception
+    {
+        CategoryOptionGroup categoryOptionGroup = categoryOptionGroupService.getCategoryOptionGroup( id );
+
+        categoryOptionGroupService.deleteCategoryOptionGroup( categoryOptionGroup );
+
+        return SUCCESS;
+    }
+
+}

=== added file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup/ShowAddCategoryOptionGroupAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup/ShowAddCategoryOptionGroupAction.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup/ShowAddCategoryOptionGroupAction.java	2014-02-13 09:51:36 +0000
@@ -0,0 +1,83 @@
+/*
+ * 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.dd.action.categoryoptiongroup;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.hisp.dhis.dataelement.DataElementCategoryOption;
+import org.hisp.dhis.dataelement.DataElementCategoryService;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.opensymphony.xwork2.Action;
+
+/**
+ * @author Chau Thu Tran
+ * 
+ * @version $ ShowAddCategoryOptionGroupAction.java Feb 12, 2014 11:20:01 PM $
+ */
+public class ShowAddCategoryOptionGroupAction
+    implements Action
+{
+    // -------------------------------------------------------------------------
+    // Dependencies
+    // -------------------------------------------------------------------------
+
+    @Autowired
+    private DataElementCategoryService dataElementCategoryService;
+
+    // -------------------------------------------------------------------------
+    // Input
+    // -------------------------------------------------------------------------
+
+    private List<DataElementCategoryOption> categoryOptions;
+
+    public List<DataElementCategoryOption> getCategoryOptions()
+    {
+        return categoryOptions;
+    }
+
+    // -------------------------------------------------------------------------
+    // Action implementation
+    // -------------------------------------------------------------------------
+
+    public void setDataElementCategoryService( DataElementCategoryService dataElementCategoryService )
+    {
+        this.dataElementCategoryService = dataElementCategoryService;
+    }
+
+    @Override
+    public String execute()
+        throws Exception
+    {
+        categoryOptions = new ArrayList<DataElementCategoryOption>( dataElementCategoryService.getAllDataElementCategoryOptions() );
+        
+        return SUCCESS;
+    }
+
+}

=== added file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup/ShowUpdateCategoryOptionGroupAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup/ShowUpdateCategoryOptionGroupAction.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup/ShowUpdateCategoryOptionGroupAction.java	2014-02-13 09:51:36 +0000
@@ -0,0 +1,115 @@
+/*
+ * 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.dd.action.categoryoptiongroup;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.hisp.dhis.dataelement.CategoryOptionGroup;
+import org.hisp.dhis.dataelement.CategoryOptionGroupService;
+import org.hisp.dhis.dataelement.DataElementCategoryOption;
+import org.hisp.dhis.dataelement.DataElementCategoryService;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.opensymphony.xwork2.Action;
+
+/**
+ * @author Chau Thu Tran
+ * 
+ * @version $ ShowUpdateCategoryOptionGroupAction.java Feb 12, 2014 11:20:01 PM
+ *          $
+ */
+public class ShowUpdateCategoryOptionGroupAction
+    implements Action
+{
+    // -------------------------------------------------------------------------
+    // Dependencies
+    // -------------------------------------------------------------------------
+
+    @Autowired
+    private CategoryOptionGroupService categoryOptionGroupService;
+
+    @Autowired
+    private DataElementCategoryService dataElementCategoryService;
+
+    // -------------------------------------------------------------------------
+    // Input && Output
+    // -------------------------------------------------------------------------
+
+    private int id;
+
+    public void setId( int id )
+    {
+        this.id = id;
+    }
+
+    private CategoryOptionGroup categoryOptionGroup;
+
+    public CategoryOptionGroup getCategoryOptionGroup()
+    {
+        return categoryOptionGroup;
+    }
+
+    private List<DataElementCategoryOption> categoryOptions;
+
+    public List<DataElementCategoryOption> getCategoryOptions()
+    {
+        return categoryOptions;
+    }
+
+    private List<DataElementCategoryOption> groupMembers;
+
+    public List<DataElementCategoryOption> getGroupMembers()
+    {
+        return groupMembers;
+    }
+
+    // -------------------------------------------------------------------------
+    // Action implementation
+    // -------------------------------------------------------------------------
+
+    public void setDataElementCategoryService( DataElementCategoryService dataElementCategoryService )
+    {
+        this.dataElementCategoryService = dataElementCategoryService;
+    }
+
+    @Override
+    public String execute()
+        throws Exception
+    {
+        categoryOptionGroup = categoryOptionGroupService.getCategoryOptionGroup( id );
+
+        groupMembers = new ArrayList<DataElementCategoryOption>( categoryOptionGroup.getMembers() );
+
+        categoryOptions = new ArrayList<DataElementCategoryOption>(
+            dataElementCategoryService.getAllDataElementCategoryOptions() );
+
+        return SUCCESS;
+    }
+
+}

=== added file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup/UpdateCategoryOptionGroupAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup/UpdateCategoryOptionGroupAction.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup/UpdateCategoryOptionGroupAction.java	2014-02-13 09:51:36 +0000
@@ -0,0 +1,122 @@
+/*
+ * 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.dd.action.categoryoptiongroup;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.hisp.dhis.dataelement.CategoryOptionGroup;
+import org.hisp.dhis.dataelement.CategoryOptionGroupService;
+import org.hisp.dhis.dataelement.DataElementCategoryService;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.opensymphony.xwork2.Action;
+
+/**
+ * @author Chau Thu Tran
+ * 
+ * @version $ UpdateCategoryOptionGroupAction.java Feb 12, 2014 11:25:01 PM $
+ */
+public class UpdateCategoryOptionGroupAction
+    implements Action
+{
+    // -------------------------------------------------------------------------
+    // Dependencies
+    // -------------------------------------------------------------------------
+
+    @Autowired
+    private CategoryOptionGroupService categoryOptionGroupService;
+
+    @Autowired
+    private DataElementCategoryService dataElementCategoryService;
+
+    // -------------------------------------------------------------------------
+    // Input
+    // -------------------------------------------------------------------------
+
+    private int id;
+
+    public void setId( int id )
+    {
+        this.id = id;
+    }
+
+    private String name;
+
+    public void setName( String name )
+    {
+        this.name = name;
+    }
+
+    private String shortName;
+
+    public void setShortName( String shortName )
+    {
+        this.shortName = shortName;
+    }
+
+    private String code;
+
+    public void setCode( String code )
+    {
+        this.code = code;
+    }
+
+    private Set<String> groupMembers = new HashSet<String>();
+
+    public void setGroupMembers( Set<String> groupMembers )
+    {
+        this.groupMembers = groupMembers;
+    }
+
+    // -------------------------------------------------------------------------
+    // Action implementation
+    // -------------------------------------------------------------------------
+
+    @Override
+    public String execute()
+        throws Exception
+    {
+        CategoryOptionGroup categoryOptionGroup = categoryOptionGroupService.getCategoryOptionGroup( id );
+        categoryOptionGroup.setName( name );
+        categoryOptionGroup.setShortName( shortName );
+        categoryOptionGroup.setCode( code );
+        categoryOptionGroup.getMembers().clear();
+
+        for ( String id : groupMembers )
+        {
+            categoryOptionGroup.addCategoryOption( dataElementCategoryService.getDataElementCategoryOption( Integer
+                .parseInt( id ) ) );
+        }
+
+        categoryOptionGroupService.addCategoryOptionGroup( categoryOptionGroup );
+
+        return SUCCESS;
+    }
+
+}

=== added file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup/ValidateCategoryOptionGroupAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup/ValidateCategoryOptionGroupAction.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categoryoptiongroup/ValidateCategoryOptionGroupAction.java	2014-02-13 09:51:36 +0000
@@ -0,0 +1,149 @@
+/*
+ * 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.dd.action.categoryoptiongroup;
+
+import org.hisp.dhis.dataelement.CategoryOptionGroup;
+import org.hisp.dhis.dataelement.CategoryOptionGroupService;
+import org.hisp.dhis.i18n.I18n;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.opensymphony.xwork2.Action;
+
+/**
+ * @author Chau Thu Tran
+ * 
+ * @version $ ValidateCategoryOptionGroupAction.java Feb 12, 2014 11:20:01 PM $
+ */
+public class ValidateCategoryOptionGroupAction
+    implements Action
+{
+    // -------------------------------------------------------------------------
+    // Dependencies
+    // -------------------------------------------------------------------------
+
+    @Autowired
+    private CategoryOptionGroupService categoryOptionGroupService;
+
+    private I18n i18n;
+
+    public void setI18n( I18n i18n )
+    {
+        this.i18n = i18n;
+    }
+
+    // -------------------------------------------------------------------------
+    // Input
+    // -------------------------------------------------------------------------
+
+    private Integer id;
+
+    public void setId( Integer id )
+    {
+        this.id = id;
+    }
+
+    private String name;
+
+    public void setName( String name )
+    {
+        this.name = name;
+    }
+
+    private String shortName;
+
+    public void setShortName( String shortName )
+    {
+        this.shortName = shortName;
+    }
+
+    private String code;
+
+    public void setCode( String code )
+    {
+        this.code = code;
+    }
+
+    private String message;
+
+    public String getMessage()
+    {
+        return message;
+    }
+
+    // -------------------------------------------------------------------------
+    // Action implementation
+    // -------------------------------------------------------------------------
+
+    @Override
+    public String execute()
+        throws Exception
+    {
+        if ( name != null )
+        {
+
+            CategoryOptionGroup match = categoryOptionGroupService.getCategoryOptionGroupByName( name );
+
+            if ( match != null && (id == null || match.getId() != id.intValue()) )
+            {
+                message = i18n.getString( "name_in_use" );
+
+                return INPUT;
+            }
+
+        }
+        
+        if ( shortName != null )
+        {
+            CategoryOptionGroup match = categoryOptionGroupService.getCategoryOptionGroupByShortName( shortName );
+
+            if ( match != null && (id == null || match.getId() != id) )
+            {
+                message = i18n.getString( "short_name_in_use" );
+
+                return INPUT;
+            }
+        }
+
+        if ( code != null && !code.trim().isEmpty() )
+        {
+            CategoryOptionGroup match = categoryOptionGroupService.getCategoryOptionGroupByCode( code );
+
+            if ( match != null && (id == null || match.getId() != id) )
+            {
+                message = i18n.getString( "code_in_use" );
+
+                return INPUT;
+            }
+        }
+
+        message = i18n.getString( "everything_is_ok" );
+
+        return SUCCESS;
+    }
+
+}

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/resources/META-INF/dhis/beans.xml	2014-02-12 16:09:47 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/resources/META-INF/dhis/beans.xml	2014-02-13 09:51:36 +0000
@@ -500,4 +500,38 @@
 
   <bean id="org.hisp.dhis.dd.action.NoAction" class="org.hisp.dhis.dd.action.NoAction" />
 
+  <!-- CategoryOptionGroup  -->
+  
+  <bean id="org.hisp.dhis.dd.action.categoryoptiongroup.AddCategoryOptionGroupAction" class="org.hisp.dhis.dd.action.categoryoptiongroup.AddCategoryOptionGroupAction"
+    scope="prototype">
+  </bean>
+  
+  <bean id="org.hisp.dhis.dd.action.categoryoptiongroup.GetCategoryOptionGroupAction" class="org.hisp.dhis.dd.action.categoryoptiongroup.GetCategoryOptionGroupAction"
+    scope="prototype">
+  </bean>
+  
+  <bean id="org.hisp.dhis.dd.action.categoryoptiongroup.GetCategoryOptionGroupListAction" class="org.hisp.dhis.dd.action.categoryoptiongroup.GetCategoryOptionGroupListAction"
+    scope="prototype">
+  </bean>
+  
+  <bean id="org.hisp.dhis.dd.action.categoryoptiongroup.RemoveCategoryOptionGroupAction" class="org.hisp.dhis.dd.action.categoryoptiongroup.RemoveCategoryOptionGroupAction"
+    scope="prototype">
+  </bean>
+  
+  <bean id="org.hisp.dhis.dd.action.categoryoptiongroup.ShowAddCategoryOptionGroupAction" class="org.hisp.dhis.dd.action.categoryoptiongroup.ShowAddCategoryOptionGroupAction"
+    scope="prototype">
+  </bean>
+  
+  <bean id="org.hisp.dhis.dd.action.categoryoptiongroup.ShowUpdateCategoryOptionGroupAction" class="org.hisp.dhis.dd.action.categoryoptiongroup.ShowUpdateCategoryOptionGroupAction"
+    scope="prototype">
+  </bean>
+  
+  <bean id="org.hisp.dhis.dd.action.categoryoptiongroup.UpdateCategoryOptionGroupAction" class="org.hisp.dhis.dd.action.categoryoptiongroup.UpdateCategoryOptionGroupAction"
+    scope="prototype">
+  </bean>
+  
+  <bean id="org.hisp.dhis.dd.action.categoryoptiongroup.ValidateCategoryOptionGroupAction" class="org.hisp.dhis.dd.action.categoryoptiongroup.ValidateCategoryOptionGroupAction"
+    scope="prototype">
+  </bean>
+  
 </beans>

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/resources/org/hisp/dhis/dd/i18n_module.properties'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/resources/org/hisp/dhis/dd/i18n_module.properties	2014-01-31 18:08:43 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/resources/org/hisp/dhis/dd/i18n_module.properties	2014-02-13 09:51:36 +0000
@@ -216,4 +216,9 @@
 attribute=Attribute
 option_set_for_data_values=Option set for data values
 option_set_for_comments=Option set for comments
-organisation_unit_counts=Organisation unit counts
\ No newline at end of file
+organisation_unit_counts=Organisation unit counts
+catergory_option_group = Catergory option group
+catergory_option_group_management = Catergory option group management
+create_new_category_option_group = Create new catergory option group
+edit_category_option_group = Edit catergory option group
+confirm_delete_catergory_option_group = Are you sure you want to delete this catergory option group?
\ No newline at end of file

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/resources/struts.xml'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/resources/struts.xml	2014-02-12 16:09:47 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/resources/struts.xml	2014-02-13 09:51:36 +0000
@@ -678,6 +678,77 @@
       <result name="error" type="velocity-json">/dhis-web-commons/ajax/jsonResponseError.vm</result>
       <param name="onExceptionReturn">plainTextError</param>
     </action>
+    
+    <!-- CategoryOptionGroup -->
+    
+    <action name="categoryOptionGroup"
+		class="org.hisp.dhis.dd.action.categoryoptiongroup.GetCategoryOptionGroupListAction">
+		<result name="success" type="velocity">/main.vm</result>
+		<param name="page">/dhis-web-maintenance-datadictionary/categoryOptionGroup.vm</param>
+		<param name="menu">/dhis-web-maintenance-datadictionary/menu.vm</param>
+		<param name="javascripts">javascript/categoryOptionGroup.js</param>
+	</action>
+
+	<action name="getCategoryOptionGroup"
+		class="org.hisp.dhis.dd.action.categoryoptiongroup.GetCategoryOptionGroupAction">
+		<result name="success" type="velocity-json">
+			/dhis-web-commons/ajax/jsonCategoryOptionGroup.vm
+		</result>
+		<param name="onExceptionReturn">plainTextError</param>
+	</action>
+
+	<action name="removeCategoryOptionGroup"
+		class="org.hisp.dhis.dd.action.categoryoptiongroup.RemoveCategoryOptionGroupAction">
+		<result name="success" type="velocity-json">
+			/dhis-web-commons/ajax/jsonResponseSuccess.vm
+		</result>
+		<param name="requiredAuthorities">F_CATEGORY_ATTRIBUTE_GROUP_DELETE</param>
+	</action>
+
+	<action name="addCategoryOptionGroup"
+		class="org.hisp.dhis.dd.action.categoryoptiongroup.AddCategoryOptionGroupAction">
+		<result name="success" type="redirect">categoryOptionGroup.action
+		</result>
+		<param name="requiredAuthorities">F_CATEGORY_ATTRIBUTE_GROUP_ADD</param>
+	</action>
+
+	<action name="showAddCategoryOptionGroupForm" class="org.hisp.dhis.dd.action.categoryoptiongroup.ShowAddCategoryOptionGroupAction">
+		<result name="success" type="velocity">/main.vm</result>
+		<param name="page">/dhis-web-maintenance-datadictionary/addCategoryOptionGroupForm.vm</param>
+		<param name="javascripts">javascript/categoryOptionGroup.js</param>
+		<param name="stylesheets">style/basic.css</param>
+		<param name="requiredAuthorities">F_CATEGORY_ATTRIBUTE_GROUP_ADD</param>
+	</action>
+
+	<action name="showUpdateCategoryOptionGroupForm"
+		class="org.hisp.dhis.dd.action.categoryoptiongroup.ShowUpdateCategoryOptionGroupAction">
+		<result name="success" type="velocity">/main.vm</result>
+		<param name="page">/dhis-web-maintenance-datadictionary/updateCategoryOptionGroupForm.vm</param>
+		<param name="javascripts">javascript/categoryOptionGroup.js</param>
+		<param name="stylesheets">style/basic.css</param>
+		<param name="requiredAuthorities">F_CATEGORY_ATTRIBUTE_GROUP_ADD</param>
+	</action>
+
+	<action name="updateCategoryOptionGroup"
+		class="org.hisp.dhis.dd.action.categoryoptiongroup.UpdateCategoryOptionGroupAction">
+		<result name="success" type="redirect">categoryOptionGroup.action
+		</result>
+		<param name="requiredAuthorities">F_CATEGORY_ATTRIBUTE_GROUP_ADD</param>
+	</action>
+
+	<action name="validateCategoryOptionGroup"
+		class="org.hisp.dhis.dd.action.categoryoptiongroup.ValidateCategoryOptionGroupAction">
+		<result name="success" type="velocity-json">
+			/dhis-web-commons/ajax/jsonResponseSuccess.vm
+		</result>
+		<result name="error" type="velocity-json">
+			/dhis-web-commons/ajax/jsonResponseError.vm
+		</result>
+		<result name="input" type="velocity-json">
+			/dhis-web-commons/ajax/jsonResponseInput.vm
+		</result>
+		<param name="onExceptionReturn">plainTextError</param>
+	</action>
 
   </package>
 

=== added file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/addCategoryOptionGroupForm.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/addCategoryOptionGroupForm.vm	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/addCategoryOptionGroupForm.vm	2014-02-13 09:51:36 +0000
@@ -0,0 +1,92 @@
+<script type="text/javascript">
+	jQuery(function() {
+        validation2('addCategoryOptionGroupForm', function ( form ) {
+            form.submit();
+        },function(){
+			selectAllById('groupMembers');
+			if(jQuery("#groupMembers option").length > 0 ){
+				setFieldValue('hasOptions', 'true');
+			}
+		});
+
+        checkValueIsExist("name", "validateCategoryOptionGroup.action");
+		checkValueIsExist( "shortName", "validateCategoryOptionGroup.action" );
+	    checkValueIsExist( "code", "validateCategoryOptionGroup.action" );
+		
+		jQuery("#availableCategoryOptionsList").dhisAjaxSelect({
+			source: "../dhis-web-commons-ajax-json/getDataElementCategoryOptions.action",
+			iterator: "dataElementCategoryOptions",
+			connectedTo: 'groupMembers',
+			handler: function(item) {
+				var option = jQuery("<option data-id='" + item.groups + "' />");
+				option.text( item.name );
+				option.attr( "value", item.id );
+
+				return option;
+			}
+		});
+	});
+</script>
+
+<h3>$i18n.getString( "create_new_category_option_group" )</h3>
+
+<form id="addCategoryOptionGroupForm" action="addCategoryOptionGroup.action" method="post" class="inputForm">
+
+<table>
+	<tr>
+		<th colspan="2">$i18n.getString( "details" )</th>
+	</tr>
+
+	<tr>
+		<td style="width: 120px;"><label for="name">$i18n.getString( "name" ) <em title="$i18n.getString( 'required' )" class="required">*</em></label></td>
+        <td><input type="text" id="name" name="name" class="{validate:{required:true}}"/></td>
+    </tr>
+	<tr>
+		<td><label for="shortName">$i18n.getString( "short_name" ) <em title="$i18n.getString( 'required' )" class="required">*</em></label></td>
+		<td><input type="text" id="shortName" name="shortName" class="{validate:{required:true}}"/></td>
+	</tr>
+	<tr>
+		<td><label for="code">$i18n.getString( "code" )</label></td>
+		<td><input type="text" id="code" name="code" /></td>
+	</tr>
+</table>
+
+<table>
+    <colgroup>
+      <col style="width: 500px;"/>
+      <col/>
+      <col style="width: 500px;"/>
+    </colgroup>
+
+	<tr>
+		<th>$i18n.getString( "available_category_options" )</th>
+		<th></th>
+		<th>$i18n.getString( "group_members" )
+			<input type='hidden' id='hasOptions' name='hasOptions' class="{validate:{required:true}}">
+		</th>
+	</tr>
+
+	<tr>
+		<td>
+			<select id="availableCategoryOptionsList" name="availableCategoryOptionsList" multiple="multiple" style="height: 200px; width: 100%;"></select>
+		</td>
+		
+		<td style="text-align:center">
+        	<input type="button" value="&gt;" title="$i18n.getString( 'move_selected' )" style="width:50px" onclick="dhisAjaxSelect_moveAllSelected( 'availableCategoryOptionsList' );"/><br/>
+            <input type="button" value="&lt;" title="$i18n.getString( 'remove_selected' )" style="width:50px" onclick="dhisAjaxSelect_moveAllSelected( 'groupMembers' );"/><br/>
+			<input type="button" value="&gt;&gt;" title="$i18n.getString('move_all')" style="width:50px" onclick="dhisAjaxSelect_moveAll( 'availableCategoryOptionsList' );"/><br/>
+			<input type="button" value="&lt;&lt;" title="$i18n.getString('remove_all')" style="width:50px" onclick="dhisAjaxSelect_moveAll( 'groupMembers' );"/>
+		</td>
+
+		<td>
+			<select id="groupMembers" name="groupMembers" multiple="multiple" style="height: 200px; width: 100%; margin-top: 22px;"></select>
+		</td>
+	</tr>
+</table>
+
+<p>
+	<input type="submit" value="$i18n.getString( 'add' )" style="width:10em"/>
+	<input type="button" value="$i18n.getString( 'cancel' )" onclick="dhis2.commons.redirectCurrentPage( 'dataElementGroup.action' )" style="width:10em"/>
+</p>
+
+</form>

=== added file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/categoryOptionGroup.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/categoryOptionGroup.vm	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/categoryOptionGroup.vm	2014-02-13 09:51:36 +0000
@@ -0,0 +1,75 @@
+
+<script type="text/javascript">
+	jQuery(document).ready(function(){
+		tableSorter( 'categoryOptionGroupList' );	
+	});
+
+	var i18n_confirm_delete = '$encoder.jsEscape( $i18n.getString( "confirm_delete_catergory_option_group" ) , "'")';
+	var i18n_adding_catergory_option_group_failed = '$encoder.jsEscape( $i18n.getString( "adding_catergory_option_group_failed" ) , "'")';
+	var	i18n_saving_catergory_option_group_failed = '$encoder.jsEscape( $i18n.getString( "saving_catergory_option_group_failed" ) , "'")';
+</script>
+
+<h3>$i18n.getString( "catergory_option_group_management" )</h3>
+
+<div id="contextMenu" class="contextMenu">
+  <ul id="contextMenuItems" class="contextMenuItems">
+    <li><a data-target-fn="showUpdateCategoryOptionGroupForm"><i class="fa fa-edit"></i>&nbsp;&nbsp;$i18n.getString( "edit" )</a></li>
+    <li><a data-target-fn="translateWithContext"><i class="fa fa-globe"></i>&nbsp;&nbsp;$i18n.getString( "translation_translate" )</a></li>
+    <li><a data-target-fn="removeCategoryOptionGroup"><i class="fa fa-trash-o"></i>&nbsp;&nbsp;$i18n.getString( "remove" )</a></li>
+    <li><a data-target-fn="showCategoryOptionGroupDetails"><i class="fa fa-info-circle"></i>&nbsp;&nbsp;$i18n.getString( "show_details" )</a></li>
+  </ul>
+</div>
+
+<table class="mainPageTable">
+	<tr>
+		<td style="vertical-align:top">
+			<table width="100%">
+				<tr>
+					<td>#filterDiv( "categoryOptionGroup" )</td>
+					<td style="text-align:right"><input type="button" value="$i18n.getString( 'add_new' )" onclick="window.location.href='showAddCategoryOptionGroupForm.action'" style="width:80px"/></td>
+				</tr>
+			</table>
+			<div id="content">
+			<table class="listTable" id="categoryOptionGroupList">			
+				<thead>
+					<tr>
+						<th>$i18n.getString( "name" )</th>
+					</tr>
+				</thead>
+				<tbody id="list">
+				#foreach( $categoryOptionGroup in $categoryOptionGroups )
+				<tr id="tr${categoryOptionGroup.id}" data-id="$!categoryOptionGroup.id" data-uid="$!categoryOptionGroup.uid" data-type="CategoryOptionGroup" data-name="$encoder.htmlEncode( $!categoryOptionGroup.displayName )"
+            data-can-manage="$security.canManage( $categoryOptionGroup )"
+            data-can-update="$security.canUpdate( $categoryOptionGroup )"
+            data-can-delete="$security.canDelete( $categoryOptionGroup )">
+          <td>$encoder.htmlEncode( $!categoryOptionGroup.displayName )</td>
+				</tr>
+				#end
+				</tbody>
+			</table>
+			<p></p>
+			#parse( "/dhis-web-commons/paging/paging.vm" )
+			</div>
+		</td>
+
+		<td id="detailsData">
+			<div id="detailsArea">
+				<div id="hideDetailsArea">
+					<a href="javascript:hideDetails()" title="$i18n.getString( 'hide_details' )"><img src="../images/hide.png" alt="$i18n.getString( 'hide_details' )"/></a>
+				</div>
+				<p><label>$i18n.getString( "name" ):</label><br/><span id="nameField"></span></p>
+				<p><label>$i18n.getString( "short_name" ):</label><br/><span id="shortNameField"></span></p>
+				<p><label>$i18n.getString( "code" ):</label><br/><span id="codeField"></span></p>
+				<p><label>$i18n.getString( "number_of_members" ):</label><br/><span id="memberCountField"></span></p>
+			</div>
+
+			<div id="warningArea">
+          <div id="hideDetailsArea">
+              <a href="javascript:hideWarning()" title="$i18n.getString( 'hide_warning' )"><img src="../images/hide.png" alt="$i18n.getString( 'hide_warning' )"/></a>
+          </div>
+          <p><span id="warningField"></span></p>
+      </div>
+			
+		</td>
+	</tr>
+</table>

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/index.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/index.vm	2014-02-12 16:09:47 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/index.vm	2014-02-13 09:51:36 +0000
@@ -5,7 +5,8 @@
 	#introListImgItem( "dataElementGroup.action" "data_element_group" "dataelement" )
     #introListImgItem( "dataElementGroupEditor.action" "data_element_group_editor" "dataelement" )
     #introListImgItem( "dataElementGroupSet.action" "data_element_group_set" "groupset" )
-    #introListImgItem( "categoryOption.action" "data_element_category_option" "category" )
+    #introListImgItem( "categoryOption.action" "category_option_group" "category" )
+    #introListImgItem( "categoryOptionGroup.action" "ategory_option_group" "category" )
     #introListImgItem( "category.action" "data_element_category" "category" )
     #introListImgItem( "categoryCombo.action" "data_element_category_combo" "category" )
     #introListImgItem( "dataDictionary.action" "data_dictionary" "datadictionary" )

=== added file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/javascript/categoryOptionGroup.js'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/javascript/categoryOptionGroup.js	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/javascript/categoryOptionGroup.js	2014-02-13 09:51:36 +0000
@@ -0,0 +1,34 @@
+$(function() {
+  dhis2.contextmenu.makeContextMenu({
+    menuId: 'contextMenu',
+    menuItemActiveClass: 'contextMenuItemActive'
+  });
+});
+
+// -----------------------------------------------------------------------------
+// View details
+// -----------------------------------------------------------------------------
+
+function showUpdateCategoryOptionGroupForm( context ) {
+  location.href = 'showUpdateCategoryOptionGroupForm.action?id=' + context.id;
+}
+
+function showCategoryOptionGroupDetails( context ) {
+  jQuery.getJSON('getCategoryOptionGroup.action', { id: context.id },
+    function( json ) {
+      setInnerHTML('nameField', json.categoryOptionGroup.name);
+      setInnerHTML('codeField', json.categoryOptionGroup.code);
+      setInnerHTML('shortNameField', json.categoryOptionGroup.shortName);
+      setInnerHTML('memberCountField', json.categoryOptionGroup.memberCount);
+
+      showDetails();
+    });
+}
+
+// -----------------------------------------------------------------------------
+// Remove CategoryOption
+// -----------------------------------------------------------------------------
+
+function removeCategoryOptionGroup( context ) {
+  removeItem(context.id, context.name, i18n_confirm_delete, 'removeCategoryOptionGroup.action');
+}

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/menu.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/menu.vm	2014-02-12 16:09:47 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/menu.vm	2014-02-13 09:51:36 +0000
@@ -6,6 +6,7 @@
     <li><a href="dataElementGroupEditor.action">$i18n.getString( "data_element_group_editor" )&nbsp;</a></li>
 	<li><a href="dataElementGroupSet.action">$i18n.getString( "data_element_group_set" )&nbsp;</a></li>
     <li><a href="categoryOption.action">$i18n.getString( "category_option" )&nbsp;</a></li>
+    <li><a href="categoryOptionGroup.action">$i18n.getString( "category_option_group" )&nbsp;</a></li>
     <li><a href="category.action">$i18n.getString( "category" )&nbsp;</a></li>
     <li><a href="categoryCombo.action">$i18n.getString( "category_combination" )&nbsp;</a></li>
     <li><a href="dataDictionary.action">$i18n.getString( "data_dictionary" )&nbsp;</a></li>

=== added file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/multidimensional/addConceptForm.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/multidimensional/addConceptForm.vm	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/multidimensional/addConceptForm.vm	2014-02-13 09:51:36 +0000
@@ -0,0 +1,33 @@
+<script type="text/javascript">
+	jQuery(document).ready(	function(){
+		var rules = getValidationRules("concept");
+		rules["name"].custome_regex = [/^[a-zA-Z][a-zA-Z0-9_]{0,9}$/,'$i18n.getString( 'regex_add_edit_concept' )']; 
+
+		validation2( 'addConceptForm', function( form ) { form.submit() }, {
+			'rules': rules
+		} );
+
+		checkValueIsExist( "name", "validateAddUpdateConcept.action" );				
+	});
+</script>
+
+<h3>$i18n.getString( "create_new_concept" )</h3>
+
+<form id="addConceptForm" action="addConcept.action" method="post" >
+
+<table>
+	<tr>
+		<th colspan="2">$i18n.getString( "details" )</th>
+	</tr>
+	<tr>
+		<td><label for="name">$i18n.getString( "name" ) <em title="$i18n.getString( "required" )" class="required">*</em></label></td>
+		<td><input type="text" id="name" name="name" style="width:20em"/></td>
+	</tr>
+	<tr>
+		<td></td>
+		<td><input type="submit" value="$i18n.getString( 'add' )" style="width:10em"/>
+		<input type="button" value="$i18n.getString( 'cancel' )" onclick="dhis2.commons.redirectCurrentPage( 'concept.action' )" style="width:10em"/></td>
+	</tr>
+</table>
+
+</form>

=== added file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/multidimensional/concept.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/multidimensional/concept.vm	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/multidimensional/concept.vm	2014-02-13 09:51:36 +0000
@@ -0,0 +1,73 @@
+<script type="text/javascript">
+	jQuery(document).ready(function() {
+		tableSorter( 'listTable' );
+	});
+
+  var i18n_confirm_delete = '$encoder.jsEscape( $i18n.getString( "confirm_delete_concept" ) , "'")';
+	var i18n_adding_concept_failed = '$encoder.jsEscape( $i18n.getString( "adding_concept_failed" ) , "'")';
+	var i18n_saving_concept_failed = '$encoder.jsEscape( $i18n.getString( "saving_concept_failed" ) , "'")';
+</script>
+
+<h3>$i18n.getString( "concept_management" ) #openHelp( "concept" )</h3>
+
+<div id="contextMenu" class="contextMenu">
+  <ul id="contextMenuItems" class="contextMenuItems">
+    <li><a data-target-fn="showUpdateConcept"><i class="fa fa-edit"></i>&nbsp;&nbsp;$i18n.getString( "edit" )</a></li>
+    <li><a data-target-fn="removeConcept"><i class="fa fa-trash-o"></i>&nbsp;&nbsp;$i18n.getString( "remove" )</a></li>
+    <li><a data-target-fn="showConceptDetails"><i class="fa fa-info-circle"></i>&nbsp;&nbsp;$i18n.getString( "show_details" )</a></li>
+  </ul>
+</div>
+
+<table class="mainPageTable">
+	<tr>
+		<td style="vertical-align:top">
+			<table width="100%">
+				<tr>
+					<td>#filterDiv( "concept" )</td>
+					<td colspan="4" style="text-align:right"><input type="button" value="$i18n.getString( 'add_new' )" onclick="window.location.href='showAddConceptForm.action'" style="width:80px"/></td>
+				</tr>
+			</table>
+			<table class="listTable" id="listTable">
+        <thead>
+				<tr>
+					<th>$i18n.getString( "name" )</th>
+				</tr>
+        </thead>
+				<tbody id="list">
+				#foreach( $concept in $concepts )
+				#if( $concept.id != $defaultConcept.id )
+				<tr id="tr${concept.id}" data-id="$!concept.id" data-uid="$!concept.uid" data-type="Concept" data-name="$encoder.htmlEncode( $!concept.displayName )"
+            data-can-manage="$security.canManage( $concept )"
+            data-can-update="$security.canUpdate( $concept )"
+            data-can-delete="$security.canDelete( $concept )">
+          <td>$encoder.htmlEncode( $!concept.displayName )</td>
+				</tr>
+				#end
+				#end
+				</tbody>
+			</table>
+			<p></p>
+			#parse( "/dhis-web-commons/paging/paging.vm" )
+		</td>
+
+    <td id="detailsData">
+      <div id="detailsArea">
+        <div id="hideDetailsArea">
+          <a href="javascript:hideDetails()" title="$i18n.getString( 'hide_details' )">
+            <img src="../images/hide.png" alt="$i18n.getString( 'hide_details' )"/>
+          </a>
+        </div>
+        <p><label>$i18n.getString( "name" ):</label><br/><span id="nameField"></span></p>
+      </div>
+
+      <div id="warningArea">
+        <div id="hideDetailsArea">
+          <a href="javascript:hideWarning()" title="$i18n.getString( 'hide_warning' )">
+            <img src="../images/hide.png" alt="$i18n.getString( 'hide_warning' )"/>
+          </a>
+        </div>
+        <p><span id="warningField"></span></p>
+      </div>
+    </td>
+  </tr>
+</table>

=== added file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/multidimensional/updateConceptForm.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/multidimensional/updateConceptForm.vm	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/multidimensional/updateConceptForm.vm	2014-02-13 09:51:36 +0000
@@ -0,0 +1,37 @@
+<script type="text/javascript">
+	jQuery(document).ready(	function(){
+		var rules = getValidationRules("concept");
+		rules["name"].custome_regex = [/^[a-zA-Z][a-zA-Z0-9_]{0,9}$/,'$i18n.getString( 'regex_add_edit_concept' )']; 
+
+		validation2( 'updateConceptForm', function( form ) { form.submit() }, {
+			'rules': rules
+		} );		
+
+		checkValueIsExist( "name", "validateAddUpdateConcept.action", {id: $concept.id});				
+	});
+</script>
+
+<h3>$i18n.getString( "edit_concept" )</h3>
+
+<form id="updateConceptForm" action="updateConceptInstance.action" method="post" >
+
+<div>
+	<input type="hidden" id="id" name="id" value="$concept.id"/>
+</div>
+
+<table>
+	<tr>
+		<th colspan="2">$i18n.getString( "details" )</th>
+	</tr>
+	<tr>
+		<td><label for="name">$i18n.getString( "name" ) <em title="$i18n.getString( 'required' )" class="required">*</em></label></td>
+		<td><input type="text" id="name" name="name" value="$encoder.htmlEncode( $concept.name )" style="width:20em"/></td>
+	</tr>
+	<tr>
+		<td></td>
+		<td><input type="submit" value="$i18n.getString( 'save' )" style="width:10em"/>
+		<input type="button" value="$i18n.getString( 'cancel' )" onclick="dhis2.commons.redirectCurrentPage( 'concept.action' )" style="width:10em"/></td>
+	</tr>
+</table>
+
+</form>

=== added file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/updateCategoryOptionGroupForm.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/updateCategoryOptionGroupForm.vm	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/updateCategoryOptionGroupForm.vm	2014-02-13 09:51:36 +0000
@@ -0,0 +1,110 @@
+<script type="text/javascript">
+	jQuery(function() {
+        validation( 'updateCategoryOptionGroupForm', function( form )
+        {
+            form.submit();
+        },function(){
+			selectAllById('groupMembers');
+			if(jQuery("#groupMembers option").length > 0 ){
+				setFieldValue('hasOptions', 'true');
+			}
+		});
+
+        checkValueIsExist( "name", "validateCategoryOptionGroup.action", {
+            id : getFieldValue( 'id' )
+        } );
+		
+		checkValueIsExist( "shortName", "validateCategoryOptionGroup.action", {
+            id : getFieldValue( 'id' )
+        } );
+		
+		checkValueIsExist( "code", "validateCategoryOptionGroup.action", {
+            id : getFieldValue( 'id' )
+        } );
+
+		jQuery("#availableCategoryOptionsList").dhisAjaxSelect({
+			source: "../dhis-web-commons-ajax-json/getDataElementCategoryOptions.action",
+			iterator: "dataElementCategoryOptions",
+			connectedTo: 'groupMembers',
+			handler: function(item) {
+				var option = jQuery("<option data-id='" + item.groups + "' />");
+				option.text( item.name );
+				option.attr( "value", item.id );
+
+				return option;
+			}
+		});
+	});
+</script>
+
+<h3>$i18n.getString( "edit_category_option_group" )</h3>
+
+<form id="updateCategoryOptionGroupForm" action="updateCategoryOptionGroup.action" method="post" class="inputForm">
+
+<div>
+	<input type="hidden" id="id" name="id" value="$categoryOptionGroup.id"/>
+</div>
+
+<table>
+	<tr>
+		<th colspan="2">$i18n.getString( "details" )</th>
+	</tr>
+
+	<tr>
+		<td style="width: 120px;"><label for="name">$i18n.getString( "name" ) <em title="$i18n.getString( 'required' )" class="required">*</em></label></td>
+		<td><input type="text" id="name" name="name" class="{validate:{required:true}}" value="$encoder.htmlEncode( $!categoryOptionGroup.name )">
+		</td>
+	</tr>
+	<tr>
+		<td><label for="shortName">$i18n.getString( "short_name" ) <em title="$i18n.getString( 'required' )" class="required">*</em></label></td>
+		<td><input type="text" id="shortName" name="shortName" value="$!encoder.htmlEncode( $categoryOptionGroup.shortName )"></td>
+	</tr>
+	<tr>
+		<td><label for="code">$i18n.getString( "code" )</label></td>
+		<td><input type="text" id="code" name="code" class="{validate:{required:true}}" value="$!encoder.htmlEncode( $categoryOptionGroup.code )"></td>
+	</tr>
+</table>
+
+<table>
+    <colgroup>
+      <col style="width: 500px;"/>
+      <col/>
+      <col style="width: 500px;"/>
+    </colgroup>
+
+	<tr>
+		<th>$i18n.getString( "available_category_options" )</th>
+		<th></th>
+		<th>$i18n.getString( "group_members" )
+			<input type='hidden' id='hasOptions' name='hasOptions' class="{validate:{required:true}}">
+		</th>
+	</tr>
+
+	<tr>
+		<td>
+			<select id="availableCategoryOptionsList" name="availableCategoryOptionsList" multiple="multiple" style="height: 200px; width: 100%;"></select>
+		</td>
+
+        <td style="text-align:center">          
+        	<input type="button" value="&gt;" title="$i18n.getString( 'move_selected' )" style="width:50px" onclick="dhisAjaxSelect_moveAllSelected( 'availableCategoryOptionsList' );"/><br/>
+            <input type="button" value="&lt;" title="$i18n.getString( 'remove_selected' )" style="width:50px" onclick="dhisAjaxSelect_moveAllSelected( 'groupMembers' );"/><br/>
+			<input type="button" value="&gt;&gt;" title="$i18n.getString('move_all')" style="width:50px" onclick="dhisAjaxSelect_moveAll( 'availableCategoryOptionsList' );"/><br/>
+			<input type="button" value="&lt;&lt;" title="$i18n.getString('remove_all')" style="width:50px" onclick="dhisAjaxSelect_moveAll( 'groupMembers' );"/>
+        </td>
+
+		<td>
+			<select id="groupMembers" name="groupMembers" multiple="multiple" style="height: 200px; width: 100%; margin-top: 22px;">
+				#foreach( $categoryOption in $groupMembers )
+					<option value="$categoryOption.id">$encoder.htmlEncode( $categoryOption.displayName )</option>
+				#end
+			</select>
+		</td>
+	</tr>
+</table>
+
+<p>
+	<input type="submit" value="$i18n.getString( 'save' )" style="width:10em"/>
+	<input type="button" value="$i18n.getString( 'cancel' )" onclick="dhis2.commons.redirectCurrentPage( 'categoryOptionGroup.action' )" style="width:10em"/>
+</p>
+
+</form>

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-program/src/main/java/org/hisp/dhis/trackedentity/action/trackedentityattribute/GetAttributeListAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-program/src/main/java/org/hisp/dhis/trackedentity/action/trackedentityattribute/GetAttributeListAction.java	2014-02-07 20:25:49 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-program/src/main/java/org/hisp/dhis/trackedentity/action/trackedentityattribute/GetAttributeListAction.java	2014-02-13 09:51:36 +0000
@@ -28,22 +28,23 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+import static org.apache.commons.lang.StringUtils.isNotBlank;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
 import org.hisp.dhis.common.comparator.IdentifiableObjectNameComparator;
+import org.hisp.dhis.paging.ActionPagingSupport;
 import org.hisp.dhis.trackedentity.TrackedEntityAttribute;
 import org.hisp.dhis.trackedentity.TrackedEntityAttributeService;
 
-import com.opensymphony.xwork2.Action;
-
 /**
  * @author Abyot Asalefew Gizaw
  * @version $Id$
  */
 public class GetAttributeListAction
-    implements Action
+    extends ActionPagingSupport<TrackedEntityAttribute>
 {
     // -------------------------------------------------------------------------
     // Dependency
@@ -67,6 +68,18 @@
         return attributes;
     }
 
+    private String key;
+
+    public String getKey()
+    {
+        return key;
+    }
+
+    public void setKey( String key )
+    {
+        this.key = key;
+    }
+
     // -------------------------------------------------------------------------
     // Action implementation
     // -------------------------------------------------------------------------
@@ -74,8 +87,22 @@
     public String execute()
         throws Exception
     {
-        attributes = new ArrayList<TrackedEntityAttribute>(attributeService.getAllTrackedEntityAttributes());
-        
+        if ( isNotBlank( key ) ) // Filter on key only if set
+        {
+            this.paging = createPaging( attributeService.getTrackedEntityAttributeCountByName( key ) );
+
+            attributes = new ArrayList<TrackedEntityAttribute>(
+                attributeService.getTrackedEntityAttributesBetweenByName( key, paging.getStartPos(),
+                    paging.getPageSize() ) );
+        }
+        else
+        {
+            this.paging = createPaging( attributeService.getTrackedEntityAttributeCount() );
+
+            attributes = new ArrayList<TrackedEntityAttribute>( attributeService.getTrackedEntityAttributesBetween(
+                paging.getStartPos(), paging.getPageSize() ) );
+        }
+
         Collections.sort( attributes, IdentifiableObjectNameComparator.INSTANCE );
 
         return SUCCESS;

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-program/src/main/resources/org/hisp/dhis/trackedentity/i18n_module.properties'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-program/src/main/resources/org/hisp/dhis/trackedentity/i18n_module.properties	2014-02-10 05:42:16 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-program/src/main/resources/org/hisp/dhis/trackedentity/i18n_module.properties	2014-02-13 09:51:36 +0000
@@ -448,7 +448,7 @@
 report_date_to_use  = Report Date to use
 the_properties_to_open_data_entry_form_after_enrolment_is_active_in_the_stage = The properties to open data entry form after enrollment is active in the stage
 add_relative = Add relative
-who_is_the_new_relative_to_the_existing_tracked_entity = Who is the new relative to the existing tracked entity instance?
+who_is_the_new_relative_to_the_existing_tracked_entity_instance = Who is the new relative to the existing tracked entity instance?
 program_for_new_relative_to_be_enrolled_in = Program for new relative to be enrolled in
 health_worker = Health worker
 is_hidden = Is hidden ?