← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 18637: Improvements to data integrity in data admin app. Removed velocity dependence for rendering data ...

 

Merge authors:
  Halvdan Hoem Grelland (halvdanhg)
------------------------------------------------------------
revno: 18637 [merge]
committer: Halvdan Hoem Grelland <halvdanhg@xxxxxxxxx>
branch nick: dhis2
timestamp: Thu 2015-03-19 15:49:49 +0100
message:
  Improvements to data integrity in data admin app. Removed velocity dependence for rendering data integrity reports. Reports are now fetched from the system/taskSummaries/dataintegrity endpoint.
removed:
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/responseDataIntegrity.vm
added:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataintegrity/FlattenedDataIntegrityReport.java
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataintegrity/DataIntegrityReport.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/DataIntegrityController.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/SystemController.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/resources/struts.xml
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/index.vm
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/javascript/dataIntegrity.js
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/menu.vm


--
lp:dhis2
https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk

Your team DHIS 2 developers is subscribed to branch lp:dhis2.
To unsubscribe from this branch go to https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk/+edit-subscription
=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataintegrity/DataIntegrityReport.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataintegrity/DataIntegrityReport.java	2015-03-04 16:26:10 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataintegrity/DataIntegrityReport.java	2015-03-13 14:06:36 +0000
@@ -52,47 +52,47 @@
 public class DataIntegrityReport
 {
     private List<DataElement> dataElementsWithoutDataSet;
-
+    
     private List<DataElement> dataElementsWithoutGroups;
-
+    
     private Map<DataElement, Collection<DataSet>> dataElementsAssignedToDataSetsWithDifferentPeriodTypes;
-
+    
     private SortedMap<DataElement, Collection<DataElementGroup>> dataElementsViolatingExclusiveGroupSets;
 
     private SortedMap<DataSet, Collection<DataElement>> dataElementsInDataSetNotInForm;
 
     private Map<DataSet, Set<DataElementOperand>> categoryOptionCombosNotInDataElementCategoryCombo;
-
+    
     private List<DataSet> dataSetsNotAssignedToOrganisationUnits;
-
+    
     private List<Section> sectionsWithInvalidCategoryCombinations;
 
     private Collection<Collection<Indicator>> indicatorsWithIdenticalFormulas;
-
+    
     private List<Indicator> indicatorsWithoutGroups;
-
+    
     private Map<Indicator, String> invalidIndicatorNumerators;
-
+    
     private Map<Indicator, String> invalidIndicatorDenominators;
-
+    
     private SortedMap<Indicator, Collection<IndicatorGroup>> indicatorsViolatingExclusiveGroupSets;
-
+    
     private List<Period> duplicatePeriods;
-
+    
     private List<OrganisationUnit> organisationUnitsWithCyclicReferences;
-
+    
     private List<OrganisationUnit> orphanedOrganisationUnits;
-
+    
     private List<OrganisationUnit> organisationUnitsWithoutGroups;
-
+    
     private SortedMap<OrganisationUnit, Collection<OrganisationUnitGroup>> organisationUnitsViolatingExclusiveGroupSets;
-
+    
     private List<OrganisationUnitGroup> organisationUnitGroupsWithoutGroupSets;
-
+    
     private List<ValidationRule> validationRulesWithoutGroups;
-
+    
     private Map<ValidationRule, String> invalidValidationRuleLeftSideExpressions;
-
+    
     private Map<ValidationRule, String> invalidValidationRuleRightSideExpressions;
 
     //-------------------------------------------------------------------------

=== added file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataintegrity/FlattenedDataIntegrityReport.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataintegrity/FlattenedDataIntegrityReport.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataintegrity/FlattenedDataIntegrityReport.java	2015-03-19 14:32:07 +0000
@@ -0,0 +1,246 @@
+package org.hisp.dhis.dataintegrity;
+
+/*
+ * Copyright (c) 2004-2015, 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 com.fasterxml.jackson.annotation.JsonProperty;
+import org.hisp.dhis.common.IdentifiableObject;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+/**
+ * Flattened, easily serializable object derivable from the more complex DataIntegrityReport.
+ * Use an instance of this object to serialize and deliver a DataIntegrityReport.
+ *
+ * @author Halvdan Hoem Grelland <halvdanhg@xxxxxxxxx>
+ */
+public class FlattenedDataIntegrityReport
+{
+    @JsonProperty
+    private List<String> dataElementsWithoutDataSet;
+
+    @JsonProperty
+    private List<String> dataElementsWithoutGroups;
+
+    @JsonProperty
+    private Map<String, Collection<String>> dataElementsAssignedToDataSetsWithDifferentPeriodTypes;
+
+    @JsonProperty
+    private SortedMap<String, Collection<String>> dataElementsViolatingExclusiveGroupSets;
+
+    @JsonProperty
+    private SortedMap<String, Collection<String>> dataElementsInDataSetNotInForm;
+
+    @JsonProperty
+    private Map<String, Set<String>> categoryOptionCombosNotInDataElementCategoryCombo;
+
+    @JsonProperty
+    private List<String> dataSetsNotAssignedToOrganisationUnits;
+
+    @JsonProperty
+    private List<String> sectionsWithInvalidCategoryCombinations;
+
+    @JsonProperty
+    private Collection<Collection<String>> indicatorsWithIdenticalFormulas;
+
+    @JsonProperty
+    private List<String> indicatorsWithoutGroups;
+
+    @JsonProperty
+    private Map<String, String> invalidIndicatorNumerators;
+
+    @JsonProperty
+    private Map<String, String> invalidIndicatorDenominators;
+
+    @JsonProperty
+    private SortedMap<String, Collection<String>> indicatorsViolatingExclusiveGroupSets;
+
+    @JsonProperty
+    private List<String> duplicatePeriods;
+
+    @JsonProperty
+    private List<String> organisationUnitsWithCyclicReferences;
+
+    @JsonProperty
+    private List<String> orphanedOrganisationUnits;
+
+    @JsonProperty
+    private List<String> organisationUnitsWithoutGroups;
+
+    @JsonProperty
+    private SortedMap<String, Collection<String>> organisationUnitsViolatingExclusiveGroupSets;
+
+    @JsonProperty
+    private List<String> organisationUnitGroupsWithoutGroupSets;
+
+    @JsonProperty
+    private List<String> validationRulesWithoutGroups;
+
+    @JsonProperty
+    private Map<String, String> invalidValidationRuleLeftSideExpressions;
+
+    @JsonProperty
+    private Map<String, String> invalidValidationRuleRightSideExpressions;
+
+    public FlattenedDataIntegrityReport( org.hisp.dhis.dataintegrity.DataIntegrityReport report )
+    {
+        dataElementsWithoutDataSet = transformCollection( report.getDataElementsWithoutDataSet() );
+
+        dataElementsWithoutGroups = transformCollection( report.getDataElementsWithoutGroups() );
+
+        dataElementsAssignedToDataSetsWithDifferentPeriodTypes = transformMapOfCollections( report.getDataElementsAssignedToDataSetsWithDifferentPeriodTypes() );
+
+        dataElementsViolatingExclusiveGroupSets = transformSortedMap( report.getDataElementsViolatingExclusiveGroupSets() );
+
+        dataElementsInDataSetNotInForm = transformSortedMap( report.getDataElementsInDataSetNotInForm() );
+
+        categoryOptionCombosNotInDataElementCategoryCombo = transformMapOfSets( report.getCategoryOptionCombosNotInDataElementCategoryCombo() );
+
+        dataSetsNotAssignedToOrganisationUnits = transformCollection( report.getDataSetsNotAssignedToOrganisationUnits() );
+
+        sectionsWithInvalidCategoryCombinations = transformCollection( report.getSectionsWithInvalidCategoryCombinations() );
+
+        indicatorsWithIdenticalFormulas = transformCollectionOfCollections( report.getIndicatorsWithIdenticalFormulas() );
+
+        indicatorsWithoutGroups = transformCollection( report.getIndicatorsWithoutGroups() );
+
+        invalidIndicatorNumerators = transformMapOfStrings( report.getInvalidIndicatorNumerators() );
+
+        invalidIndicatorDenominators = transformMapOfStrings( report.getInvalidIndicatorDenominators() );
+
+        indicatorsViolatingExclusiveGroupSets = transformSortedMap( report.getIndicatorsViolatingExclusiveGroupSets() );
+
+        duplicatePeriods = transformCollection( report.getDuplicatePeriods() );
+
+        organisationUnitsWithCyclicReferences = transformCollection( report.getOrganisationUnitsWithCyclicReferences() );
+
+        orphanedOrganisationUnits = transformCollection( report.getOrphanedOrganisationUnits() );
+
+        organisationUnitsWithoutGroups = transformCollection( report.getOrganisationUnitsWithoutGroups() );
+
+        organisationUnitsViolatingExclusiveGroupSets = transformSortedMap( report.getOrganisationUnitsViolatingExclusiveGroupSets() );
+
+        organisationUnitGroupsWithoutGroupSets = transformCollection( report.getOrganisationUnitGroupsWithoutGroupSets() );
+
+        validationRulesWithoutGroups = transformCollection( report.getValidationRulesWithoutGroups() );
+
+        invalidValidationRuleLeftSideExpressions = transformMapOfStrings( report.getInvalidValidationRuleLeftSideExpressions() );
+
+        invalidValidationRuleRightSideExpressions = transformMapOfStrings( report.getInvalidValidationRuleRightSideExpressions() );
+    }
+
+    // -------------------------------------------------------------------------
+    // Supportive methods
+    // -------------------------------------------------------------------------
+
+    private Collection<Collection<String>> transformCollectionOfCollections( Collection<? extends Collection<? extends IdentifiableObject>> collection )
+    {
+        Collection<Collection<String>> newCollection = new HashSet<>();
+
+        for ( Collection<? extends IdentifiableObject> c : collection )
+        {
+            newCollection.add( transformCollection( c ) );
+        }
+
+        return newCollection;
+    }
+
+    private Map<String, Set<String>> transformMapOfSets( Map<? extends IdentifiableObject, ? extends Set<? extends IdentifiableObject>> map )
+    {
+        HashMap<String, Set<String>> newMap = new HashMap<>();
+
+        for ( Map.Entry<? extends IdentifiableObject, ? extends Set<? extends IdentifiableObject>> entry : map.entrySet() )
+        {
+            Set<String> value = new HashSet<>();
+            value.addAll( transformCollection( entry.getValue() ));
+
+            newMap.put( entry.getKey().getDisplayName(), value );
+        }
+
+        return newMap;
+    }
+
+    private Map<String, String> transformMapOfStrings( Map<? extends IdentifiableObject, String> map )
+    {
+        HashMap<String, String> newMap = new HashMap<>( map.size() );
+
+        for ( Map.Entry<? extends IdentifiableObject, String> entry : map.entrySet() )
+        {
+            newMap.put( entry.getKey().getDisplayName(), entry.getValue() );
+        }
+
+        return newMap;
+    }
+
+    private Map<String, Collection<String>> transformMapOfCollections( Map<? extends IdentifiableObject, ? extends Collection<? extends IdentifiableObject>> map )
+    {
+        HashMap<String, Collection<String>> newMap = new HashMap<>();
+
+        for ( Map.Entry<? extends IdentifiableObject, ? extends Collection<? extends IdentifiableObject>> entry : map.entrySet() )
+        {
+            Collection<String> value = new HashSet<>();
+            value.addAll( transformCollection( entry.getValue() ) );
+
+            newMap.put( entry.getKey().getDisplayName(), value );
+        }
+
+        return newMap;
+    }
+
+    private List<String> transformCollection( Collection<? extends IdentifiableObject> collection )
+    {
+        List<String> newCollection = new ArrayList<>( collection.size() );
+
+        for ( IdentifiableObject o : collection )
+        {
+            newCollection.add( o.getDisplayName() );
+        }
+
+        return newCollection;
+    }
+
+    private SortedMap<String, Collection<String>> transformSortedMap( SortedMap<? extends IdentifiableObject, ? extends Collection<? extends IdentifiableObject>> map )
+    {
+        SortedMap<String, Collection<String>> newMap = new TreeMap<>();
+
+        for ( SortedMap.Entry<? extends IdentifiableObject, ? extends Collection<? extends IdentifiableObject>> entry : map.entrySet() )
+        {
+            newMap.put( entry.getKey().getDisplayName(), transformCollection( entry.getValue() ) );
+        }
+
+        return newMap;
+    }
+}

=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/DataIntegrityController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/DataIntegrityController.java	2015-03-05 13:40:39 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/DataIntegrityController.java	2015-03-13 18:32:20 +0000
@@ -37,6 +37,7 @@
 import org.hisp.dhis.user.CurrentUserService;
 import org.hisp.dhis.webapi.utils.ContextUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
@@ -66,9 +67,10 @@
     public static final String RESOURCE_PATH = "/dataIntegrity";
 
     //--------------------------------------------------------------------------
-    // Asynchronous data integrity task
+    // Start asynchronous data integrity task
     //--------------------------------------------------------------------------
 
+    @PreAuthorize( "hasRole('ALL') or hasRole('F_PERFORM_MAINTENANCE')" )
     @RequestMapping( value = DataIntegrityController.RESOURCE_PATH, method = RequestMethod.POST )
     public void runAsyncDataIntegrity( HttpServletResponse response, HttpServletRequest request )
     {

=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/SystemController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/SystemController.java	2015-03-05 13:40:39 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/SystemController.java	2015-03-19 13:04:23 +0000
@@ -29,6 +29,8 @@
  */
 
 import org.hisp.dhis.common.CodeGenerator;
+import org.hisp.dhis.dataintegrity.DataIntegrityReport;
+import org.hisp.dhis.dataintegrity.FlattenedDataIntegrityReport;
 import org.hisp.dhis.dxf2.metadata.ImportSummary;
 import org.hisp.dhis.dxf2.common.JacksonUtils;
 import org.hisp.dhis.node.exception.InvalidTypeException;
@@ -123,8 +125,6 @@
     @RequestMapping( value = "/taskSummaries/{category}", method = RequestMethod.GET, produces = { "*/*", "application/json" } )
     public void getTaskSummaryJson( HttpServletResponse response, @PathVariable( "category" ) String category ) throws IOException
     {
-        ImportSummary importSummary = new ImportSummary();
-
         if ( category != null )
         {
             TaskCategory taskCategory = TaskCategory.valueOf( category.toUpperCase() );
@@ -132,14 +132,22 @@
             TaskId taskId = new TaskId( taskCategory, currentUserService.getCurrentUser() );
 
             // TODO Support DataIntegrityReport (make task summary generic).
-            if ( !taskCategory.equals( TaskCategory.DATAINTEGRITY ) )
-            {
-                importSummary = (ImportSummary) notifier.getTaskSummary( taskId );
-                notifier.clear( taskId );
+            // TODO Also avoid null pointer on fetching unfinished task
+            if ( taskCategory.equals( TaskCategory.DATAINTEGRITY ) )
+            {
+                DataIntegrityReport dataIntegrityReport = (DataIntegrityReport) notifier.getTaskSummary( taskId );
+                JacksonUtils.toJson( response.getOutputStream(), new FlattenedDataIntegrityReport( dataIntegrityReport ) );
+                return;
+            }
+            else
+            {
+                ImportSummary importSummary = (ImportSummary) notifier.getTaskSummary( taskId );
+                JacksonUtils.toJson( response.getOutputStream(), importSummary );
+                return;
             }
         }
 
-        JacksonUtils.toJson( response.getOutputStream(), importSummary );
+        JacksonUtils.toJson( response.getOutputStream(), new ImportSummary() );
     }
 
     @RequestMapping( value = "/info", method = RequestMethod.GET, produces = { "application/json", "application/javascript" } )

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/resources/struts.xml'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/resources/struts.xml	2015-03-04 16:26:10 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/resources/struts.xml	2015-03-13 18:32:20 +0000
@@ -118,7 +118,7 @@
 
     <!-- Data integrity -->
 
-    <action name="displayDataIntegrityForm" class="org.hisp.dhis.dataadmin.action.NoAction">
+    <action name="dataIntegrity" class="org.hisp.dhis.dataadmin.action.NoAction">
       <result name="success" type="velocity">/main.vm</result>
       <param name="menu">/dhis-web-maintenance-dataadmin/menu.vm</param>
       <param name="page">/dhis-web-maintenance-dataadmin/dataIntegrity.vm</param>
@@ -126,13 +126,6 @@
       <param name="requiredAuthorities">F_PERFORM_MAINTENANCE</param>
     </action>
 
-    <action name="getDataIntegrityReport" class="org.hisp.dhis.dataadmin.action.dataintegrity.GetDataIntegrityReportAction">
-      <result name="success" type="velocity-json">/dhis-web-maintenance-dataadmin/responseDataIntegrity.vm</result>
-      <param name="category">DATAINTEGRITY</param>
-      <param name="onExceptionReturn">plainTextError</param>
-      <param name="requiredAuthorities">F_PERFORM_MAINTENANCE</param>
-    </action>
-
     <!-- Statistics -->
 
     <action name="viewStatistics" class="org.hisp.dhis.dataadmin.action.NoAction">

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/index.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/index.vm	2014-08-28 08:47:36 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/index.vm	2015-03-13 18:42:40 +0000
@@ -2,7 +2,7 @@
 
 <ul class="introList">
     #introListImgItem( "displayDataBrowserForm.action" "data_browser" "databrowser" )
-    #introListImgItem( "displayDataIntegrityForm.action" "data_integrity" "dataintegrity" )
+    #introListImgItem( "dataIntegrity.action" "data_integrity" "dataintegrity" )
     #introListImgItem( "displayMaintenanceForm.action" "maintenance" "maintenance" )
     #introListImgItem( "displayResourceTableForm.action" "resource_table" "resourcetable" )
     #introListImgItem( "locale.action" "locale" "datadictionary" )
@@ -11,10 +11,10 @@
     #introListImgItem( "displayDuplicateDataEliminationForm.action" "duplicate_data_elimination" "duplicatedataelimination" )
     #introListImgItem( "viewStatistics.action" "data_statistics" "datastatistics" )
     #introListImgItem( "lockException.action" "lock_exception" "datalocking" )
-	#introListImgItem( "getMinMaxValidationParams.action" "min_max_value_generation" "minmaxvaluegeneration" )
+    #introListImgItem( "getMinMaxValidationParams.action" "min_max_value_generation" "minmaxvaluegeneration" )
     #introListImgItem( "constant.action" "constant" "constant" )
-	#introListImgItem( "optionSet.action" "option_set" "resource" )
+    #introListImgItem( "optionSet.action" "option_set" "resource" )
     #introListImgItem( "showCache.action" "cache_statistics" "cachestatistics" )
-	#introListImgItem( "attribute.action" "attribute" "attribute" )
-	#introListImgItem( "viewScheduledTasks.action" "scheduling" "scheduling" )
+    #introListImgItem( "attribute.action" "attribute" "attribute" )
+    #introListImgItem( "viewScheduledTasks.action" "scheduling" "scheduling" )
 </ul>

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/javascript/dataIntegrity.js'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/javascript/dataIntegrity.js	2015-03-05 13:08:37 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/javascript/dataIntegrity.js	2015-03-19 14:32:07 +0000
@@ -16,7 +16,7 @@
 
 function pollDataIntegrityCheckFinished() {
     pingNotifications( 'DATAINTEGRITY', 'notificationsTable', function() {
-        $.getJSON( "getDataIntegrityReport.action", {}, function( json ) {
+        $.getJSON( "../../api/system/taskSummaries/dataintegrity", {}, function( json ) {
             hideLoader();
             $( "#di-title" ).hide();
             $( "#di-completed" ).show();
@@ -28,56 +28,105 @@
 }
 
 function populateIntegrityItems( json ) {
-    displayViolationList( json.dataElementsWithoutDataSet, "dataElementsWithoutDataSet", false );
-    displayViolationList( json.dataElementsWithoutGroups, "dataElementsWithoutGroups", false );
-    displayViolationList( json.dataElementsViolatingExclusiveGroupSets, "dataElementsViolatingExclusiveGroupSets", true );
-    displayViolationList( json.dataElementsInDataSetNotInForm, "dataElementsInDataSetNotInForm", true );
-    displayViolationList( json.dataElementsAssignedToDataSetsWithDifferentPeriodTypes, "dataElementsAssignedToDataSetsWithDifferentPeriodTypes", true );
-    displayViolationList( json.categoryOptionCombosNotInDataElementCategoryCombo, "categoryOptionCombosNotInDataElementCategoryCombo", true );
-    displayViolationList( json.dataSetsNotAssignedToOrganisationUnits, "dataSetsNotAssignedToOrganisationUnits", false );
-    displayViolationList( json.sectionsWithInvalidCategoryCombinations, "sectionsWithInvalidCategoryCombinations", false );
-    displayViolationList( json.indicatorsWithIdenticalFormulas, "indicatorsWithIdenticalFormulas", false );
-    displayViolationList( json.indicatorsWithoutGroups, "indicatorsWithoutGroups", false );
-    displayViolationList( json.invalidIndicatorNumerators, "invalidIndicatorNumerators", true );
-    displayViolationList( json.invalidIndicatorDenominators, "invalidIndicatorDenominators", true );
-    displayViolationList( json.indicatorsViolatingExclusiveGroupSets, "indicatorsViolatingExclusiveGroupSets", true );
-    displayViolationList( json.organisationUnitsWithCyclicReferences, "organisationUnitsWithCyclicReferences", false );
-    displayViolationList( json.orphanedOrganisationUnits, "orphanedOrganisationUnits", false );
-    displayViolationList( json.organisationUnitsWithoutGroups, "organisationUnitsWithoutGroups", false );
-    displayViolationList( json.organisationUnitsViolatingExclusiveGroupSets, "organisationUnitsViolatingExclusiveGroupSets", true );
-    displayViolationList( json.organisationUnitGroupsWithoutGroupSets, "organisationUnitGroupsWithoutGroupSets", false );
-    displayViolationList( json.duplicatePeriods, "duplicatePeriods", false );
-    displayViolationList( json.validationRulesWithoutGroups, "validationRulesWithoutGroups", false );
-    displayViolationList( json.invalidValidationRuleLeftSideExpressions, "invalidValidationRuleLeftSideExpressions", true );
-    displayViolationList( json.invalidValidationRuleRightSideExpressions, "invalidValidationRuleRightSideExpressions", true );
-}
-
-function displayViolationList( list, id, lineBreak ) {
-    var $button = $( "#" + id + "Button" );
-    var $container = $( "#" + id + "Div" );
-
-    if ( list.length > 0 ) {
-        // Display image "drop-down" button
-        $button
-           .attr( { src: "../images/down.png", title: "View violations" } )
-           .css( { cursor: "pointer" } )
-           .click( function() { $container.slideToggle( "fast" ); } );
-
-        // Populate violation div
-        var violations = "";
-        
-        for ( var i = 0; i < list.length; i++ ) {
-            violations += list[i] + "<br>";
-            violations += !!lineBreak ? "<br>" : "";
-        }
-        
-        $container.html( violations );
-    }
-    else
-    {
-        // Display image "check" button
-        $button.attr({ src: "../images/check.png", title: "No violations" });
-    }
-        
-    $container.hide();
+
+    // Render functions
+
+    var asMap = function( obj, lineBreak ) {
+        var violationsText = "";
+
+        for ( var o in obj ) {
+            if ( obj.hasOwnProperty( o ) ) {
+                violationsText += o + ": " + obj[o];
+                violationsText += "<br>" + ( !!lineBreak ? "<br>" : "" );
+            }
+        }
+
+        return violationsText;
+    };
+
+    var asListList = function( obj, lineBreak ) {
+        var violationsText = "";
+
+        obj.forEach( function( o ) {
+            o.forEach( function( s ) {
+                violationsText += s + ", ";
+            } );
+            violationsText += "<br>" + ( !!lineBreak ? "<br>" : "" );
+        } );
+
+        return violationsText;
+    };
+
+    var asMapList = function( obj, lineBreak ) {
+        var violationsText = "";
+
+        for ( var o in obj ) {
+            if( obj.hasOwnProperty( o ) ) {
+                violationsText += o + ": ";
+                obj[o].forEach( function( s ) {
+                    violationsText += s + ", ";
+                } );
+                violationsText += "<br>" + ( !!lineBreak ? "<br>" : "" );
+            }
+        }
+
+        return violationsText;
+    };
+
+    var asList = function( list, lineBreak ) {
+        var violationsText = "";
+
+        list.forEach( function( violation ) {
+            violationsText += violation + "<br>" + ( !!lineBreak ? "<br>" : "" );
+        } );
+
+        return violationsText;
+    };
+
+    // Displays an item using the selected renderer function
+
+    var displayViolation = function( obj, id, lineBreak, renderFunc ) {
+
+        var $button = $( "#" + id + "Button" );
+        var $container = $( "#" + id + "Div" );
+
+        if ( typeof obj !== "undefined" ) {
+            $button
+                .attr( { src: "../images/down.png", title: "View violations" } )
+                .css( { cursor: "pointer" } )
+                .click( function() { $container.slideToggle( "fast" ); } );
+
+            $container.html( renderFunc( obj, lineBreak ) );
+
+        } else {
+            $button.attr({ src: "../images/check.png", title: "No violations" } );
+        }
+
+        $container.hide();
+    };
+
+    // Display each reported item
+
+    displayViolation( json.dataElementsWithoutDataSet, "dataElementsWithoutDataSet", false, asList );
+    displayViolation( json.dataElementsWithoutGroups, "dataElementsWithoutGroups", false, asList );
+    displayViolation( json.dataElementsViolatingExclusiveGroupSets, "dataElementsViolatingExclusiveGroupSets", true, asMapList );
+    displayViolation( json.dataElementsInDataSetNotInForm, "dataElementsInDataSetNotInForm", true, asMapList );
+    displayViolation( json.dataElementsAssignedToDataSetsWithDifferentPeriodTypes, "dataElementsAssignedToDataSetsWithDifferentPeriodTypes", true, asMapList );
+    displayViolation( json.categoryOptionCombosNotInDataElementCategoryCombo, "categoryOptionCombosNotInDataElementCategoryCombo", true, asMapList );
+    displayViolation( json.dataSetsNotAssignedToOrganisationUnits, "dataSetsNotAssignedToOrganisationUnits", false, asList );
+    displayViolation( json.sectionsWithInvalidCategoryCombinations, "sectionsWithInvalidCategoryCombinations", false, asList );
+    displayViolation( json.indicatorsWithIdenticalFormulas, "indicatorsWithIdenticalFormulas", false, asListList );
+    displayViolation( json.indicatorsWithoutGroups, "indicatorsWithoutGroups", false, asList );
+    displayViolation( json.invalidIndicatorNumerators, "invalidIndicatorNumerators", true, asMap );
+    displayViolation( json.invalidIndicatorDenominators, "invalidIndicatorDenominators", true, asMap );
+    displayViolation( json.indicatorsViolatingExclusiveGroupSets, "indicatorsViolatingExclusiveGroupSets", true, asMapList );
+    displayViolation( json.duplicatePeriods, "duplicatePeriods", false, asList );
+    displayViolation( json.organisationUnitsWithCyclicReferences, "organisationUnitsWithCyclicReferences", false, asList );
+    displayViolation( json.orphanedOrganisationUnits, "orphanedOrganisationUnits", false, asList );
+    displayViolation( json.organisationUnitsWithoutGroups, "organisationUnitsWithoutGroups", false, asList );
+    displayViolation( json.organisationUnitsViolatingExclusiveGroupSets, "organisationUnitsViolatingExclusiveGroupSets", true, asMapList );
+    displayViolation( json.organisationUnitGroupsWithoutGroupSets, "organisationUnitGroupsWithoutGroupSets", false, asList );
+    displayViolation( json.validationRulesWithoutGroups, "validationRulesWithoutGroups", false, asList );
+    displayViolation( json.invalidValidationRuleLeftSideExpressions, "invalidValidationRuleLeftSideExpressions", true, asMapList );
+    displayViolation( json.invalidValidationRuleRightSideExpressions, "invalidValidationRuleRightSideExpressions", true, asMapList );
 }

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/menu.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/menu.vm	2014-08-28 08:47:36 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/menu.vm	2015-03-13 18:42:40 +0000
@@ -2,20 +2,20 @@
 <h2>$i18n.getString( "data_administration" )&nbsp;</h2>
 
 <ul>
-	<li><a href="displayDataBrowserForm.action">$i18n.getString( "data_browser" )&nbsp;</a></li>
-    <li><a href="displayDataIntegrityForm.action">$i18n.getString( "data_integrity" )&nbsp;</a></li>
-	<li><a href="displayMaintenanceForm.action">$i18n.getString( "maintenance" )&nbsp;</a></li>
-	<li><a href="displayResourceTableForm.action">$i18n.getString( "resource_table" )&nbsp;</a></li>
-	<li><a href="locale.action">$i18n.getString( "locale" )&nbsp;</a></li>
-	<li><a href="sqlView.action">$i18n.getString( "sql_view" )&nbsp;</a></li>
-	<li><a href="displayOrganisationUnitMergeForm.action">$i18n.getString( "organisation_unit_merge" )&nbsp;</a></li>
+    <li><a href="displayDataBrowserForm.action">$i18n.getString( "data_browser" )&nbsp;</a></li>
+    <li><a href="dataIntegrity.action">$i18n.getString( "data_integrity" )&nbsp;</a></li>
+    <li><a href="displayMaintenanceForm.action">$i18n.getString( "maintenance" )&nbsp;</a></li>
+    <li><a href="displayResourceTableForm.action">$i18n.getString( "resource_table" )&nbsp;</a></li>
+    <li><a href="locale.action">$i18n.getString( "locale" )&nbsp;</a></li>
+    <li><a href="sqlView.action">$i18n.getString( "sql_view" )&nbsp;</a></li>
+    <li><a href="displayOrganisationUnitMergeForm.action">$i18n.getString( "organisation_unit_merge" )&nbsp;</a></li>
     <li><a href="displayDuplicateDataEliminationForm.action">$i18n.getString( "duplicate_data_elimination" )&nbsp;</a></li>
-	<li><a href="viewStatistics.action">$i18n.getString( "data_statistics" )&nbsp;</a></li>
+    <li><a href="viewStatistics.action">$i18n.getString( "data_statistics" )&nbsp;</a></li>
     <li><a href="lockException.action">$i18n.getString( "lock_exception" )&nbsp;</a></li>
-	<li><a href="getMinMaxValidationParams.action">$i18n.getString( "min_max_value_generation")&nbsp;</a></li>
-	<li><a href="constant.action">$i18n.getString( "constant")&nbsp;</a></li>
-	<li><a href="optionSet.action">$i18n.getString( "option_set")&nbsp;</a></li>
-	<li><a href="showCache.action">$i18n.getString( "cache_statistics" )&nbsp;</a></li>
-	<li><a href="attribute.action">$i18n.getString( "attribute" )&nbsp;</a></li>
-	<li><a href="viewScheduledTasks.action">$i18n.getString( "scheduling" )</a></li>	
+    <li><a href="getMinMaxValidationParams.action">$i18n.getString( "min_max_value_generation")&nbsp;</a></li>
+    <li><a href="constant.action">$i18n.getString( "constant")&nbsp;</a></li>
+    <li><a href="optionSet.action">$i18n.getString( "option_set")&nbsp;</a></li>
+    <li><a href="showCache.action">$i18n.getString( "cache_statistics" )&nbsp;</a></li>
+    <li><a href="attribute.action">$i18n.getString( "attribute" )&nbsp;</a></li>
+    <li><a href="viewScheduledTasks.action">$i18n.getString( "scheduling" )</a></li>
 </ul>

=== removed file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/responseDataIntegrity.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/responseDataIntegrity.vm	2015-03-04 17:01:31 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/responseDataIntegrity.vm	1970-01-01 00:00:00 +0000
@@ -1,63 +0,0 @@
-#macro( violation $name $list )
-#set( $size = $list.size() )
-"$!encoder.jsEncode( ${name} )": [
-#foreach( $o in $list )
-"$!encoder.jsonEncode( ${o.displayName} )"#if( $velocityCount < $size ),#end
-#end
-]
-#end
-
-#macro( violationWithCollection $name $list )
-#set( $listSize = $list.size() )
-"$!encoder.jsonEncode( ${name} )": [
-#foreach( $o in $list )
-#set( $oSize = $o.size() )
-"#foreach( $p in $o ) $!encoder.jsonEncode( ${p.displayName} ) #if( $velocityCount < $oSize ), #end
-#end "#if( $velocityCount < $listSize ),#end
-#end
-]
-#end
-
-#macro( violationWithMap $name $map )
-#set( $size = $map.keySet().size() )
-"$!encoder.jsonEncode( ${name} )": [
-#foreach( $o in $map.keySet() )
-"$!encoder.jsonEncode( ${o.displayName} ): $map.get( $o )"#if( $velocityCount < $size ),#end
-#end
-]
-#end
-
-#macro( violationWithMapList $name $map )
-#set( $mapSize = $map.keySet().size() )
-"$!encoder.jsonEncode( ${name} )": [
-#foreach( $o in $map.keySet() )
-#set( $listSize = $map.get( $o ).size() )
-"$!encoder.jsonEncode( ${o.displayName} ):#foreach( $p in $map.get( $o ) ) $!encoder.jsonEncode( ${p.displayName} )#if( $velocityCount < $listSize ), #end
-#end "#if( $velocityCount < $mapSize ),#end
-#end
-]
-#end
-{
-#violation( "dataElementsWithoutDataSet" $dataIntegrityReport.dataElementsWithoutDataSet ),
-#violation( "dataElementsWithoutGroups" $dataIntegrityReport.dataElementsWithoutGroups ),
-#violationWithMapList( "dataElementsViolatingExclusiveGroupSets" $dataIntegrityReport.dataElementsViolatingExclusiveGroupSets ),
-#violationWithMapList( "dataElementsInDataSetNotInForm" $dataIntegrityReport.dataElementsInDataSetNotInForm ),
-#violationWithMapList( "dataElementsAssignedToDataSetsWithDifferentPeriodTypes" $dataIntegrityReport.dataElementsAssignedToDataSetsWithDifferentPeriodTypes ),
-#violationWithMapList( "categoryOptionCombosNotInDataElementCategoryCombo" $dataIntegrityReport.categoryOptionCombosNotInDataElementCategoryCombo ),
-#violation( "dataSetsNotAssignedToOrganisationUnits" $dataIntegrityReport.dataSetsNotAssignedToOrganisationUnits ),
-#violation( "sectionsWithInvalidCategoryCombinations" $dataIntegrityReport.sectionsWithInvalidCategoryCombinations ),
-#violationWithCollection( "indicatorsWithIdenticalFormulas" $dataIntegrityReport.indicatorsWithIdenticalFormulas ),
-#violation( "indicatorsWithoutGroups" $dataIntegrityReport.indicatorsWithoutGroups ),
-#violationWithMap( "invalidIndicatorNumerators" $dataIntegrityReport.invalidIndicatorNumerators ),
-#violationWithMap( "invalidIndicatorDenominators" $dataIntegrityReport.invalidIndicatorDenominators ),
-#violationWithMapList( "indicatorsViolatingExclusiveGroupSets" $dataIntegrityReport.indicatorsViolatingExclusiveGroupSets ),
-#violation( "duplicatePeriods" $dataIntegrityReport.duplicatePeriods ),
-#violation( "organisationUnitsWithCyclicReferences" $dataIntegrityReport.organisationUnitsWithCyclicReferences ),
-#violation( "orphanedOrganisationUnits" $dataIntegrityReport.orphanedOrganisationUnits ),
-#violation( "organisationUnitsWithoutGroups" $dataIntegrityReport.organisationUnitsWithoutGroups ),
-#violationWithMapList( "organisationUnitsViolatingExclusiveGroupSets" $dataIntegrityReport.organisationUnitsViolatingExclusiveGroupSets ),
-#violation( "organisationUnitGroupsWithoutGroupSets" $dataIntegrityReport.organisationUnitGroupsWithoutGroupSets ),
-#violation( "validationRulesWithoutGroups" $dataIntegrityReport.validationRulesWithoutGroups ),
-#violationWithMap( "invalidValidationRuleLeftSideExpressions" $dataIntegrityReport.invalidValidationRuleLeftSideExpressions ),
-#violationWithMap( "invalidValidationRuleRightSideExpressions" $dataIntegrityReport.invalidValidationRuleRightSideExpressions )
-}