← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 18212: Applied patch from TW. Implements POST of aggregation queries in web api.

 

------------------------------------------------------------
revno: 18212
committer: Lars Helge Overland <larshelge@xxxxxxxxx>
branch nick: dhis2
timestamp: Mon 2015-02-09 23:18:20 +0100
message:
  Applied patch from TW. Implements POST of aggregation queries in web api.
added:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/caseaggregation/AggregationQueries.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/caseaggregation/AggregationQuery.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AggregationQueryController.java
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/caseaggregation/CaseAggregationConditionService.java
  dhis-2/dhis-services/dhis-service-eventreporting/src/main/java/org/hisp/dhis/caseaggregation/DefaultCaseAggregationConditionService.java
  dhis-2/dhis-services/dhis-service-eventreporting/src/test/java/org/hisp/dhis/caseaggregation/CaseAggregationConditionServiceTest.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
=== added file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/caseaggregation/AggregationQueries.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/caseaggregation/AggregationQueries.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/caseaggregation/AggregationQueries.java	2015-02-09 22:18:20 +0000
@@ -0,0 +1,36 @@
+package org.hisp.dhis.caseaggregation;
+
+/*
+ * Copyright (c) 2004-2014, 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.HashSet;
+
+public class AggregationQueries
+    extends HashSet<AggregationQuery>
+{
+}

=== added file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/caseaggregation/AggregationQuery.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/caseaggregation/AggregationQuery.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/caseaggregation/AggregationQuery.java	2015-02-09 22:18:20 +0000
@@ -0,0 +1,139 @@
+package org.hisp.dhis.caseaggregation;
+
+/*
+ * Copyright (c) 2004-2014, 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;
+
+public class AggregationQuery
+{
+    private String id;
+
+    private String name;
+
+    private String dataSet;
+
+    private String dataElement;
+
+    private String categoryOptionCombo;
+
+    private String dataElementForGroupBy;
+
+    private String operator;
+
+    private String expression;
+
+    @JsonProperty
+    public String getId()
+    {
+        return id;
+    }
+
+    @JsonProperty
+    public void setId( String id )
+    {
+        this.id = id;
+    }
+
+    @JsonProperty
+    public String getName()
+    {
+        return name;
+    }
+
+    public void setName( String name )
+    {
+        this.name = name;
+    }
+
+    @JsonProperty
+    public String getDataSet()
+    {
+        return dataSet;
+    }
+
+    public void setDataSet( String dataSet )
+    {
+        this.dataSet = dataSet;
+    }
+
+    @JsonProperty
+    public String getDataElement()
+    {
+        return dataElement;
+    }
+
+    public void setDataElement( String dataElement )
+    {
+        this.dataElement = dataElement;
+    }
+
+    @JsonProperty
+    public String getCategoryOptionCombo()
+    {
+        return categoryOptionCombo;
+    }
+
+    public void setCategoryOptionCombo( String categoryOptionCombo )
+    {
+        this.categoryOptionCombo = categoryOptionCombo;
+    }
+
+    @JsonProperty
+    public String getDataElementForGroupBy()
+    {
+        return dataElementForGroupBy;
+    }
+
+    public void setDataElementForGroupBy( String dataElementForGroupBy )
+    {
+        this.dataElementForGroupBy = dataElementForGroupBy;
+    }
+
+    @JsonProperty
+    public String getOperator()
+    {
+        return operator;
+    }
+
+    public void setOperator( String operator )
+    {
+        this.operator = operator;
+    }
+
+    @JsonProperty
+    public String getExpression()
+    {
+        return expression;
+    }
+
+    public void setExpression( String expression )
+    {
+        this.expression = expression;
+    }
+}

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/caseaggregation/CaseAggregationConditionService.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/caseaggregation/CaseAggregationConditionService.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/caseaggregation/CaseAggregationConditionService.java	2015-02-09 22:18:20 +0000
@@ -92,6 +92,16 @@
      *         match.
      */
     CaseAggregationCondition getCaseAggregationCondition( String name );
+
+    /**
+     * Returns a {@link CaseAggregationCondition} with a given name.
+     *
+     * @param id the uid of the CaseAggregationCondition to return.
+     *
+     * @return the CaseAggregationCondition with the given uid, or null if no
+     *         match.
+     */
+    CaseAggregationCondition getCaseAggregationConditionByUid( String id );
     
     /**
      * Returns all {@link CaseAggregationCondition}
@@ -274,4 +284,5 @@
      */
     List<Grid> getAggregateValue( Collection<CaseAggregationCondition> caseAggregationConditions, Collection<Integer> orgunitIds,
         Collection<Period> periods, I18nFormat format, I18n i18n );
