← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 22220: support creation of indicators and validation rules in new dxf2 importer, including tests

 

------------------------------------------------------------
revno: 22220
committer: Morten Olav Hansen <morten@xxxxxxxxx>
branch nick: dhis2
timestamp: Thu 2016-03-10 13:06:01 +0700
message:
  support creation of indicators and validation rules in new dxf2 importer, including tests
added:
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata2/objectbundle/hooks/ValidationRuleObjectBundleHook.java
  dhis-2/dhis-services/dhis-service-dxf2/src/test/resources/dxf2/metadata_with_indicators.json
  dhis-2/dhis-services/dhis-service-dxf2/src/test/resources/dxf2/metadata_with_vr.json
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/preheat/PreheatService.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/preheat/DefaultPreheatService.java
  dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/metadata2/objectbundle/ObjectBundleServiceTest.java


--
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/preheat/PreheatService.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/preheat/PreheatService.java	2016-03-08 04:49:20 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/preheat/PreheatService.java	2016-03-10 06:06:01 +0000
@@ -83,7 +83,8 @@
 
     /**
      * Checks but does not connect any references, returns check report
-     *  @param objects    Object to check
+     *
+     * @param objects    Object to check
      * @param preheat    Preheat Cache to use
      * @param identifier Use this identifier type to check references
      */
@@ -91,6 +92,7 @@
 
     /**
      * Checks but does not connect any references, returns check report
+     *
      * @param object     Object to check
      * @param preheat    Preheat Cache to use
      * @param identifier Use this identifier type to check references
@@ -104,5 +106,5 @@
      * @param preheat    Preheat Cache to use
      * @param identifier Use this identifier type to attach references
      */
-    <T extends IdentifiableObject> void connectReferences( T object, Preheat preheat, PreheatIdentifier identifier );
+    void connectReferences( Object object, Preheat preheat, PreheatIdentifier identifier );
 }

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/preheat/DefaultPreheatService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/preheat/DefaultPreheatService.java	2016-03-09 16:32:51 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/preheat/DefaultPreheatService.java	2016-03-10 06:06:01 +0000
@@ -33,6 +33,7 @@
 import org.hisp.dhis.common.IdentifiableObject;
 import org.hisp.dhis.common.IdentifiableObjectManager;
 import org.hisp.dhis.common.MergeMode;
+import org.hisp.dhis.dataelement.DataElement;
 import org.hisp.dhis.dataelement.DataElementOperand;
 import org.hisp.dhis.feedback.ErrorCode;
 import org.hisp.dhis.feedback.ObjectErrorReport;
@@ -48,6 +49,7 @@
 import org.hisp.dhis.user.User;
 import org.hisp.dhis.user.UserCredentials;
 import org.hisp.dhis.user.UserGroup;
+import org.hisp.dhis.validation.ValidationRule;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.StringUtils;
@@ -303,6 +305,35 @@
 
                 } );
 
+                if ( ValidationRule.class.isInstance( object ) )
+                {
+                    ValidationRule validationRule = (ValidationRule) object;
+
+                    if ( !uidMap.containsKey( DataElement.class ) ) uidMap.put( DataElement.class, new HashSet<>() );
+                    if ( !codeMap.containsKey( DataElement.class ) ) codeMap.put( DataElement.class, new HashSet<>() );
+
+                    if ( validationRule.getLeftSide() != null && !validationRule.getLeftSide().getDataElementsInExpression().isEmpty() )
+                    {
+                        validationRule.getLeftSide().getDataElementsInExpression().stream()
+                            .forEach( de -> {
+                                if ( !StringUtils.isEmpty( de.getUid() ) ) uidMap.get( DataElement.class ).add( de.getUid() );
+                                if ( !StringUtils.isEmpty( de.getCode() ) ) codeMap.get( DataElement.class ).add( de.getCode() );
+                            } );
+                    }
+
+                    if ( validationRule.getRightSide() != null && !validationRule.getRightSide().getDataElementsInExpression().isEmpty() )
+                    {
+                        validationRule.getRightSide().getDataElementsInExpression().stream()
+                            .forEach( de -> {
+                                if ( !StringUtils.isEmpty( de.getUid() ) ) uidMap.get( DataElement.class ).add( de.getUid() );
+                                if ( !StringUtils.isEmpty( de.getCode() ) ) codeMap.get( DataElement.class ).add( de.getCode() );
+                            } );
+                    }
+
+                    if ( uidMap.get( DataElement.class ).isEmpty() ) uidMap.remove( DataElement.class );
+                    if ( codeMap.get( DataElement.class ).isEmpty() ) codeMap.remove( DataElement.class );
+                }
+
                 if ( !uidMap.containsKey( Attribute.class ) ) uidMap.put( Attribute.class, new HashSet<>() );
                 if ( !codeMap.containsKey( Attribute.class ) ) codeMap.put( Attribute.class, new HashSet<>() );
 
