← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 5751: Work in progress on new solution for database i18n. The old one is not reliable as it is manipula...

 

Merge authors:
  Lars Helge Øverland (larshelge)
------------------------------------------------------------
revno: 5751 [merge]
committer: Lars Helge Overland <larshelge@xxxxxxxxx>
branch nick: dhis2
timestamp: Thu 2012-01-19 12:46:10 +0100
message:
  Work in progress on new solution for database i18n. The old one is not reliable as it is manipulating the persisted properties. Introduced new properties displayName, displayShortName and displayDescription on Identifiable/NameableObject.
removed:
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/i18n/I18nObject.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/i18n/interceptor/I18nObjectInterceptor.java
  dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/i18n/I18nServiceTranslationTest.java
  dhis-2/dhis-services/dhis-service-i18n/src/main/java/org/hisp/dhis/i18n/I18nUpgrader.java
added:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/IdentifiableObjectManager.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/common/DefaultIdentifiableObjectManager.java
  dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/common/
  dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/common/IdentifiableObjectManagerTest.java
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseIdentifiableObject.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseNameableObject.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/GenericStore.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/IdentifiableObject.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/NameableObject.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataelement/DefaultDataElementService.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataset/DefaultDataSetService.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataset/DefaultSectionService.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/i18n/DefaultI18nService.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/i18n/I18nService.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/indicator/DefaultIndicatorService.java
  dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/i18n/I18nServiceTest.java
  dhis-2/dhis-services/dhis-service-i18n/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-support/dhis-support-hibernate/src/main/java/org/hisp/dhis/hibernate/HibernateGenericStore.java
  dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/ReflectionUtils.java
  dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/i18n/i18n.js
  dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/i18n/translate.vm
  dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/i18n/action/I18nAction.java
  dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/i18n/action/TranslateAction.java
  dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/i18n/action/ValidateAddDuplicatedTranslationAction.java
  dhis-2/dhis-web/dhis-web-commons/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-web/dhis-web-commons/src/main/resources/i18n_global.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/common/BaseIdentifiableObject.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseIdentifiableObject.java	2011-12-26 10:07:59 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseIdentifiableObject.java	2012-01-19 04:42:07 +0000
@@ -76,6 +76,11 @@
      * The date this object was last updated.
      */
     protected Date lastUpdated;
+    
+    /**
+     * The i18n variant of the name. Should not be persisted.
+     */
+    protected transient String displayName;
 
     // -------------------------------------------------------------------------
     // Constructors
@@ -165,6 +170,16 @@
         this.lastUpdated = lastUpdated;
     }
 
+    public String getDisplayName()
+    {
+        return displayName != null && !displayName.trim().isEmpty() ? displayName : name;
+    }
+
+    public void setDisplayName( String displayName )
+    {
+        this.displayName = displayName;
+    }
+
     // -------------------------------------------------------------------------
     // Logic
     // -------------------------------------------------------------------------

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseNameableObject.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseNameableObject.java	2011-12-26 10:07:59 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseNameableObject.java	2012-01-19 04:42:07 +0000
@@ -62,6 +62,20 @@
      * Description of this Object.
      */
     protected String description;