+
 }

=== modified file 'dhis-2/dhis-services/dhis-service-eventreporting/src/main/java/org/hisp/dhis/caseaggregation/DefaultCaseAggregationConditionService.java'
--- dhis-2/dhis-services/dhis-service-eventreporting/src/main/java/org/hisp/dhis/caseaggregation/DefaultCaseAggregationConditionService.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-services/dhis-service-eventreporting/src/main/java/org/hisp/dhis/caseaggregation/DefaultCaseAggregationConditionService.java	2015-02-09 22:18:20 +0000
@@ -178,7 +178,13 @@
     {
         return i18n( i18nService, aggregationConditionStore.getByName( name ) );
     }
-    
+
+    @Override
+    public CaseAggregationCondition getCaseAggregationConditionByUid( String uid )
+    {
+        return i18n( i18nService, aggregationConditionStore.getByUid( uid ) );
+    }
+
     @Override
     public void updateCaseAggregationCondition( CaseAggregationCondition caseAggregationCondition )
     {

=== modified file 'dhis-2/dhis-services/dhis-service-eventreporting/src/test/java/org/hisp/dhis/caseaggregation/CaseAggregationConditionServiceTest.java'
--- dhis-2/dhis-services/dhis-service-eventreporting/src/test/java/org/hisp/dhis/caseaggregation/CaseAggregationConditionServiceTest.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-services/dhis-service-eventreporting/src/test/java/org/hisp/dhis/caseaggregation/CaseAggregationConditionServiceTest.java	2015-02-09 22:18:20 +0000
@@ -28,38 +28,15 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-
 import org.hisp.dhis.DhisSpringTest;
-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.DataElementCategoryOptionCombo;
-import org.hisp.dhis.dataelement.DataElementCategoryService;
-import org.hisp.dhis.dataelement.DataElementDomain;
-import org.hisp.dhis.dataelement.DataElementService;
+import org.hisp.dhis.dataelement.*;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
 import org.hisp.dhis.organisationunit.OrganisationUnitService;
 import org.hisp.dhis.period.DailyPeriodType;
 import org.hisp.dhis.period.Period;
 import org.hisp.dhis.period.PeriodService;
 import org.hisp.dhis.period.PeriodType;
-import org.hisp.dhis.program.Program;
-import org.hisp.dhis.program.ProgramInstance;
-import org.hisp.dhis.program.ProgramInstanceService;
-import org.hisp.dhis.program.ProgramService;
-import org.hisp.dhis.program.ProgramStage;
-import org.hisp.dhis.program.ProgramStageInstance;
-import org.hisp.dhis.program.ProgramStageInstanceService;
-import org.hisp.dhis.program.ProgramStageService;
+import org.hisp.dhis.program.*;
 import org.hisp.dhis.trackedentity.TrackedEntityAttribute;
 import org.hisp.dhis.trackedentity.TrackedEntityAttributeService;
 import org.hisp.dhis.trackedentity.TrackedEntityInstance;
@@ -71,6 +48,12 @@
 import org.junit.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import static org.junit.Assert.*;
+
 /**
  * @author Chau Thu Tran
  * 
@@ -361,6 +344,15 @@
     }
 
     @Test
+    public void testGetCaseAggregationConditionByUid()
+    {
+        conditionA.setUid( "ABC" );
+        aggConditionServiceService.addCaseAggregationCondition( conditionA );
+
+        assertEquals( conditionA, aggConditionServiceService.getCaseAggregationConditionByUid( "ABC" ) );
+    }
+
+    @Test
     public void testGetAllCaseAggregationCondition()
     {
         aggConditionServiceService.addCaseAggregationCondition( conditionA );

=== added file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AggregationQueryController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AggregationQueryController.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AggregationQueryController.java	2015-02-09 22:18:20 +0000
@@ -0,0 +1,171 @@
+package org.hisp.dhis.webapi.controller;
+
+/*
+ * Copyright (c) 2004-2014, 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.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hisp.dhis.caseaggregation.AggregationQueries;
+import org.hisp.dhis.caseaggregation.AggregationQuery;
+import org.hisp.dhis.caseaggregation.CaseAggregationCondition;
+import org.hisp.dhis.caseaggregation.CaseAggregationConditionService;
+import org.hisp.dhis.dataelement.DataElement;
+import org.hisp.dhis.dataelement.DataElementCategoryService;
+import org.hisp.dhis.dataelement.DataElementService;
+import org.hisp.dhis.program.ProgramService;
+import org.hisp.dhis.program.ProgramStageService;
+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.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+@Controller
+@RequestMapping( value = AggregationQueryController.RESOURCE_PATH )
+public class AggregationQueryController
+{
+    private final static Log log = LogFactory.getLog( AggregationQueryController.class );
+
+    public static final String RESOURCE_PATH = "/aggregationQueries";
+
+    @Autowired
+    private CaseAggregationConditionService aggregationConditionService;
+
+    @Autowired
+    private ProgramService programService;
+
+    @Autowired
+    private ProgramStageService programStageService;
+
+    @Autowired
+    private DataElementService dataElementService;
+
+    @Autowired
+    private DataElementCategoryService dataElementCategoryService;
+
+    @RequestMapping( method = RequestMethod.POST, consumes = "application/json" )
+    @PreAuthorize( "hasRole('ALL') or hasRole('F_TRACKED_ENTITY_AGGREGATION')" )
+    public void postAggregationQueryJson( @RequestBody AggregationQueries aggregationQueries,
+        HttpServletResponse response )
+    {
+        for ( AggregationQuery aggregationQuery : aggregationQueries )
+        {
+            CaseAggregationCondition caseAggregationCondition = convertToCaseAggregationCondition( aggregationQuery );
+            
+            if ( caseAggregationCondition.getId() == 0 )
+            {
+                aggregationConditionService.addCaseAggregationCondition( caseAggregationCondition );
+            }
+            else
+            {
+                aggregationConditionService.updateCaseAggregationCondition( caseAggregationCondition );
+            }
+        }
+    }
+    
+    private CaseAggregationCondition convertToCaseAggregationCondition( AggregationQuery aggregationQuery )
+    {
+        String id = aggregationQuery.getId();
+        CaseAggregationCondition expression = aggregationConditionService.getCaseAggregationConditionByUid( id );
+        
+        if ( expression == null )
+        {
+            expression = new CaseAggregationCondition();
+            expression.setUid( id );
+        }
+
+        expression.setName( aggregationQuery.getName() );
+        expression.setOperator( aggregationQuery.getOperator() );
+        expression.setAggregationDataElement( dataElementService.getDataElement( aggregationQuery.getDataElement() ) );
+
+        if ( aggregationQuery.getCategoryOptionCombo() == null )
+        {
+            expression.setOptionCombo( dataElementCategoryService.getDefaultDataElementCategoryOptionCombo() );
+        }
+        else
+        {
+            expression.setOptionCombo( dataElementCategoryService.getDataElementCategoryOptionCombo( aggregationQuery.getCategoryOptionCombo() ) );
+        }
+
+        String deIdForGroupBy = aggregationQuery.getDataElementForGroupBy();
+        
+        if ( deIdForGroupBy != null )
+        {
+            DataElement deSum = dataElementService.getDataElement( deIdForGroupBy );
+            expression.setDeSum( deSum );
+        }
+
+        expression.setAggregationExpression( convertDataElementExpression( aggregationQuery.getExpression() ) );
+
+        return expression;
+    }
+
+    private String convertDataElementExpression( String expression )
+    {
+        String UID_PATTERN = "[A-Za-z0-9]+";
+        String UID_TOKEN_PATTERN = "(#\\{(" + UID_PATTERN + ")})";
+
+        StringBuffer replacedExpressionBuffer = new StringBuffer();
+
+        Pattern dePattern = Pattern.compile( "(?<=\\[" + CaseAggregationCondition.OBJECT_PROGRAM_STAGE_DATAELEMENT
+            + CaseAggregationCondition.SEPARATOR_OBJECT + ")"
+            + UID_TOKEN_PATTERN + CaseAggregationCondition.SEPARATOR_ID
+            + UID_TOKEN_PATTERN + CaseAggregationCondition.SEPARATOR_ID
+            + UID_TOKEN_PATTERN
+            + "(?=\\])" );
+
+        Matcher matcher = dePattern.matcher( expression );
+        
+        while ( matcher.find() )
+        {
+            String programUid = matcher.group( 2 );
+            int programId = programService.getProgram( programUid ).getId();
+
+            String programStageUid = matcher.group( 4 );
+            int programStageId = programStageService.getProgramStage( programStageUid ).getId();
+
+            String dataElementUid = matcher.group( 6 );
+            int dataElementId = dataElementService.getDataElement( dataElementUid ).getId();
+
+            matcher.appendReplacement( replacedExpressionBuffer,
+                String.format( "%d.%d.%d", programId, programStageId, dataElementId ) );
+        }
+
+        matcher.appendTail( replacedExpressionBuffer );
+
+        String parsedExpression = replacedExpressionBuffer.toString();
+        log.info( "Replacing " + expression + " with " + parsedExpression );
+        return parsedExpression;
+    }
+}