@@ -541,7 +572,7 @@
 
     @Override
     @SuppressWarnings( "unchecked" )
-    public <T extends IdentifiableObject> void connectReferences( T object, Preheat preheat, PreheatIdentifier identifier )
+    public void connectReferences( Object object, Preheat preheat, PreheatIdentifier identifier )
     {
         if ( object == null )
         {
@@ -561,12 +592,12 @@
 
                 if ( !p.isCollection() )
                 {
-                    T refObject = ReflectionUtils.invokeMethod( object, p.getGetterMethod() );
-                    T ref = preheat.get( identifier, refObject );
+                    IdentifiableObject refObject = ReflectionUtils.invokeMethod( object, p.getGetterMethod() );
+                    IdentifiableObject ref = preheat.get( identifier, refObject );
 
                     if ( Preheat.isDefaultClass( refObject ) && (ref == null || "default".equals( refObject.getName() )) )
                     {
-                        ref = (T) defaults.get( refObject.getClass() );
+                        ref = defaults.get( refObject.getClass() );
                     }
 
                     if ( ref != null && ref.getId() == 0 )
@@ -580,16 +611,16 @@
                 }
                 else
                 {
-                    Collection<T> objects = ReflectionUtils.newCollectionInstance( p.getKlass() );
+                    Collection<IdentifiableObject> objects = ReflectionUtils.newCollectionInstance( p.getKlass() );
                     Collection<IdentifiableObject> refObjects = ReflectionUtils.invokeMethod( object, p.getGetterMethod() );
 
                     for ( IdentifiableObject refObject : refObjects )
                     {
-                        T ref = preheat.get( identifier, (T) refObject );
+                        IdentifiableObject ref = preheat.get( identifier, refObject );
 
                         if ( Preheat.isDefaultClass( refObject ) && (ref == null || "default".equals( refObject.getName() )) )
                         {
-                            ref = (T) defaults.get( refObject.getClass() );
+                            ref = defaults.get( refObject.getClass() );
                         }
 
                         if ( ref != null && ref.getId() != 0 ) objects.add( ref );

=== added file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata2/objectbundle/hooks/ValidationRuleObjectBundleHook.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata2/objectbundle/hooks/ValidationRuleObjectBundleHook.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata2/objectbundle/hooks/ValidationRuleObjectBundleHook.java	2016-03-10 06:06:01 +0000
@@ -0,0 +1,70 @@
+package org.hisp.dhis.dxf2.metadata2.objectbundle.hooks;
+
+/*
+ * Copyright (c) 2004-2016, 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 org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.dxf2.metadata2.objectbundle.ObjectBundle;
+import org.hisp.dhis.expression.Expression;
+import org.hisp.dhis.validation.ValidationRule;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
+ */
+@Component
+public class ValidationRuleObjectBundleHook extends AbstractObjectBundleHook
+{
+    @Override
+    public void preCreate( IdentifiableObject identifiableObject, ObjectBundle objectBundle )
+    {
+        if ( !ValidationRule.class.isInstance( identifiableObject ) ) return;
+        ValidationRule validationRule = (ValidationRule) identifiableObject;
+
+        Expression leftSide = validationRule.getLeftSide();
+        Expression rightSide = validationRule.getRightSide();
+
+        preheatService.connectReferences( leftSide, objectBundle.getPreheat(), objectBundle.getPreheatIdentifier() );
+        preheatService.connectReferences( rightSide, objectBundle.getPreheat(), objectBundle.getPreheatIdentifier() );
+
+        sessionFactory.getCurrentSession().save( leftSide );
+        sessionFactory.getCurrentSession().save( rightSide );
+
+        validationRule.setLeftSide( leftSide );
+        validationRule.setRightSide( rightSide );
+    }
+
+    @Override
+    public void preUpdate( IdentifiableObject identifiableObject, ObjectBundle objectBundle )
+    {
+        if ( !ValidationRule.class.isInstance( identifiableObject ) ) return;
+        ValidationRule validationRule = (ValidationRule) identifiableObject;
+        validationRule.setLeftSide( null );
+        validationRule.setRightSide( null );
+    }
+}

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/metadata2/objectbundle/ObjectBundleServiceTest.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/metadata2/objectbundle/ObjectBundleServiceTest.java	2016-03-09 10:26:29 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/metadata2/objectbundle/ObjectBundleServiceTest.java	2016-03-10 06:06:01 +0000
@@ -47,6 +47,7 @@
 import org.hisp.dhis.feedback.ErrorReport;
 import org.hisp.dhis.feedback.ObjectErrorReport;
 import org.hisp.dhis.importexport.ImportStrategy;
+import org.hisp.dhis.indicator.Indicator;
 import org.hisp.dhis.option.Option;
 import org.hisp.dhis.option.OptionSet;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
@@ -61,6 +62,7 @@
 import org.hisp.dhis.user.User;
 import org.hisp.dhis.user.UserAuthorityGroup;
 import org.hisp.dhis.user.UserGroup;
+import org.hisp.dhis.validation.ValidationRule;
 import org.junit.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.io.ClassPathResource;
@@ -966,6 +968,70 @@
         assertEquals( 1, dataSet.getCompulsoryDataElementOperands().size() );
     }
 
+    @Test
+    public void testCreateMetadataWithIndicator() throws IOException
+    {
+        Map<Class<? extends IdentifiableObject>, List<IdentifiableObject>> metadata = renderService.fromMetadata(
+            new ClassPathResource( "dxf2/metadata_with_indicators.json" ).getInputStream(), RenderFormat.JSON );
+
+        ObjectBundleParams params = new ObjectBundleParams();
+        params.setObjectBundleMode( ObjectBundleMode.COMMIT );
+        params.setImportMode( ImportStrategy.CREATE );
+        params.setObjects( metadata );
+
+        ObjectBundle bundle = objectBundleService.create( params );
+        ObjectBundleValidation validate = objectBundleService.validate( bundle );
+        assertTrue( validate.getObjectErrorReportsMap().isEmpty() );
+
+        objectBundleService.commit( bundle );
+
+        List<OrganisationUnit> organisationUnits = manager.getAll( OrganisationUnit.class );
+        List<DataElement> dataElements = manager.getAll( DataElement.class );
+        List<Indicator> indicators = manager.getAll( Indicator.class );
+
+        assertFalse( organisationUnits.isEmpty() );
+        assertEquals( 3, dataElements.size() );
+        assertEquals( 1, indicators.size() );
+    }
+
+    @Test
+    public void testCreateMetadataWithValidationRules() throws IOException
+    {
+        Map<Class<? extends IdentifiableObject>, List<IdentifiableObject>> metadata = renderService.fromMetadata(
+            new ClassPathResource( "dxf2/metadata_with_vr.json" ).getInputStream(), RenderFormat.JSON );
+
+        ObjectBundleParams params = new ObjectBundleParams();
+        params.setObjectBundleMode( ObjectBundleMode.COMMIT );
+        params.setImportMode( ImportStrategy.CREATE );
+        params.setObjects( metadata );
+
+        ObjectBundle bundle = objectBundleService.create( params );
+        ObjectBundleValidation validate = objectBundleService.validate( bundle );
+        assertTrue( validate.getObjectErrorReportsMap().isEmpty() );
+
+        objectBundleService.commit( bundle );
+
+        List<DataSet> dataSets = manager.getAll( DataSet.class );
+        List<OrganisationUnit> organisationUnits = manager.getAll( OrganisationUnit.class );
+        List<DataElement> dataElements = manager.getAll( DataElement.class );
+        List<UserAuthorityGroup> userRoles = manager.getAll( UserAuthorityGroup.class );
+        List<User> users = manager.getAll( User.class );
+        List<ValidationRule> validationRules = manager.getAll( ValidationRule.class );
+
+        assertFalse( dataSets.isEmpty() );
+        assertFalse( organisationUnits.isEmpty() );
+        assertFalse( dataElements.isEmpty() );
+        assertFalse( users.isEmpty() );
+        assertFalse( userRoles.isEmpty() );
+        assertEquals( 1, validationRules.size() );
+
+        ValidationRule validationRule = validationRules.get( 0 );
+        assertNotNull( validationRule.getLeftSide() );
+        assertNotNull( validationRule.getRightSide() );
+        assertFalse( validationRule.getLeftSide().getDataElementsInExpression().isEmpty() );
+        assertFalse( validationRule.getRightSide().getDataElementsInExpression().isEmpty() );
+    }
+
     private void defaultSetup()
     {
         DataElement de1 = createDataElement( 'A' );

=== added file 'dhis-2/dhis-services/dhis-service-dxf2/src/test/resources/dxf2/metadata_with_indicators.json'
--- dhis-2/dhis-services/dhis-service-dxf2/src/test/resources/dxf2/metadata_with_indicators.json	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/test/resources/dxf2/metadata_with_indicators.json	2016-03-10 06:06:01 +0000
@@ -0,0 +1,298 @@
+{
+  "dataElements": [
+    {
+      "zeroIsSignificant": false,
+      "aggregationLevels": [ ],
+      "shortName": "DataElementShortA",
+      "categoryCombo": {
+        "id": "hhxbASI7F8C"
+      },
+      "valueType": "NUMBER",
+      "user": {
+        "id": "Fiob73BgnJm"
+      },
+      "id": "epE3XMALioY",
+      "created": "2016-03-10T04:23:22.978+0000",
+      "name": "DataElementA",
+      "attributeValues": [ ],
+      "code": "DataElementCodeA",
+      "domainType": "AGGREGATE",
+      "lastUpdated": "2016-03-10T04:23:22.981+0000",
+      "userGroupAccesses": [ ],
+      "publicAccess": "rw------",
+      "aggregationType": "SUM",
+      "description": "DataElementDescriptionA"
+    },
+    {
+      "name": "DataElementB",
+      "created": "2016-03-10T04:31:27.758+0000",
+      "id": "fJ37vbwWMYR",
+      "code": "DataElementCodeB",
+      "attributeValues": [ ],
+      "categoryCombo": {
+        "id": "hhxbASI7F8C"
+      },
+      "valueType": "NUMBER",
+      "shortName": "DataElementShortB",
+      "aggregationLevels": [ ],
+      "zeroIsSignificant": false,
+      "user": {
+        "id": "Fiob73BgnJm"
+      },
+      "aggregationType": "SUM",
+      "description": "DataElementDescriptionB",
+      "lastUpdated": "2016-03-10T04:31:27.766+0000",
+      "domainType": "AGGREGATE",
+      "publicAccess": "rw------",
+      "userGroupAccesses": [ ]
+    },
+    {
+      "publicAccess": "rw------",
+      "userGroupAccesses": [ ],
+      "lastUpdated": "2016-03-10T04:37:07.620+0000",
+      "domainType": "AGGREGATE",
+      "description": "DataElementDescriptionC",
+      "aggregationType": "SUM",
+      "user": {
+        "id": "Fiob73BgnJm"
+      },
+      "categoryCombo": {
+        "id": "hhxbASI7F8C"
+      },
+      "valueType": "NUMBER",
+      "shortName": "DataElementShortC",
+      "aggregationLevels": [ ],
+      "zeroIsSignificant": false,
+      "code": "DataElementCodeC",
+      "attributeValues": [ ],
+      "created": "2016-03-10T04:37:07.604+0000",
+      "name": "DataElementC",
+      "id": "xlkdTPUZiPy"
+    }
+  ],
+  "users": [
+    {
+      "organisationUnits": [
+        {
+          "id": "rgG3Pygddq1"
+        }
+      ],
+      "surname": "admin",
+      "lastUpdated": "2016-03-10T04:22:23.892+0000",
+      "userCredentials": {
+        "user": {
+          "id": "Fiob73BgnJm"
+        },
+        "lastLogin": "2016-03-10T04:21:43.759+0000",
+        "disabled": false,
+        "invitation": false,
+        "userRoles": [
+          {
+            "id": "AVtowuIxwPY"
+          }
+        ],
+        "catDimensionConstraints": [ ],
+        "userInfo": {
+          "id": "Fiob73BgnJm"
+        },
+        "passwordLastUpdated": "2016-03-10T04:21:43.760+0000",
+        "selfRegistered": false,
+        "created": "2016-03-10T04:21:43.854+0000",
+        "cogsDimensionConstraints": [ ],
+        "externalAuth": false,
+        "username": "admin"
+      },
+      "teiSearchOrganisationUnits": [ ],
+      "attributeValues": [ ],
+      "id": "Fiob73BgnJm",
+      "dataViewOrganisationUnits": [ ],
+      "created": "2016-03-10T04:21:43.732+0000",
+      "firstName": "admin"
+    }
+  ],
+  "date": "2016-03-10T04:57:35.441+0000",
+  "categoryOptions": [
+    {
+      "organisationUnits": [ ],
+      "publicAccess": "--------",
+      "userGroupAccesses": [ ],
+      "shortName": "default",
+      "lastUpdated": "2016-03-10T04:21:28.568+0000",
+      "attributeValues": [ ],
+      "name": "default",
+      "created": "2016-03-10T04:21:28.507+0000",
+      "id": "hrv3BmsyY0z"
+    }
+  ],
+  "categoryOptionCombos": [
+    {
+      "categoryCombo": {
+        "id": "hhxbASI7F8C"
+      },
+      "name": "default",
+      "created": "2016-03-10T04:21:28.546+0000",
+      "lastUpdated": "2016-03-10T04:21:28.546+0000",
+      "id": "OqLTH91vKYK",
+      "ignoreApproval": false,
+      "categoryOptions": [
+        {
+          "id": "hrv3BmsyY0z"
+        }
+      ]
+    }
+  ],
+  "indicatorTypes": [
+    {
+      "id": "fwlQ75eDqMU",
+      "number": true,
+      "name": "Percent",
+      "created": "2016-03-10T04:40:14.723+0000",
+      "lastUpdated": "2016-03-10T04:40:14.725+0000",
+      "factor": 100
+    }
+  ],
+  "indicators": [
+    {
+      "lastUpdated": "2016-03-10T04:41:35.392+0000",
+      "indicatorType": {
+        "id": "fwlQ75eDqMU"
+      },
+      "publicAccess": "rw------",
+      "userGroupAccesses": [ ],
+      "denominator": "#{fJ37vbwWMYR.OqLTH91vKYK}",
+      "description": "IndicatorDescriptionA",
+      "denominatorDescription": "Denominator",
+      "shortName": "IndicatorShortA",
+      "decimals": 2,
+      "user": {
+        "id": "Fiob73BgnJm"
+      },
+      "numerator": "#{epE3XMALioY.OqLTH91vKYK}",
+      "created": "2016-03-10T04:41:35.390+0000",
+      "name": "IndicatorA",
+      "id": "qMCPmTC9yF6",
+      "attributeValues": [ ],
+      "numeratorDescription": "Numerator",
+      "code": "IndicatorCodeA",
+      "annualized": false
+    }
+  ],
+  "trackedEntities": [
+    {
+      "created": "2016-03-10T04:28:25.000+0000",
+      "name": "Person",
+      "lastUpdated": "2016-03-10T04:28:25.000+0000",
+      "id": "K0wAVaOSKb7",
+      "attributeValues": [ ],
+      "description": "Person"
+    }
+  ],
+  "categoryCombos": [
+    {
+      "userGroupAccesses": [ ],
+      "dataDimensionType": "DISAGGREGATION",
+      "categories": [
+        {
+          "id": "udEngdjvWir"
+        }
+      ],
+      "publicAccess": "--------",
+      "skipTotal": false,
+      "lastUpdated": "2016-03-10T04:21:28.561+0000",
+      "id": "hhxbASI7F8C",
+      "created": "2016-03-10T04:21:28.544+0000",
+      "name": "default"
+    }
+  ],
+  "userRoles": [
+    {
+      "name": "Superuser",
+      "programs": [ ],
+      "created": "2016-03-10T04:21:43.745+0000",
+      "id": "AVtowuIxwPY",
+      "dataSets": [ ],
+      "lastUpdated": "2016-03-10T04:21:43.745+0000",
+      "authorities": [
+        "F_TRACKED_ENTITY_INSTANCE_SEARCH_IN_ALL_ORGUNITS",
+        "ALL",
+        "F_USERGROUP_MANAGING_RELATIONSHIPS_ADD",
+        "F_REPORTTABLE_PUBLIC_ADD",
+        "F_TRACKED_ENTITY_INSTANCE_DELETE",
+        "F_USER_GROUPS_READ_ONLY_ADD_MEMBERS",
+        "F_MAP_PUBLIC_ADD",
+        "F_USER_ADD_WITHIN_MANAGED_GROUP",
+        "F_TRACKED_ENTITY_INSTANCE_SEARCH",
+        "F_PROGRAM_ENROLLMENT",
+        "F_REPORTTABLE_EXTERNAL",
+        "F_SQLVIEW_EXTERNAL",
+        "F_GIS_ADMIN",
+        "F_REPLICATE_USER",
+        "F_INSERT_CUSTOM_JS_CSS",
+        "F_DASHBOARD_PUBLIC_ADD",
+        "F_METADATA_IMPORT",
+        "F_CHART_PUBLIC_ADD",
+        "F_VIEW_UNAPPROVED_DATA",
+        "F_CHART_EXTERNAL",
+        "F_USERGROUP_MANAGING_RELATIONSHIPS_VIEW",
+        "F_METADATA_EXPORT",
+        "F_PROGRAM_UNENROLLMENT",
+        "F_APPROVE_DATA",
+        "F_ACCEPT_DATA_LOWER_LEVELS",
+        "F_TRACKED_ENTITY_INSTANCE_ADD",
+        "F_USERGROUP_PUBLIC_ADD",
+        "F_OAUTH2_CLIENT_MANAGE",
+        "F_TRACKED_ENTITY_DATAVALUE_ADD",
+        "F_PROGRAM_DASHBOARD_CONFIG_ADMIN",
+        "F_MAP_EXTERNAL",
+        "F_APPROVE_DATA_LOWER_LEVELS",
+        "F_TRACKED_ENTITY_DATAVALUE_DELETE"
+      ],
+      "publicAccess": "--------",
+      "userGroupAccesses": [ ]
+    }
+  ],
+  "organisationUnitLevels": [
+    {
+      "level": 1,
+      "id": "hQCkEtl9g1C",
+      "name": "Level 1",
+      "created": "2016-03-10T04:22:05.052+0000",
+      "lastUpdated": "2016-03-10T04:22:05.053+0000"
+    }
+  ],
+  "categories": [
+    {
+      "dataDimension": true,
+      "lastUpdated": "2016-03-10T04:36:06.190+0000",
+      "dataDimensionType": "DISAGGREGATION",
+      "userGroupAccesses": [ ],
+      "publicAccess": "--------",
+      "id": "udEngdjvWir",
+      "created": "2016-03-10T04:21:28.538+0000",
+      "name": "default",
+      "categoryOptions": [
+        {
+          "id": "hrv3BmsyY0z"
+        }
+      ]
+    }
+  ],
+  "organisationUnits": [
+    {
+      "user": {
+        "id": "Fiob73BgnJm"
+      },
+      "lastUpdated": "2016-03-10T04:21:57.675+0000",
+      "shortName": "Country",
+      "openingDate": "2016-03-10",
+      "attributeValues": [ ],
+      "description": "",
+      "name": "Country",
+      "created": "2016-03-10T04:21:57.658+0000",
+      "uuid": "56b2e5c7-2fda-4bab-85bd-426716287eca",
+      "featureType": "NONE",
+      "path": "/rgG3Pygddq1",
+      "id": "rgG3Pygddq1"
+    }
+  ]
+}

=== added file 'dhis-2/dhis-services/dhis-service-dxf2/src/test/resources/dxf2/metadata_with_vr.json'
--- dhis-2/dhis-services/dhis-service-dxf2/src/test/resources/dxf2/metadata_with_vr.json	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/test/resources/dxf2/metadata_with_vr.json	2016-03-10 06:06:01 +0000
@@ -0,0 +1,344 @@
+{
+  "categoryOptions": [
+    {
+      "userGroupAccesses": [ ],
+      "publicAccess": "--------",
+      "name": "default",
+      "lastUpdated": "2016-03-10T04:59:27.887+0000",
+      "attributeValues": [ ],
+      "created": "2016-03-10T04:59:27.872+0000",
+      "id": "SCLqnaPwVHY",
+      "shortName": "default",
+      "organisationUnits": [ ]
+    }
+  ],
+  "dataElements": [
+    {
+      "valueType": "NUMBER",
+      "code": "DataElementCodeA",
+      "aggregationType": "SUM",
+      "user": {
+        "id": "ZK1wkC59FCw"
+      },
+      "aggregationLevels": [ ],
+      "shortName": "DataElementShortA",
+      "attributeValues": [ ],
+      "description": "DataElementDescriptionA",
+      "zeroIsSignificant": false,
+      "created": "2016-03-10T05:02:18.868+0000",
+      "id": "jocQSivF2ry",
+      "categoryCombo": {
+        "id": "SI0XITt9Oh4"
+      },
+      "domainType": "AGGREGATE",
+      "lastUpdated": "2016-03-10T05:02:18.871+0000",
+      "name": "DataElementA",
+      "userGroupAccesses": [ ],
+      "publicAccess": "rw------"
+    },
+    {
+      "aggregationType": "SUM",
+      "valueType": "NUMBER",
+      "code": "DataElementCodeB",
+      "user": {
+        "id": "ZK1wkC59FCw"
+      },
+      "aggregationLevels": [ ],
+      "categoryCombo": {
+        "id": "SI0XITt9Oh4"
+      },
+      "domainType": "AGGREGATE",
+      "shortName": "DataElementShortB",
+      "attributeValues": [ ],
+      "description": "DataElementDescriptionB",
+      "zeroIsSignificant": false,
+      "id": "X0ypiOyoDbw",
+      "created": "2016-03-10T05:02:47.023+0000",
+      "lastUpdated": "2016-03-10T05:02:47.024+0000",
+      "publicAccess": "rw------",
+      "userGroupAccesses": [ ],
+      "name": "DataElementB"
+    },
+    {
+      "user": {
+        "id": "ZK1wkC59FCw"
+      },
+      "aggregationLevels": [ ],
+      "aggregationType": "SUM",
+      "code": "DataElementCodeC",
+      "valueType": "NUMBER",
+      "userGroupAccesses": [ ],
+      "name": "DataElementC",
+      "publicAccess": "rw------",
+      "lastUpdated": "2016-03-10T05:04:44.334+0000",
+      "domainType": "AGGREGATE",
+      "categoryCombo": {
+        "id": "SI0XITt9Oh4"
+      },
+      "attributeValues": [ ],
+      "description": "DataElementDescriptionC",
+      "zeroIsSignificant": false,
+      "id": "vAczVs4mxna",
+      "created": "2016-03-10T05:04:44.329+0000",
+      "shortName": "DataElementShortC"
+    }
+  ],
+  "categoryOptionCombos": [
+    {
+      "lastUpdated": "2016-03-10T04:59:27.884+0000",
+      "categoryCombo": {
+        "id": "SI0XITt9Oh4"
+      },
+      "name": "default",
+      "ignoreApproval": false,
+      "categoryOptions": [
+        {
+          "id": "SCLqnaPwVHY"
+        }
+      ],
+      "id": "NQigT2ThzgD",
+      "created": "2016-03-10T04:59:27.884+0000"
+    }
+  ],
+  "trackedEntities": [
+    {
+      "name": "Person",
+      "id": "uh6tOHZTlG0",
+      "attributeValues": [ ],
+      "description": "Person"
+    }
+  ],
+  "organisationUnits": [
+    {
+      "user": {
+        "id": "ZK1wkC59FCw"
+      },
+      "uuid": "b8b03f02-6a01-4786-9343-937692400cec",
+      "path": "/SR705r4KVRu",
+      "lastUpdated": "2016-03-10T05:01:10.717+0000",
+      "name": "Country",
+      "featureType": "NONE",
+      "shortName": "Country",
+      "description": "",
+      "attributeValues": [ ],
+      "created": "2016-03-10T05:01:10.702+0000",
+      "openingDate": "2016-03-10",
+      "id": "SR705r4KVRu"
+    }
+  ],
+  "users": [
+    {
+      "teiSearchOrganisationUnits": [ ],
+      "dataViewOrganisationUnits": [ ],
+      "lastUpdated": "2016-03-10T05:01:28.993+0000",
+      "userCredentials": {
+        "username": "admin",
+        "disabled": false,
+        "passwordLastUpdated": "2016-03-10T05:00:11.791+0000",
+        "created": "2016-03-10T05:00:11.882+0000",
+        "selfRegistered": false,
+        "invitation": false,
+        "catDimensionConstraints": [ ],
+        "cogsDimensionConstraints": [ ],
+        "externalAuth": false,
+        "user": {
+          "id": "ZK1wkC59FCw"
+        },
+        "userRoles": [
+          {
+            "id": "VIkpd2KHCb1"
+          }
+        ],
+        "lastLogin": "2016-03-10T05:00:11.791+0000",
+        "userInfo": {
+          "id": "ZK1wkC59FCw"
+        }
+      },
+      "surname": "admin",
+      "attributeValues": [ ],
+      "created": "2016-03-10T05:00:11.766+0000",
+      "id": "ZK1wkC59FCw",
+      "firstName": "admin",
+      "organisationUnits": [
+        {
+          "id": "SR705r4KVRu"
+        }
+      ]
+    }
+  ],
+  "organisationUnitLevels": [
+    {
+      "lastUpdated": "2016-03-10T05:01:14.582+0000",
+      "name": "Level 1",
+      "level": 1,
+      "created": "2016-03-10T05:01:14.581+0000",
+      "id": "fMEk5rewunw"
+    }
+  ],
+  "categories": [
+    {
+      "dataDimension": true,
+      "created": "2016-03-10T04:59:27.881+0000",
+      "id": "f66ygHaFS1v",
+      "dataDimensionType": "DISAGGREGATION",
+      "categoryOptions": [
+        {
+          "id": "SCLqnaPwVHY"
+        }
+      ],
+      "publicAccess": "--------",
+      "name": "default",
+      "userGroupAccesses": [ ],
+      "lastUpdated": "2016-03-10T04:59:28.064+0000"
+    }
+  ],
+  "categoryCombos": [
+    {
+      "lastUpdated": "2016-03-10T04:59:27.886+0000",
+      "name": "default",
+      "userGroupAccesses": [ ],
+      "publicAccess": "--------",
+      "dataDimensionType": "DISAGGREGATION",
+      "id": "SI0XITt9Oh4",
+      "created": "2016-03-10T04:59:27.883+0000",
+      "categories": [
+        {
+          "id": "f66ygHaFS1v"
+        }
+      ],
+      "skipTotal": false
+    }
+  ],
+  "userRoles": [
+    {
+      "dataSets": [ ],
+      "name": "Superuser",
+      "userGroupAccesses": [ ],
+      "publicAccess": "--------",
+      "authorities": [
+        "F_TRACKED_ENTITY_INSTANCE_SEARCH_IN_ALL_ORGUNITS",
+        "ALL",
+        "F_USERGROUP_MANAGING_RELATIONSHIPS_ADD",
+        "F_REPORTTABLE_PUBLIC_ADD",
+        "F_TRACKED_ENTITY_INSTANCE_DELETE",
+        "F_USER_GROUPS_READ_ONLY_ADD_MEMBERS",
+        "F_MAP_PUBLIC_ADD",
+        "F_USER_ADD_WITHIN_MANAGED_GROUP",
+        "F_TRACKED_ENTITY_INSTANCE_SEARCH",
+        "F_PROGRAM_ENROLLMENT",
+        "F_REPORTTABLE_EXTERNAL",
+        "F_SQLVIEW_EXTERNAL",
+        "F_GIS_ADMIN",
+        "F_REPLICATE_USER",
+        "F_INSERT_CUSTOM_JS_CSS",
+        "F_DASHBOARD_PUBLIC_ADD",
+        "F_METADATA_IMPORT",
+        "F_CHART_PUBLIC_ADD",
+        "F_VIEW_UNAPPROVED_DATA",
+        "F_CHART_EXTERNAL",
+        "F_USERGROUP_MANAGING_RELATIONSHIPS_VIEW",
+        "F_METADATA_EXPORT",
+        "F_PROGRAM_UNENROLLMENT",
+        "F_APPROVE_DATA",
+        "F_ACCEPT_DATA_LOWER_LEVELS",
+        "F_TRACKED_ENTITY_INSTANCE_ADD",
+        "F_USERGROUP_PUBLIC_ADD",
+        "F_OAUTH2_CLIENT_MANAGE",
+        "F_TRACKED_ENTITY_DATAVALUE_ADD",
+        "F_PROGRAM_DASHBOARD_CONFIG_ADMIN",
+        "F_MAP_EXTERNAL",
+        "F_APPROVE_DATA_LOWER_LEVELS",
+        "F_TRACKED_ENTITY_DATAVALUE_DELETE"
+      ],
+      "programs": [ ],
+      "lastUpdated": "2016-03-10T05:00:11.778+0000",
+      "id": "VIkpd2KHCb1",
+      "created": "2016-03-10T05:00:11.778+0000"
+    }
+  ],
+  "date": "2016-03-10T05:11:08.778+0000",
+  "dataSets": [
+    {
+      "version": 1,
+      "user": {
+        "id": "ZK1wkC59FCw"
+      },
+      "noValueRequiresComment": false,
+      "openFuturePeriods": 0,
+      "dataElementDecoration": false,
+      "validCompleteOnly": false,
+      "code": "DataSetCodeA",
+      "renderHorizontally": false,
+      "timelyDays": 15,
+      "mobile": false,
+      "indicators": [ ],
+      "compulsoryDataElementOperands": [ ],
+      "name": "DataSetA",
+      "userGroupAccesses": [ ],
+      "publicAccess": "rw------",
+      "notifyCompletingUser": false,
+      "lastUpdated": "2016-03-10T05:05:15.994+0000",
+      "skipOffline": false,
+      "renderAsTabs": false,
+      "created": "2016-03-10T05:05:10.398+0000",
+      "periodType": "Monthly",
+      "id": "NGblLqp6Cyu",
+      "attributeValues": [ ],
+      "expiryDays": 0,
+      "shortName": "DataSetShortA",
+      "dataElements": [
+        {
+          "id": "jocQSivF2ry"
+        },
+        {
+          "id": "X0ypiOyoDbw"
+        },
+        {
+          "id": "vAczVs4mxna"
+        }
+      ],
+      "fieldCombinationRequired": false,
+      "organisationUnits": [
+        {
+          "id": "SR705r4KVRu"
+        }
+      ],
+      "categoryCombo": {
+        "id": "SI0XITt9Oh4"
+      }
+    }
+  ],
+  "validationRules": [
+    {
+      "leftSide": {
+        "description": "Left Side",
+        "expression": "#{jocQSivF2ry.NQigT2ThzgD}",
+        "dataElements": [
+          {
+            "id": "jocQSivF2ry"
+          }
+        ],
+        "missingValueStrategy": "SKIP_IF_ANY_VALUE_MISSING"
+      },
+      "importance": "MEDIUM",
+      "rightSide": {
+        "description": "Right Side",
+        "expression": "#{X0ypiOyoDbw.NQigT2ThzgD}",
+        "dataElements": [
+          {
+            "id": "X0ypiOyoDbw"
+          }
+        ],
+        "missingValueStrategy": "SKIP_IF_ANY_VALUE_MISSING"
+      },
+      "name": "ValidationRuleA",
+      "lastUpdated": "2016-03-10T05:09:40.689+0000",
+      "periodType": "Monthly",
+      "id": "ztzsVjSIWg7",
+      "created": "2016-03-10T05:09:40.688+0000",
+      "description": "ValidationRuleA",
+      "operator": "equal_to",
+      "ruleType": "VALIDATION"
+    }
+  ]
+}