+    
+    /**
+     * The i18n variant of the short name. Should not be persisted.
+     */
+    protected transient String displayShortName;
+    
+    /**
+     * The i18n variant of the description. Should not be persisted.
+     */
+    protected transient String displayDescription;
+
+    // -------------------------------------------------------------------------
+    // Constructors
+    // -------------------------------------------------------------------------
 
     public BaseNameableObject()
     {
@@ -112,4 +126,24 @@
     {
         this.description = description;
     }
+
+    public String getDisplayShortName()
+    {
+        return displayShortName != null && !displayShortName.trim().isEmpty() ? displayShortName : shortName;
+    }
+
+    public void setDisplayShortName( String displayShortName )
+    {
+        this.displayShortName = displayShortName;
+    }
+
+    public String getDisplayDescription()
+    {
+        return displayDescription != null && !displayDescription.trim().isEmpty() ? displayDescription : description;
+    }
+
+    public void setDisplayDescription( String displayDescription )
+    {
+        this.displayDescription = displayDescription;
+    }
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/GenericStore.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/GenericStore.java	2011-12-26 10:07:59 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/GenericStore.java	2012-01-19 11:43:06 +0000
@@ -36,6 +36,11 @@
 public interface GenericStore<T>
 {
     /**
+     * Class of the object for this store.
+     */
+    Class<T> getClazz();
+    
+    /**
      * Saves the given object instance.
      * 
      * @param object the object instance.

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/IdentifiableObject.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/IdentifiableObject.java	2012-01-19 03:59:07 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/IdentifiableObject.java	2012-01-19 04:42:07 +0000
@@ -32,6 +32,8 @@
 public interface IdentifiableObject
     extends ImportableObject, LinkableObject, Comparable<IdentifiableObject>
 {
+    final String[] I18N_PROPERTIES = { "name" };
+    
     int getId();
 
     String getUid();
@@ -41,4 +43,6 @@
     String getCode();
 
     Date getLastUpdated();
+
+    String getDisplayName();
 }

=== added file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/IdentifiableObjectManager.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/IdentifiableObjectManager.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/IdentifiableObjectManager.java	2012-01-19 11:46:10 +0000
@@ -0,0 +1,8 @@
+package org.hisp.dhis.common;
+
+public interface IdentifiableObjectManager
+{
+    IdentifiableObject getObject( String uid, String simpleClassName );
+    
+    IdentifiableObject getObject( int id, String simpleClassName );
+}

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/NameableObject.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/NameableObject.java	2012-01-19 03:59:07 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/NameableObject.java	2012-01-19 04:42:07 +0000
@@ -30,9 +30,15 @@
 public interface NameableObject 
     extends IdentifiableObject
 {
+    final String[] I18N_PROPERTIES = { "name", "shortName", "description" };
+            
     String getAlternativeName();
 
     String getShortName();
 
     String getDescription();
+    
+    String getDisplayShortName();
+    
+    String getDisplayDescription();
 }
\ No newline at end of file

=== added file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/common/DefaultIdentifiableObjectManager.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/common/DefaultIdentifiableObjectManager.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/common/DefaultIdentifiableObjectManager.java	2012-01-19 11:46:10 +0000
@@ -0,0 +1,46 @@
+package org.hisp.dhis.common;
+
+import java.util.Set;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+public class DefaultIdentifiableObjectManager
+    implements IdentifiableObjectManager
+{
+    private Set<GenericIdentifiableObjectStore<IdentifiableObject>> objectStores;
+
+    @Autowired
+    public void setObjectStores( Set<GenericIdentifiableObjectStore<IdentifiableObject>> objectStores )
+    {
+        this.objectStores = objectStores;
+    }
+
+    @Transactional
+    public IdentifiableObject getObject( String uid, String simpleClassName )
+    {
+        for ( GenericIdentifiableObjectStore<IdentifiableObject> objectStore : objectStores )
+        {
+            if ( simpleClassName.equals( objectStore.getClass().getSimpleName() ) )
+            {
+                return objectStore.getByUid( uid );
+            }
+        }
+        
+        return null;
+    }
+    
+    @Transactional
+    public IdentifiableObject getObject( int id, String simpleClassName )
+    {
+        for ( GenericIdentifiableObjectStore<IdentifiableObject> objectStore : objectStores )
+        {
+            if ( simpleClassName.equals( objectStore.getClazz().getSimpleName() ) )
+            {
+                return objectStore.get( id );
+            }
+        }
+        
+        return null;
+    }
+}

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataelement/DefaultDataElementService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataelement/DefaultDataElementService.java	2011-12-26 10:07:59 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataelement/DefaultDataElementService.java	2012-01-19 11:43:06 +0000
@@ -98,16 +98,12 @@
     {
         int id = dataElementStore.save( dataElement );
 
-        i18nService.addObject( dataElement );
-
         return id;
     }
 
     public void updateDataElement( DataElement dataElement )
     {
         dataElementStore.update( dataElement );
-
-        i18nService.verify( dataElement );
     }
 
     public void deleteDataElement( DataElement dataElement )
@@ -355,16 +351,12 @@
     {
         int id = dataElementGroupStore.save( dataElementGroup );
 
-        i18nService.addObject( dataElementGroup );
-
         return id;
     }
 
     public void updateDataElementGroup( DataElementGroup dataElementGroup )
     {
         dataElementGroupStore.update( dataElementGroup );
-
-        i18nService.verify( dataElementGroup );
     }
 
     public void deleteDataElementGroup( DataElementGroup dataElementGroup )
@@ -455,18 +447,12 @@
 
     public int addDataElementGroupSet( DataElementGroupSet groupSet )
     {
-        int id = dataElementGroupSetStore.save( groupSet );
-
-        i18nService.addObject( groupSet );
-
-        return id;
+        return dataElementGroupSetStore.save( groupSet );
     }
 
     public void updateDataElementGroupSet( DataElementGroupSet groupSet )
     {
         dataElementGroupSetStore.update( groupSet );
-
-        i18nService.verify( groupSet );
     }
 
     public void deleteDataElementGroupSet( DataElementGroupSet groupSet )

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataset/DefaultDataSetService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataset/DefaultDataSetService.java	2011-12-26 10:07:59 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataset/DefaultDataSetService.java	2012-01-19 11:43:06 +0000
@@ -90,14 +90,10 @@
 
     public int addDataSet( DataSet dataSet )
     {
-        int id = dataSetStore.save( dataSet );
-
-        i18nService.addObject( dataSet );
-
         log.info( AuditLogUtil.logMessage( currentUserService.getCurrentUsername(),
             AuditLogUtil.ACTION_ADD, DataSet.class.getSimpleName(), dataSet.getName() ) );
 
-        return id;
+        return dataSetStore.save( dataSet );
     }
 
     public void updateDataSet( DataSet dataSet )
@@ -106,8 +102,6 @@
 
         log.info( AuditLogUtil.logMessage( currentUserService.getCurrentUsername(),
             AuditLogUtil.ACTION_EDIT, DataSet.class.getSimpleName(), dataSet.getName() ) );
-
-        i18nService.verify( dataSet );
     }
 
     public void deleteDataSet( DataSet dataSet )

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataset/DefaultSectionService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataset/DefaultSectionService.java	2011-12-26 10:07:59 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataset/DefaultSectionService.java	2012-01-19 11:43:06 +0000
@@ -71,8 +71,6 @@
     {
         int id = sectionStore.save( section );
 
-        i18nService.addObject( section );
-
         return id;
     }
 
@@ -101,7 +99,5 @@
     public void updateSection( Section section )
     {
         sectionStore.update( section );
-
-        i18nService.verify( section );
     }
 }

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/i18n/DefaultI18nService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/i18n/DefaultI18nService.java	2012-01-04 10:03:24 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/i18n/DefaultI18nService.java	2012-01-19 11:43:06 +0000
@@ -27,13 +27,16 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+import static org.hisp.dhis.i18n.locale.LocaleManager.DHIS_STANDARD_LOCALE;
 import static org.hisp.dhis.system.util.ReflectionUtils.getClassName;
 import static org.hisp.dhis.system.util.ReflectionUtils.getId;
 import static org.hisp.dhis.system.util.ReflectionUtils.getProperty;
 import static org.hisp.dhis.system.util.ReflectionUtils.isCollection;
 import static org.hisp.dhis.system.util.ReflectionUtils.setProperty;
 
+import java.text.DateFormat;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Hashtable;
@@ -41,6 +44,8 @@
 import java.util.Locale;
 import java.util.Map;
 
+import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.NameableObject;
 import org.hisp.dhis.i18n.locale.LocaleManager;
 import org.hisp.dhis.translation.Translation;
 import org.hisp.dhis.translation.TranslationService;
@@ -70,17 +75,6 @@
     }
 
     // -------------------------------------------------------------------------
-    // Setters
-    // -------------------------------------------------------------------------
-
-    private Collection<I18nObject> objects;
-
-    public void setObjects( Collection<I18nObject> objects )
-    {
-        this.objects = objects;
-    }
-
-    // -------------------------------------------------------------------------
     // Internationalise
     // -------------------------------------------------------------------------
 
@@ -94,7 +88,7 @@
         internationalise( object, localeManager.getCurrentLocale() );
     }
 
-    public void localise( Object object, Locale locale )
+    public void localise( Object object, Locale locale ) //TODO remove/rename?
     {
         if ( isCollection( object ) )
         {
@@ -106,156 +100,91 @@
 
     private void internationalise( Object object, Locale locale )
     {
-        I18nObject i18nObject = isI18nObject( object );
-
-        if ( i18nObject != null && locale != null )
-        {
-            Collection<Translation> translations = translationService.getTranslations( getClassName( object ),
-                getId( object ), locale );
-
-            Map<String, String> translationsCurrentLocale = convertTranslations( translations );
-
-            Collection<Translation> translationsFallback = null; // Not initialized unless needed
-            Map<String, String> translationsFallbackLocale = null; // Not initialized unless needed
-
-            List<String> propertyNames = i18nObject.getPropertyNames();
-
-            for ( String property : propertyNames )
-            {
-                String value = translationsCurrentLocale.get( property );
-
+        if ( object == null || DHIS_STANDARD_LOCALE.equals( locale ) )
+        {
+            return;
+        }        
+        
+        List<String> properties = getTranslationProperties( object );
+        
+        Collection<Translation> translations = translationService.getTranslations( getClassName( object ),
+            getId( object ), locale );
+        
+        Map<String, String> translationMap = convertTranslations( translations );
+        
+        for ( String property : properties )
+        {
+            String value = translationMap.get( property );
+            
+            if ( value != null && !value.isEmpty() )
+            {
+                setProperty( object, "display", property, value );
+            }
+        }
+    }
+
+    private void internationaliseCollection( Collection<?> objects )
+    {
+        internationaliseCollection( objects, localeManager.getCurrentLocale() );
+    }
+
+    private void internationaliseCollection( Collection<?> objects, Locale locale )
+    {
+        if ( objects == null || objects.size() == 0 || DHIS_STANDARD_LOCALE.equals( locale ) )
+        {
+            return;
+        }        
+        
+        Object peek = objects.iterator().next();
+
+        List<String> properties = getTranslationProperties( peek );
+        
+        Collection<Translation> translations = translationService.getTranslations( getClassName( peek ), locale );
+
+        for ( Object object : objects )
+        {
+            Map<String, String> translationMap = getTranslationsForObject( translations, getId( object ) );
+            
+            for ( String property : properties )
+            {
+                String value = translationMap.get( property );
+                
                 if ( value != null && !value.isEmpty() )
                 {
-                    setProperty( object, property, value );
-                }
-                else
-                {
-                    if ( translationsFallback == null )
-                    {
-                        translationsFallback = translationService.getTranslations( getClassName( object ),
-                            getId( object ), localeManager.getFallbackLocale() );
-
-                        translationsFallbackLocale = convertTranslations( translationsFallback );
-                    }
-
-                    value = translationsFallbackLocale.get( property );
-
-                    if ( value != null && !value.isEmpty() )
-                    {
-                        setProperty( object, property, value );
-                    }
-                }
-            }
-        }
-    }
-
-    private void internationaliseCollection( Collection<?> intObjects )
-    {
-        internationaliseCollection( intObjects, localeManager.getCurrentLocale() );
-    }
-
-    private void internationaliseCollection( Collection<?> intObjects, Locale locale )
-    {
-        if ( intObjects == null || intObjects.size() == 0 )
-        {
-            return;
-        }
-
-        I18nObject i18nObject = isI18nObject( intObjects.iterator().next() );
-
-        if ( i18nObject != null && locale != null )
-        {
-            Collection<Translation> allTranslations = translationService.getTranslations( i18nObject.getClassName(), locale );
-
-            Collection<Translation> fallbackTranslations = null; // Not initialized unless needed
-            Map<String, String> fallbackTranslationsMap = null; // Not initialized unless needed
-
-            for ( Object object : intObjects )
-            {
-                Map<String, String> translations = getTranslationsForObject( allTranslations, getId( object ) );
-                for ( Map.Entry<String, String> translation : translations.entrySet() )
-                {
-                    String property = translation.getKey();
-                    String value = translation.getValue();
-
-                    if ( value != null && !value.isEmpty() )
-                    {
-                        setProperty( object, property, value );
-                    }
-                    else
-                    {
-                        if ( fallbackTranslations == null )
-                        {
-                            fallbackTranslations = translationService.getTranslations( i18nObject.getClassName(),
-                                locale );
-
-                            fallbackTranslationsMap = getTranslationsForObject( fallbackTranslations, getId( object ) );
-                        }
-
-                        value = fallbackTranslationsMap.get( property );
-
-                        if ( value != null && !value.isEmpty() )
-                        {
-                            setProperty( object, property, value );
-                        }
-                    }
-                }
-            }
-        }
-    }
-
+                    setProperty( object, "display", property, value );
+                }
+            }
+        }
+    }
+    
+    public Map<String, String> getObjectTranslations( Object object )
+    {
+        List<String> properties = getTranslationProperties( object );
+        
+        Map<String, String> translations = new HashMap<String, String>();
+        
+        for ( String property : properties )
+        {
+            translations.put( property, getProperty( object, property ) );
+        }
+        
+        return translations;
+    }
+
+    public List<String> getTranslationProperties( Object object )
+    {
+        if ( object == null || !( object instanceof IdentifiableObject ) )
+        {
+            throw new IllegalArgumentException( "I18n objects must be not null and identifiable" );
+        }
+        
+        return ( object instanceof NameableObject ) ? Arrays.asList( NameableObject.I18N_PROPERTIES ) : Arrays.asList( IdentifiableObject.I18N_PROPERTIES );        
+    }
+    
     // -------------------------------------------------------------------------
     // Object
     // -------------------------------------------------------------------------
 
-    public void addObject( Object object )
-    {
-        I18nObject i18nObject = isI18nObject( object );
-
-        Locale locale = localeManager.getCurrentLocale();
-
-        if ( i18nObject != null && locale != null )
-        {
-            String className = getClassName( object );
-            int id = getId( object );
-
-            Map<String, String> translations = new Hashtable<String, String>();
-
-            for ( String property : i18nObject.getPropertyNames() )
-            {
-                String value = getProperty( object, property );
-
-                if ( value != null && !value.isEmpty() )
-                {
-                    translations.put( property, value );
-                }
-                else
-                {
-                	translations.put( property, "" );
-                }
-            }
-
-            updateTranslation( className, id, locale, translations );
-        }
-    }
-
-    public void verify( Object object )
-    {
-        if ( isI18nObject( object ) != null )
-        {
-            addObject( object );
-
-            // -----------------------------------------------------------------
-            // Set properties from fallback locale
-            // -----------------------------------------------------------------
-
-            if ( !localeManager.getCurrentLocale().equals( localeManager.getFallbackLocale() ) )
-            {
-                internationalise( object, localeManager.getFallbackLocale() );
-            }
-        }
-    }
-
     public void removeObject( Object object )
     {
         if ( object != null )
@@ -264,14 +193,6 @@
         }
     }
 
-    public void setToFallback( Object object )
-    {
-        if ( isI18nObject( object ) != null )
-        {
-            internationalise( object, localeManager.getFallbackLocale() );
-        }
-    }
-
     // -------------------------------------------------------------------------
     // Translation
     // -------------------------------------------------------------------------
@@ -309,123 +230,10 @@
     {
         return convertTranslations( translationService.getTranslations( className, id, locale ) );
     }
-
-    // -------------------------------------------------------------------------
-    // Property
-    // -------------------------------------------------------------------------
-
-    public List<String> getPropertyNames( String className )
-    {
-        for ( I18nObject i18nObject : objects )
-        {
-            if ( i18nObject.getClassName().equals( className ) )
-            {
-                return i18nObject.getPropertyNames();
-            }
-        }
-
-        return null;
-    }
-
-    public Map<String, String> getPropertyNamesLabel( String className )
-    {
-        for ( I18nObject i18nObject : objects )
-        {
-            if ( i18nObject.getClassName().equals( className ) )
-            {
-                Map<String, String> propertyNamesLabel = new Hashtable<String, String>();
-
-                for ( String property : i18nObject.getPropertyNames() )
-                {
-                    propertyNamesLabel.put( property, convertPropertyToKey( property ) );
-                }
-
-                return propertyNamesLabel;
-            }
-        }
-
-        return null;
-    }
-
-    public Map<String, Map<String, String>> getRulePropertyNames( String className )
-    {
-        for ( I18nObject i18nObject : objects )
-        {
-            if ( i18nObject.getClassName().equals( className ) )
-            {
-                return i18nObject.getRulePropertyNames();
-            }
-        }
-
-        return null;
-    }
-
-    public List<String> getUniquePropertyNames( String className )
-    {
-        for ( I18nObject i18nObject : objects )
-        {
-            if ( i18nObject.getClassName().equals( className ) )
-            {
-                List<String> uniqueProperyNames = new ArrayList<String>();
-                Map<String, Map<String, String>> rules = i18nObject.getRulePropertyNames();
-
-                for ( String property : getPropertyNames( className ) )
-                {
-                    if ( rules.get( property ).get( "unique" ).equals( "true" ) )
-                    {
-                        uniqueProperyNames.add( property );
-                    }
-                }
-
-                return uniqueProperyNames;
-            }
-        }
-
-        return null;
-    }
-
-    public Map<String, String> getUniquePropertyNamesLabel( String className )
-    {
-        for ( I18nObject i18Object : objects )
-        {
-            if ( i18Object.getClassName().equals( className ) )
-            {
-                Map<String, String> uniquePropertyNamesLabel = new HashMap<String, String>();
-
-                for ( String uniqueProperty : getUniquePropertyNames( className ) )
-                {
-                    uniquePropertyNamesLabel.put( uniqueProperty, convertPropertyToKey( uniqueProperty ) );
-                }
-
-                return uniquePropertyNamesLabel;
-            }
-        }
-
-        return null;
-    }
-
-    // -------------------------------------------------------------------------
-    // Locale
-    // -------------------------------------------------------------------------
-
-    public Collection<Locale> getAvailableLocales()
-    {
-        List<Locale> locales = localeManager.getLocalesOrderedByPriority();
-
-        Collection<Locale> translationLocales = translationService.getAvailableLocales();
-
-        if ( translationLocales != null )
-        {
-            for ( Locale locale : translationLocales )
-            {
-                if ( !locales.contains( locale ) )
-                {
-                    locales.add( locale );
-                }
-            }
-        }
-
-        return locales;
+    
+    public List<Locale> getAvailableLocales()
+    {
+        return Arrays.asList( DateFormat.getAvailableLocales() );
     }
 
     // -------------------------------------------------------------------------
@@ -477,55 +285,4 @@
 
         return translationMap;
     }
-
-    /**
-     * Converts the property to a i18n keystring alternativeName produces
-     * alternative_name.
-     * 
-     * @param propName string to parse.
-     * @return the modified string.
-     */
-    private String convertPropertyToKey( String propName )
-    {
-        StringBuffer str = new StringBuffer();
-
-        char[] chars = propName.toCharArray();
-
-        for ( int i = 0; i < chars.length; i++ )
-        {
-            if ( Character.isUpperCase( chars[i] ) )
-            {
-                str.append( "_" ).append( Character.toLowerCase( chars[i] ) );
-            }
-            else
-            {
-                str.append( chars[i] );
-            }
-        }
-
-        return str.toString();
-    }
-
-    /**
-     * Test if an object is not null and enabled for i18n. Returns the
-     * I18nObject if so. Returns null if not so.
-     * 
-     * @param object the object to test.
-     * @return the I18nObject or null.
-     */
-    private I18nObject isI18nObject( Object object )
-    {
-        if ( object != null )
-        {
-            for ( I18nObject i18nObject : objects )
-            {
-                if ( i18nObject.match( object ) )
-                {
-                    return i18nObject;
-                }
-            }
-        }
-
-        return null;
-    }
 }

=== removed file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/i18n/I18nObject.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/i18n/I18nObject.java	2011-12-26 10:07:59 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/i18n/I18nObject.java	1970-01-01 00:00:00 +0000
@@ -1,96 +0,0 @@
-package org.hisp.dhis.i18n;
-
-/*
- * Copyright (c) 2004-2012, 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.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author Oyvind Brucker
- * @modifier Dang Duy Hieu
- * @since 2010-04-15
- */
-public class I18nObject
-{
-    private String className;
-
-    private List<String> propertyNames = new ArrayList<String>();
-
-    private Map<String, Map<String, String>> rulePropertyNames = new HashMap<String, Map<String, String>>();
-
-    public String getClassName()
-    {
-        return className;
-    }
-
-    public void setClassName( String className )
-    {
-        this.className = className;
-    }
-
-    // -------------------------------------------------------------------------
-    // PropertyNames
-    // -------------------------------------------------------------------------
-
-    public List<String> getPropertyNames()
-    {
-        return propertyNames;
-    }
-
-    public void setPropertyNames( List<String> propertyNames )
-    {
-        this.propertyNames = propertyNames;
-    }
-
-    // -------------------------------------------------------------------------
-    // RulePropertyNames
-    // -------------------------------------------------------------------------
-
-    public Map<String, Map<String, String>> getRulePropertyNames()
-    {
-        return rulePropertyNames;
-    }
-
-    public void setRulePropertyNames( Map<String, Map<String, String>> rulePropertyNames )
-    {
-        this.rulePropertyNames = rulePropertyNames;
-    }
-
-    public boolean match( Object object )
-    {
-        if ( object == null )
-        {
-            return false;
-        }
-
-        return className.equalsIgnoreCase( object.getClass().getSimpleName() );
-    }
-
-}

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/i18n/I18nService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/i18n/I18nService.java	2011-12-26 10:07:59 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/i18n/I18nService.java	2012-01-19 11:43:06 +0000
@@ -30,7 +30,6 @@
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
-import java.util.Collection;
 
 /**
  * @author Oyvind Brucker
@@ -49,18 +48,16 @@
     
     public void localise( Object object, Locale locale );
     
+    Map<String, String> getObjectTranslations( Object object );
+    
+    List<String> getTranslationProperties( Object object );
+    
     // -------------------------------------------------------------------------
     // Object
     // -------------------------------------------------------------------------
 
-    public void addObject( Object object );
-
-    public void verify( Object object );
-
     public void removeObject( Object object );
 
-    public void setToFallback( Object object );
-
     // -------------------------------------------------------------------------
     // Translation
     // -------------------------------------------------------------------------
@@ -68,24 +65,6 @@
     public void updateTranslation( String className, int id, Locale thisLocale, Map<String, String> translations );
 
     public Map<String, String> getTranslations( String className, int id, Locale locale );
-
-    // -------------------------------------------------------------------------
-    // Property
-    // -------------------------------------------------------------------------
-
-    public List<String> getPropertyNames( String className );
-
-    public List<String> getUniquePropertyNames( String className );
-
-    public Map<String, String> getPropertyNamesLabel( String className );
-
-    public Map<String, String> getUniquePropertyNamesLabel( String className );
     
-    public Map<String, Map<String, String>> getRulePropertyNames( String className );
-
-    // -------------------------------------------------------------------------
-    // Locale
-    // -------------------------------------------------------------------------
-
-    public Collection<Locale> getAvailableLocales();
+    List<Locale> getAvailableLocales();
 }

=== removed file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/i18n/interceptor/I18nObjectInterceptor.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/i18n/interceptor/I18nObjectInterceptor.java	2011-12-26 10:07:59 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/i18n/interceptor/I18nObjectInterceptor.java	1970-01-01 00:00:00 +0000
@@ -1,118 +0,0 @@
-package org.hisp.dhis.i18n.interceptor;
-
-/*
- * Copyright (c) 2004-2012, 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.lang.reflect.Method;
-import org.hisp.dhis.i18n.I18nService;
-import org.aspectj.lang.ProceedingJoinPoint;
-
-/**
- * @author Torgeir Lorange Ostby
- * @author Lars Helge Overland
- * @version $Id: I18nObjectInterceptor.java 5992 2008-10-19 11:52:20Z larshelg $
- */
-public class I18nObjectInterceptor
-{
-    private static final String ADD = "add";
-
-    private static final String UPDATE = "update";
-
-    private static final String SAVE = "save";
-
-    private static final String DELETE = "delete";
-
-    private static final String GET_ID_METHOD = "getId";
-
-    // -------------------------------------------------------------------------
-    // Dependencies
-    // -------------------------------------------------------------------------
-
-    private I18nService i18nService;
-
-    public void setI18nService( I18nService service )
-    {
-        i18nService = service;
-    }
-
-    // -------------------------------------------------------------------------
-    // MethodInterceptor implementation
-    // -------------------------------------------------------------------------
-
-    public void intercept( ProceedingJoinPoint joinPoint )
-        throws Throwable
-    {
-        String methodName = joinPoint.getSignature().toShortString();
-
-        if ( joinPoint.getArgs() != null && joinPoint.getArgs().length > 0 )
-        {
-            Object object = joinPoint.getArgs()[0];
-        
-            if ( methodName.startsWith( ADD ) )
-            {
-                joinPoint.proceed();
-
-                i18nService.addObject( object );
-            }
-            else if ( methodName.startsWith( UPDATE ) )
-            {
-                i18nService.verify( object );
-
-                joinPoint.proceed();
-            }
-            else if ( methodName.startsWith( DELETE ) )
-            {
-                joinPoint.proceed();
-
-                i18nService.removeObject( object );
-            }
-            else if ( methodName.startsWith( SAVE ) )
-            {
-                Method getIdMethod = object.getClass().getMethod( GET_ID_METHOD, new Class[0] );
-
-                int id = (Integer) getIdMethod.invoke( object, new Object[0] );
-
-                if ( id == 0 )
-                {
-                    joinPoint.proceed();
-
-                    i18nService.addObject( object );
-                }
-                else
-                {
-                    i18nService.verify( object );
-
-                    joinPoint.proceed();
-                }
-            }
-        }
-        else
-        {
-            joinPoint.proceed();
-        }
-    }
-}

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/indicator/DefaultIndicatorService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/indicator/DefaultIndicatorService.java	2011-12-26 10:07:59 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/indicator/DefaultIndicatorService.java	2012-01-19 11:43:06 +0000
@@ -92,18 +92,12 @@
 
     public int addIndicator( Indicator indicator )
     {
-        int id = indicatorStore.save( indicator );
-
-        i18nService.addObject( indicator );
-
-        return id;
+        return indicatorStore.save( indicator );
     }
 
     public void updateIndicator( Indicator indicator )
     {
         indicatorStore.update( indicator );
-
-        i18nService.verify( indicator );
     }
 
     public void deleteIndicator( Indicator indicator )
@@ -207,18 +201,12 @@
 
     public int addIndicatorType( IndicatorType indicatorType )
     {
-        int id = indicatorTypeStore.save( indicatorType );
-
-        i18nService.addObject( indicatorType );
-
-        return id;
+        return indicatorTypeStore.save( indicatorType );
     }
 
     public void updateIndicatorType( IndicatorType indicatorType )
     {
         indicatorTypeStore.update( indicatorType );
-
-        i18nService.verify( indicatorType );
     }
 
     public void deleteIndicatorType( IndicatorType indicatorType )
@@ -287,18 +275,12 @@
 
     public int addIndicatorGroup( IndicatorGroup indicatorGroup )
     {
-        int id = indicatorGroupStore.save( indicatorGroup );
-
-        i18nService.addObject( indicatorGroup );
-
-        return id;
+        return indicatorGroupStore.save( indicatorGroup );
     }
 
     public void updateIndicatorGroup( IndicatorGroup indicatorGroup )
     {
         indicatorGroupStore.update( indicatorGroup );
-
-        i18nService.verify( indicatorGroup );
     }
 
     public void deleteIndicatorGroup( IndicatorGroup indicatorGroup )
@@ -386,18 +368,12 @@
 
     public int addIndicatorGroupSet( IndicatorGroupSet groupSet )
     {
-        int id = indicatorGroupSetStore.save( groupSet );
-
-        i18nService.addObject( groupSet );
-
-        return id;
+        return indicatorGroupSetStore.save( groupSet );
     }
 
     public void updateIndicatorGroupSet( IndicatorGroupSet groupSet )
     {
         indicatorGroupSetStore.update( groupSet );
-
-        i18nService.verify( groupSet );
     }
 
     public void deleteIndicatorGroupSet( IndicatorGroupSet groupSet )

=== 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	2012-01-18 08:40:55 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/beans.xml	2012-01-19 11:43:06 +0000
@@ -540,6 +540,8 @@
     </property>
   </bean>
 
+  <bean id="org.hisp.dhis.common.IdentifiableObjectManager" class="org.hisp.dhis.common.DefaultIdentifiableObjectManager"/>  
+
   <!-- I18nService -->
 
   <bean id="org.hisp.dhis.i18n.I18nService" class="org.hisp.dhis.i18n.DefaultI18nService">
@@ -549,422 +551,6 @@
     <property name="translationService">
       <ref bean="org.hisp.dhis.translation.TranslationService" />
     </property>
-    <property name="objects">
-      <list>
-        <ref bean="I18nDataElement" />
-        <ref bean="I18nDataElementGroup" />
-        <ref bean="I18nDataElementGroupSet" />
-        <ref bean="I18nIndicator" />
-        <ref bean="I18nIndicatorType" />
-        <ref bean="I18nIndicatorGroup" />
-        <ref bean="I18nIndicatorGroupSet" />
-        <ref bean="I18nDataSet" />
-        <ref bean="I18nOrganisationUnit" />
-		<ref bean="I18nOrganisationUnitGroup" />
-		<ref bean="I18nOrganisationUnitGroupSet" />
-        <ref bean="I18nSection" />
-		<ref bean="I18nDataElementCategory" />
-      </list>
-    </property>
-  </bean>
-
-  <!-- I18n object definitions -->
-
-  <bean id="I18nDataElement" class="org.hisp.dhis.i18n.I18nObject">
-    <property name="className" value="DataElement" />
-    <property name="propertyNames">
-      <list>
-        <value>name</value>
-        <value>shortName</value>
-        <value>description</value>
-      </list>
-    </property>
-
-    <property name="rulePropertyNames">
-      <map>
-        <entry key="name">
-          <map>
-            <entry key="unique" value="true" />
-            <entry key="required" value="true" />
-            <entry key="minlength" value="2" />
-            <entry key="maxlength" value="160" />
-            <entry key="regex" value="''" />
-            <entry key="message" value="" />
-          </map>
-        </entry>
-        <entry key="shortName">
-          <map>
-            <entry key="unique" value="true" />
-            <entry key="required" value="false" />
-            <entry key="minlength" value="0" />
-            <entry key="maxlength" value="25" />
-            <entry key="regex">
-              <value><![CDATA[/^[^\d][^\^\-(&lt;&gt;&apos;&quot;){=+}\[!@#$%*\]\\/`:~|;,\.\?]*$/]]></value>
-            </entry>
-            <entry key="message" value="translation_shortname_wellformed" />
-          </map>
-        </entry>
-        <entry key="description">
-          <map>
-            <entry key="unique" value="false" />
-            <entry key="required" value="false" />
-            <entry key="minlength" value="0" />
-            <entry key="maxlength" value="200" />
-            <entry key="regex" value="''" />
-            <entry key="message" value="" />
-          </map>
-        </entry>
-      </map>
-    </property>
-  </bean>
-
-  <bean id="I18nDataElementGroup" class="org.hisp.dhis.i18n.I18nObject">
-    <property name="className" value="DataElementGroup" />
-    <property name="propertyNames">
-      <list>
-        <value>name</value>
-      </list>
-    </property>
-
-    <property name="rulePropertyNames">
-      <map>
-        <entry key="name">
-          <map>
-            <entry key="unique" value="true" />
-            <entry key="required" value="true" />
-            <entry key="minlength" value="2" />
-            <entry key="maxlength" value="160" />
-            <entry key="regex" value="''" />
-            <entry key="message" value="" />
-          </map>
-        </entry>
-      </map>
-    </property>
-
-  </bean>
-
-  <bean id="I18nDataElementGroupSet" class="org.hisp.dhis.i18n.I18nObject">
-    <property name="className" value="DataElementGroupSet" />
-    <property name="propertyNames">
-      <list>
-        <value>name</value>
-      </list>
-    </property>
-    <property name="rulePropertyNames">
-      <map>
-        <entry key="name">
-          <map>
-            <entry key="unique" value="true" />
-            <entry key="required" value="true" />
-            <entry key="minlength" value="2" />
-            <entry key="maxlength" value="160" />
-            <entry key="regex" value="''" />
-            <entry key="message" value="" />
-          </map>
-        </entry>
-      </map>
-    </property>
-  </bean>
-
-  <bean id="I18nIndicator" class="org.hisp.dhis.i18n.I18nObject">
-    <property name="className" value="Indicator" />
-    <property name="propertyNames">
-      <list>
-        <value>name</value>
-        <value>shortName</value>
-        <value>description</value>
-      </list>
-    </property>
-
-    <property name="rulePropertyNames">
-      <map>
-        <entry key="name">
-          <map>
-            <entry key="unique" value="true" />
-            <entry key="required" value="true" />
-            <entry key="minlength" value="2" />
-            <entry key="maxlength" value="160" />
-            <entry key="regex" value="''" />
-            <entry key="message" value="" />
-          </map>
-        </entry>
-        <entry key="shortName">
-          <map>
-            <entry key="unique" value="true" />
-            <entry key="required" value="false" />
-            <entry key="minlength" value="0" />
-            <entry key="maxlength" value="25" />
-            <entry key="regex">
-              <value><![CDATA[/^[^\d][^\^\-(&lt;&gt;&apos;&quot;){=+}\[!@#$%*\]\\/`:~|;,\.\?]*$/]]></value>
-            </entry>
-            <entry key="message" value="translation_shortname_wellformed" />
-          </map>
-        </entry>
-        <entry key="description">
-          <map>
-            <entry key="unique" value="false" />
-            <entry key="required" value="false" />
-            <entry key="minlength" value="0" />
-            <entry key="maxlength" value="200" />
-            <entry key="regex" value="''" />
-            <entry key="message" value="" />
-          </map>
-        </entry>
-      </map>
-    </property>
-  </bean>
-
-  <bean id="I18nIndicatorType" class="org.hisp.dhis.i18n.I18nObject">
-    <property name="className" value="IndicatorType" />
-    <property name="propertyNames">
-      <list>
-        <value>name</value>
-      </list>
-    </property>
-
-    <property name="rulePropertyNames">
-      <map>
-        <entry key="name">
-          <map>
-            <entry key="unique" value="true" />
-            <entry key="required" value="true" />
-            <entry key="minlength" value="2" />
-            <entry key="maxlength" value="160" />
-            <entry key="regex" value="''" />
-            <entry key="message" value="" />
-          </map>
-        </entry>
-      </map>
-    </property>
-  </bean>
-
-  <bean id="I18nIndicatorGroup" class="org.hisp.dhis.i18n.I18nObject">
-    <property name="className" value="IndicatorGroup" />
-    <property name="propertyNames">
-      <list>
-        <value>name</value>
-      </list>
-    </property>
-
-    <property name="rulePropertyNames">
-      <map>
-        <entry key="name">
-          <map>
-            <entry key="unique" value="true" />
-            <entry key="required" value="true" />
-            <entry key="minlength" value="2" />
-            <entry key="maxlength" value="160" />
-            <entry key="regex" value="''" />
-            <entry key="message" value="" />
-          </map>
-        </entry>
-      </map>
-    </property>
-  </bean>
-
-  <bean id="I18nIndicatorGroupSet" class="org.hisp.dhis.i18n.I18nObject">
-    <property name="className" value="IndicatorGroupSet" />
-    <property name="propertyNames">
-      <list>
-        <value>name</value>
-      </list>
-    </property>
-
-    <property name="rulePropertyNames">
-      <map>
-        <entry key="name">
-          <map>
-            <entry key="unique" value="true" />
-            <entry key="required" value="true" />
-            <entry key="minlength" value="2" />
-            <entry key="maxlength" value="160" />
-            <entry key="regex" value="''" />
-            <entry key="message" value="" />
-          </map>
-        </entry>
-      </map>
-    </property>
-  </bean>
-
-  <bean id="I18nOrganisationUnit" class="org.hisp.dhis.i18n.I18nObject">
-    <property name="className" value="OrganisationUnit" />
-    <property name="propertyNames">
-      <list>
-        <value>name</value>
-        <value>shortName</value>
-      </list>
-    </property>
-
-    <property name="rulePropertyNames">
-      <map>
-        <entry key="name">
-          <map>
-            <entry key="unique" value="true" />
-            <entry key="required" value="true" />
-            <entry key="minlength" value="2" />
-            <entry key="maxlength" value="160" />
-            <entry key="regex" value="''" />
-            <entry key="message" value="" />
-          </map>
-        </entry>
-        <entry key="shortName">
-          <map>
-            <entry key="unique" value="false" />
-            <entry key="required" value="false" />
-            <entry key="minlength" value="0" />
-            <entry key="maxlength" value="25" />
-            <entry key="regex">
-              <value><![CDATA[/^[^\d][^\^\-(&lt;&gt;&apos;&quot;){=+}\[!@#$%*\]\\/`:~|;,\.\?]*$/]]></value>
-            </entry>
-            <entry key="message" value="translation_shortname_wellformed" />
-          </map>
-        </entry>
-      </map>
-    </property>
-  </bean>
-
-  <bean id="I18nOrganisationUnitGroup" class="org.hisp.dhis.i18n.I18nObject">
-    <property name="className" value="OrganisationUnitGroup" />
-    <property name="propertyNames">
-      <list>
-        <value>name</value>
-      </list>
-    </property>
-
-    <property name="rulePropertyNames">
-      <map>
-        <entry key="name">
-          <map>
-            <entry key="unique" value="true" />
-            <entry key="required" value="true" />
-            <entry key="minlength" value="2" />
-            <entry key="maxlength" value="160" />
-            <entry key="regex" value="''" />
-            <entry key="message" value="" />
-          </map>
-        </entry>
-      </map>
-    </property>
-  </bean>
-
-  <bean id="I18nOrganisationUnitGroupSet" class="org.hisp.dhis.i18n.I18nObject">
-    <property name="className" value="OrganisationUnitGroupSet" />
-    <property name="propertyNames">
-      <list>
-        <value>name</value>
-        <value>description</value>
-      </list>
-    </property>
-
-    <property name="rulePropertyNames">
-      <map>
-        <entry key="name">
-          <map>
-            <entry key="unique" value="true" />
-            <entry key="required" value="true" />
-            <entry key="minlength" value="2" />
-            <entry key="maxlength" value="160" />
-            <entry key="regex" value="''" />
-            <entry key="message" value="" />
-          </map>
-        </entry>
-        <entry key="description">
-          <map>
-            <entry key="unique" value="false" />
-            <entry key="required" value="false" />
-            <entry key="minlength" value="0" />
-            <entry key="maxlength" value="200" />
-            <entry key="regex" value="''" />
-            <entry key="message" value="" />
-          </map>
-        </entry>
-      </map>
-    </property>
-  </bean>
-
-  <bean id="I18nDataSet" class="org.hisp.dhis.i18n.I18nObject">
-    <property name="className" value="DataSet" />
-    <property name="propertyNames">
-      <list>
-        <value>name</value>
-        <value>shortName</value>
-      </list>
-    </property>
-
-    <property name="rulePropertyNames">
-      <map>
-        <entry key="name">
-          <map>
-            <entry key="unique" value="true" />
-            <entry key="required" value="true" />
-            <entry key="minlength" value="2" />
-            <entry key="maxlength" value="160" />
-            <entry key="regex" value="''" />
-            <entry key="message" value="" />
-          </map>
-        </entry>
-        <entry key="shortName">
-          <map>
-            <entry key="unique" value="true" />
-            <entry key="required" value="false" />
-            <entry key="minlength" value="0" />
-            <entry key="maxlength" value="25" />
-            <entry key="regex">
-              <value><![CDATA[/^[^\d][^\^\-(&lt;&gt;&apos;&quot;){=+}\[!@#$%*\]\\/`:~|;,\.\?]*$/]]></value>
-            </entry>
-            <entry key="message" value="translation_shortname_wellformed" />
-          </map>
-        </entry>
-      </map>
-    </property>
-  </bean>
-
-  <bean id="I18nSection" class="org.hisp.dhis.i18n.I18nObject">
-    <property name="className" value="Section" />
-    <property name="propertyNames">
-      <list>
-        <value>name</value>
-      </list>
-    </property>
-
-    <property name="rulePropertyNames">
-      <map>
-        <entry key="name">
-          <map>
-            <entry key="unique" value="true" />
-            <entry key="required" value="true" />
-            <entry key="minlength" value="2" />
-            <entry key="maxlength" value="160" />
-            <entry key="regex" value="''" />
-            <entry key="message" value="" />
-          </map>
-        </entry>
-      </map>
-    </property>
-  </bean>
-
-  <bean id="I18nDataElementCategory" class="org.hisp.dhis.i18n.I18nObject">
-    <property name="className" value="DataElementCategory" />
-    <property name="propertyNames">
-      <list>
-        <value>name</value>
-      </list>
-    </property>
-
-    <property name="rulePropertyNames">
-      <map>
-        <entry key="name">
-          <map>
-            <entry key="unique" value="true" />
-            <entry key="required" value="true" />
-            <entry key="minlength" value="2" />
-            <entry key="maxlength" value="160" />
-            <entry key="regex" value="''" />
-            <entry key="message" value="" />
-          </map>
-        </entry>
-      </map>
-    </property>
   </bean>
 
   <!-- Startup routine definitions -->

=== added directory 'dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/common'
=== added file 'dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/common/IdentifiableObjectManagerTest.java'
--- dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/common/IdentifiableObjectManagerTest.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/common/IdentifiableObjectManagerTest.java	2012-01-19 11:46:10 +0000
@@ -0,0 +1,42 @@
+package org.hisp.dhis.common;
+
+import org.hisp.dhis.DhisSpringTest;
+import org.hisp.dhis.dataelement.DataElement;
+import org.hisp.dhis.dataelement.DataElementGroup;
+import org.hisp.dhis.dataelement.DataElementService;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import static junit.framework.Assert.*;
+
+public class IdentifiableObjectManagerTest
+    extends DhisSpringTest
+{
+    @Autowired
+    private DataElementService dataElementService;
+    
+    @Autowired
+    private IdentifiableObjectManager identifiableObjectManager;
+    
+    @Test
+    public void testGetObject()
+    {
+        DataElement dataElementA = createDataElement( 'A' );
+        DataElement dataElementB = createDataElement( 'B' );
+        
+        int dataElementIdA = dataElementService.addDataElement( dataElementA );
+        int dataElementIdB = dataElementService.addDataElement( dataElementB );
+        
+        DataElementGroup dataElementGroupA = createDataElementGroup( 'A' );
+        DataElementGroup dataElementGroupB = createDataElementGroup( 'B' );
+        
+        int dataElementGroupIdA = dataElementService.addDataElementGroup( dataElementGroupA );
+        int dataElementGroupIdB = dataElementService.addDataElementGroup( dataElementGroupB );
+        
+        assertEquals( dataElementA, identifiableObjectManager.getObject( dataElementIdA, DataElement.class.getSimpleName() ) );
+        assertEquals( dataElementB, identifiableObjectManager.getObject( dataElementIdB, DataElement.class.getSimpleName() ) );
+        
+        assertEquals( dataElementGroupA, identifiableObjectManager.getObject( dataElementGroupIdA, DataElementGroup.class.getSimpleName() ) );
+        assertEquals( dataElementGroupB, identifiableObjectManager.getObject( dataElementGroupIdB, DataElementGroup.class.getSimpleName() ) );
+    }
+}

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/i18n/I18nServiceTest.java'
--- dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/i18n/I18nServiceTest.java	2011-12-26 10:07:59 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/i18n/I18nServiceTest.java	2012-01-19 11:43:06 +0000
@@ -27,21 +27,9 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertTrue;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
 import org.hisp.dhis.DhisSpringTest;
 import org.hisp.dhis.i18n.locale.LocaleManager;
 import org.hisp.dhis.mock.MockLocaleManager;
-import org.hisp.dhis.organisationunit.OrganisationUnit;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -65,24 +53,12 @@
     {
         i18nService = (I18nService) getBean( I18nService.ID );
         
-        localeManager = new MockLocaleManager(); //(LocaleManager) getBean( "org.hisp.dhis.i18n.locale.LocaleManagerDb" );
+        localeManager = new MockLocaleManager();
         
         setDependency( i18nService, "localeManager", localeManager );
     }
 
     // -------------------------------------------------------------------------
-    // Testdata
-    // -------------------------------------------------------------------------
-
-    private int id1 = 0;
-
-    private int id2 = 1;
-
-    private int id3 = 2;
-
-    private String className1 = "OrganisationUnit";
-
-    // -------------------------------------------------------------------------
     // Tests
     // -------------------------------------------------------------------------
     
@@ -90,228 +66,6 @@
     public void testUpdateTranslation()
         throws Exception
     {
-        String organisationUnitNameUK = "organisationUnitName1";
-
-        OrganisationUnit organisationUnit1 = new OrganisationUnit( organisationUnitNameUK, "shortName1",
-            "organisationUnitCode1", new Date(), new Date(), true, "comment" );
-
-        organisationUnit1.setId( id1 );
-
-        Map<String, String> translations1 = new Hashtable<String, String>();
-
-        translations1.put( "name", "orgunit_1" );
-        translations1.put( "shortName", "org-1" );
-        translations1.put( "comment", "Just another orgunit" );
-
-        localeManager.setCurrentLocale( Locale.UK );
-
-        i18nService.updateTranslation( className1, id1, Locale.UK, translations1 );
-
-        i18nService.internationalise( organisationUnit1 );
-        assertEquals( organisationUnit1.getName(), "orgunit_1" );
-
-        translations1.put( "name", "orgunit-1" );
-        i18nService.updateTranslation( className1, id1, Locale.UK, translations1 );
-
-        i18nService.internationalise( organisationUnit1 );
-        assertEquals( organisationUnit1.getName(), "orgunit-1" );
-
-        /**
-         * Collection
-         */
-
-        String organisationUnitNameUK2 = "organisationUnitName2";
-        String organisationUnitNameUK3 = "organisationUnitName1";
-
-        OrganisationUnit organisationUnit2 = new OrganisationUnit( organisationUnitNameUK2, "shortName2",
-            "organisationUnitCode2", new Date(), new Date(), true, "comment" );
-
-        OrganisationUnit organisationUnit3 = new OrganisationUnit( organisationUnitNameUK3, "shortName3",
-            "organisationUnitCode3", new Date(), new Date(), true, "comment" );
-        organisationUnit2.setId( id2 );
-        organisationUnit3.setId( id3 );
-
-        List<OrganisationUnit> orgunits = new ArrayList<OrganisationUnit>();
-        orgunits.add( organisationUnit1 );
-        orgunits.add( organisationUnit2 );
-        orgunits.add( organisationUnit3 );
-
-        translations1.put( "name", "orgunit-2" );
-        translations1.put( "shortName", "org-2" );
-        translations1.put( "comment", "Just another orgunit" );
-
-        i18nService.updateTranslation( className1, id2, Locale.UK, translations1 );
-        translations1.put( "name", "orgunit-3" );
-        translations1.put( "shortName", "org-3" );
-        translations1.put( "comment", "Just another orgunit" );
-        i18nService.updateTranslation( className1, id3, Locale.UK, translations1 );
-
-        i18nService.internationalise( orgunits );
-
-        for ( int i = 0; i < orgunits.size(); i++ )
-        {
-            OrganisationUnit orgunit = orgunits.get( i );
-
-            assertEquals( orgunit.getName(), "orgunit-" + (i + 1) );
-        }
-    }
-
-    @Test
-    public void testAddObject()
-        throws Exception
-    {
-        OrganisationUnit organisationUnit1 = new OrganisationUnit( "orgunit-1", "org-1", "organisationUnitCode1",
-            new Date(), new Date(), true, "comment" );
-        organisationUnit1.setId( id1 );
-
-        Locale fallbackLocale = localeManager.getFallbackLocale();
-
-        Locale locale = Locale.FRANCE;
-
-        if ( locale.equals( fallbackLocale ) )
-        {
-            locale = Locale.GERMANY;
-        }
-
-        Map<String, String> translationsFr = new Hashtable<String, String>();
-
-        translationsFr.put( "name", "orgunit_1" );
-        translationsFr.put( "shortName", "org_1" );
-        translationsFr.put( "comment", "Just another orgunit" );
-
-        localeManager.setCurrentLocale( localeManager.getFallbackLocale() );
-
-        i18nService.addObject( organisationUnit1 );
-        i18nService.updateTranslation( className1, id1, locale, translationsFr );
-
-        localeManager.setCurrentLocale( locale );
-
-        i18nService.internationalise( organisationUnit1 );
-
-        assertEquals( "orgunit_1", organisationUnit1.getName() );
-        assertEquals( "org_1", organisationUnit1.getShortName() );
-
-        localeManager.setCurrentLocale( fallbackLocale );
-
-        i18nService.internationalise( organisationUnit1 );
-
-        assertEquals( "orgunit-1", organisationUnit1.getName() );
-        assertEquals( "org-1", organisationUnit1.getShortName() );
-    }
-
-    @Test
-    public void testVerify()
-        throws Exception
-    {
-        OrganisationUnit organisationUnit1 = new OrganisationUnit( "orgunit-1", "org-1", "organisationUnitCode1",
-            new Date(), new Date(), true, "comment" );
-        organisationUnit1.setId( id1 );
-
-        /**
-         * Find a different locale than the fallback locale
-         */
-        Locale fallbackLocale = localeManager.getFallbackLocale();
-
-        localeManager.setCurrentLocale( fallbackLocale );
-
-        Locale locale = Locale.FRANCE;
-
-        if ( locale.equals( fallbackLocale ) )
-        {
-            locale = Locale.GERMANY;
-        }
-
-        /**
-         * The user adds a new object using the fallback locale
-         */
-
-        i18nService.addObject( organisationUnit1 );
-
-        /**
-         * Properties are changed using a different locale
-         */
-
-        localeManager.setCurrentLocale( locale );
-
-        organisationUnit1.setName( "orgunit_1" );
-
-        i18nService.verify( organisationUnit1 );
-
-        assertEquals( "orgunit-1", organisationUnit1.getName() );
-
-        /**
-         * Request a translation to verify that the translation is kept
-         */
-
-        localeManager.setCurrentLocale( locale );
-
-        i18nService.internationalise( organisationUnit1 );
-
-        assertEquals( "orgunit_1", organisationUnit1.getName() );
-    }
-
-    @Test
-    public void testGetAvailableLocales()
-        throws Exception
-    {
-        OrganisationUnit organisationUnit1 = new OrganisationUnit( "orgunit", "shortName1", "organisationUnitCode1",
-            new Date(), new Date(), true, "comment" );
-        organisationUnit1.setId( id1 );
-        Map<String, String> translations1 = new Hashtable<String, String>();
-        translations1.put( "name", "orgunit-1" );
-        translations1.put( "shortName", "org-1" );
-        translations1.put( "comment", "Just another orgunit" );
-
-        i18nService.updateTranslation( className1, id1, Locale.UK, translations1 );
-        i18nService.updateTranslation( className1, id1, Locale.FRANCE, translations1 );
-        i18nService.updateTranslation( className1, id1, Locale.US, translations1 );
-
-        Collection<Locale> availableLocales = i18nService.getAvailableLocales();
-
-        assertEquals( 3, availableLocales.size() );
-        assertTrue( availableLocales.contains( Locale.UK ) );
-        assertTrue( availableLocales.contains( Locale.FRANCE ) );
-        assertTrue( availableLocales.contains( Locale.US ) );
-    }
-
-    @Test
-    public void testSetToFallback()
-        throws Exception
-    {
-        OrganisationUnit organisationUnit1 = new OrganisationUnit( "orgunit", "shortName1", "organisationUnitCode1",
-            new Date(), new Date(), true, "comment" );
-        organisationUnit1.setId( id1 );
-
-        Map<String, String> translationsFallback = new Hashtable<String, String>();
-        translationsFallback.put( "name", "orgunit-1" );
-        translationsFallback.put( "shortName", "org-1" );
-
-        Map<String, String> translationsNotFallback = new Hashtable<String, String>();
-        translationsNotFallback.put( "name", "orgunit_1" );
-        translationsNotFallback.put( "shortName", "org_1" );
-
-        Locale notFallbackLocale = Locale.FRANCE;
-
-        Locale fallbackLocale = localeManager.getFallbackLocale();
-
-        if ( notFallbackLocale.equals( fallbackLocale ) )
-        {
-            notFallbackLocale = Locale.GERMANY;
-        }
-
-        i18nService.updateTranslation( className1, id1, fallbackLocale, translationsFallback );
-        i18nService.updateTranslation( className1, id1, notFallbackLocale, translationsNotFallback );
-
-        localeManager.setCurrentLocale( notFallbackLocale );
-
-        i18nService.internationalise( organisationUnit1 );
-
-        assertEquals( "orgunit_1", organisationUnit1.getName() );
-        assertEquals( "org_1", organisationUnit1.getShortName() );
-
-        i18nService.setToFallback( organisationUnit1 );
-
-        assertEquals( "orgunit-1", organisationUnit1.getName() );
-        assertEquals( "org-1", organisationUnit1.getShortName() );
+        
     }
 }
\ No newline at end of file

=== removed file 'dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/i18n/I18nServiceTranslationTest.java'
--- dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/i18n/I18nServiceTranslationTest.java	2011-02-15 20:14:22 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/i18n/I18nServiceTranslationTest.java	1970-01-01 00:00:00 +0000
@@ -1,218 +0,0 @@
-package org.hisp.dhis.i18n;
-
-/*
- * Copyright (c) 2004-2005, 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 <ORGANIZATION> 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 static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertNotNull;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-
-import org.hisp.dhis.DhisSpringTest;
-import org.hisp.dhis.dataelement.DataElement;
-import org.hisp.dhis.i18n.locale.LocaleManager;
-import org.hisp.dhis.mock.MockLocaleManager;
-import org.hisp.dhis.translation.Translation;
-import org.hisp.dhis.translation.TranslationService;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Lars Helge Overland
- * @version $Id$
- */
-public class I18nServiceTranslationTest
-    extends DhisSpringTest
-{
-    private I18nService i18nService;
-
-    private LocaleManager localeManager;
-    
-    private TranslationService translationService;
-    
-    private DataElement dataElementA;
-    
-    private int dataElementIdA = 10;
-    
-    private String dataElementClassNameA = DataElement.class.getSimpleName();
-    
-    private Map<String, String> translationsA;
-    private Map<String, String> translationsB;
-    
-    private Locale localeA = Locale.FRANCE;
-    private Locale localeB = Locale.GERMANY;
-
-    // -------------------------------------------------------------------------
-    // Fixture
-    // -------------------------------------------------------------------------
-
-    @Before
-    public void setUpTest()
-    {
-        i18nService = (I18nService) getBean( I18nService.ID );
-
-        localeManager = new MockLocaleManager(); // (LocaleManager) getBean( "org.hisp.dhis.i18n.locale.LocaleManagerDb" );
-        
-        translationService = (TranslationService) getBean( TranslationService.ID );
-
-        setDependency( i18nService, "localeManager", localeManager );
-        
-        localeManager.setCurrentLocale( localeA );
-        
-        dataElementA = createDataElement( 'A' );
-        dataElementA.setId( dataElementIdA );
-        
-        translationsA = new HashMap<String, String>();
-        translationsA.put( "name", "DataElementFrA" );
-        translationsA.put( "shortName", "ShortNameFrA" );
-        translationsA.put( "description", "DescriptionFrA" );
-                
-        translationsB = new HashMap<String, String>();
-        translationsB.put( "name", "DataElementGeA" );
-        translationsB.put( "shortName", "ShortNameGeA" );
-        translationsB.put( "description", "DescriptionGeA" );
-    }
-
-    // -------------------------------------------------------------------------
-    // Internationalise
-    // -------------------------------------------------------------------------
-
-    @Test
-    public void internationalise()
-    {
-        i18nService.addObject( dataElementA );
-        
-        i18nService.internationalise( dataElementA );
-        
-        assertEquals( "DataElementA", dataElementA.getName() );
-        assertEquals( "DataElementShortA", dataElementA.getShortName() );
-        assertEquals( "DataElementDescriptionA", dataElementA.getDescription() );
-        
-        i18nService.updateTranslation( dataElementClassNameA, dataElementIdA, localeB, translationsB );
-        
-        localeManager.setCurrentLocale( localeB );
-
-        i18nService.internationalise( dataElementA );
-        
-        assertEquals( "DataElementGeA", dataElementA.getName() );
-        assertEquals( "ShortNameGeA", dataElementA.getShortName() );
-        assertEquals( "DescriptionGeA", dataElementA.getDescription() );
-    }
-    
-    @Test
-    public void internationaliseCollection()
-    {
-        Collection<DataElement> dataElements = new ArrayList<DataElement>();
-        dataElements.add( dataElementA );
-        dataElements.add( dataElementA );
-        dataElements.add( dataElementA );
-        
-        i18nService.internationalise( dataElements );
-        
-        for ( DataElement dataElement : dataElements )
-        {
-            assertEquals( "DataElementA", dataElement.getName() );
-            assertEquals( "DataElementShortA", dataElement.getShortName() );
-            assertEquals( "DataElementDescriptionA", dataElement.getDescription() );            
-        }
-
-        i18nService.updateTranslation( dataElementClassNameA, dataElementIdA, localeB, translationsB );
-        
-        localeManager.setCurrentLocale( localeB );
-        
-        i18nService.internationalise( dataElements );
-
-        for ( DataElement dataElement : dataElements )
-        {
-            assertEquals( "DataElementGeA", dataElement.getName() );
-            assertEquals( "ShortNameGeA", dataElement.getShortName() );
-            assertEquals( "DescriptionGeA", dataElement.getDescription() );          
-        }
-    }
-    
-    // -------------------------------------------------------------------------
-    // Object
-    // -------------------------------------------------------------------------
-
-    @Test
-    public void addObject()
-    {
-        i18nService.addObject( dataElementA );
-        
-        Collection<Translation> translations = translationService.getTranslations( dataElementClassNameA, dataElementIdA, localeA );
-        
-        assertNotNull( translations );
-        assertEquals( 3, translations.size() );
-        
-        i18nService.addObject( null );
-    }
-    
-    // -------------------------------------------------------------------------
-    // Translation
-    // -------------------------------------------------------------------------
-
-    @Test
-    public void updateTranslation()
-    {
-        // No existing translations exist
-        
-        i18nService.updateTranslation( dataElementClassNameA, dataElementIdA, localeA, translationsA );
-        
-        assertEquals( "DataElementFrA", translationService.getTranslation( dataElementClassNameA, dataElementIdA, localeA, "name" ).getValue() );
-        assertEquals( "ShortNameFrA", translationService.getTranslation( dataElementClassNameA, dataElementIdA, localeA, "shortName" ).getValue() );
-        assertEquals( "DescriptionFrA", translationService.getTranslation( dataElementClassNameA, dataElementIdA, localeA, "description" ).getValue() );
-        
-        // There are existing translations
-
-        translationsA.put( "name", "DataElementUpdatedA" );
-        translationsA.put( "shortName", "ShortNameUpdatedA" );
-        translationsA.put( "description", "DescriptionUpdatedA" );
-
-        i18nService.updateTranslation( dataElementClassNameA, dataElementIdA, localeA, translationsA );
-
-        assertEquals( "DataElementUpdatedA", translationService.getTranslation( dataElementClassNameA, dataElementIdA, localeA, "name" ).getValue() );
-        assertEquals( "ShortNameUpdatedA", translationService.getTranslation( dataElementClassNameA, dataElementIdA, localeA, "shortName" ).getValue() );
-        assertEquals( "DescriptionUpdatedA", translationService.getTranslation( dataElementClassNameA, dataElementIdA, localeA, "description" ).getValue() );
-    }
-    
-    @Test
-    public void getTranslations()
-    {
-        i18nService.updateTranslation( dataElementClassNameA, dataElementIdA, localeA, translationsA );
-        
-        Map<String, String> translations = i18nService.getTranslations( dataElementClassNameA, dataElementIdA, localeA );
-        
-        assertEquals( 3, translations.keySet().size() );
-        assertEquals( "DataElementFrA", translations.get( "name" ) );
-        assertEquals( "ShortNameFrA", translations.get( "shortName" ) );
-        assertEquals( "DescriptionFrA", translations.get( "description" ) );
-    }
-}

=== removed file 'dhis-2/dhis-services/dhis-service-i18n/src/main/java/org/hisp/dhis/i18n/I18nUpgrader.java'
--- dhis-2/dhis-services/dhis-service-i18n/src/main/java/org/hisp/dhis/i18n/I18nUpgrader.java	2011-12-26 10:07:59 +0000
+++ dhis-2/dhis-services/dhis-service-i18n/src/main/java/org/hisp/dhis/i18n/I18nUpgrader.java	1970-01-01 00:00:00 +0000
@@ -1,397 +0,0 @@
-package org.hisp.dhis.i18n;
-
-/*
- * Copyright (c) 2004-2012, 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;
-import java.util.Locale;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.hisp.dhis.datadictionary.DataDictionary;
-import org.hisp.dhis.datadictionary.DataDictionaryService;
-import org.hisp.dhis.dataelement.DataElement;
-import org.hisp.dhis.dataelement.DataElementCategory;
-import org.hisp.dhis.dataelement.DataElementCategoryCombo;
-import org.hisp.dhis.dataelement.DataElementCategoryOption;
-import org.hisp.dhis.dataelement.DataElementCategoryService;
-import org.hisp.dhis.dataelement.DataElementGroup;
-import org.hisp.dhis.dataelement.DataElementService;
-import org.hisp.dhis.dataset.DataSet;
-import org.hisp.dhis.dataset.DataSetService;
-import org.hisp.dhis.i18n.locale.LocaleManager;
-import org.hisp.dhis.indicator.Indicator;
-import org.hisp.dhis.indicator.IndicatorGroup;
-import org.hisp.dhis.indicator.IndicatorService;
-import org.hisp.dhis.indicator.IndicatorType;
-import org.hisp.dhis.organisationunit.OrganisationUnit;
-import org.hisp.dhis.organisationunit.OrganisationUnitGroup;
-import org.hisp.dhis.organisationunit.OrganisationUnitGroupService;
-import org.hisp.dhis.organisationunit.OrganisationUnitGroupSet;
-import org.hisp.dhis.organisationunit.OrganisationUnitService;
-import org.hisp.dhis.system.startup.AbstractStartupRoutine;
-import org.hisp.dhis.system.util.SystemUtils;
-import org.hisp.dhis.translation.Translation;
-import org.hisp.dhis.translation.TranslationService;
-
-/**
- * The purpose of the I18nUpgrader is to give all objects in the database a default
- * translation at startup time. Objects might be added with other means than the 
- * DHIS 2 API and will so need to be given a default translation.
- * 
- * @author Oyvind Brucker
- */
-public class I18nUpgrader
-    extends AbstractStartupRoutine
-{
-    private static Log log = LogFactory.getLog( I18nUpgrader.class );
-
-    String ID = I18nUpgrader.class.getName();
-
-    // -------------------------------------------------------------------------
-    // Dependencies
-    // -------------------------------------------------------------------------
-
-    private DataElementService dataElementService;
-
-    public void setDataElementService( DataElementService dataElementService )
-    {
-        this.dataElementService = dataElementService;
-    }
-
-    private DataSetService dataSetService;
-    
-    public void setDataSetService( DataSetService dataSetService )
-    {
-        this.dataSetService = dataSetService;
-    }
-
-    private OrganisationUnitGroupService organisationUnitGroupService;
-
-    public void setOrganisationUnitGroupService( OrganisationUnitGroupService organisationUnitGroupService )
-    {
-        this.organisationUnitGroupService = organisationUnitGroupService;
-    }
-
-    private OrganisationUnitService organisationUnitService;
-
-    public void setOrganisationUnitService( OrganisationUnitService organisationUnitService )
-    {
-        this.organisationUnitService = organisationUnitService;
-    }
-
-    private IndicatorService indicatorService;
-
-    public void setIndicatorService( IndicatorService indicatorService )
-    {
-        this.indicatorService = indicatorService;
-    }
-    
-    private DataDictionaryService dataDictionaryService;
-
-    public void setDataDictionaryService( DataDictionaryService dataDictionaryService )
-    {
-        this.dataDictionaryService = dataDictionaryService;
-    }    
-    
-    private DataElementCategoryService categoryService;
-    
-    public void setCategoryService( DataElementCategoryService categoryService )
-    {
-        this.categoryService = categoryService;
-    }
-
-    private LocaleManager localeManager;
-
-    public void setLocaleManager( LocaleManager localeManager )
-    {
-        this.localeManager = localeManager;
-    }
-
-    private TranslationService translationService;
-
-    public void setTranslationService( TranslationService translationService )
-    {
-        this.translationService = translationService;
-    }    
-
-    private I18nService i18nService;
-
-    public void setI18nService( I18nService i18nService )
-    {
-        this.i18nService = i18nService;
-    }
-
-    // -------------------------------------------------------------------------
-    // Execute
-    // -------------------------------------------------------------------------
-    
-    public void execute()
-    {
-        // ---------------------------------------------------------------------
-        // Check permission to run
-        // ---------------------------------------------------------------------
-
-        if ( !SystemUtils.isRunningForUse() )
-        {
-            return;
-        }
-
-        // ---------------------------------------------------------------------
-        // Check if it should run - if so make the i18n service aware of all objects
-        // ---------------------------------------------------------------------
-
-        Collection<Translation> translations = translationService.getAllTranslations();
-
-        if ( translations == null || translations.isEmpty() )
-        {
-            Locale orgLocale = localeManager.getCurrentLocale();
-
-            localeManager.setCurrentLocale( localeManager.getFallbackLocale() );
-
-            log.info( "I18n Upgrader running using locale " + localeManager.getFallbackLocale().getDisplayName() );
-
-            // ---------------------------------------------------------------------
-            // DataElement
-            // ---------------------------------------------------------------------
-
-            Collection<DataElement> dataElements = dataElementService.getAllDataElements();
-
-            if ( dataElements != null && !dataElements.isEmpty() )
-            {
-                log.info( "I18n Upgrader: DataElement (" + dataElements.size() + ")" );
-
-                for ( DataElement dataElement : dataElements )
-                {
-                    i18nService.addObject( dataElement );
-                }
-            }
-
-            // ---------------------------------------------------------------------
-            // DataElementGroup
-            // ---------------------------------------------------------------------
-
-            Collection<DataElementGroup> dataElementGroups = dataElementService.getAllDataElementGroups();
-
-            if ( dataElementGroups != null && !dataElementGroups.isEmpty() )
-            {
-                log.info( "I18n Upgrader: dataElementGroup (" + dataElementGroups.size() + ")" );
-
-                for ( DataElementGroup dataElementGroup : dataElementGroups )
-                {
-                    i18nService.addObject( dataElementGroup );
-                }
-            }
-
-            // ---------------------------------------------------------------------
-            // Indicator
-            // ---------------------------------------------------------------------
-
-            Collection<Indicator> indicators = indicatorService.getAllIndicators();
-
-            if ( indicators != null && !indicators.isEmpty() )
-            {
-                log.info( "I18n Upgrader: Indicator (" + indicators.size() + ")" );
-
-                for ( Indicator indicator : indicators )
-                {
-                    i18nService.addObject( indicator );
-                }
-            }
-
-            // ---------------------------------------------------------------------
-            // IndicatorType
-            // ---------------------------------------------------------------------
-
-            Collection<IndicatorType> indicatorTypes = indicatorService.getAllIndicatorTypes();
-
-            if ( indicatorTypes != null && !indicatorTypes.isEmpty() )
-            {
-                log.info( "I18n Upgrader: indicatorType (" + indicatorTypes.size() + ")" );
-
-                for ( IndicatorType indicatorType : indicatorTypes )
-                {
-                    i18nService.addObject( indicatorType );
-                }
-            }
-
-            // ---------------------------------------------------------------------
-            // IndicatorGroup
-            // ---------------------------------------------------------------------
-
-            Collection<IndicatorGroup> indicatorGroups = indicatorService.getAllIndicatorGroups();
-
-            if ( indicatorGroups != null && !indicatorGroups.isEmpty() )
-            {
-                log.info( "I18n Upgrader: indicatorGroup (" + indicatorGroups.size() + ")" );
-
-                for ( IndicatorGroup indicatorGroup : indicatorGroups )
-                {
-                    i18nService.addObject( indicatorGroup );
-                }
-            }
-
-            // ---------------------------------------------------------------------
-            // OrganisationUnit
-            // ---------------------------------------------------------------------
-
-            Collection<OrganisationUnit> orgunits = organisationUnitService.getAllOrganisationUnits();
-
-            if ( orgunits != null && !orgunits.isEmpty() )
-            {
-                log.info( "I18n Upgrader: OrganisationUnit (" + orgunits.size() + ")" );
-
-                for ( OrganisationUnit orgunit : orgunits )
-                {
-                    i18nService.addObject( orgunit );
-                }
-            }
-
-            // ---------------------------------------------------------------------
-            // OrganisationUnitGroup
-            // ---------------------------------------------------------------------
-
-            Collection<OrganisationUnitGroup> orgunitGroups = organisationUnitGroupService
-                .getAllOrganisationUnitGroups();
-
-            if ( orgunitGroups != null && !orgunitGroups.isEmpty() )
-            {
-                log.info( "I18n Upgrader: OrganisationUnitGroup (" + orgunitGroups.size() + ")" );
-
-                for ( OrganisationUnitGroup orgunitGroup : orgunitGroups )
-                {
-                    i18nService.addObject( orgunitGroup );
-                }
-            }
-
-            // ---------------------------------------------------------------------
-            // OrganisationUnitGroupSet
-            // ---------------------------------------------------------------------
-
-            Collection<OrganisationUnitGroupSet> orgunitGroupSets = organisationUnitGroupService
-                .getAllOrganisationUnitGroupSets();
-
-            if ( orgunitGroupSets != null && !orgunitGroupSets.isEmpty() )
-            {
-                log.info( "I18n Upgrader: OrganisationUnitGroupSet (" + orgunitGroupSets.size() + ")" );
-
-                for ( OrganisationUnitGroupSet orgunitGroupSet : orgunitGroupSets )
-                {
-                    i18nService.addObject( orgunitGroupSet );
-                }
-            }
-
-            // ---------------------------------------------------------------------
-            // DataSet
-            // ---------------------------------------------------------------------
-
-            Collection<DataSet> dataSets = dataSetService.getAllDataSets();
-
-            if ( dataSets != null && !dataSets.isEmpty() )
-            {
-                log.info( "I18n Upgrader: DataSet (" + dataSets.size() + ")" );
-
-                for ( DataSet dataSet : dataSets )
-                {
-                    i18nService.addObject( dataSet );
-                }
-            }
-
-            // ---------------------------------------------------------------------
-            // DataDictionary
-            // ---------------------------------------------------------------------
-
-            Collection<DataDictionary> dataDictionaries = dataDictionaryService.getAllDataDictionaries();
-            
-            if ( dataDictionaries != null && !dataDictionaries.isEmpty() )
-            {
-                log.info( "I81n Upgrader: DataDictionary (" + dataDictionaries.size() + ")" );
-                
-                for ( DataDictionary dataDictionary : dataDictionaries )
-                {
-                    i18nService.addObject( dataDictionary );
-                }
-            }
-
-            localeManager.setCurrentLocale( orgLocale );
-            
-            // ---------------------------------------------------------------------
-            // DataElementCategory
-            // ---------------------------------------------------------------------
-
-            Collection<DataElementCategory> categories = categoryService.getAllDataElementCategories();
-            
-            if ( categories != null && !categories.isEmpty() )
-            {
-                log.info( "I81n Upgrader: DataElementCategory (" + categories.size() + ")" );
-                
-                for ( DataElementCategory category : categories )
-                {
-                    i18nService.addObject( category );
-                }
-            }
-
-            localeManager.setCurrentLocale( orgLocale );
-            
-            // ---------------------------------------------------------------------
-            // DataElementCategoryOption
-            // ---------------------------------------------------------------------            
-            
-            Collection<DataElementCategoryOption> categoryOptions = categoryService.getAllDataElementCategoryOptions();
-            
-            if ( categoryOptions != null && !categoryOptions.isEmpty() )
-            {
-                log.info( "I81n Upgrader: DataElementCategoryOption (" + categoryOptions.size() + ")" );                
-                
-                for ( DataElementCategoryOption categoryOption : categoryOptions )
-                {
-                    i18nService.addObject( categoryOption );                    
-                }
-            }
-
-            localeManager.setCurrentLocale( orgLocale );
-            
-            // ---------------------------------------------------------------------
-            // DataElementCategoryCombo
-            // ---------------------------------------------------------------------
-
-            Collection<DataElementCategoryCombo> categoryCombos = categoryService.getAllDataElementCategoryCombos();
-            
-            if ( categoryCombos != null && !categoryCombos.isEmpty() )
-            {
-                log.info( "I81n Upgrader: DataElementCategoryCombo (" + categoryCombos.size() + ")" );
-                
-                for ( DataElementCategoryCombo categoryCombo : categoryCombos )
-                {
-                    i18nService.addObject( categoryCombo );
-                }
-            }
-
-            localeManager.setCurrentLocale( orgLocale );
-        }
-    }
-}

=== modified file 'dhis-2/dhis-services/dhis-service-i18n/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-services/dhis-service-i18n/src/main/resources/META-INF/dhis/beans.xml	2012-01-05 20:39:23 +0000
+++ dhis-2/dhis-services/dhis-service-i18n/src/main/resources/META-INF/dhis/beans.xml	2012-01-19 11:43:06 +0000
@@ -33,52 +33,4 @@
     </property>
   </bean>
   
-  <!-- Upgrader -->
-
-  <bean id="org.hisp.dhis.i18n.I18nUpgrader" class="org.hisp.dhis.i18n.I18nUpgrader">
-    <property name="i18nService">
-      <ref bean="org.hisp.dhis.i18n.I18nService" />
-    </property>
-    <property name="translationService">
-      <ref bean="org.hisp.dhis.translation.TranslationService" />
-    </property>
-    <property name="dataElementService">
-      <ref bean="org.hisp.dhis.dataelement.DataElementService" />
-    </property>
-    <property name="organisationUnitService">
-      <ref bean="org.hisp.dhis.organisationunit.OrganisationUnitService" />
-    </property>
-    <property name="organisationUnitGroupService">
-      <ref bean="org.hisp.dhis.organisationunit.OrganisationUnitGroupService" />
-    </property>
-    <property name="dataSetService">
-      <ref bean="org.hisp.dhis.dataset.DataSetService" />
-    </property>
-    <property name="indicatorService">
-      <ref bean="org.hisp.dhis.indicator.IndicatorService" />
-    </property>
-    <property name="dataDictionaryService">
-      <ref bean="org.hisp.dhis.datadictionary.DataDictionaryService" />
-    </property>
-    <property name="categoryService">
-      <ref bean="org.hisp.dhis.dataelement.DataElementCategoryService" />
-    </property>
-    <property name="localeManager">
-      <ref bean="org.hisp.dhis.i18n.locale.LocaleManagerDb" />
-    </property>
-    <property name="name" value="I18nUpgrader" />
-    <property name="runlevel" value="8" />
-    <property name="skipInTests" value="true" />
-  </bean>
-
-  <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
-    <property name="targetObject" ref="org.hisp.dhis.system.startup.StartupRoutineExecutor" />
-    <property name="targetMethod" value="addStartupRoutine" />
-    <property name="arguments">
-      <list>
-        <ref local="org.hisp.dhis.i18n.I18nUpgrader" />
-      </list>
-    </property>
-  </bean>
-
 </beans>

=== modified file 'dhis-2/dhis-support/dhis-support-hibernate/src/main/java/org/hisp/dhis/hibernate/HibernateGenericStore.java'
--- dhis-2/dhis-support/dhis-support-hibernate/src/main/java/org/hisp/dhis/hibernate/HibernateGenericStore.java	2011-12-26 10:07:59 +0000
+++ dhis-2/dhis-support/dhis-support-hibernate/src/main/java/org/hisp/dhis/hibernate/HibernateGenericStore.java	2012-01-19 11:43:06 +0000
@@ -69,7 +69,7 @@
     /**
      * Could be overridden programmatically.
      */
-    protected Class<T> getClazz()
+    public Class<T> getClazz()
     {
         return clazz;
     }

=== modified file 'dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/ReflectionUtils.java'
--- dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/ReflectionUtils.java	2011-12-26 10:07:59 +0000
+++ dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/ReflectionUtils.java	2012-01-19 11:43:06 +0000
@@ -84,8 +84,8 @@
      * if the operation fails.
      *
      * @param object Object to modify
-     * @param name   Name of property to set
-     * @param value  Value the property will be set to
+     * @param name Name of property to set
+     * @param value Value the property will be set to
      */
     public static void setProperty( Object object, String name, String value )
     {
@@ -111,6 +111,22 @@
     }
 
     /**
+     * Sets a property for the supplied object. Throws an UnsupportedOperationException
+     * if the operation fails.
+     *
+     * @param object Object to modify
+     * @param namePrefix prefix of the property name to set 
+     * @param name Name of property to set
+     * @param value Value the property will be set to
+     */
+    public static void setProperty( Object object, String namePrefix, String name, String value )
+    {
+        String prefixed = namePrefix + name.substring( 0, 1 ).toUpperCase() + name.substring( 1, name.length() );
+        
+        setProperty( object, prefixed, value );
+    }
+
+    /**
      * Returns the name of the class that the object is an instance of
      * org.hisp.dhis.indicator.Indicactor returns Indicator.
      *

=== modified file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/i18n/i18n.js'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/i18n/i18n.js	2011-09-30 03:59:15 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/i18n/i18n.js	2012-01-19 11:43:06 +0000
@@ -24,32 +24,6 @@
 	}
 }
 
-function getReference()
-{
-	clearFields( ' Ref' );
-
-    var loc = getFieldValue( 'referenceLoc' );
-
-    if ( loc != "heading" )
-    {
-		jQuery.postJSON( 'getTranslations.action', {
-			id: getFieldValue ( 'objectId' ),
-			className: getFieldValue ( 'className' ),
-			loc: loc
-		}, function ( json )
-		{
-			var translations = json.translations;
-
-			for ( var i = 0; i < translations.length; i++ )
-			{
-				var field = document.getElementById( translations[i].key + ' Ref' );
-
-				if ( field != null ) field.innerHTML = translations[i].value;
-			}
-		});
-	}
-}
-
 function clearFields( prefix )
 {
 	prefix = prefix ? prefix : '';
@@ -59,40 +33,3 @@
         byId( propNames[i] + prefix ).innerHTML = "";
     }
 }
-
-function addLocale()
-{
-    var loc = document.getElementById("loc");
-
-    var language = document.getElementById("language").value;
-    var country = document.getElementById("country").value;
-    
-    if ( language == null || language.length != 2 )
-    {
-    	setMessage( language_must_be_two_chars );
-    	return;
-    }
-    
-    if ( country == null || country.length != 2 )
-    {
-    	setMessage( country_must_be_two_chars );
-    	return;
-    }
-    
-	var toAdd = language + "_" + country;
-	
-	if ( listContains( loc, toAdd ) == true )
-	{
-		setMessage( locale_already_exists );
-		return;
-	}
-	
-    var option = document.createElement("option");
-
-    option.value = toAdd;
-    option.text = toAdd;
-
-    loc.add(option, null);
-
-    setMessage( locale_added + " " + toAdd );
-}
\ No newline at end of file

=== modified file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/i18n/translate.vm'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/i18n/translate.vm	2011-09-30 03:49:43 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/i18n/translate.vm	2012-01-19 11:43:06 +0000
@@ -1,13 +1,4 @@
-<script>
-//-----------------------------------------------------------------------
-//init jQuery validation for translateForm
-//-----------------------------------------------------------------------
-	jQuery(document).ready(	function(){
-		validation( 'translateForm', function( form ){ form.submit()} );	
-		setMessage( '$!message' );
-	});
 
-</script>
 <input type="hidden" id="curLocaleCode" value="$locale.getLanguage()_$locale.getCountry()"/>
 
 <form id="translateForm" action="translate.action" method="post">
@@ -29,32 +20,19 @@
 	<td style="width:12em"></td>
 	<td style="width:20em">
         <select id="loc" name="loc" onchange="getTranslation()" style="min-width:20em">
-            <option value="heading">$i18n.getString( "translation_select_locale" )</option>
-			#foreach ($locale in $availableLocales )
-				<option value="$locale" #if( $currentLocale == $locale ) selected="selected" #end>$locale.displayName</option>
-			#end
-		</select>
-    </td>
-    <td style="width:20em">
-        <select id="referenceLoc" name="referenceLocal" onchange="getReference()" style="min-width:20em">
-            <option value="heading">$i18n.getString( "translation_select_ref" )</option>
-			#foreach ($locale in $availableLocales )
-			    <option value="$locale" #if( $currentRefLocale == $locale ) selected="selected" #end>$locale.displayName</option>
-			#end
-		</select>
-    </td>
+            <option value="NONE">$i18n.getString( "translation_select_locale" )</option>
+			#foreach ( $locale in $availableLocales )
+				<option value="$locale" #if( $currentLocale == $locale ) selected="selected" #end>$!locale.displayName</option>
+			#end
+		</select>
+    </td>
+    <td style="width:20em"></td>
     </tr>
 	#foreach ( $propertyName in $propertyNames )
 	<tr>
-	    #set ($prop = $propertyNamesLabel.get( $propertyName ))
-	    #set ($rules = $rulePropertyNames.get( $propertyName ))
-		
-		<td style="width:10em"><label for="$propertyName" style="width:20em">$i18n.getString( "translation_label_$prop" ) </label></td>
-		<td>
-			<input type="text" id="$propertyName" name="$propertyName" maxlength="$rules.get('maxlength')" value="$encoder.htmlEncode( $translations.get( $propertyName ) )" style="width:20em" 
-				class="{validate:{required:$rules.get('required'),minlength:$rules.get('minlength'),custome_regex:[$rules.get('regex'),'$i18n.getString( $rules.get('message') )']}}"/>
-		</td>
-		<td><span id="$propertyName Ref" name="$propertyName Ref" style="width:20em">$encoder.htmlEncode( $referenceTranslations.get( $propertyName ) )</span></td>
+		<td style="width:10em"><label style="width:20em">$i18n.getString( "translation_label_$propertyName" )</label></td>
+		<td><input type="text" id="$propertyName" name="$propertyName" value="$!encoder.htmlEncode( $translations.get( $propertyName ) )" style="width:20em"/></td>
+		<td><span style="width:20em">$!encoder.htmlEncode( $referenceTranslations.get( $propertyName ) )</span></td>
 	</tr>
 	#end
 	<tr>
@@ -66,41 +44,14 @@
 	</tr>
 </table>
 </form>
-<h3>$i18n.getString( "translation_addlocale")</h3>
-<table>
-	<tr>
-		<th colspan="2">Details</th>
-	</tr>
-	<tr>
-		<td style="width:12em"><label for="language">$i18n.getString( "translation_languagecode" )</label></td>
-		<td><input type="text" id="language" name="language" size="2" style="width:20em"/></td>
-	</tr>
-	<tr>
-		<td><label for="country">$i18n.getString( "translation_countrycode" ) </label></td>
-		<td><input type="text" id="country" name="country" size="2" style="width:20em"/></td>
-	</tr>
-	<tr>
-		<td></td>
-		<td><input type="button" value="$i18n.getString( 'translation_add' )" onclick="addLocale()" style="width:10em"/></td>
-		<td></td>
-	</tr>
-</table>
 
 <span id="message"></span>
 
 <script type="text/javascript">
-
     var propNames = new Array()
     #set( $count = 0 )
     #foreach ( $propertyName in $propertyNames )
         propNames[$count] = "$propertyName";
         #set( $count = $count + 1 )
     #end
-
-    var locale_added = '$i18n.getString( "translation_locale_added" )';
-    var language_must_be_two_chars = '$i18n.getString( "translation_language_must_be_two_chars" )';
-    var country_must_be_two_chars = '$i18n.getString( "translation_country_must_be_two_chars" )';
-    var variant_must_be_specified = '$i18n.getString( "translation_variant_must_be_specified" )';
-    var locale_already_exists = '$i18n.getString( "translation_locale_already_exists" )';
-	
-</script>
\ No newline at end of file
+</script>

=== modified file 'dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/i18n/action/I18nAction.java'
--- dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/i18n/action/I18nAction.java	2010-06-06 13:49:53 +0000
+++ dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/i18n/action/I18nAction.java	2012-01-19 11:43:06 +0000
@@ -27,13 +27,14 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import java.util.Collection;
-import java.util.HashMap;
+import java.util.ArrayList;
 import java.util.Hashtable;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 
+import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.IdentifiableObjectManager;
 import org.hisp.dhis.i18n.I18nService;
 import org.hisp.dhis.i18n.locale.LocaleManager;
 
@@ -50,19 +51,19 @@
 {
     private String className;
 
-    private String objectId;
+    private Integer objectId;
 
     private String returnUrl;
 
     private String message;
 
+    private List<Locale> availableLocales = new ArrayList<Locale>();
+    
     private Map<String, String> translations = new Hashtable<String, String>();
 
     private Map<String, String> referenceTranslations = new Hashtable<String, String>();
-
-    private Map<String, String> propertyLabels = new Hashtable<String, String>();
-
-    private Map<String, Map<String, String>> rulePropertyNames = new HashMap<String, Map<String, String>>();
+    
+    private List<String> propertyNames = new ArrayList<String>();
 
     // -------------------------------------------------------------------------
     // Dependencies
@@ -81,6 +82,13 @@
     {
         this.localeManager = localeManager;
     }
+    
+    private IdentifiableObjectManager identifiableObjectManager;
+
+    public void setIdentifiableObjectManager( IdentifiableObjectManager identifiableObjectManager )
+    {
+        this.identifiableObjectManager = identifiableObjectManager;
+    }
 
     // -------------------------------------------------------------------------
     // Input
@@ -91,7 +99,7 @@
         this.className = className;
     }
 
-    public void setObjectId( String objectId )
+    public void setObjectId( Integer objectId )
     {
         this.objectId = objectId;
     }
@@ -115,7 +123,7 @@
         return className;
     }
 
-    public String getObjectId()
+    public Integer getObjectId()
     {
         return objectId;
     }
@@ -125,25 +133,14 @@
         return returnUrl;
     }
 
-    public Collection<Locale> getAvailableLocales()
-        throws Exception
-    {
-        return i18nService.getAvailableLocales();
-    }
-
-    public List<String> getPropertyNames()
-    {
-        return i18nService.getPropertyNames( className );
-    }
-
-    public Map<String, String> getPropertyNamesLabel()
-    {
-        return propertyLabels;
-    }
-    
-    public Map<String, Map<String, String>> getRulePropertyNames()
-    {
-        return rulePropertyNames;
+    public String getMessage()
+    {
+        return message;
+    }
+
+    public List<Locale> getAvailableLocales()
+    {
+        return availableLocales;
     }
 
     public Map<String, String> getReferenceTranslations()
@@ -156,19 +153,9 @@
         return translations;
     }
 
-    public Locale getCurrentLocale()
-    {
-        return localeManager.getCurrentLocale();
-    }
-
-    public Locale getCurrentRefLocale()
-    {
-        return localeManager.getFallbackLocale();
-    }
-
-    public String getMessage()
-    {
-        return message;
+    public List<String> getPropertyNames()
+    {
+        return propertyNames;
     }
 
     // -------------------------------------------------------------------------
@@ -178,32 +165,16 @@
     public String execute()
         throws Exception
     {
-        rulePropertyNames = i18nService.getRulePropertyNames( className );
+        availableLocales = i18nService.getAvailableLocales();
         
-        propertyLabels = i18nService.getPropertyNamesLabel( className );
-
-        translations = i18nService.getTranslations( className, Integer.parseInt( objectId ), getCurrentLocale() );
-
-        referenceTranslations = i18nService.getTranslations( className, Integer.parseInt( objectId ),
-            getCurrentRefLocale() );
-
-        /**
-         * Fill in empty strings for null values
-         */
-
-        for ( String property : getPropertyNames() )
-        {
-            if ( translations.get( property ) == null )
-            {
-                translations.put( property, "" );
-            }
-            if ( referenceTranslations.get( property ) == null )
-            {
-                referenceTranslations.put( property, "" );
-            }
-        }
+        translations = i18nService.getTranslations( className, objectId, localeManager.getCurrentLocale() );
+
+        IdentifiableObject object = identifiableObjectManager.getObject( objectId, className );
+
+        referenceTranslations = i18nService.getObjectTranslations( object );
+
+        propertyNames = i18nService.getTranslationProperties( object );
 
         return SUCCESS;
     }
-
 }

=== modified file 'dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/i18n/action/TranslateAction.java'
--- dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/i18n/action/TranslateAction.java	2012-01-04 07:00:57 +0000
+++ dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/i18n/action/TranslateAction.java	2012-01-19 11:43:06 +0000
@@ -37,29 +37,22 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.struts2.ServletActionContext;
-import org.hisp.dhis.i18n.I18n;
+import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.IdentifiableObjectManager;
 import org.hisp.dhis.i18n.I18nService;
 import org.hisp.dhis.system.util.LocaleUtils;
-import org.hisp.dhis.translation.Translation;
-import org.hisp.dhis.translation.TranslationService;
 
 import com.opensymphony.xwork2.Action;
 
 /**
  * @author Oyvind Brucker
- * @version $Id$
  * @modifier Dang Duy Hieu
- * @since 2010-03-24
  */
 public class TranslateAction
     implements Action
 {
     private static final Log log = LogFactory.getLog( TranslateAction.class );
 
-    private static final String SUFFIX_WARNING_MESSAGE = "_with";
-
-    private static final String PREFIX_WARNING_MESSAGE = "translation_duplicated_";
-
     private String className;
 
     private String objectId;
@@ -81,22 +74,11 @@
         this.i18nService = i18nService;
     }
 
-    private TranslationService translationService;
-
-    public void setTranslationService( TranslationService translationService )
-    {
-        this.translationService = translationService;
-    }
-
-    // -------------------------------------------------------------------------
-    // I18n Object
-    // -------------------------------------------------------------------------
-
-    private I18n i18n;
-
-    public void setI18n( I18n i18n )
-    {
-        this.i18n = i18n;
+    private IdentifiableObjectManager identifiableObjectManager;
+
+    public void setIdentifiableObjectManager( IdentifiableObjectManager identifiableObjectManager )
+    {
+        this.identifiableObjectManager = identifiableObjectManager;
     }
 
     // -------------------------------------------------------------------------
@@ -159,77 +141,35 @@
     public String execute()
         throws Exception
     {
-        log.info( "\n\nClassname: " + className + ", id: " + objectId + ", loc: " + loc );
-
+        log.info( "Classname: " + className + ", id: " + objectId + ", loc: " + loc );
+
+        IdentifiableObject object = identifiableObjectManager.getObject( Integer.parseInt( objectId ), className );
+
+        List<String> propertyNames = i18nService.getTranslationProperties( object );
+        
         Locale thisLocale = LocaleUtils.getLocale( loc );
 
         HttpServletRequest request = ServletActionContext.getRequest();
 
         Map<String, String> translations = new Hashtable<String, String>();
-
-        List<String> propertyNames = i18nService.getPropertyNames( className );
-        List<String> uniquePropertyNames = i18nService.getUniquePropertyNames( className );
-
+        
         for ( String propertyName : propertyNames )
         {
             String[] translation = request.getParameterValues( propertyName );
 
-            if ( translation != null && translation.length > 0  )
+            if ( translation != null && translation.length > 0 && translation[0] != null && !translation[0].trim().isEmpty() )
             {
-                if ( uniquePropertyNames.contains( propertyName ) && translation[0].length() > 0 )
-                {
-                    if ( this.isDuplicatedInTranslation( thisLocale, propertyName, translation[0] ) )
-                    {
-                        return INPUT;
-                    }
-                }
-                else if ( translation[0].length() == 0 )
-                {
-                	translation[0] = "";
-                }
-
                 translations.put( propertyName, translation[0] );
             }
         }
 
-        log.info( "\nTranslations: " + translations );
+        log.info( "Translations: " + translations );
 
-        if ( thisLocale != null && !loc.equals( "heading" ) )
+        if ( thisLocale != null && !loc.equals( "NONE" ) )
         {
             i18nService.updateTranslation( className, Integer.parseInt( objectId ), thisLocale, translations );
         }
 
-        message = "";
-
         return SUCCESS;
     }
-
-    // -------------------------------------------------------------------------
-    // Supportive methods
-    // -------------------------------------------------------------------------
-
-    private String getBuildUpMessage( Translation obj, String property )
-    {
-        String message = i18n.getString( PREFIX_WARNING_MESSAGE + property + SUFFIX_WARNING_MESSAGE )
-            + " <br/><br/> <center><strong>[ " + className + " ]  -  [ "
-            + i18n.getString( "translation_label_" + property ) + " = \"" + obj.getValue() + "\" ]</strong></center>";
-
-        return message;
-    }
-
-    private boolean isDuplicatedInTranslation( Locale locale, String property, String value )
-    {
-        Translation objMatch = translationService.getTranslation( className, locale, property, value, Integer
-            .parseInt( objectId ) );
-
-        if ( objMatch != null )
-        {
-            message = this.getBuildUpMessage( objMatch, property.toLowerCase() );
-
-            return true;
-        }
-
-        return false;
-    }
-
 }

=== modified file 'dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/i18n/action/ValidateAddDuplicatedTranslationAction.java'
--- dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/i18n/action/ValidateAddDuplicatedTranslationAction.java	2010-05-11 14:20:51 +0000
+++ dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/i18n/action/ValidateAddDuplicatedTranslationAction.java	2012-01-19 11:43:06 +0000
@@ -27,7 +27,6 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import java.util.List;
 import java.util.Locale;
 
 import org.apache.commons.logging.Log;
@@ -35,7 +34,6 @@
 import org.hisp.dhis.i18n.I18n;
 import org.hisp.dhis.i18n.I18nService;
 import org.hisp.dhis.system.util.LocaleUtils;
-import org.hisp.dhis.translation.Translation;
 import org.hisp.dhis.translation.TranslationService;
 
 import com.opensymphony.xwork2.Action;
@@ -169,6 +167,7 @@
         // Checking duplicated name
         // -------------------------------------------------------------
 
+        /*
         List<String> propertyNames = i18nService.getPropertyNames( className );
 
         for ( String propertyName : propertyNames )
@@ -206,7 +205,7 @@
                 }
             }
         }
-
+*/
         message = "OK";
 
         return SUCCESS;

=== modified file 'dhis-2/dhis-web/dhis-web-commons/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-web/dhis-web-commons/src/main/resources/META-INF/dhis/beans.xml	2012-01-05 20:39:23 +0000
+++ dhis-2/dhis-web/dhis-web-commons/src/main/resources/META-INF/dhis/beans.xml	2012-01-19 11:43:06 +0000
@@ -287,6 +287,9 @@
     <property name="localeManager">
       <ref bean="org.hisp.dhis.i18n.locale.LocaleManagerDb" />
     </property>
+	<property name="identifiableObjectManager">
+	  <ref bean="org.hisp.dhis.common.IdentifiableObjectManager" />
+	</property>
   </bean>
 
   <bean id="org.hisp.dhis.i18n.action.GetTranslationsAction" class="org.hisp.dhis.i18n.action.GetTranslationsAction">
@@ -299,9 +302,9 @@
     <property name="i18nService">
       <ref bean="org.hisp.dhis.i18n.I18nService" />
     </property>
-    <property name="translationService">
-      <ref bean="org.hisp.dhis.translation.TranslationService" />
-    </property>
+	<property name="identifiableObjectManager">
+	  <ref bean="org.hisp.dhis.common.IdentifiableObjectManager" />
+	</property>
   </bean>
 
   <bean id="org.hisp.dhis.i18n.action.ValidateAddDuplicatedTranslationAction" class="org.hisp.dhis.i18n.action.ValidateAddDuplicatedTranslationAction">

=== modified file 'dhis-2/dhis-web/dhis-web-commons/src/main/resources/i18n_global.properties'
--- dhis-2/dhis-web/dhis-web-commons/src/main/resources/i18n_global.properties	2012-01-18 08:40:55 +0000
+++ dhis-2/dhis-web/dhis-web-commons/src/main/resources/i18n_global.properties	2012-01-19 11:43:06 +0000
@@ -211,7 +211,7 @@
 translation_save=Save
 translation_label_id=Id
 translation_label_name=Name
-translation_label_short_name=Short name
+translation_label_shortName=Short name
 translation_label_description=Description
 translation_label_comment=Comment
 translation_label_region=Region