← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 20962: Analytics. Split out methods from AnalyticsService/EventAnalyticsService to DataQueryService/Even...

 

Merge authors:
  Lars Helge Øverland (larshelge)
------------------------------------------------------------
revno: 20962 [merge]
committer: Lars Helge Overland <larshelge@xxxxxxxxx>
branch nick: dhis2
timestamp: Thu 2015-11-05 01:41:46 -0500
message:
  Analytics. Split out methods from AnalyticsService/EventAnalyticsService to DataQueryService/EventDataQueryService.
added:
  dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/DataQueryService.java
  dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultDataQueryService.java
  dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/EventDataQueryService.java
  dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/DefaultEventDataQueryService.java
renamed:
  dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/data/AnalyticsServiceTest.java => dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/data/DataQueryServiceTest.java
  dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/event/data/EventAnalyticsServiceTest.java => dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/event/data/EventDataQueryServiceTest.java
modified:
  dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/AnalyticsService.java
  dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultAnalyticsService.java
  dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultQueryPlanner.java
  dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/EventAnalyticsService.java
  dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/DefaultEventAnalyticsService.java
  dhis-2/dhis-services/dhis-service-analytics/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/data/MockAnalyticsService.java
  dhis-2/dhis-services/dhis-service-reporting/src/main/java/org/hisp/dhis/datasetreport/jdbc/AnalyticsDataSetReportStore.java
  dhis-2/dhis-services/dhis-service-reporting/src/main/java/org/hisp/dhis/mapgeneration/GeoToolsMapGenerationService.java
  dhis-2/dhis-services/dhis-service-reporting/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AnalyticsController.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/EventAnalyticsController.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/mapping/GeoFeatureController.java
  dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/data/DataQueryServiceTest.java
  dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/event/data/EventDataQueryServiceTest.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-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/AnalyticsService.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/AnalyticsService.java	2015-09-17 16:33:12 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/AnalyticsService.java	2015-11-05 02:57:57 +0000
@@ -28,36 +28,35 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import java.util.Date;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 import org.hisp.dhis.common.AnalyticalObject;
-import org.hisp.dhis.common.DimensionalObject;
-import org.hisp.dhis.common.DisplayProperty;
 import org.hisp.dhis.common.Grid;
-import org.hisp.dhis.common.IdentifiableProperty;
-import org.hisp.dhis.common.IllegalQueryException;
 import org.hisp.dhis.i18n.I18nFormat;
-import org.hisp.dhis.organisationunit.OrganisationUnit;
 
 /**
- * <p>This interface is responsible for retrieving aggregated data. Data will be
- * returned in a grid object or as a dimensional key-value mapping.</p>
+ * <p>
+ * This interface is responsible for retrieving aggregated data. Data will be
+ * returned in a grid object or as a dimensional key-value mapping.
+ * </p>
  * 
- * <p>Most objects accept a DataQueryParams object which encapsulates the query 
+ * <p>
+ * Most objects accept a DataQueryParams object which encapsulates the query
  * parameters. The dimensions in the response will appear in the same order as
  * they are set on the DataQueryParams object. You can use various methods for
  * setting indicators, data elements, data sets, periods, organisation units,
  * categories, data element group sets and organisation unit group sets on the
- * the DataQueryParams object. Objects can be defined as dimensions or filters.</p>
+ * the DataQueryParams object. Objects can be defined as dimensions or filters.
+ * </p>
  * 
- * <p>Example usage for setting multiple indicators and a period as dimensions
- * and an organisation unit as filter. In the grid response the first column
- * will contain indicator identifiers, the second column will contain period
+ * <p>
+ * Example usage for setting multiple indicators and a period as dimensions and
+ * an organisation unit as filter. In the grid response the first column will
+ * contain indicator identifiers, the second column will contain period
  * identifiers and the third column will contain aggregated values. Note that
- * the organisation unit is excluded since it is defined as a filter:</p>
+ * the organisation unit is excluded since it is defined as a filter:
+ * </p>
  * 
  * <pre>
  * <code>
@@ -71,14 +70,16 @@
  * </code>
  * </pre>
  * 
- * <p>Example usage for including category option combos in the response. Note that 
- * the index position of category option combos will follow the order of when the
- * enableCategoryOptionCombos method was called. In the map response, the keys
- * will represent the dimensions defined in the DataQueryParams object and will
- * contain dimension identifiers separated by the "-" character. The key will
- * be of type String and contain a data element identifier, a category option 
- * combo identifier and an organisation unit identifier in that order. The map 
- * values will be the aggregated values of type Double:</p>
+ * <p>
+ * Example usage for including category option combos in the response. Note that
+ * the index position of category option combos will follow the order of when
+ * the enableCategoryOptionCombos method was called. In the map response, the
+ * keys will represent the dimensions defined in the DataQueryParams object and
+ * will contain dimension identifiers separated by the "-" character. The key
+ * will be of type String and contain a data element identifier, a category
+ * option combo identifier and an organisation unit identifier in that order.
+ * The map values will be the aggregated values of type Double:
+ * </p>
  * 
  * <pre>
  * <code>
@@ -98,10 +99,13 @@
 public interface AnalyticsService
 {
     final String NAMES_META_KEY = "names";
+
     final String PAGER_META_KEY = "pager";
+
     final String OU_HIERARCHY_KEY = "ouHierarchy";
+
     final String OU_NAME_HIERARCHY_KEY = "ouNameHierarchy";
-    
+
     /**
      * Generates aggregated values for the given query.
      * 
@@ -109,25 +113,36 @@
      * @return aggregated data as a Grid object.
      */
     Grid getAggregatedDataValues( DataQueryParams params );
-    
+
     /**
      * Generates an aggregated value grid for the given query. The grid will
      * represent a table with dimensions used as columns and rows as specified
      * in columns and rows dimension arguments.
      * 
      * @param params the data query parameters.
-     * @param tableLayout whether to render the grid as a table with columns and rows,
-     *        or as a normalized plain data source.
+     * @param tableLayout whether to render the grid as a table with columns and
+     *        rows, or as a normalized plain data source.
      * @param columns the identifiers of the dimensions to use as columns.
      * @param rows the identifiers of the dimensions to use as rows.
      * @return aggregated data as a Grid object.
      */
-    Grid getAggregatedDataValues( DataQueryParams params, boolean tableLayout, List<String> columns, List<String> rows );
-
-    /**
-     * Generates a mapping where the key represents the dimensional item identifiers
-     * concatenated by "-" and the value is the corresponding aggregated data value
-     * based on the given DataQueryParams.
+    Grid getAggregatedDataValues( DataQueryParams params, boolean tableLayout, List<String> columns,
+        List<String> rows );
+    
+    /**
+     * Generates an aggregated value grid for the given query based on the given
+     * analytical object.
+     * 
+     * @param object the analytical object.
+     * @param format the i18n format.
+     * @return aggregated data as a Grid object.
+     */
+    Grid getAggregatedDataValues( AnalyticalObject object, I18nFormat format );
+    
+    /**
+     * Generates a mapping where the key represents the dimensional item
+     * identifiers concatenated by "-" and the value is the corresponding
+     * aggregated data value based on the given DataQueryParams.
      * 
      * @param params the DataQueryParams.
      * @return a mapping of dimensional items and aggregated data values.
@@ -135,101 +150,13 @@
     Map<String, Object> getAggregatedDataValueMapping( DataQueryParams params );
 
     /**
-     * Generates a mapping where the key represents the dimensional item identifiers
-     * concatenated by "-" and the value is the corresponding aggregated data value
-     * based on the given AnalyticalObject.
+     * Generates a mapping where the key represents the dimensional item
+     * identifiers concatenated by "-" and the value is the corresponding
+     * aggregated data value based on the given AnalyticalObject.
      * 
      * @param object the BaseAnalyticalObject.
      * @param format the I18nFormat, can be null.
      * @return a mapping of dimensional items and aggregated data values.
      */
     Map<String, Object> getAggregatedDataValueMapping( AnalyticalObject object, I18nFormat format );
-
-    /**
-     * Creates a data query parameter object from the given URL.
-     * 
-     * @param dimensionParams the dimension URL parameters.
-     * @param filterParams the filter URL parameters.
-     * @param aggregationType the aggregation type.
-     * @param measureCriteria the measure criteria.
-     * @param skipMeta whether to skip the meta data part of the response.
-     * @param skipData whether to skip the data part of the response.
-     * @param skipRounding whether to skip rounding and provide full precision 
-     *        for values.
-     * @param completedOnly whether to only include completed events.
-     * @param hierarchyMeta whether to include meta data about the organisation 
-     *        units in the hierarchy.
-     * @param ignoreLimit whether to ignore the max number of cells limit.
-     * @param hideEmptyRows whether to hide rows without data values, applies to
-     *        table layout.
-     * @param showHierarchy whether to show the organisation unit hierarchy 
-     *        together with the name.
-     * @param displayProperty the property to display for meta-data.
-     * @param outputIdScheme the identifier scheme to use in the query response.
-     * @param approvalLevel the approval level identifier.
-     * @param relativePeriodDate the date to use as basis for relative periods.
-     * @param userOrgUnit the user organisation unit to use, overrides current user.
-     * @param program the program identifier.
-     * @param stage the program stage identifier.
-     * @param format the i18n format.
-     * @return a data query parameter object created based on the given URL info.
-     */
-    DataQueryParams getFromUrl( Set<String> dimensionParams, Set<String> filterParams, AggregationType aggregationType, String measureCriteria, 
-        boolean skipMeta, boolean skipData, boolean skipRounding, boolean completedOnly, boolean hierarchyMeta, boolean ignoreLimit, 
-        boolean hideEmptyRows, boolean showHierarchy, DisplayProperty displayProperty, IdentifiableProperty outputIdScheme, String approvalLevel, 
-        Date relativePeriodDate, String userOrgUnit, String program, String stage, I18nFormat format );
-    
-    /**
-     * Creates a data query parameter object from the given BaseAnalyticalObject.
-     * 
-     * @param object the BaseAnalyticalObject
-     * @param format the i18n format.
-     * @return a data query parameter object created based on the given BaseAnalyticalObject.
-     */
-    DataQueryParams getFromAnalyticalObject( AnalyticalObject object, I18nFormat format );
-    
-    /**
-     * Creates a list of DimensionalObject from the given set of dimension params.
-     * 
-     * @param dimensionParams the dimension URL params.
-     * @param relativePeriodDate the date to use as basis for relative periods.
-     * @param userOrgUnit the user organisation unit param, overrides current
-     *        user, can be null.
-     * @param format the i18n format.
-     * @return a list of DimensionalObject.
-     */
-    List<DimensionalObject> getDimensionalObjects( Set<String> dimensionParams, Date relativePeriodDate, String userOrgUnit, I18nFormat format );
-    
-    /**
-     * Returns a persisted DimensionalObject generated from the given  dimension 
-     * identifier and list of dimension options.
-     * 
-     * For the pe dimension items, relative periods represented by enums will be 
-     * replaced by real ISO periods relative to the current date. For the ou 
-     * dimension items, the user  organisation unit enums 
-     * USER_ORG_UNIT|USER_ORG_UNIT_CHILDREN will be replaced by the persisted 
-     * organisation units for the current user.
-     * 
-     * @param dimension the dimension identifier.
-     * @param items the dimension items.
-     * @param relativePeriodDate the date to use for generating relative periods, can be null.
-     * @param userOrgUnits the list of user organisation units, overrides current
-     *        user, can be null.
-     * @param format the I18nFormat, can be null.
-     * @param allowNull return null if no dimension was found.
-     * @throws IllegalQueryException if no dimensions was found.
-     * @return list of DimensionalObjects.
-     */
-    DimensionalObject getDimension( String dimension, List<String> items, Date relativePeriodDate, 
-        List<OrganisationUnit> userOrgUnits, I18nFormat format, boolean allowNull );
-    
-    /**
-     * Returns a list of user organisation units, looking first at the given user 
-     * org unit parameter, second at the organisation units associated with the
-     * current user. Returns an empty list if no organisation units are found.
-     * 
-     * @param userOrgUnit the user org unit parameter string.
-     * @return a list of organisation units.
-     */
-    List<OrganisationUnit> getUserOrgUnits( String userOrgUnit );
 }

=== added file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/DataQueryService.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/DataQueryService.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/DataQueryService.java	2015-11-05 02:57:57 +0000
@@ -0,0 +1,138 @@
+package org.hisp.dhis.analytics;
+
+/*
+ * 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 java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+import org.hisp.dhis.analytics.AggregationType;
+import org.hisp.dhis.common.AnalyticalObject;
+import org.hisp.dhis.common.DimensionalObject;
+import org.hisp.dhis.common.DisplayProperty;
+import org.hisp.dhis.common.IdentifiableProperty;
+import org.hisp.dhis.common.IllegalQueryException;
+import org.hisp.dhis.i18n.I18nFormat;
+import org.hisp.dhis.organisationunit.OrganisationUnit;
+
+/**
+ * Service which provides methods for assembling DataQueryParams objects.
+ * 
+* @author Lars Helge Overland
+*/
+public interface DataQueryService
+{
+    /**
+     * Creates a data query parameter object from the given URL.
+     * 
+     * @param dimensionParams the dimension URL parameters.
+     * @param filterParams the filter URL parameters.
+     * @param aggregationType the aggregation type.
+     * @param measureCriteria the measure criteria.
+     * @param skipMeta whether to skip the meta data part of the response.
+     * @param skipData whether to skip the data part of the response.
+     * @param skipRounding whether to skip rounding and provide full precision 
+     *        for values.
+     * @param completedOnly whether to only include completed events.
+     * @param hierarchyMeta whether to include meta data about the organisation 
+     *        units in the hierarchy.
+     * @param ignoreLimit whether to ignore the max number of cells limit.
+     * @param hideEmptyRows whether to hide rows without data values, applies to
+     *        table layout.
+     * @param showHierarchy whether to show the organisation unit hierarchy 
+     *        together with the name.
+     * @param displayProperty the property to display for meta-data.
+     * @param outputIdScheme the identifier scheme to use in the query response.
+     * @param approvalLevel the approval level identifier.
+     * @param relativePeriodDate the date to use as basis for relative periods.
+     * @param userOrgUnit the user organisation unit to use, overrides current user.
+     * @param program the program identifier.
+     * @param stage the program stage identifier.
+     * @param format the i18n format.
+     * @return a data query parameter object created based on the given URL info.
+     */
+    DataQueryParams getFromUrl( Set<String> dimensionParams, Set<String> filterParams, AggregationType aggregationType, String measureCriteria, 
+        boolean skipMeta, boolean skipData, boolean skipRounding, boolean completedOnly, boolean hierarchyMeta, boolean ignoreLimit, 
+        boolean hideEmptyRows, boolean showHierarchy, DisplayProperty displayProperty, IdentifiableProperty outputIdScheme, String approvalLevel, 
+        Date relativePeriodDate, String userOrgUnit, String program, String stage, I18nFormat format );
+    
+    /**
+     * Creates a data query parameter object from the given BaseAnalyticalObject.
+     * 
+     * @param object the BaseAnalyticalObject
+     * @param format the i18n format.
+     * @return a data query parameter object created based on the given BaseAnalyticalObject.
+     */
+    DataQueryParams getFromAnalyticalObject( AnalyticalObject object, I18nFormat format );
+    
+    /**
+     * Creates a list of DimensionalObject from the given set of dimension params.
+     * 
+     * @param dimensionParams the dimension URL params.
+     * @param relativePeriodDate the date to use as basis for relative periods.
+     * @param userOrgUnit the user organisation unit param, overrides current
+     *        user, can be null.
+     * @param format the i18n format.
+     * @return a list of DimensionalObject.
+     */
+    List<DimensionalObject> getDimensionalObjects( Set<String> dimensionParams, Date relativePeriodDate, String userOrgUnit, I18nFormat format );
+    
+    /**
+     * Returns a persisted DimensionalObject generated from the given  dimension 
+     * identifier and list of dimension options.
+     * 
+     * For the pe dimension items, relative periods represented by enums will be 
+     * replaced by real ISO periods relative to the current date. For the ou 
+     * dimension items, the user  organisation unit enums 
+     * USER_ORG_UNIT|USER_ORG_UNIT_CHILDREN will be replaced by the persisted 
+     * organisation units for the current user.
+     * 
+     * @param dimension the dimension identifier.
+     * @param items the dimension items.
+     * @param relativePeriodDate the date to use for generating relative periods, can be null.
+     * @param userOrgUnits the list of user organisation units, overrides current
+     *        user, can be null.
+     * @param format the I18nFormat, can be null.
+     * @param allowNull return null if no dimension was found.
+     * @throws IllegalQueryException if no dimensions was found.
+     * @return list of DimensionalObjects.
+     */
+    DimensionalObject getDimension( String dimension, List<String> items, Date relativePeriodDate, 
+        List<OrganisationUnit> userOrgUnits, I18nFormat format, boolean allowNull );
+    
+    /**
+     * Returns a list of user organisation units, looking first at the given user 
+     * org unit parameter, second at the organisation units associated with the
+     * current user. Returns an empty list if no organisation units are found.
+     * 
+     * @param userOrgUnit the user org unit parameter string.
+     * @return a list of organisation units.
+     */
+    List<OrganisationUnit> getUserOrgUnits( String userOrgUnit );
+}

=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultAnalyticsService.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultAnalyticsService.java	2015-11-03 23:28:48 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultAnalyticsService.java	2015-11-05 02:57:57 +0000
@@ -34,35 +34,17 @@
 import static org.hisp.dhis.analytics.AnalyticsTableManager.ORGUNIT_TARGET_TABLE_NAME;
 import static org.hisp.dhis.analytics.DataQueryParams.COMPLETENESS_DIMENSION_TYPES;
 import static org.hisp.dhis.analytics.DataQueryParams.CO_INDEX;
-import static org.hisp.dhis.analytics.DataQueryParams.DISPLAY_NAME_ATTRIBUTEOPTIONCOMBO;
-import static org.hisp.dhis.analytics.DataQueryParams.DISPLAY_NAME_CATEGORYOPTIONCOMBO;
 import static org.hisp.dhis.analytics.DataQueryParams.DISPLAY_NAME_DATA_X;
-import static org.hisp.dhis.analytics.DataQueryParams.DISPLAY_NAME_LATITUDE;
-import static org.hisp.dhis.analytics.DataQueryParams.DISPLAY_NAME_LONGITUDE;
-import static org.hisp.dhis.analytics.DataQueryParams.DISPLAY_NAME_ORGUNIT;
-import static org.hisp.dhis.analytics.DataQueryParams.DISPLAY_NAME_PERIOD;
 import static org.hisp.dhis.analytics.DataQueryParams.DX_INDEX;
-import static org.hisp.dhis.analytics.DataQueryParams.KEY_DE_GROUP;
-import static org.hisp.dhis.common.DimensionalObject.ATTRIBUTEOPTIONCOMBO_DIM_ID;
 import static org.hisp.dhis.common.DimensionalObject.CATEGORYOPTIONCOMBO_DIM_ID;
 import static org.hisp.dhis.common.DimensionalObject.DATA_X_DIM_ID;
 import static org.hisp.dhis.common.DimensionalObject.DIMENSION_SEP;
-import static org.hisp.dhis.common.DimensionalObject.LATITUDE_DIM_ID;
-import static org.hisp.dhis.common.DimensionalObject.LONGITUDE_DIM_ID;
 import static org.hisp.dhis.common.DimensionalObject.ORGUNIT_DIM_ID;
 import static org.hisp.dhis.common.DimensionalObject.PERIOD_DIM_ID;
-import static org.hisp.dhis.common.IdentifiableObjectUtils.getLocalPeriodIdentifier;
 import static org.hisp.dhis.common.IdentifiableObjectUtils.getLocalPeriodIdentifiers;
 import static org.hisp.dhis.common.IdentifiableObjectUtils.getUids;
 import static org.hisp.dhis.common.NameableObjectUtils.asList;
 import static org.hisp.dhis.common.NameableObjectUtils.asTypedList;
-import static org.hisp.dhis.commons.collection.ListUtils.sort;
-import static org.hisp.dhis.commons.util.TextUtils.splitSafe;
-import static org.hisp.dhis.organisationunit.OrganisationUnit.KEY_LEVEL;
-import static org.hisp.dhis.organisationunit.OrganisationUnit.KEY_ORGUNIT_GROUP;
-import static org.hisp.dhis.organisationunit.OrganisationUnit.KEY_USER_ORGUNIT;
-import static org.hisp.dhis.organisationunit.OrganisationUnit.KEY_USER_ORGUNIT_CHILDREN;
-import static org.hisp.dhis.organisationunit.OrganisationUnit.KEY_USER_ORGUNIT_GRANDCHILDREN;
 import static org.hisp.dhis.organisationunit.OrganisationUnit.getParentGraphMap;
 import static org.hisp.dhis.organisationunit.OrganisationUnit.getParentNameGraphMap;
 import static org.hisp.dhis.period.PeriodType.getPeriodTypeFromIsoString;
@@ -71,15 +53,12 @@
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.Future;
-import java.util.stream.Collectors;
 
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.logging.Log;
@@ -91,6 +70,7 @@
 import org.hisp.dhis.analytics.AnalyticsUtils;
 import org.hisp.dhis.analytics.DataQueryGroups;
 import org.hisp.dhis.analytics.DataQueryParams;
+import org.hisp.dhis.analytics.DataQueryService;
 import org.hisp.dhis.analytics.DimensionItem;
 import org.hisp.dhis.analytics.QueryPlanner;
 import org.hisp.dhis.analytics.event.EventAnalyticsService;
@@ -99,52 +79,36 @@
 import org.hisp.dhis.calendar.DateTimeUnit;
 import org.hisp.dhis.common.AnalyticalObject;
 import org.hisp.dhis.common.BaseDimensionalObject;
-import org.hisp.dhis.common.CodeGenerator;
 import org.hisp.dhis.common.CombinationGenerator;
-import org.hisp.dhis.common.DataDimensionItem;
 import org.hisp.dhis.common.DataDimensionItemType;
 import org.hisp.dhis.common.DimensionType;
 import org.hisp.dhis.common.DimensionalObject;
 import org.hisp.dhis.common.DimensionalObjectUtils;
-import org.hisp.dhis.common.DisplayProperty;
 import org.hisp.dhis.common.Grid;
 import org.hisp.dhis.common.GridHeader;
-import org.hisp.dhis.common.IdentifiableObjectManager;
 import org.hisp.dhis.common.IdentifiableObjectUtils;
-import org.hisp.dhis.common.IdentifiableProperty;
-import org.hisp.dhis.common.IllegalQueryException;
 import org.hisp.dhis.common.MapMap;
 import org.hisp.dhis.common.NameableObject;
 import org.hisp.dhis.common.NameableObjectUtils;
-import org.hisp.dhis.common.comparator.IdentifiableObjectNameComparator;
 import org.hisp.dhis.commons.collection.ListUtils;
 import org.hisp.dhis.commons.util.DebugUtils;
 import org.hisp.dhis.constant.ConstantService;
 import org.hisp.dhis.dataelement.DataElement;
 import org.hisp.dhis.dataelement.DataElementCategoryCombo;
 import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo;
-import org.hisp.dhis.dataelement.DataElementGroup;
 import org.hisp.dhis.dataelement.DataElementOperand;
-import org.hisp.dhis.dataelement.DataElementOperandService;
 import org.hisp.dhis.expression.ExpressionService;
 import org.hisp.dhis.i18n.I18nFormat;
 import org.hisp.dhis.indicator.Indicator;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
 import org.hisp.dhis.organisationunit.OrganisationUnitGroup;
-import org.hisp.dhis.organisationunit.OrganisationUnitService;
 import org.hisp.dhis.period.Period;
 import org.hisp.dhis.period.PeriodType;
-import org.hisp.dhis.period.RelativePeriodEnum;
-import org.hisp.dhis.period.RelativePeriods;
-import org.hisp.dhis.period.comparator.AscendingPeriodEndDateComparator;
-import org.hisp.dhis.program.ProgramService;
-import org.hisp.dhis.program.ProgramStageService;
 import org.hisp.dhis.reporttable.ReportTable;
 import org.hisp.dhis.setting.Setting;
 import org.hisp.dhis.setting.SystemSettingManager;
 import org.hisp.dhis.system.grid.ListGrid;
 import org.hisp.dhis.system.util.MathUtils;
-import org.hisp.dhis.system.util.ReflectionUtils;
 import org.hisp.dhis.system.util.SystemUtils;
 import org.hisp.dhis.user.CurrentUserService;
 import org.hisp.dhis.user.User;
@@ -177,40 +141,23 @@
     private QueryPlanner queryPlanner;
 
     @Autowired
-    private IdentifiableObjectManager idObjectManager;
-    
-    @Autowired
-    private OrganisationUnitService organisationUnitService;
-
-    @Autowired
     private ExpressionService expressionService;
 
     @Autowired
     private ConstantService constantService;
 
     @Autowired
-    private DataElementOperandService operandService;
-
-    @Autowired
     private SystemSettingManager systemSettingManager;
 
     @Autowired
     private EventAnalyticsService eventAnalyticsService;    
     
     @Autowired
-    private ProgramService programService;
-    
-    @Autowired
-    private ProgramStageService programStageService;
+    private DataQueryService dataQueryService;
     
     @Autowired
     private CurrentUserService currentUserService;
 
-    public void setCurrentUserService( CurrentUserService currentUserService )
-    {
-        this.currentUserService = currentUserService; // Testing purposes
-    }
-
     // -------------------------------------------------------------------------
     // Methods for retrieving aggregated data
     // -------------------------------------------------------------------------
@@ -693,6 +640,14 @@
     }
 
     @Override
+    public Grid getAggregatedDataValues( AnalyticalObject object, I18nFormat format )
+    {
+        DataQueryParams params = dataQueryService.getFromAnalyticalObject( object, format );
+        
+        return getAggregatedDataValues( params );
+    }
+    
+    @Override
     public Map<String, Object> getAggregatedDataValueMapping( DataQueryParams params )
     {
         Grid grid = getAggregatedDataValues( params );
@@ -703,7 +658,7 @@
     @Override
     public Map<String, Object> getAggregatedDataValueMapping( AnalyticalObject object, I18nFormat format )
     {
-        DataQueryParams params = getFromAnalyticalObject( object, format );
+        DataQueryParams params = dataQueryService.getFromAnalyticalObject( object, format );
 
         return getAggregatedDataValueMapping( params );
     }
@@ -899,418 +854,6 @@
     }
 
     // -------------------------------------------------------------------------
-    // Methods for assembling DataQueryParams
-    // -------------------------------------------------------------------------
-
-    @Override
-    public DataQueryParams getFromUrl( Set<String> dimensionParams, Set<String> filterParams, AggregationType aggregationType,
-        String measureCriteria, boolean skipMeta, boolean skipData, boolean skipRounding, boolean completedOnly, boolean hierarchyMeta, boolean ignoreLimit,
-        boolean hideEmptyRows, boolean showHierarchy, DisplayProperty displayProperty, IdentifiableProperty outputIdScheme, 
-        String approvalLevel, Date relativePeriodDate, String userOrgUnit, String program, String stage, I18nFormat format )
-    {
-        DataQueryParams params = new DataQueryParams();
-        
-        params.setIgnoreLimit( ignoreLimit );
-
-        if ( dimensionParams != null && !dimensionParams.isEmpty() )
-        {
-            params.addDimensions( getDimensionalObjects( dimensionParams, relativePeriodDate, userOrgUnit, format ) );
-        }
-
-        if ( filterParams != null && !filterParams.isEmpty() )
-        {
-            params.getFilters().addAll( getDimensionalObjects( filterParams, relativePeriodDate, userOrgUnit, format ) );
-        }
-
-        if ( measureCriteria != null && !measureCriteria.isEmpty() )
-        {
-            params.setMeasureCriteria( DataQueryParams.getMeasureCriteriaFromParam( measureCriteria ) );
-        }
-
-        params.setAggregationType( aggregationType );
-        params.setSkipMeta( skipMeta );
-        params.setSkipData( skipData );
-        params.setSkipRounding( skipRounding );
-        params.setCompletedOnly( completedOnly );
-        params.setHierarchyMeta( hierarchyMeta );
-        params.setHideEmptyRows( hideEmptyRows );
-        params.setShowHierarchy( showHierarchy );
-        params.setDisplayProperty( displayProperty );
-        params.setOutputIdScheme( outputIdScheme );
-        params.setApprovalLevel( approvalLevel );
-        
-        if ( program != null )
-        {
-            params.setProgram( programService.getProgram( program ) );
-        }
-
-        if ( stage != null )
-        {
-            params.setProgramStage( programStageService.getProgramStage( stage ) );
-        }
-
-        return params;
-    }
-
-    @Override
-    public DataQueryParams getFromAnalyticalObject( AnalyticalObject object, I18nFormat format )
-    {
-        DataQueryParams params = new DataQueryParams();
-        
-        if ( object != null )
-        {
-            params.setProgram( object.getProgram() );
-            
-            List<OrganisationUnit> userOrgUnits = getUserOrgUnits( null );
-            
-            Date date = object.getRelativePeriodDate();
-
-            object.populateAnalyticalProperties();
-
-            for ( DimensionalObject column : object.getColumns() )
-            {
-                params.addDimension( getDimension( column.getDimension(), getUids( column.getItems() ), date, userOrgUnits, format, false ) );
-            }
-
-            for ( DimensionalObject row : object.getRows() )
-            {
-                params.addDimension( getDimension( row.getDimension(), getUids( row.getItems() ), date, userOrgUnits, format, false ) );
-            }
-
-            for ( DimensionalObject filter : object.getFilters() )
-            {
-                params.getFilters().add( getDimension( filter.getDimension(), getUids( filter.getItems() ), date, userOrgUnits, format, false ) );
-            }
-        }
-
-        return params;
-    }
-
-    @Override
-    public List<DimensionalObject> getDimensionalObjects( Set<String> dimensionParams, Date relativePeriodDate, String userOrgUnit, I18nFormat format )
-    {
-        List<DimensionalObject> list = new ArrayList<>();
-        
-        List<OrganisationUnit> userOrgUnits = getUserOrgUnits( userOrgUnit );
-
-        if ( dimensionParams != null )
-        {
-            for ( String param : dimensionParams )
-            {
-                String dimension = DimensionalObjectUtils.getDimensionFromParam( param );
-                List<String> items = DimensionalObjectUtils.getDimensionItemsFromParam( param );
-
-                if ( dimension != null && items != null )
-                {
-                    list.add( getDimension( dimension, items, relativePeriodDate, userOrgUnits, format, false ) );
-                }
-            }
-        }
-
-        return list;
-    }
-
-    // TODO verify that current user can read each dimension and dimension item
-    // TODO optimize so that org unit levels + boundary are used in query instead of fetching all org units one by one
-
-    @Override
-    public DimensionalObject getDimension( String dimension, List<String> items, Date relativePeriodDate, 
-        List<OrganisationUnit> userOrgUnits, I18nFormat format, boolean allowNull )
-    {
-        final boolean allItems = items.isEmpty();
-        
-        if ( DATA_X_DIM_ID.equals( dimension ) )
-        {
-            List<NameableObject> dataDimensionItems = new ArrayList<>();
-
-            for ( String uid : items )
-            {
-                if ( uid.startsWith( KEY_DE_GROUP ) )
-                {
-                    String groupUid = DimensionalObjectUtils.getUidFromGroupParam( uid );
-                    
-                    DataElementGroup group = idObjectManager.get( DataElementGroup.class, groupUid );
-                    
-                    if ( group != null )
-                    {
-                        dataDimensionItems.addAll( group.getMembers() );
-                    }
-                }
-                else if ( DimensionalObjectUtils.isValidDimensionalOperand( uid ) )
-                {
-                    DataElementOperand operand = operandService.getDataElementOperand( 
-                        splitSafe( uid, DataElementOperand.ESCAPED_SEPARATOR, 0 ), splitSafe( uid, DataElementOperand.ESCAPED_SEPARATOR, 1 ) );
-                    
-                    if ( operand != null )
-                    {
-                        dataDimensionItems.add( operand );
-                    }
-                }
-                else if ( CodeGenerator.isValidCode( uid ) )
-                {
-                    NameableObject item = idObjectManager.get( DataDimensionItem.DATA_DIMENSION_CLASSES, uid );
-                    
-                    if ( item != null )
-                    {
-                        dataDimensionItems.add( item );
-                    }
-                }
-            }
-            
-            if ( dataDimensionItems.isEmpty() )
-            {
-                throw new IllegalQueryException( "Dimension dx is present in query without any valid dimension options" );
-            }
-
-            DimensionalObject object = new BaseDimensionalObject( dimension, DimensionType.DATA_X, null, DISPLAY_NAME_DATA_X, dataDimensionItems );
-            
-            return object;
-            
-            //TODO proper handling of operands and option combinations
-        }
-
-        if ( CATEGORYOPTIONCOMBO_DIM_ID.equals( dimension ) )
-        {
-            List<NameableObject> cocs = new ArrayList<NameableObject>();
-            
-            for ( String uid : items )
-            {
-                DataElementCategoryOptionCombo coc = idObjectManager.get( DataElementCategoryOptionCombo.class, uid );
-                
-                if ( coc != null )
-                {
-                    cocs.add( coc );
-                }
-            }
-            
-            DimensionalObject object = new BaseDimensionalObject( dimension, DimensionType.CATEGORY_OPTION_COMBO, null, DISPLAY_NAME_CATEGORYOPTIONCOMBO, cocs );
-
-            return object;
-        }
-
-        if ( ATTRIBUTEOPTIONCOMBO_DIM_ID.equals( dimension ) )
-        {
-            List<NameableObject> aocs = new ArrayList<NameableObject>();
-            
-            for ( String uid : items )
-            {
-                DataElementCategoryOptionCombo aoc = idObjectManager.get( DataElementCategoryOptionCombo.class, uid );
-                
-                if ( aoc != null )
-                {
-                    aocs.add( aoc );
-                }
-            }
-            
-            DimensionalObject object = new BaseDimensionalObject( dimension, DimensionType.ATTRIBUTE_OPTION_COMBO, null, DISPLAY_NAME_ATTRIBUTEOPTIONCOMBO, aocs );
-
-            return object;
-        }
-        
-        if ( PERIOD_DIM_ID.equals( dimension ) )
-        {
-            Calendar calendar = PeriodType.getCalendar();
-
-            Set<Period> periods = new HashSet<>();
-
-            for ( String isoPeriod : items )
-            {
-                if ( RelativePeriodEnum.contains( isoPeriod ) )
-                {
-                    RelativePeriodEnum relativePeriod = RelativePeriodEnum.valueOf( isoPeriod );
-                    List<Period> relativePeriods = RelativePeriods.getRelativePeriodsFromEnum( relativePeriod, relativePeriodDate, format, true );
-                    periods.addAll( relativePeriods );
-                }
-                else
-                {
-                    Period period = PeriodType.getPeriodFromIsoString( isoPeriod );
-
-                    if ( period != null )
-                    {
-                        periods.add( period );
-                    }
-                }
-            }
-
-            if ( periods.isEmpty() )
-            {
-                throw new IllegalQueryException( "Dimension pe is present in query without any valid dimension options" );
-            }
-
-            for ( Period period : periods )
-            {
-                String name = format != null ? format.formatPeriod( period ) : null;
-                period.setName( name );
-                period.setShortName( name );
-
-                if ( !calendar.isIso8601() )
-                {
-                    period.setUid( getLocalPeriodIdentifier( period, calendar ) );
-                }
-            }
-
-            List<Period> periodList = new ArrayList<>( periods );
-            Collections.sort( periodList, AscendingPeriodEndDateComparator.INSTANCE );
-
-            DimensionalObject object = new BaseDimensionalObject( dimension, DimensionType.PERIOD, null, DISPLAY_NAME_PERIOD, asList( periodList ) );
-
-            return object;
-        }
-
-        if ( ORGUNIT_DIM_ID.equals( dimension ) )
-        {
-            List<NameableObject> ous = new ArrayList<>();
-            List<Integer> levels = new ArrayList<>();
-            List<OrganisationUnitGroup> groups = new ArrayList<>();
-
-            for ( String ou : items )
-            {
-                if ( KEY_USER_ORGUNIT.equals( ou ) && userOrgUnits != null && !userOrgUnits.isEmpty() )
-                {
-                    ous.addAll( userOrgUnits );
-                }
-                else if ( KEY_USER_ORGUNIT_CHILDREN.equals( ou ) && userOrgUnits != null && !userOrgUnits.isEmpty() )
-                {
-                    ous.addAll( OrganisationUnit.getSortedChildren( userOrgUnits ) );
-                }
-                else if ( KEY_USER_ORGUNIT_GRANDCHILDREN.equals( ou ) && userOrgUnits != null && !userOrgUnits.isEmpty() )
-                {
-                    ous.addAll( OrganisationUnit.getSortedGrandChildren( userOrgUnits ) );
-                }
-                else if ( ou != null && ou.startsWith( KEY_LEVEL ) )
-                {
-                    int level = DimensionalObjectUtils.getLevelFromLevelParam( ou );
-
-                    if ( level > 0 )
-                    {
-                        levels.add( level );
-                    }
-                }
-                else if ( ou != null && ou.startsWith( KEY_ORGUNIT_GROUP ) )
-                {
-                    String uid = DimensionalObjectUtils.getUidFromGroupParam( ou );
-
-                    OrganisationUnitGroup group = idObjectManager.get( OrganisationUnitGroup.class, uid );
-
-                    if ( group != null )
-                    {
-                        groups.add( group );
-                    }
-                }
-                else if ( CodeGenerator.isValidCode( ou ) )
-                {
-                    OrganisationUnit unit = organisationUnitService.getOrganisationUnit( ou );
-
-                    if ( unit != null )
-                    {
-                        ous.add( unit );
-                    }
-                }
-            }
-
-            ous = ous.stream().distinct().collect( Collectors.toList() ); // Remove duplicates
-            
-            List<NameableObject> orgUnits = new ArrayList<>();
-            List<OrganisationUnit> ousList = NameableObjectUtils.asTypedList( ous );
-
-            if ( !levels.isEmpty() )
-            {
-                orgUnits.addAll( sort( organisationUnitService.getOrganisationUnitsAtLevels( levels, ousList ), IdentifiableObjectNameComparator.INSTANCE ) );
-            }
-
-            if ( !groups.isEmpty() )
-            {
-                orgUnits.addAll( sort( organisationUnitService.getOrganisationUnits( groups, ousList ), IdentifiableObjectNameComparator.INSTANCE ) );
-            }
-
-            // -----------------------------------------------------------------
-            // When levels / groups are present, OUs are considered boundaries
-            // -----------------------------------------------------------------
-
-            if ( levels.isEmpty() && groups.isEmpty() )
-            {
-                orgUnits.addAll( ous );
-            }
-
-            if ( orgUnits.isEmpty() )
-            {
-                throw new IllegalQueryException( "Dimension ou is present in query without any valid dimension options" );
-            }
-
-            orgUnits = orgUnits.stream().distinct().collect( Collectors.toList() ); // Remove duplicates
-            
-            DimensionalObject object = new BaseDimensionalObject( dimension, DimensionType.ORGANISATIONUNIT, null, DISPLAY_NAME_ORGUNIT, orgUnits );
-
-            return object;
-        }
-
-        if ( LONGITUDE_DIM_ID.contains( dimension ) )
-        {
-            DimensionalObject object = new BaseDimensionalObject( dimension, DimensionType.STATIC, null, DISPLAY_NAME_LONGITUDE, new ArrayList<NameableObject>() );
-
-            return object;
-        }
-
-        if ( LATITUDE_DIM_ID.contains( dimension ) )
-        {
-            DimensionalObject object = new BaseDimensionalObject( dimension, DimensionType.STATIC, null, DISPLAY_NAME_LATITUDE, new ArrayList<NameableObject>() );
-
-            return object;
-        }
-
-        DimensionalObject dimObject = idObjectManager.get( DataQueryParams.DYNAMIC_DIM_CLASSES, dimension );
-
-        if ( dimObject != null && dimObject.isDataDimension() )
-        {
-            Class<?> dimClass = ReflectionUtils.getRealClass( dimObject.getClass() );
-            
-            Class<? extends NameableObject> itemClass = DimensionalObject.DIMENSION_CLASS_ITEM_CLASS_MAP.get( dimClass );
-            
-            List<NameableObject> dimItems = !allItems ? asList( idObjectManager.getByUidOrdered( itemClass, items ) ) : dimObject.getItems();
-                        
-            DimensionalObject object = new BaseDimensionalObject( dimension, dimObject.getDimensionType(), null, dimObject.getName(), dimItems, allItems );
-            
-            return object;
-        }
-
-        if ( allowNull )
-        {
-            return null;
-        }
-
-        throw new IllegalQueryException( "Dimension identifier does not reference any dimension: " + dimension );
-    }
-
-    @Override
-    public List<OrganisationUnit> getUserOrgUnits( String userOrgUnit )
-    {
-        List<OrganisationUnit> units = new ArrayList<>();
-        
-        User currentUser = currentUserService.getCurrentUser();
-        
-        if ( userOrgUnit != null )
-        {
-            List<String> ous = DimensionalObjectUtils.getItemsFromParam( userOrgUnit );
-            
-            for ( String ou : ous )
-            {
-                OrganisationUnit unit = idObjectManager.get( OrganisationUnit.class, ou );
-                
-                if ( unit != null )
-                {
-                    units.add( unit );
-                }
-            }
-        }
-        else if ( currentUser != null && currentUser.hasOrganisationUnit() )
-        {
-            units = currentUser.getSortedOrganisationUnits();
-        }
-        
-        return units;
-    }
-
-    // -------------------------------------------------------------------------
     // Supportive methods
     // -------------------------------------------------------------------------
 

=== added file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultDataQueryService.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultDataQueryService.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultDataQueryService.java	2015-11-05 02:57:57 +0000
@@ -0,0 +1,543 @@
+package org.hisp.dhis.analytics.data;
+
+/*
+ * 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 static org.hisp.dhis.analytics.DataQueryParams.DISPLAY_NAME_ATTRIBUTEOPTIONCOMBO;
+import static org.hisp.dhis.analytics.DataQueryParams.DISPLAY_NAME_CATEGORYOPTIONCOMBO;
+import static org.hisp.dhis.analytics.DataQueryParams.DISPLAY_NAME_DATA_X;
+import static org.hisp.dhis.analytics.DataQueryParams.DISPLAY_NAME_LATITUDE;
+import static org.hisp.dhis.analytics.DataQueryParams.DISPLAY_NAME_LONGITUDE;
+import static org.hisp.dhis.analytics.DataQueryParams.DISPLAY_NAME_ORGUNIT;
+import static org.hisp.dhis.analytics.DataQueryParams.DISPLAY_NAME_PERIOD;
+import static org.hisp.dhis.analytics.DataQueryParams.KEY_DE_GROUP;
+import static org.hisp.dhis.common.DimensionalObject.ATTRIBUTEOPTIONCOMBO_DIM_ID;
+import static org.hisp.dhis.common.DimensionalObject.CATEGORYOPTIONCOMBO_DIM_ID;
+import static org.hisp.dhis.common.DimensionalObject.DATA_X_DIM_ID;
+import static org.hisp.dhis.common.DimensionalObject.LATITUDE_DIM_ID;
+import static org.hisp.dhis.common.DimensionalObject.LONGITUDE_DIM_ID;
+import static org.hisp.dhis.common.DimensionalObject.ORGUNIT_DIM_ID;
+import static org.hisp.dhis.common.DimensionalObject.PERIOD_DIM_ID;
+import static org.hisp.dhis.common.IdentifiableObjectUtils.getLocalPeriodIdentifier;
+import static org.hisp.dhis.common.IdentifiableObjectUtils.getUids;
+import static org.hisp.dhis.common.NameableObjectUtils.asList;
+import static org.hisp.dhis.commons.collection.ListUtils.sort;
+import static org.hisp.dhis.commons.util.TextUtils.splitSafe;
+import static org.hisp.dhis.organisationunit.OrganisationUnit.KEY_LEVEL;
+import static org.hisp.dhis.organisationunit.OrganisationUnit.KEY_ORGUNIT_GROUP;
+import static org.hisp.dhis.organisationunit.OrganisationUnit.KEY_USER_ORGUNIT;
+import static org.hisp.dhis.organisationunit.OrganisationUnit.KEY_USER_ORGUNIT_CHILDREN;
+import static org.hisp.dhis.organisationunit.OrganisationUnit.KEY_USER_ORGUNIT_GRANDCHILDREN;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.hisp.dhis.analytics.AggregationType;
+import org.hisp.dhis.analytics.DataQueryParams;
+import org.hisp.dhis.analytics.DataQueryService;
+import org.hisp.dhis.calendar.Calendar;
+import org.hisp.dhis.common.AnalyticalObject;
+import org.hisp.dhis.common.BaseDimensionalObject;
+import org.hisp.dhis.common.CodeGenerator;
+import org.hisp.dhis.common.DataDimensionItem;
+import org.hisp.dhis.common.DimensionType;
+import org.hisp.dhis.common.DimensionalObject;
+import org.hisp.dhis.common.DimensionalObjectUtils;
+import org.hisp.dhis.common.DisplayProperty;
+import org.hisp.dhis.common.IdentifiableObjectManager;
+import org.hisp.dhis.common.IdentifiableProperty;
+import org.hisp.dhis.common.IllegalQueryException;
+import org.hisp.dhis.common.NameableObject;
+import org.hisp.dhis.common.NameableObjectUtils;
+import org.hisp.dhis.common.comparator.IdentifiableObjectNameComparator;
+import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo;
+import org.hisp.dhis.dataelement.DataElementGroup;
+import org.hisp.dhis.dataelement.DataElementOperand;
+import org.hisp.dhis.dataelement.DataElementOperandService;
+import org.hisp.dhis.i18n.I18nFormat;
+import org.hisp.dhis.organisationunit.OrganisationUnit;
+import org.hisp.dhis.organisationunit.OrganisationUnitGroup;
+import org.hisp.dhis.organisationunit.OrganisationUnitService;
+import org.hisp.dhis.period.Period;
+import org.hisp.dhis.period.PeriodType;
+import org.hisp.dhis.period.RelativePeriodEnum;
+import org.hisp.dhis.period.RelativePeriods;
+import org.hisp.dhis.period.comparator.AscendingPeriodEndDateComparator;
+import org.hisp.dhis.program.ProgramService;
+import org.hisp.dhis.program.ProgramStageService;
+import org.hisp.dhis.system.util.ReflectionUtils;
+import org.hisp.dhis.user.CurrentUserService;
+import org.hisp.dhis.user.User;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+* @author Lars Helge Overland
+*/
+public class DefaultDataQueryService
+    implements DataQueryService
+{
+    @Autowired
+    private IdentifiableObjectManager idObjectManager;
+    
+    @Autowired
+    private OrganisationUnitService organisationUnitService;
+
+    @Autowired
+    private DataElementOperandService operandService;
+
+    @Autowired
+    private ProgramService programService;
+    
+    @Autowired
+    private ProgramStageService programStageService;
+    
+    @Autowired
+    private CurrentUserService currentUserService;
+
+    public void setCurrentUserService( CurrentUserService currentUserService )
+    {
+        this.currentUserService = currentUserService; // Testing purposes
+    }
+
+    // -------------------------------------------------------------------------
+    // DataQueryService implementation
+    // -------------------------------------------------------------------------
+
+    @Override
+    public DataQueryParams getFromUrl( Set<String> dimensionParams, Set<String> filterParams, AggregationType aggregationType,
+        String measureCriteria, boolean skipMeta, boolean skipData, boolean skipRounding, boolean completedOnly, boolean hierarchyMeta, boolean ignoreLimit,
+        boolean hideEmptyRows, boolean showHierarchy, DisplayProperty displayProperty, IdentifiableProperty outputIdScheme, 
+        String approvalLevel, Date relativePeriodDate, String userOrgUnit, String program, String stage, I18nFormat format )
+    {
+        DataQueryParams params = new DataQueryParams();
+        
+        params.setIgnoreLimit( ignoreLimit );
+
+        if ( dimensionParams != null && !dimensionParams.isEmpty() )
+        {
+            params.addDimensions( getDimensionalObjects( dimensionParams, relativePeriodDate, userOrgUnit, format ) );
+        }
+
+        if ( filterParams != null && !filterParams.isEmpty() )
+        {
+            params.getFilters().addAll( getDimensionalObjects( filterParams, relativePeriodDate, userOrgUnit, format ) );
+        }
+
+        if ( measureCriteria != null && !measureCriteria.isEmpty() )
+        {
+            params.setMeasureCriteria( DataQueryParams.getMeasureCriteriaFromParam( measureCriteria ) );
+        }
+
+        params.setAggregationType( aggregationType );
+        params.setSkipMeta( skipMeta );
+        params.setSkipData( skipData );
+        params.setSkipRounding( skipRounding );
+        params.setCompletedOnly( completedOnly );
+        params.setHierarchyMeta( hierarchyMeta );
+        params.setHideEmptyRows( hideEmptyRows );
+        params.setShowHierarchy( showHierarchy );
+        params.setDisplayProperty( displayProperty );
+        params.setOutputIdScheme( outputIdScheme );
+        params.setApprovalLevel( approvalLevel );
+        
+        if ( program != null )
+        {
+            params.setProgram( programService.getProgram( program ) );
+        }
+
+        if ( stage != null )
+        {
+            params.setProgramStage( programStageService.getProgramStage( stage ) );
+        }
+
+        return params;
+    }
+
+    @Override
+    public DataQueryParams getFromAnalyticalObject( AnalyticalObject object, I18nFormat format )
+    {
+        DataQueryParams params = new DataQueryParams();
+        
+        if ( object != null )
+        {
+            params.setProgram( object.getProgram() );
+            
+            List<OrganisationUnit> userOrgUnits = getUserOrgUnits( null );
+            
+            Date date = object.getRelativePeriodDate();
+
+            object.populateAnalyticalProperties();
+
+            for ( DimensionalObject column : object.getColumns() )
+            {
+                params.addDimension( getDimension( column.getDimension(), getUids( column.getItems() ), date, userOrgUnits, format, false ) );
+            }
+
+            for ( DimensionalObject row : object.getRows() )
+            {
+                params.addDimension( getDimension( row.getDimension(), getUids( row.getItems() ), date, userOrgUnits, format, false ) );
+            }
+
+            for ( DimensionalObject filter : object.getFilters() )
+            {
+                params.getFilters().add( getDimension( filter.getDimension(), getUids( filter.getItems() ), date, userOrgUnits, format, false ) );
+            }
+        }
+
+        return params;
+    }
+
+    @Override
+    public List<DimensionalObject> getDimensionalObjects( Set<String> dimensionParams, Date relativePeriodDate, String userOrgUnit, I18nFormat format )
+    {
+        List<DimensionalObject> list = new ArrayList<>();
+        
+        List<OrganisationUnit> userOrgUnits = getUserOrgUnits( userOrgUnit );
+
+        if ( dimensionParams != null )
+        {
+            for ( String param : dimensionParams )
+            {
+                String dimension = DimensionalObjectUtils.getDimensionFromParam( param );
+                List<String> items = DimensionalObjectUtils.getDimensionItemsFromParam( param );
+
+                if ( dimension != null && items != null )
+                {
+                    list.add( getDimension( dimension, items, relativePeriodDate, userOrgUnits, format, false ) );
+                }
+            }
+        }
+
+        return list;
+    }
+
+    // TODO verify that current user can read each dimension and dimension item
+    // TODO optimize so that org unit levels + boundary are used in query instead of fetching all org units one by one
+
+    @Override
+    public DimensionalObject getDimension( String dimension, List<String> items, Date relativePeriodDate, 
+        List<OrganisationUnit> userOrgUnits, I18nFormat format, boolean allowNull )
+    {
+        final boolean allItems = items.isEmpty();
+        
+        if ( DATA_X_DIM_ID.equals( dimension ) )
+        {
+            List<NameableObject> dataDimensionItems = new ArrayList<>();
+
+            for ( String uid : items )
+            {
+                if ( uid.startsWith( KEY_DE_GROUP ) )
+                {
+                    String groupUid = DimensionalObjectUtils.getUidFromGroupParam( uid );
+                    
+                    DataElementGroup group = idObjectManager.get( DataElementGroup.class, groupUid );
+                    
+                    if ( group != null )
+                    {
+                        dataDimensionItems.addAll( group.getMembers() );
+                    }
+                }
+                else if ( DimensionalObjectUtils.isValidDimensionalOperand( uid ) )
+                {
+                    DataElementOperand operand = operandService.getDataElementOperand( 
+                        splitSafe( uid, DataElementOperand.ESCAPED_SEPARATOR, 0 ), splitSafe( uid, DataElementOperand.ESCAPED_SEPARATOR, 1 ) );
+                    
+                    if ( operand != null )
+                    {
+                        dataDimensionItems.add( operand );
+                    }
+                }
+                else if ( CodeGenerator.isValidCode( uid ) )
+                {
+                    NameableObject item = idObjectManager.get( DataDimensionItem.DATA_DIMENSION_CLASSES, uid );
+                    
+                    if ( item != null )
+                    {
+                        dataDimensionItems.add( item );
+                    }
+                }
+            }
+            
+            if ( dataDimensionItems.isEmpty() )
+            {
+                throw new IllegalQueryException( "Dimension dx is present in query without any valid dimension options" );
+            }
+
+            DimensionalObject object = new BaseDimensionalObject( dimension, DimensionType.DATA_X, null, DISPLAY_NAME_DATA_X, dataDimensionItems );
+            
+            return object;
+            
+            //TODO proper handling of operands and option combinations
+        }
+
+        if ( CATEGORYOPTIONCOMBO_DIM_ID.equals( dimension ) )
+        {
+            List<NameableObject> cocs = new ArrayList<NameableObject>();
+            
+            for ( String uid : items )
+            {
+                DataElementCategoryOptionCombo coc = idObjectManager.get( DataElementCategoryOptionCombo.class, uid );
+                
+                if ( coc != null )
+                {
+                    cocs.add( coc );
+                }
+            }
+            
+            DimensionalObject object = new BaseDimensionalObject( dimension, DimensionType.CATEGORY_OPTION_COMBO, null, DISPLAY_NAME_CATEGORYOPTIONCOMBO, cocs );
+
+            return object;
+        }
+
+        if ( ATTRIBUTEOPTIONCOMBO_DIM_ID.equals( dimension ) )
+        {
+            List<NameableObject> aocs = new ArrayList<NameableObject>();
+            
+            for ( String uid : items )
+            {
+                DataElementCategoryOptionCombo aoc = idObjectManager.get( DataElementCategoryOptionCombo.class, uid );
+                
+                if ( aoc != null )
+                {
+                    aocs.add( aoc );
+                }
+            }
+            
+            DimensionalObject object = new BaseDimensionalObject( dimension, DimensionType.ATTRIBUTE_OPTION_COMBO, null, DISPLAY_NAME_ATTRIBUTEOPTIONCOMBO, aocs );
+
+            return object;
+        }
+        
+        if ( PERIOD_DIM_ID.equals( dimension ) )
+        {
+            Calendar calendar = PeriodType.getCalendar();
+
+            Set<Period> periods = new HashSet<>();
+
+            for ( String isoPeriod : items )
+            {
+                if ( RelativePeriodEnum.contains( isoPeriod ) )
+                {
+                    RelativePeriodEnum relativePeriod = RelativePeriodEnum.valueOf( isoPeriod );
+                    List<Period> relativePeriods = RelativePeriods.getRelativePeriodsFromEnum( relativePeriod, relativePeriodDate, format, true );
+                    periods.addAll( relativePeriods );
+                }
+                else
+                {
+                    Period period = PeriodType.getPeriodFromIsoString( isoPeriod );
+
+                    if ( period != null )
+                    {
+                        periods.add( period );
+                    }
+                }
+            }
+
+            if ( periods.isEmpty() )
+            {
+                throw new IllegalQueryException( "Dimension pe is present in query without any valid dimension options" );
+            }
+
+            for ( Period period : periods )
+            {
+                String name = format != null ? format.formatPeriod( period ) : null;
+                period.setName( name );
+                period.setShortName( name );
+
+                if ( !calendar.isIso8601() )
+                {
+                    period.setUid( getLocalPeriodIdentifier( period, calendar ) );
+                }
+            }
+
+            List<Period> periodList = new ArrayList<>( periods );
+            Collections.sort( periodList, AscendingPeriodEndDateComparator.INSTANCE );
+
+            DimensionalObject object = new BaseDimensionalObject( dimension, DimensionType.PERIOD, null, DISPLAY_NAME_PERIOD, asList( periodList ) );
+
+            return object;
+        }
+
+        if ( ORGUNIT_DIM_ID.equals( dimension ) )
+        {
+            List<NameableObject> ous = new ArrayList<>();
+            List<Integer> levels = new ArrayList<>();
+            List<OrganisationUnitGroup> groups = new ArrayList<>();
+
+            for ( String ou : items )
+            {
+                if ( KEY_USER_ORGUNIT.equals( ou ) && userOrgUnits != null && !userOrgUnits.isEmpty() )
+                {
+                    ous.addAll( userOrgUnits );
+                }
+                else if ( KEY_USER_ORGUNIT_CHILDREN.equals( ou ) && userOrgUnits != null && !userOrgUnits.isEmpty() )
+                {
+                    ous.addAll( OrganisationUnit.getSortedChildren( userOrgUnits ) );
+                }
+                else if ( KEY_USER_ORGUNIT_GRANDCHILDREN.equals( ou ) && userOrgUnits != null && !userOrgUnits.isEmpty() )
+                {
+                    ous.addAll( OrganisationUnit.getSortedGrandChildren( userOrgUnits ) );
+                }
+                else if ( ou != null && ou.startsWith( KEY_LEVEL ) )
+                {
+                    int level = DimensionalObjectUtils.getLevelFromLevelParam( ou );
+
+                    if ( level > 0 )
+                    {
+                        levels.add( level );
+                    }
+                }
+                else if ( ou != null && ou.startsWith( KEY_ORGUNIT_GROUP ) )
+                {
+                    String uid = DimensionalObjectUtils.getUidFromGroupParam( ou );
+
+                    OrganisationUnitGroup group = idObjectManager.get( OrganisationUnitGroup.class, uid );
+
+                    if ( group != null )
+                    {
+                        groups.add( group );
+                    }
+                }
+                else if ( CodeGenerator.isValidCode( ou ) )
+                {
+                    OrganisationUnit unit = organisationUnitService.getOrganisationUnit( ou );
+
+                    if ( unit != null )
+                    {
+                        ous.add( unit );
+                    }
+                }
+            }
+
+            ous = ous.stream().distinct().collect( Collectors.toList() ); // Remove duplicates
+            
+            List<NameableObject> orgUnits = new ArrayList<>();
+            List<OrganisationUnit> ousList = NameableObjectUtils.asTypedList( ous );
+
+            if ( !levels.isEmpty() )
+            {
+                orgUnits.addAll( sort( organisationUnitService.getOrganisationUnitsAtLevels( levels, ousList ), IdentifiableObjectNameComparator.INSTANCE ) );
+            }
+
+            if ( !groups.isEmpty() )
+            {
+                orgUnits.addAll( sort( organisationUnitService.getOrganisationUnits( groups, ousList ), IdentifiableObjectNameComparator.INSTANCE ) );
+            }
+
+            // -----------------------------------------------------------------
+            // When levels / groups are present, OUs are considered boundaries
+            // -----------------------------------------------------------------
+
+            if ( levels.isEmpty() && groups.isEmpty() )
+            {
+                orgUnits.addAll( ous );
+            }
+
+            if ( orgUnits.isEmpty() )
+            {
+                throw new IllegalQueryException( "Dimension ou is present in query without any valid dimension options" );
+            }
+
+            orgUnits = orgUnits.stream().distinct().collect( Collectors.toList() ); // Remove duplicates
+            
+            DimensionalObject object = new BaseDimensionalObject( dimension, DimensionType.ORGANISATIONUNIT, null, DISPLAY_NAME_ORGUNIT, orgUnits );
+
+            return object;
+        }
+
+        if ( LONGITUDE_DIM_ID.contains( dimension ) )
+        {
+            DimensionalObject object = new BaseDimensionalObject( dimension, DimensionType.STATIC, null, DISPLAY_NAME_LONGITUDE, new ArrayList<NameableObject>() );
+
+            return object;
+        }
+
+        if ( LATITUDE_DIM_ID.contains( dimension ) )
+        {
+            DimensionalObject object = new BaseDimensionalObject( dimension, DimensionType.STATIC, null, DISPLAY_NAME_LATITUDE, new ArrayList<NameableObject>() );
+
+            return object;
+        }
+
+        DimensionalObject dimObject = idObjectManager.get( DataQueryParams.DYNAMIC_DIM_CLASSES, dimension );
+
+        if ( dimObject != null && dimObject.isDataDimension() )
+        {
+            Class<?> dimClass = ReflectionUtils.getRealClass( dimObject.getClass() );
+            
+            Class<? extends NameableObject> itemClass = DimensionalObject.DIMENSION_CLASS_ITEM_CLASS_MAP.get( dimClass );
+            
+            List<NameableObject> dimItems = !allItems ? asList( idObjectManager.getByUidOrdered( itemClass, items ) ) : dimObject.getItems();
+                        
+            DimensionalObject object = new BaseDimensionalObject( dimension, dimObject.getDimensionType(), null, dimObject.getName(), dimItems, allItems );
+            
+            return object;
+        }
+
+        if ( allowNull )
+        {
+            return null;
+        }
+
+        throw new IllegalQueryException( "Dimension identifier does not reference any dimension: " + dimension );
+    }
+
+    @Override
+    public List<OrganisationUnit> getUserOrgUnits( String userOrgUnit )
+    {
+        List<OrganisationUnit> units = new ArrayList<>();
+        
+        User currentUser = currentUserService.getCurrentUser();
+        
+        if ( userOrgUnit != null )
+        {
+            List<String> ous = DimensionalObjectUtils.getItemsFromParam( userOrgUnit );
+            
+            for ( String ou : ous )
+            {
+                OrganisationUnit unit = idObjectManager.get( OrganisationUnit.class, ou );
+                
+                if ( unit != null )
+                {
+                    units.add( unit );
+                }
+            }
+        }
+        else if ( currentUser != null && currentUser.hasOrganisationUnit() )
+        {
+            units = currentUser.getSortedOrganisationUnits();
+        }
+        
+        return units;
+    }
+}

=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultQueryPlanner.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultQueryPlanner.java	2015-10-08 13:50:01 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultQueryPlanner.java	2015-11-05 02:57:57 +0000
@@ -150,11 +150,6 @@
             violation = "Category option combos cannot be specified when data elements are not specified";
         }
 
-        if ( !params.getProgramIndicators().isEmpty() && !params.hasProgram() )
-        {
-            violation = "Program must be specified when program indicators are specified";
-        }
-
         if ( !params.getAllProgramDataElements().isEmpty() && !params.hasProgram() )
         {
             violation = "Program must be specified when tracker data elements are specified";

=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/EventAnalyticsService.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/EventAnalyticsService.java	2015-09-17 16:41:41 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/EventAnalyticsService.java	2015-11-05 02:57:57 +0000
@@ -28,14 +28,7 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import java.util.Set;
-
-import org.hisp.dhis.analytics.AggregationType;
-import org.hisp.dhis.analytics.EventOutputType;
-import org.hisp.dhis.analytics.SortOrder;
 import org.hisp.dhis.common.AnalyticalObject;
-import org.hisp.dhis.common.DisplayProperty;
-import org.hisp.dhis.common.EventAnalyticalObject;
 import org.hisp.dhis.common.Grid;
 import org.hisp.dhis.i18n.I18nFormat;
 
@@ -44,69 +37,17 @@
  */
 public interface EventAnalyticsService
 {    
+    String ITEM_EVENT = "psi";
+    String ITEM_PROGRAM_STAGE = "ps";
+    String ITEM_EXECUTION_DATE = "eventdate";
+    String ITEM_LONGITUDE = "longitude";
+    String ITEM_LATITUDE = "latitude";
+    String ITEM_ORG_UNIT_NAME = "ouname";
+    String ITEM_ORG_UNIT_CODE = "oucode";
+    
     Grid getAggregatedEventData( EventQueryParams params );
     
     Grid getAggregatedEventData( AnalyticalObject object, I18nFormat format );
     
     Grid getEvents( EventQueryParams params );
-
-    /**
-     * Used for aggregate query.
-     * 
-     * @param program the program identifier.
-     * @param stage the program stage identifier.
-     * @param startDate the start date.
-     * @param endDate the end date.
-     * @param dimension the set of dimensions.
-     * @param filter the set of filters.
-     * @param value the value dimension identifier.
-     * @param aggregationType the aggregation type for the value dimension.
-     * @param skipMeta whether to skip meta-data in the response.
-     * @param skipData whether to skip data in the response.
-     * @param skipRounding whether to skip rounding of values in response.
-     * @param completedOnly whether to only include completed events.
-     * @param hierarchyMeta whether to include hierarchy meta-data in the response.
-     * @param showHierarchy whether to include hierarchy meta-data names in the response.
-     * @param sortOrder the sort order of the aggregate values.
-     * @param limit the max limit of records to return.
-     * @param outputType the event output type.
-     * @param collapseDataDimensions collapse data dimensions into a single dimension.
-     * @param aggregateData return aggregated data values for data dimensions instead of items.
-     * @param displayProperty the display property to use for meta-data.
-     * @param userOrgUnit the user organisation unit to use, overrides current user.
-     * @param format the i18n format.
-     */
-    EventQueryParams getFromUrl( String program, String stage, String startDate, String endDate, 
-        Set<String> dimension, Set<String> filter, String value, AggregationType aggregationType, 
-        boolean skipMeta, boolean skipData, boolean skipRounding, boolean completedOnly, boolean hierarchyMeta, boolean showHierarchy, SortOrder sortOrder, Integer limit, 
-        EventOutputType outputType, boolean collapseDataDimensions, boolean aggregateData, DisplayProperty displayProperty, String userOrgUnit, I18nFormat format );
-
-    /**
-     * Used for event query.
-     * 
-     * @param program the program identifier.
-     * @param stage the program stage identifier.
-     * @param startDate the start date.
-     * @param endDate the end date.
-     * @param dimension the set of dimensions.
-     * @param filter the set of filters.
-     * @param ouMode the organisation unit mode.
-     * @param asc the dimensions to be sorted ascending.
-     * @param desc the dimensions to be sorted descending.
-     * @param skipMeta whether to skip meta-data in the response.
-     * @param skipData whether to skip data in the response.
-     * @param completedOnly whether to only include completed events.
-     * @param hierarchyMeta whether to include hierarchy meta-data in the response.
-     * @param coordinatesOnly whether to only return events which have coordinates.
-     * @param displayProperty the display property to use for meta-data.
-     * @param userOrgUnit the user organisation unit to use, overrides current user.
-     * @param page the page number.
-     * @param pageSize the page size.
-     * @param format the i18n format.
-     */
-    EventQueryParams getFromUrl( String program, String stage, String startDate, String endDate, Set<String> dimension, Set<String> filter, 
-        String ouMode, Set<String> asc, Set<String> desc, boolean skipMeta, boolean skipData, boolean completedOnly, boolean hierarchyMeta, boolean coordinatesOnly, 
-        DisplayProperty displayProperty, String userOrgUnit, Integer page, Integer pageSize, I18nFormat format );
-    
-    EventQueryParams getFromAnalyticalObject( EventAnalyticalObject object, I18nFormat format );
 }

=== added file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/EventDataQueryService.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/EventDataQueryService.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/EventDataQueryService.java	2015-11-05 02:57:57 +0000
@@ -0,0 +1,104 @@
+package org.hisp.dhis.analytics.event;
+
+/*
+ * 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 java.util.Set;
+
+import org.hisp.dhis.analytics.AggregationType;
+import org.hisp.dhis.analytics.EventOutputType;
+import org.hisp.dhis.analytics.SortOrder;
+import org.hisp.dhis.common.DisplayProperty;
+import org.hisp.dhis.common.EventAnalyticalObject;
+import org.hisp.dhis.i18n.I18nFormat;
+
+/**
+ * @author Lars Helge Overland
+ */
+public interface EventDataQueryService
+{
+    /**
+     * Used for aggregate query.
+     * 
+     * @param program the program identifier.
+     * @param stage the program stage identifier.
+     * @param startDate the start date.
+     * @param endDate the end date.
+     * @param dimension the set of dimensions.
+     * @param filter the set of filters.
+     * @param value the value dimension identifier.
+     * @param aggregationType the aggregation type for the value dimension.
+     * @param skipMeta whether to skip meta-data in the response.
+     * @param skipData whether to skip data in the response.
+     * @param skipRounding whether to skip rounding of values in response.
+     * @param completedOnly whether to only include completed events.
+     * @param hierarchyMeta whether to include hierarchy meta-data in the response.
+     * @param showHierarchy whether to include hierarchy meta-data names in the response.
+     * @param sortOrder the sort order of the aggregate values.
+     * @param limit the max limit of records to return.
+     * @param outputType the event output type.
+     * @param collapseDataDimensions collapse data dimensions into a single dimension.
+     * @param aggregateData return aggregated data values for data dimensions instead of items.
+     * @param displayProperty the display property to use for meta-data.
+     * @param userOrgUnit the user organisation unit to use, overrides current user.
+     * @param format the i18n format.
+     */
+    EventQueryParams getFromUrl( String program, String stage, String startDate, String endDate, 
+        Set<String> dimension, Set<String> filter, String value, AggregationType aggregationType, 
+        boolean skipMeta, boolean skipData, boolean skipRounding, boolean completedOnly, boolean hierarchyMeta, boolean showHierarchy, SortOrder sortOrder, Integer limit, 
+        EventOutputType outputType, boolean collapseDataDimensions, boolean aggregateData, DisplayProperty displayProperty, String userOrgUnit, I18nFormat format );
+
+    /**
+     * Used for event query.
+     * 
+     * @param program the program identifier.
+     * @param stage the program stage identifier.
+     * @param startDate the start date.
+     * @param endDate the end date.
+     * @param dimension the set of dimensions.
+     * @param filter the set of filters.
+     * @param ouMode the organisation unit mode.
+     * @param asc the dimensions to be sorted ascending.
+     * @param desc the dimensions to be sorted descending.
+     * @param skipMeta whether to skip meta-data in the response.
+     * @param skipData whether to skip data in the response.
+     * @param completedOnly whether to only include completed events.
+     * @param hierarchyMeta whether to include hierarchy meta-data in the response.
+     * @param coordinatesOnly whether to only return events which have coordinates.
+     * @param displayProperty the display property to use for meta-data.
+     * @param userOrgUnit the user organisation unit to use, overrides current user.
+     * @param page the page number.
+     * @param pageSize the page size.
+     * @param format the i18n format.
+     */
+    EventQueryParams getFromUrl( String program, String stage, String startDate, String endDate, Set<String> dimension, Set<String> filter, 
+        String ouMode, Set<String> asc, Set<String> desc, boolean skipMeta, boolean skipData, boolean completedOnly, boolean hierarchyMeta, boolean coordinatesOnly, 
+        DisplayProperty displayProperty, String userOrgUnit, Integer page, Integer pageSize, I18nFormat format );
+    
+    EventQueryParams getFromAnalyticalObject( EventAnalyticalObject object, I18nFormat format );
+}

=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/DefaultEventAnalyticsService.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/DefaultEventAnalyticsService.java	2015-10-19 12:40:24 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/DefaultEventAnalyticsService.java	2015-11-05 02:57:57 +0000
@@ -31,34 +31,26 @@
 import static org.hisp.dhis.analytics.AnalyticsService.NAMES_META_KEY;
 import static org.hisp.dhis.analytics.AnalyticsService.OU_HIERARCHY_KEY;
 import static org.hisp.dhis.analytics.AnalyticsService.OU_NAME_HIERARCHY_KEY;
-import static org.hisp.dhis.common.DimensionalObject.DIMENSION_NAME_SEP;
-import static org.hisp.dhis.common.DimensionalObject.ITEM_SEP;
 import static org.hisp.dhis.common.DimensionalObject.ORGUNIT_DIM_ID;
 import static org.hisp.dhis.common.DimensionalObject.PERIOD_DIM_ID;
-import static org.hisp.dhis.common.DimensionalObjectUtils.getDimensionFromParam;
-import static org.hisp.dhis.common.DimensionalObjectUtils.getDimensionItemsFromParam;
 import static org.hisp.dhis.common.IdentifiableObjectUtils.getUids;
 import static org.hisp.dhis.common.NameableObjectUtils.asTypedList;
 import static org.hisp.dhis.organisationunit.OrganisationUnit.getParentGraphMap;
 import static org.hisp.dhis.organisationunit.OrganisationUnit.getParentNameGraphMap;
 
 import java.util.Collection;
-import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import org.apache.commons.lang3.StringUtils;
-import org.hisp.dhis.analytics.AggregationType;
 import org.hisp.dhis.analytics.AnalyticsSecurityManager;
 import org.hisp.dhis.analytics.AnalyticsService;
 import org.hisp.dhis.analytics.DataQueryParams;
-import org.hisp.dhis.analytics.EventOutputType;
-import org.hisp.dhis.analytics.SortOrder;
 import org.hisp.dhis.analytics.event.EventAnalyticsManager;
 import org.hisp.dhis.analytics.event.EventAnalyticsService;
+import org.hisp.dhis.analytics.event.EventDataQueryService;
 import org.hisp.dhis.analytics.event.EventQueryParams;
 import org.hisp.dhis.analytics.event.EventQueryPlanner;
 import org.hisp.dhis.common.AnalyticalObject;
@@ -73,73 +65,28 @@
 import org.hisp.dhis.common.NameableObject;
 import org.hisp.dhis.common.NameableObjectUtils;
 import org.hisp.dhis.common.Pager;
-import org.hisp.dhis.common.QueryFilter;
 import org.hisp.dhis.common.QueryItem;
-import org.hisp.dhis.common.QueryOperator;
-import org.hisp.dhis.common.ValueType;
-import org.hisp.dhis.commons.collection.ListUtils;
-import org.hisp.dhis.dataelement.DataElement;
-import org.hisp.dhis.dataelement.DataElementService;
 import org.hisp.dhis.i18n.I18nFormat;
-import org.hisp.dhis.legend.LegendService;
-import org.hisp.dhis.legend.LegendSet;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
 import org.hisp.dhis.program.Program;
-import org.hisp.dhis.program.ProgramIndicator;
-import org.hisp.dhis.program.ProgramIndicatorService;
-import org.hisp.dhis.program.ProgramService;
 import org.hisp.dhis.program.ProgramStage;
-import org.hisp.dhis.program.ProgramStageService;
 import org.hisp.dhis.system.grid.ListGrid;
-import org.hisp.dhis.system.util.DateUtils;
-import org.hisp.dhis.trackedentity.TrackedEntityAttribute;
-import org.hisp.dhis.trackedentity.TrackedEntityAttributeService;
 import org.hisp.dhis.user.CurrentUserService;
 import org.hisp.dhis.user.User;
 import org.hisp.dhis.util.Timer;
 import org.springframework.beans.factory.annotation.Autowired;
 
-import com.google.common.base.MoreObjects;
-import com.google.common.collect.Lists;
-
 /**
  * @author Lars Helge Overland
  */
 public class DefaultEventAnalyticsService
     implements EventAnalyticsService
 {
-    private static final String ITEM_EVENT = "psi";
-    private static final String ITEM_PROGRAM_STAGE = "ps";
-    private static final String ITEM_EXECUTION_DATE = "eventdate";
-    private static final String ITEM_LONGITUDE = "longitude";
-    private static final String ITEM_LATITUDE = "latitude";
-    private static final String ITEM_ORG_UNIT_NAME = "ouname";
-    private static final String ITEM_ORG_UNIT_CODE = "oucode";
-    private static final String COL_NAME_EVENTDATE = "executiondate";
-
-    private static final List<String> SORTABLE_ITEMS = Lists.newArrayList( 
-        ITEM_EXECUTION_DATE, ITEM_ORG_UNIT_NAME, ITEM_ORG_UNIT_CODE );
-
-    @Autowired
-    private ProgramService programService;
-
-    @Autowired
-    private ProgramStageService programStageService;
-
-    @Autowired
-    private DataElementService dataElementService;
-
-    @Autowired
-    private TrackedEntityAttributeService attributeService;
-    
-    @Autowired
-    private ProgramIndicatorService programIndicatorService;
-    
-    @Autowired
-    private LegendService legendService;
-
     @Autowired
     private EventAnalyticsManager analyticsManager;
+    
+    @Autowired
+    private EventDataQueryService eventDataQueryService;
 
     @Autowired
     private AnalyticsSecurityManager securityManager;
@@ -148,9 +95,6 @@
     private EventQueryPlanner queryPlanner;
 
     @Autowired
-    private AnalyticsService analyticsService;
-
-    @Autowired
     private CurrentUserService currentUserService;
     
     // -------------------------------------------------------------------------
@@ -280,7 +224,7 @@
     @Override
     public Grid getAggregatedEventData( AnalyticalObject object, I18nFormat format )
     {
-        EventQueryParams params = getFromAnalyticalObject( (EventAnalyticalObject) object, format );
+        EventQueryParams params = eventDataQueryService.getFromAnalyticalObject( (EventAnalyticalObject) object, format );
         
         return getAggregatedEventData( params );
     }
@@ -373,229 +317,10 @@
         return grid;
     }
 
-    @Override
-    public EventQueryParams getFromUrl( String program, String stage, String startDate, String endDate,
-        Set<String> dimension, Set<String> filter, String value, AggregationType aggregationType, boolean skipMeta, boolean skipData, boolean skipRounding, 
-        boolean completedOnly, boolean hierarchyMeta, boolean showHierarchy, SortOrder sortOrder, Integer limit, EventOutputType outputType, boolean collapseDataDimensions, 
-        boolean aggregateData, DisplayProperty displayProperty, String userOrgUnit, I18nFormat format )
-    {
-        EventQueryParams params = getFromUrl( program, stage, startDate, endDate, dimension, filter, null, null, null,
-            skipMeta, skipData, completedOnly, hierarchyMeta, false, displayProperty, userOrgUnit, null, null, format );
-                
-        params.setValue( getValueDimension( value ) );
-        params.setAggregationType( aggregationType );
-        params.setSkipRounding( skipRounding );
-        params.setShowHierarchy( showHierarchy );
-        params.setSortOrder( sortOrder );
-        params.setLimit( limit );
-        params.setOutputType( MoreObjects.firstNonNull( outputType, EventOutputType.EVENT ) );
-        params.setCollapseDataDimensions( collapseDataDimensions );
-        params.setAggregateData( aggregateData );
-
-        return params;
-    }
-
-    @Override
-    public EventQueryParams getFromUrl( String program, String stage, String startDate, String endDate,
-        Set<String> dimension, Set<String> filter, String ouMode, Set<String> asc, Set<String> desc,
-        boolean skipMeta, boolean skipData, boolean completedOnly, boolean hierarchyMeta, boolean coordinatesOnly, 
-        DisplayProperty displayProperty, String userOrgUnit, Integer page, Integer pageSize, I18nFormat format )
-    {
-        EventQueryParams params = new EventQueryParams();
-        
-        List<OrganisationUnit> userOrgUnits = analyticsService.getUserOrgUnits( userOrgUnit );
-
-        Program pr = programService.getProgram( program );
-
-        if ( pr == null )
-        {
-            throw new IllegalQueryException( "Program does not exist: " + program );
-        }
-
-        ProgramStage ps = programStageService.getProgramStage( stage );
-
-        if ( StringUtils.isNotEmpty( stage ) && ps == null )
-        {
-            throw new IllegalQueryException( "Program stage is specified but does not exist: " + stage );
-        }
-
-        Date start = null;
-        Date end = null;
-
-        if ( startDate != null && endDate != null )
-        {
-            try
-            {
-                start = DateUtils.getMediumDate( startDate );
-                end = DateUtils.getMediumDate( endDate );
-            }
-            catch ( RuntimeException ex )
-            {
-                throw new IllegalQueryException( "Start date or end date is invalid: " + startDate + " - " + endDate );
-            }
-        }
-
-        if ( dimension != null )
-        {
-            for ( String dim : dimension )
-            {
-                String dimensionId = getDimensionFromParam( dim );
-                List<String> items = getDimensionItemsFromParam( dim );                
-                DimensionalObject dimObj = analyticsService.getDimension( dimensionId, items, null, userOrgUnits, format, true );
-                
-                if ( dimObj != null )
-                {
-                    params.getDimensions().add( dimObj );
-                }
-                else
-                {
-                    params.getItems().add( getQueryItem( dim ) );
-                }
-            }
-        }
-
-        if ( filter != null )
-        {
-            for ( String dim : filter )
-            {
-                String dimensionId = getDimensionFromParam( dim );
-                List<String> items = getDimensionItemsFromParam( dim );                
-                DimensionalObject dimObj = analyticsService.getDimension( dimensionId, items, null, userOrgUnits, format, true );
-                
-                if ( dimObj != null )
-                {
-                    params.getFilters().add( dimObj );
-                }
-                else
-                {
-                    params.getItemFilters().add( getQueryItem( dim ) );
-                }
-            }
-        }
-
-        if ( asc != null )
-        {
-            for ( String sort : asc )
-            {
-                params.getAsc().add( getSortItem( sort ) );
-            }
-        }
-
-        if ( desc != null )
-        {
-            for ( String sort : desc )
-            {
-                params.getDesc().add( getSortItem( sort ) );
-            }
-        }
-
-        params.setProgram( pr );
-        params.setProgramStage( ps );
-        params.setStartDate( start );
-        params.setEndDate( end );
-        params.setOrganisationUnitMode( ouMode );
-        params.setSkipMeta( skipMeta );
-        params.setSkipData( skipData );
-        params.setCompletedOnly( completedOnly );
-        params.setHierarchyMeta( hierarchyMeta );
-        params.setCoordinatesOnly( coordinatesOnly );
-        params.setDisplayProperty( displayProperty );
-        params.setPage( page );
-        params.setPageSize( pageSize );
-        
-        return params;
-    }
-
-    @Override
-    public EventQueryParams getFromAnalyticalObject( EventAnalyticalObject object, I18nFormat format )
-    {        
-        EventQueryParams params = new EventQueryParams();
-
-        if ( object != null )
-        {
-            Date date = object.getRelativePeriodDate();
-            
-            object.populateAnalyticalProperties();
-
-            for ( DimensionalObject dimension : ListUtils.union( object.getColumns(), object.getRows() ) )
-            {
-                DimensionalObject dimObj = analyticsService.
-                    getDimension( dimension.getDimension(), getUids( dimension.getItems() ), date, null, format, true );
-                
-                if ( dimObj != null )
-                {
-                    params.getDimensions().add( dimObj );
-                }
-                else
-                {
-                    params.getItems().add( getQueryItem( dimension.getDimension(), dimension.getFilter() ) );
-                }
-            }
-            
-            for ( DimensionalObject filter : object.getFilters() )
-            {
-                DimensionalObject dimObj = analyticsService.
-                    getDimension( filter.getDimension(), getUids( filter.getItems() ), date, null, format, true );
-                
-                if ( dimObj != null )
-                {
-                    params.getFilters().add( dimObj );
-                }
-                else
-                {
-                    params.getItemFilters().add( getQueryItem( filter.getDimension(), filter.getFilter() ) );
-                }
-            }
-
-            params.setProgram( object.getProgram() );
-            params.setProgramStage( object.getProgramStage() );
-            params.setStartDate( object.getStartDate() );
-            params.setEndDate( object.getEndDate() );
-            params.setValue( object.getValue() );
-            params.setOutputType( object.getOutputType() );
-        }
-        
-        return params;
-    }
-    
     // -------------------------------------------------------------------------
     // Supportive methods
     // -------------------------------------------------------------------------
 
-    private QueryItem getQueryItem( String dimension, String filter )
-    {
-        if ( filter != null )
-        {
-            dimension += DIMENSION_NAME_SEP + filter;
-        }
-                
-        return getQueryItem( dimension );
-    }
-    
-    private QueryItem getQueryItem( String dimensionString )
-    {
-        String[] split = dimensionString.split( DIMENSION_NAME_SEP );
-
-        if ( split == null || ( split.length % 2 != 1 ) )
-        {
-            throw new IllegalQueryException( "Query item or filter is invalid: " + dimensionString );
-        }
-        
-        QueryItem queryItem = getQueryItemFromDimension( split[0] );
-        
-        if ( split.length > 1 ) // Filters specified
-        {
-            for ( int i = 1; i < split.length; i += 2 )
-            {
-                QueryOperator operator = QueryOperator.fromString( split[i] );
-                QueryFilter filter = new QueryFilter( operator, split[i+1] );
-                queryItem.getFilters().add( filter );
-            }
-        }
-        
-        return queryItem;
-    }
-    
     private Map<String, String> getUidNameMap( EventQueryParams params )
     {
         Map<String, String> map = new HashMap<>();
@@ -670,72 +395,4 @@
 
         return map;
     }
-
-    private String getSortItem( String item )
-    {
-        if ( !SORTABLE_ITEMS.contains( item.toLowerCase() ) && getQueryItem( item ) == null )
-        {
-            throw new IllegalQueryException( "Descending sort item is invalid: " + item );
-        }
-
-        item = ITEM_EXECUTION_DATE.equalsIgnoreCase( item ) ? COL_NAME_EVENTDATE : item;
-
-        return item;
-    }
-
-    private QueryItem getQueryItemFromDimension( String dimension )
-    {
-        String[] split = dimension.split( ITEM_SEP );
-
-        String item = split[0];
-
-        LegendSet legendSet = split.length > 1 && split[1] != null ? legendService.getLegendSet( split[1] ) : null;
-        
-        DataElement de = dataElementService.getDataElement( item );
-
-        if ( de != null ) //TODO check if part of program
-        {
-            return new QueryItem( de, legendSet, de.getValueType(), de.getAggregationType(), de.getOptionSet() );
-        }
-
-        TrackedEntityAttribute at = attributeService.getTrackedEntityAttribute( item );
-
-        if ( at != null )
-        {
-            return new QueryItem( at, legendSet, at.getValueType(), at.getAggregationType(), at.getOptionSet() );
-        }
-        
-        ProgramIndicator pi = programIndicatorService.getProgramIndicatorByUid( item );
-        
-        if ( pi != null )
-        {
-            return new QueryItem( pi, legendSet, ValueType.NUMBER, pi.getAggregationType(), null );
-        }
-
-        throw new IllegalQueryException( "Item identifier does not reference any data element or attribute part of the program: " + item );
-    }
-    
-    private DimensionalObject getValueDimension( String value )
-    {
-        if ( value == null )
-        {
-            return null;
-        }
-        
-        DataElement de = dataElementService.getDataElement( value );
-        
-        if ( de != null && de.isNumericType() )
-        {
-            return de;
-        }
-        
-        TrackedEntityAttribute at = attributeService.getTrackedEntityAttribute( value );
-        
-        if ( at != null && at.isNumericType() )
-        {
-            return at;
-        }
-        
-        throw new IllegalQueryException( "Value identifier does not reference any data element or attribute which are numeric type and part of the program: " + value );        
-    }
 }

=== added file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/DefaultEventDataQueryService.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/DefaultEventDataQueryService.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/DefaultEventDataQueryService.java	2015-11-05 02:57:57 +0000
@@ -0,0 +1,400 @@
+package org.hisp.dhis.analytics.event.data;
+
+/*
+ * 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 static org.hisp.dhis.common.DimensionalObject.DIMENSION_NAME_SEP;
+import static org.hisp.dhis.common.DimensionalObject.ITEM_SEP;
+import static org.hisp.dhis.common.DimensionalObjectUtils.getDimensionFromParam;
+import static org.hisp.dhis.common.DimensionalObjectUtils.getDimensionItemsFromParam;
+import static org.hisp.dhis.common.IdentifiableObjectUtils.getUids;
+
+import static org.hisp.dhis.analytics.event.EventAnalyticsService.ITEM_EXECUTION_DATE;
+import static org.hisp.dhis.analytics.event.EventAnalyticsService.ITEM_ORG_UNIT_CODE;
+import static org.hisp.dhis.analytics.event.EventAnalyticsService.ITEM_ORG_UNIT_NAME;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.lang3.StringUtils;
+import org.hisp.dhis.analytics.AggregationType;
+import org.hisp.dhis.analytics.DataQueryService;
+import org.hisp.dhis.analytics.EventOutputType;
+import org.hisp.dhis.analytics.SortOrder;
+import org.hisp.dhis.analytics.event.EventDataQueryService;
+import org.hisp.dhis.analytics.event.EventQueryParams;
+import org.hisp.dhis.common.DimensionalObject;
+import org.hisp.dhis.common.DisplayProperty;
+import org.hisp.dhis.common.EventAnalyticalObject;
+import org.hisp.dhis.common.IllegalQueryException;
+import org.hisp.dhis.common.QueryFilter;
+import org.hisp.dhis.common.QueryItem;
+import org.hisp.dhis.common.QueryOperator;
+import org.hisp.dhis.common.ValueType;
+import org.hisp.dhis.commons.collection.ListUtils;
+import org.hisp.dhis.dataelement.DataElement;
+import org.hisp.dhis.dataelement.DataElementService;
+import org.hisp.dhis.i18n.I18nFormat;
+import org.hisp.dhis.legend.LegendService;
+import org.hisp.dhis.legend.LegendSet;
+import org.hisp.dhis.organisationunit.OrganisationUnit;
+import org.hisp.dhis.program.Program;
+import org.hisp.dhis.program.ProgramIndicator;
+import org.hisp.dhis.program.ProgramIndicatorService;
+import org.hisp.dhis.program.ProgramService;
+import org.hisp.dhis.program.ProgramStage;
+import org.hisp.dhis.program.ProgramStageService;
+import org.hisp.dhis.system.util.DateUtils;
+import org.hisp.dhis.trackedentity.TrackedEntityAttribute;
+import org.hisp.dhis.trackedentity.TrackedEntityAttributeService;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.Lists;
+
+public class DefaultEventDataQueryService
+    implements EventDataQueryService
+{
+    private static final String COL_NAME_EVENTDATE = "executiondate";
+
+    private static final List<String> SORTABLE_ITEMS = Lists.newArrayList( 
+        ITEM_EXECUTION_DATE, ITEM_ORG_UNIT_NAME, ITEM_ORG_UNIT_CODE );
+
+    @Autowired
+    private ProgramService programService;
+
+    @Autowired
+    private ProgramStageService programStageService;
+
+    @Autowired
+    private DataElementService dataElementService;
+
+    @Autowired
+    private TrackedEntityAttributeService attributeService;
+    
+    @Autowired
+    private ProgramIndicatorService programIndicatorService;
+    
+    @Autowired
+    private LegendService legendService;
+
+    @Autowired
+    private DataQueryService dataQueryService;
+    
+    @Override
+    public EventQueryParams getFromUrl( String program, String stage, String startDate, String endDate,
+        Set<String> dimension, Set<String> filter, String value, AggregationType aggregationType, boolean skipMeta, boolean skipData, boolean skipRounding, 
+        boolean completedOnly, boolean hierarchyMeta, boolean showHierarchy, SortOrder sortOrder, Integer limit, EventOutputType outputType, boolean collapseDataDimensions, 
+        boolean aggregateData, DisplayProperty displayProperty, String userOrgUnit, I18nFormat format )
+    {
+        EventQueryParams params = getFromUrl( program, stage, startDate, endDate, dimension, filter, null, null, null,
+            skipMeta, skipData, completedOnly, hierarchyMeta, false, displayProperty, userOrgUnit, null, null, format );
+                
+        params.setValue( getValueDimension( value ) );
+        params.setAggregationType( aggregationType );
+        params.setSkipRounding( skipRounding );
+        params.setShowHierarchy( showHierarchy );
+        params.setSortOrder( sortOrder );
+        params.setLimit( limit );
+        params.setOutputType( MoreObjects.firstNonNull( outputType, EventOutputType.EVENT ) );
+        params.setCollapseDataDimensions( collapseDataDimensions );
+        params.setAggregateData( aggregateData );
+
+        return params;
+    }
+
+    @Override
+    public EventQueryParams getFromUrl( String program, String stage, String startDate, String endDate,
+        Set<String> dimension, Set<String> filter, String ouMode, Set<String> asc, Set<String> desc,
+        boolean skipMeta, boolean skipData, boolean completedOnly, boolean hierarchyMeta, boolean coordinatesOnly, 
+        DisplayProperty displayProperty, String userOrgUnit, Integer page, Integer pageSize, I18nFormat format )
+    {
+        EventQueryParams params = new EventQueryParams();
+        
+        List<OrganisationUnit> userOrgUnits = dataQueryService.getUserOrgUnits( userOrgUnit );
+
+        Program pr = programService.getProgram( program );
+
+        if ( pr == null )
+        {
+            throw new IllegalQueryException( "Program does not exist: " + program );
+        }
+
+        ProgramStage ps = programStageService.getProgramStage( stage );
+
+        if ( StringUtils.isNotEmpty( stage ) && ps == null )
+        {
+            throw new IllegalQueryException( "Program stage is specified but does not exist: " + stage );
+        }
+
+        Date start = null;
+        Date end = null;
+
+        if ( startDate != null && endDate != null )
+        {
+            try
+            {
+                start = DateUtils.getMediumDate( startDate );
+                end = DateUtils.getMediumDate( endDate );
+            }
+            catch ( RuntimeException ex )
+            {
+                throw new IllegalQueryException( "Start date or end date is invalid: " + startDate + " - " + endDate );
+            }
+        }
+
+        if ( dimension != null )
+        {
+            for ( String dim : dimension )
+            {
+                String dimensionId = getDimensionFromParam( dim );
+                List<String> items = getDimensionItemsFromParam( dim );                
+                DimensionalObject dimObj = dataQueryService.getDimension( dimensionId, items, null, userOrgUnits, format, true );
+                
+                if ( dimObj != null )
+                {
+                    params.getDimensions().add( dimObj );
+                }
+                else
+                {
+                    params.getItems().add( getQueryItem( dim ) );
+                }
+            }
+        }
+
+        if ( filter != null )
+        {
+            for ( String dim : filter )
+            {
+                String dimensionId = getDimensionFromParam( dim );
+                List<String> items = getDimensionItemsFromParam( dim );                
+                DimensionalObject dimObj = dataQueryService.getDimension( dimensionId, items, null, userOrgUnits, format, true );
+                
+                if ( dimObj != null )
+                {
+                    params.getFilters().add( dimObj );
+                }
+                else
+                {
+                    params.getItemFilters().add( getQueryItem( dim ) );
+                }
+            }
+        }
+
+        if ( asc != null )
+        {
+            for ( String sort : asc )
+            {
+                params.getAsc().add( getSortItem( sort ) );
+            }
+        }
+
+        if ( desc != null )
+        {
+            for ( String sort : desc )
+            {
+                params.getDesc().add( getSortItem( sort ) );
+            }
+        }
+
+        params.setProgram( pr );
+        params.setProgramStage( ps );
+        params.setStartDate( start );
+        params.setEndDate( end );
+        params.setOrganisationUnitMode( ouMode );
+        params.setSkipMeta( skipMeta );
+        params.setSkipData( skipData );
+        params.setCompletedOnly( completedOnly );
+        params.setHierarchyMeta( hierarchyMeta );
+        params.setCoordinatesOnly( coordinatesOnly );
+        params.setDisplayProperty( displayProperty );
+        params.setPage( page );
+        params.setPageSize( pageSize );
+        
+        return params;
+    }
+
+    @Override
+    public EventQueryParams getFromAnalyticalObject( EventAnalyticalObject object, I18nFormat format )
+    {        
+        EventQueryParams params = new EventQueryParams();
+
+        if ( object != null )
+        {
+            Date date = object.getRelativePeriodDate();
+            
+            object.populateAnalyticalProperties();
+
+            for ( DimensionalObject dimension : ListUtils.union( object.getColumns(), object.getRows() ) )
+            {
+                DimensionalObject dimObj = dataQueryService.
+                    getDimension( dimension.getDimension(), getUids( dimension.getItems() ), date, null, format, true );
+                
+                if ( dimObj != null )
+                {
+                    params.getDimensions().add( dimObj );
+                }
+                else
+                {
+                    params.getItems().add( getQueryItem( dimension.getDimension(), dimension.getFilter() ) );
+                }
+            }
+            
+            for ( DimensionalObject filter : object.getFilters() )
+            {
+                DimensionalObject dimObj = dataQueryService.
+                    getDimension( filter.getDimension(), getUids( filter.getItems() ), date, null, format, true );
+                
+                if ( dimObj != null )
+                {
+                    params.getFilters().add( dimObj );
+                }
+                else
+                {
+                    params.getItemFilters().add( getQueryItem( filter.getDimension(), filter.getFilter() ) );
+                }
+            }
+
+            params.setProgram( object.getProgram() );
+            params.setProgramStage( object.getProgramStage() );
+            params.setStartDate( object.getStartDate() );
+            params.setEndDate( object.getEndDate() );
+            params.setValue( object.getValue() );
+            params.setOutputType( object.getOutputType() );
+        }
+        
+        return params;
+    }
+    
+    // -------------------------------------------------------------------------
+    // Supportive methods
+    // -------------------------------------------------------------------------
+
+    private QueryItem getQueryItem( String dimension, String filter )
+    {
+        if ( filter != null )
+        {
+            dimension += DIMENSION_NAME_SEP + filter;
+        }
+                
+        return getQueryItem( dimension );
+    }
+    
+    private QueryItem getQueryItem( String dimensionString )
+    {
+        String[] split = dimensionString.split( DIMENSION_NAME_SEP );
+
+        if ( split == null || ( split.length % 2 != 1 ) )
+        {
+            throw new IllegalQueryException( "Query item or filter is invalid: " + dimensionString );
+        }
+        
+        QueryItem queryItem = getQueryItemFromDimension( split[0] );
+        
+        if ( split.length > 1 ) // Filters specified
+        {
+            for ( int i = 1; i < split.length; i += 2 )
+            {
+                QueryOperator operator = QueryOperator.fromString( split[i] );
+                QueryFilter filter = new QueryFilter( operator, split[i+1] );
+                queryItem.getFilters().add( filter );
+            }
+        }
+        
+        return queryItem;
+    }
+    
+    private String getSortItem( String item )
+    {
+        if ( !SORTABLE_ITEMS.contains( item.toLowerCase() ) && getQueryItem( item ) == null )
+        {
+            throw new IllegalQueryException( "Descending sort item is invalid: " + item );
+        }
+
+        item = ITEM_EXECUTION_DATE.equalsIgnoreCase( item ) ? COL_NAME_EVENTDATE : item;
+
+        return item;
+    }
+
+    private QueryItem getQueryItemFromDimension( String dimension )
+    {
+        String[] split = dimension.split( ITEM_SEP );
+
+        String item = split[0];
+
+        LegendSet legendSet = split.length > 1 && split[1] != null ? legendService.getLegendSet( split[1] ) : null;
+        
+        DataElement de = dataElementService.getDataElement( item );
+
+        if ( de != null ) //TODO check if part of program
+        {
+            return new QueryItem( de, legendSet, de.getValueType(), de.getAggregationType(), de.getOptionSet() );
+        }
+
+        TrackedEntityAttribute at = attributeService.getTrackedEntityAttribute( item );
+
+        if ( at != null )
+        {
+            return new QueryItem( at, legendSet, at.getValueType(), at.getAggregationType(), at.getOptionSet() );
+        }
+        
+        ProgramIndicator pi = programIndicatorService.getProgramIndicatorByUid( item );
+        
+        if ( pi != null )
+        {
+            return new QueryItem( pi, legendSet, ValueType.NUMBER, pi.getAggregationType(), null );
+        }
+
+        throw new IllegalQueryException( "Item identifier does not reference any data element or attribute part of the program: " + item );
+    }
+    
+    private DimensionalObject getValueDimension( String value )
+    {
+        if ( value == null )
+        {
+            return null;
+        }
+        
+        DataElement de = dataElementService.getDataElement( value );
+        
+        if ( de != null && de.isNumericType() )
+        {
+            return de;
+        }
+        
+        TrackedEntityAttribute at = attributeService.getTrackedEntityAttribute( value );
+        
+        if ( at != null && at.isNumericType() )
+        {
+            return at;
+        }
+        
+        throw new IllegalQueryException( "Value identifier does not reference any data element or attribute which are numeric type and part of the program: " + value );        
+    }
+}

=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/resources/META-INF/dhis/beans.xml	2015-04-22 16:20:05 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/resources/META-INF/dhis/beans.xml	2015-11-05 02:57:57 +0000
@@ -40,6 +40,8 @@
   
   <bean id="org.hisp.dhis.analytics.AnalyticsManager" class="org.hisp.dhis.analytics.data.JdbcAnalyticsManager" />
   
+  <bean id="org.hisp.dhis.analytics.DataQueryService" class="org.hisp.dhis.analytics.data.DefaultDataQueryService" />
+  
   <bean id="org.hisp.dhis.analytics.AnalyticsService" class="org.hisp.dhis.analytics.data.DefaultAnalyticsService" />
   
   <bean id="org.hisp.dhis.analytics.QueryPlanner" class="org.hisp.dhis.analytics.data.DefaultQueryPlanner" />
@@ -48,7 +50,9 @@
 
   <!-- Event analytics -->
 
-  <bean id="org.hisp.dhis.analytics.event.EventAnalyticsManager" class="org.hisp.dhis.analytics.event.data.JdbcEventAnalyticsManager"/>  
+  <bean id="org.hisp.dhis.analytics.event.EventAnalyticsManager" class="org.hisp.dhis.analytics.event.data.JdbcEventAnalyticsManager"/>
+
+  <bean id="org.hisp.dhis.analytics.event.EventDataQueryService" class="org.hisp.dhis.analytics.event.data.DefaultEventDataQueryService" />
 
   <bean id="org.hisp.dhis.analytics.event.EventAnalyticsService" class="org.hisp.dhis.analytics.event.data.DefaultEventAnalyticsService" />
 

=== renamed file 'dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/data/AnalyticsServiceTest.java' => 'dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/data/DataQueryServiceTest.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/data/AnalyticsServiceTest.java	2015-09-21 13:54:27 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/data/DataQueryServiceTest.java	2015-11-05 02:57:57 +0000
@@ -40,8 +40,8 @@
 import com.google.common.collect.Sets;
 
 import org.hisp.dhis.DhisSpringTest;
-import org.hisp.dhis.analytics.AnalyticsService;
 import org.hisp.dhis.analytics.DataQueryParams;
+import org.hisp.dhis.analytics.DataQueryService;
 import org.hisp.dhis.chart.Chart;
 import org.hisp.dhis.common.DimensionType;
 import org.hisp.dhis.common.DimensionalObject;
@@ -79,7 +79,7 @@
 /**
  * @author Lars Helge Overland
  */
-public class AnalyticsServiceTest
+public class DataQueryServiceTest
     extends DhisSpringTest
 {
     private DataElement deA;
@@ -118,7 +118,7 @@
     private PeriodType monthly = PeriodType.getPeriodTypeByName( MonthlyPeriodType.NAME );
     
     @Autowired
-    private AnalyticsService analyticsService;
+    private DataQueryService dataQueryService;
     
     @Autowired
     private DataElementService dataElementService;
@@ -247,7 +247,7 @@
         
         CurrentUserService currentUserService = new MockCurrentUserService( user );
         
-        setDependency( analyticsService, "currentUserService", currentUserService );
+        setDependency( dataQueryService, "currentUserService", currentUserService );
     }
 
     @Test
@@ -257,7 +257,7 @@
         dimensionParams.add( DimensionalObject.DATA_X_DIM_ID + DIMENSION_NAME_SEP + deA.getUid() + OPTION_SEP + deB.getUid() + OPTION_SEP + dsA.getUid() );
         dimensionParams.add( DimensionalObject.ORGUNIT_DIM_ID + DIMENSION_NAME_SEP + ouA.getUid() + OPTION_SEP + ouB.getUid() );
         
-        List<DimensionalObject> dimensionalObject = analyticsService.getDimensionalObjects( dimensionParams, null, null, null );
+        List<DimensionalObject> dimensionalObject = dataQueryService.getDimensionalObjects( dimensionParams, null, null, null );
         
         DimensionalObject dxObject = dimensionalObject.get( 0 );
         DimensionalObject ouObject = dimensionalObject.get( 1 );
@@ -283,7 +283,7 @@
         
         List<String> itemUids = IdentifiableObjectUtils.getUids( items );
         
-        DimensionalObject actual = analyticsService.getDimension( DimensionalObject.DATA_X_DIM_ID, itemUids, null, null, null, false );
+        DimensionalObject actual = dataQueryService.getDimension( DimensionalObject.DATA_X_DIM_ID, itemUids, null, null, null, false );
         
         assertEquals( DimensionalObject.DATA_X_DIM_ID, actual.getDimension() );
         assertEquals( DimensionType.DATA_X, actual.getDimensionType() );
@@ -302,7 +302,7 @@
         
         List<String> itemUids = IdentifiableObjectUtils.getUids( items );
         
-        DimensionalObject actual = analyticsService.getDimension( DimensionalObject.DATA_X_DIM_ID, itemUids, null, null, null, false );
+        DimensionalObject actual = dataQueryService.getDimension( DimensionalObject.DATA_X_DIM_ID, itemUids, null, null, null, false );
         
         assertEquals( DimensionalObject.DATA_X_DIM_ID, actual.getDimension() );
         assertEquals( DimensionType.DATA_X, actual.getDimensionType() );
@@ -317,7 +317,7 @@
         
         List<String> itemUids = IdentifiableObjectUtils.getUids( items );
 
-        DimensionalObject actual = analyticsService.getDimension( DimensionalObject.ORGUNIT_DIM_ID, itemUids, null, null, null, false );
+        DimensionalObject actual = dataQueryService.getDimension( DimensionalObject.ORGUNIT_DIM_ID, itemUids, null, null, null, false );
         
         assertEquals( DimensionalObject.ORGUNIT_DIM_ID, actual.getDimension() );
         assertEquals( DimensionType.ORGANISATIONUNIT, actual.getDimensionType() );
@@ -332,7 +332,7 @@
         
         List<String> itemUids = Lists.newArrayList( ouGroupAUid );
 
-        DimensionalObject actual = analyticsService.getDimension( DimensionalObject.ORGUNIT_DIM_ID, itemUids, null, null, null, false );
+        DimensionalObject actual = dataQueryService.getDimension( DimensionalObject.ORGUNIT_DIM_ID, itemUids, null, null, null, false );
         
         assertEquals( DimensionalObject.ORGUNIT_DIM_ID, actual.getDimension() );
         assertEquals( DimensionType.ORGANISATIONUNIT, actual.getDimensionType() );
@@ -346,7 +346,7 @@
         List<String> itemUids = Lists.newArrayList( "199501", "1999", 
             RelativePeriodEnum.LAST_4_QUARTERS.toString(), RelativePeriodEnum.THIS_YEAR.toString() );
 
-        DimensionalObject actual = analyticsService.getDimension( DimensionalObject.PERIOD_DIM_ID, itemUids, null, null, null, false );
+        DimensionalObject actual = dataQueryService.getDimension( DimensionalObject.PERIOD_DIM_ID, itemUids, null, null, null, false );
         
         assertEquals( DimensionalObject.PERIOD_DIM_ID, actual.getDimension() );
         assertEquals( DimensionType.PERIOD, actual.getDimensionType() );
@@ -361,7 +361,7 @@
         
         List<String> itemUids = IdentifiableObjectUtils.getUids( items );
         
-        DimensionalObject actual = analyticsService.getDimension( ouGroupSetA.getUid(), itemUids, null, null, null, false );
+        DimensionalObject actual = dataQueryService.getDimension( ouGroupSetA.getUid(), itemUids, null, null, null, false );
         
         assertEquals( ouGroupSetA.getUid(), actual.getDimension() );
         assertEquals( DimensionType.ORGANISATIONUNIT_GROUPSET, actual.getDimensionType() );
@@ -376,7 +376,7 @@
         
         List<String> itemUids = IdentifiableObjectUtils.getUids( items );
         
-        DimensionalObject actual = analyticsService.getDimension( deGroupSetA.getUid(), itemUids, null, null, null, false );
+        DimensionalObject actual = dataQueryService.getDimension( deGroupSetA.getUid(), itemUids, null, null, null, false );
         
         assertEquals( deGroupSetA.getUid(), actual.getDimension() );
         assertEquals( DimensionType.DATAELEMENT_GROUPSET, actual.getDimensionType() );
@@ -395,7 +395,7 @@
         Set<String> filterParams = new HashSet<>();
         filterParams.add( "ou:" + ouA.getUid() + ";" + ouB.getUid() + ";" + ouC.getUid() + ";" + ouD.getUid() + ";" + ouE.getUid() );
         
-        DataQueryParams params = analyticsService.getFromUrl( dimensionParams, filterParams, null, null, 
+        DataQueryParams params = dataQueryService.getFromUrl( dimensionParams, filterParams, null, null, 
             false, false, false, false, false, false, false, false, null, null, null, null, null, null, null, null );
         
         assertEquals( 4, params.getDataElements().size() );
@@ -413,7 +413,7 @@
         Set<String> filterParams = new HashSet<>();
         filterParams.add( "ou:" + ouA.getUid() );
         
-        DataQueryParams params = analyticsService.getFromUrl( dimensionParams, filterParams, null, null, 
+        DataQueryParams params = dataQueryService.getFromUrl( dimensionParams, filterParams, null, null, 
             false, false, false, false, false, false, false, false, null, null, null, null, null, null, null, null );
         
         assertEquals( 4, params.getDataElements().size() );
@@ -429,7 +429,7 @@
         Set<String> filterParams = new HashSet<>();
         filterParams.add( "ou:" + ouA.getUid() );
         
-        DataQueryParams params = analyticsService.getFromUrl( dimensionParams, filterParams, null, null, 
+        DataQueryParams params = dataQueryService.getFromUrl( dimensionParams, filterParams, null, null, 
             false, false, false, false, false, false, false, false, null, null, null, null, null, null, null, null );
         
         assertEquals( 2, params.getDataElements().size() );
@@ -446,7 +446,7 @@
         Set<String> filterParams = new HashSet<>();
         filterParams.add( "ou:" + ouA.getUid() );
         
-        DataQueryParams params = analyticsService.getFromUrl( dimensionParams, filterParams, null, null, 
+        DataQueryParams params = dataQueryService.getFromUrl( dimensionParams, filterParams, null, null, 
             false, false, false, false, false, false, false, false, null, null, null, null, null, null, null, null );
         
         assertEquals( 2, params.getDataElements().size() );
@@ -465,7 +465,7 @@
         Set<String> filterParams = new HashSet<>();
         filterParams.add( "ou:" + ouA.getUid() + ";" + ouB.getUid() + ";" + ouC.getUid() );
         
-        DataQueryParams params = analyticsService.getFromUrl( dimensionParams, filterParams, null, null, 
+        DataQueryParams params = dataQueryService.getFromUrl( dimensionParams, filterParams, null, null, 
             false, false, false, false, false, false, false, false, null, null, null, null, null, null, null, null );
         
         assertEquals( 3, params.getDataElements().size() );
@@ -484,7 +484,7 @@
         Set<String> filterParams = new HashSet<>();
         filterParams.add( "ou:" + ouA.getUid() + ";" + ouB.getUid() );
 
-        DataQueryParams params = analyticsService.getFromUrl( dimensionParams, filterParams, null, null, 
+        DataQueryParams params = dataQueryService.getFromUrl( dimensionParams, filterParams, null, null, 
             false, false, false, false, false, false, false, false, null, null, null, null, null, null, null, null );
         
         assertEquals( 4, params.getDataElements().size() );
@@ -500,7 +500,7 @@
         dimensionParams.add( "dx:" + deA.getUid() + ";" + deB.getUid() );
         dimensionParams.add( "pe:2011;2012" );
         
-        DataQueryParams params = analyticsService.getFromUrl( dimensionParams, null, null, null, 
+        DataQueryParams params = dataQueryService.getFromUrl( dimensionParams, null, null, null, 
             false, false, false, false, false, false, false, false, null, null, null, null, null, null, null, null );
         
         assertEquals( 1, params.getOrganisationUnits().size() );  
@@ -516,7 +516,7 @@
         dimensionParams.add( "dx:" + deA.getUid() + ";" + deB.getUid() );
         dimensionParams.add( "pe:2011;2012" );
         
-        DataQueryParams params = analyticsService.getFromUrl( dimensionParams, null, null, null, 
+        DataQueryParams params = dataQueryService.getFromUrl( dimensionParams, null, null, null, 
             false, false, false, false, false, false, false, false, null, null, null, null, null, null, null, null );
         
         assertEquals( 3, params.getOrganisationUnits().size() );  
@@ -532,7 +532,7 @@
         dimensionParams.add( "dx:" + deA.getUid() + ";" + deB.getUid() );
         dimensionParams.add( "pe:2011;2012" );
         
-        DataQueryParams params = analyticsService.getFromUrl( dimensionParams, null, null, null, 
+        DataQueryParams params = dataQueryService.getFromUrl( dimensionParams, null, null, null, 
             false, false, false, false, false, false, false, false, null, null, null, null, null, null, null, null );
         
         assertEquals( 2, params.getOrganisationUnits().size() );  
@@ -547,7 +547,7 @@
         dimensionParams.add( "dx" );
         dimensionParams.add( "pe:2012,2012S1,2012S2" );
         
-        analyticsService.getFromUrl( dimensionParams, null, null, null, 
+        dataQueryService.getFromUrl( dimensionParams, null, null, null, 
             false, false, false, false, false, false, false, false, null, null, null, null, null, null, null, null );        
     }
     
@@ -558,7 +558,7 @@
         dimensionParams.add( "dx:" + BASE_UID + "A;" + BASE_UID + "B;" + BASE_UID + "C;" + BASE_UID + "D" );
         dimensionParams.add( "pe" );
 
-        analyticsService.getFromUrl( dimensionParams, null, null, null, 
+        dataQueryService.getFromUrl( dimensionParams, null, null, null, 
             false, false, false, false, false, false, false, false, null, null, null, null, null, null, null, null );        
     }
 
@@ -569,7 +569,7 @@
         dimensionParams.add( "dx:" + BASE_UID + "A;" + BASE_UID + "B;" + BASE_UID + "C;" + BASE_UID + "D" );
         dimensionParams.add( "ou" );
         
-        analyticsService.getFromUrl( dimensionParams, null, null, null, 
+        dataQueryService.getFromUrl( dimensionParams, null, null, null, 
             false, false, false, false, false, false, false, false, null, null, null, null, null, null, null, null );        
     }
 
@@ -580,7 +580,7 @@
         dimensionParams.add( "dx:" + BASE_UID + "A;" + BASE_UID + "B;" + BASE_UID + "C;" + BASE_UID + "D" );
         dimensionParams.add( "yebo:2012,2012S1,2012S2" );
         
-        analyticsService.getFromUrl( dimensionParams, null, null, null, 
+        dataQueryService.getFromUrl( dimensionParams, null, null, null, 
             false, false, false, false, false, false, false, false, null, null, null, null, null, null, null, null );        
     }
     
@@ -601,7 +601,7 @@
         
         chart.getPeriods().add( PeriodType.getPeriodFromIsoString( "2012" ) );
         
-        DataQueryParams params = analyticsService.getFromAnalyticalObject( chart, null );
+        DataQueryParams params = dataQueryService.getFromAnalyticalObject( chart, null );
         
         assertNotNull( params );
         assertEquals( 3, params.getDataElements().size() );
@@ -629,7 +629,7 @@
         
         chart.getPeriods().add( PeriodType.getPeriodFromIsoString( "2012" ) );
         
-        DataQueryParams params = analyticsService.getFromAnalyticalObject( chart, null );
+        DataQueryParams params = dataQueryService.getFromAnalyticalObject( chart, null );
         
         assertNotNull( params );
         assertEquals( 3, params.getDataElements().size() );
@@ -657,7 +657,7 @@
         
         chart.getPeriods().add( PeriodType.getPeriodFromIsoString( "2012" ) );
         
-        DataQueryParams params = analyticsService.getFromAnalyticalObject( chart, null );
+        DataQueryParams params = dataQueryService.getFromAnalyticalObject( chart, null );
         
         assertNotNull( params );
         assertEquals( 1, params.getDataElements().size() );
@@ -675,6 +675,6 @@
         
         List<OrganisationUnit> expected = Lists.newArrayList( ouA, ouB );
         
-        assertEquals( expected, analyticsService.getUserOrgUnits( ouParam ) );
+        assertEquals( expected, dataQueryService.getUserOrgUnits( ouParam ) );
     }
 }

=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/data/MockAnalyticsService.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/data/MockAnalyticsService.java	2015-09-30 17:45:45 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/data/MockAnalyticsService.java	2015-11-05 02:57:57 +0000
@@ -28,22 +28,15 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import java.util.Date;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 import org.apache.commons.lang3.NotImplementedException;
-import org.hisp.dhis.analytics.AggregationType;
 import org.hisp.dhis.analytics.AnalyticsService;
 import org.hisp.dhis.analytics.DataQueryParams;
 import org.hisp.dhis.common.AnalyticalObject;
-import org.hisp.dhis.common.DimensionalObject;
-import org.hisp.dhis.common.DisplayProperty;
 import org.hisp.dhis.common.Grid;
-import org.hisp.dhis.common.IdentifiableProperty;
 import org.hisp.dhis.i18n.I18nFormat;
-import org.hisp.dhis.organisationunit.OrganisationUnit;
 
 /**
  * Configurable mock implementation of AnalyticsService for testing purposes.
@@ -71,6 +64,12 @@
     }
 
     @Override
+    public Grid getAggregatedDataValues( AnalyticalObject object, I18nFormat format )
+    {
+        throw new NotImplementedException( "" );
+    }
+
+    @Override
     public Map<String, Object> getAggregatedDataValueMapping( DataQueryParams params )
     {
         return valueMap;
@@ -81,38 +80,4 @@
     {
         return valueMap;
     }
-
-    @Override
-    public DataQueryParams getFromUrl( Set<String> dimensionParams, Set<String> filterParams, AggregationType aggregationType, 
-        String measureCriteria, boolean skipMeta, boolean skipData, boolean skipRounding, boolean completedOnly, boolean hierarchyMeta, boolean ignoreLimit, boolean hideEmptyRows, 
-        boolean showHierarchy, DisplayProperty displayProperty, IdentifiableProperty idScheme, String approvalLevel, Date relativePeriodDate, String userOrgUnit, 
-        String program, String stage, I18nFormat format )
-    {
-        throw new NotImplementedException( "" );
-    }
-
-    @Override
-    public DataQueryParams getFromAnalyticalObject( AnalyticalObject object, I18nFormat format )
-    {
-        throw new NotImplementedException( "" );
-    }
-    
-    @Override
-    public List<DimensionalObject> getDimensionalObjects( Set<String> dimensionParams, Date relateivePeriodDate, String userOrgUnit, I18nFormat format )
-    {
-        throw new NotImplementedException( "" );
-    }
-
-    @Override
-    public DimensionalObject getDimension( String dimension, List<String> items, Date relativePeriodDate,
-        List<OrganisationUnit> userOrgUnits, I18nFormat format, boolean allowNull )
-    {
-        throw new NotImplementedException( "" );
-    }
-
-    @Override
-    public List<OrganisationUnit> getUserOrgUnits( String userOrgUnit )
-    {
-        return null;
-    }
 }

=== renamed file 'dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/event/data/EventAnalyticsServiceTest.java' => 'dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/event/data/EventDataQueryServiceTest.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/event/data/EventAnalyticsServiceTest.java	2015-09-17 16:41:41 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/event/data/EventDataQueryServiceTest.java	2015-11-05 02:57:57 +0000
@@ -31,7 +31,7 @@
 import com.google.common.collect.Sets;
 import org.hisp.dhis.DhisSpringTest;
 import org.hisp.dhis.analytics.AggregationType;
-import org.hisp.dhis.analytics.event.EventAnalyticsService;
+import org.hisp.dhis.analytics.event.EventDataQueryService;
 import org.hisp.dhis.analytics.event.EventQueryParams;
 import org.hisp.dhis.common.AnalyticsType;
 import org.hisp.dhis.common.DimensionType;
@@ -74,7 +74,7 @@
 /**
  * @author Lars Helge Overland
  */
-public class EventAnalyticsServiceTest
+public class EventDataQueryServiceTest
     extends DhisSpringTest
 {
     private Program prA;
@@ -98,7 +98,7 @@
     private Legend legendB;
 
     @Autowired
-    private EventAnalyticsService analyticsService;
+    private EventDataQueryService dataQueryService;
 
     @Autowired
     private ProgramService programService;
@@ -180,7 +180,7 @@
         Set<String> filterParams = new HashSet<>();
         filterParams.add( "pe:201401;201402" );
 
-        EventQueryParams params = analyticsService.getFromUrl( prA.getUid(), null,
+        EventQueryParams params = dataQueryService.getFromUrl( prA.getUid(), null,
             null, null, dimensionParams, filterParams, null, null, false, false, 
             false, false, false, false, null, null, null, false, false, null, null, null );
 
@@ -200,7 +200,7 @@
         Set<String> filterParams = new HashSet<>();
         filterParams.add( "pe:201401" );
 
-        EventQueryParams params = analyticsService.getFromUrl( prA.getUid(), null,
+        EventQueryParams params = dataQueryService.getFromUrl( prA.getUid(), null,
             null, null, dimensionParams, filterParams, deA.getUid(), AggregationType.AVERAGE, 
             false, false, false, false, false, false, null, null, null, false, false, null, null, null );
 
@@ -229,7 +229,7 @@
         eventChart.getOrganisationUnits().add( ouA );
         eventChart.getOrganisationUnits().add( ouB );
 
-        EventQueryParams params = analyticsService.getFromAnalyticalObject( eventChart, null );
+        EventQueryParams params = dataQueryService.getFromAnalyticalObject( eventChart, null );
 
         assertNotNull( params );
         assertEquals( 1, params.getItems().size() );
@@ -256,7 +256,7 @@
         eventChart.getOrganisationUnits().add( ouA );
         eventChart.getOrganisationUnits().add( ouB );
 
-        EventQueryParams params = analyticsService.getFromAnalyticalObject( eventChart, null );
+        EventQueryParams params = dataQueryService.getFromAnalyticalObject( eventChart, null );
 
         assertNotNull( params );
         assertEquals( 2, params.getItems().size() );
@@ -282,7 +282,7 @@
         eventChart.getPeriods().add( peB );
         eventChart.getOrganisationUnits().add( ouA );
 
-        EventQueryParams params = analyticsService.getFromAnalyticalObject( eventChart, null );
+        EventQueryParams params = dataQueryService.getFromAnalyticalObject( eventChart, null );
 
         assertNotNull( params );
         assertEquals( 2, params.getItems().size() );
@@ -340,7 +340,7 @@
         filterParams.add( "pe:201401;201402" );
         filterParams.add( atA.getUid() + ":LE:5" );
 
-        EventQueryParams params = analyticsService.getFromUrl( prA.getUid(), null,
+        EventQueryParams params = dataQueryService.getFromUrl( prA.getUid(), null,
             null, null, dimensionParams, filterParams, null, null, false, false, 
             false, false, false, false, null, null, null, false, false, null, null, null );
 

=== modified file 'dhis-2/dhis-services/dhis-service-reporting/src/main/java/org/hisp/dhis/datasetreport/jdbc/AnalyticsDataSetReportStore.java'
--- dhis-2/dhis-services/dhis-service-reporting/src/main/java/org/hisp/dhis/datasetreport/jdbc/AnalyticsDataSetReportStore.java	2015-09-21 10:58:41 +0000
+++ dhis-2/dhis-services/dhis-service-reporting/src/main/java/org/hisp/dhis/datasetreport/jdbc/AnalyticsDataSetReportStore.java	2015-11-05 02:57:57 +0000
@@ -39,6 +39,7 @@
 import org.apache.commons.logging.LogFactory;
 import org.hisp.dhis.analytics.AnalyticsService;
 import org.hisp.dhis.analytics.DataQueryParams;
+import org.hisp.dhis.analytics.DataQueryService;
 import org.hisp.dhis.dataelement.DataElement;
 import org.hisp.dhis.dataelement.DataElementCategory;
 import org.hisp.dhis.dataset.DataSet;
@@ -48,6 +49,7 @@
 import org.hisp.dhis.organisationunit.OrganisationUnit;
 import org.hisp.dhis.period.Period;
 import org.hisp.dhis.system.filter.AggregatableDataElementFilter;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.hisp.dhis.common.NameableObject;
 import org.hisp.dhis.commons.filter.FilterUtils;
 
@@ -59,13 +61,12 @@
 {
     private static final Log log = LogFactory.getLog( AnalyticsDataSetReportStore.class );
     
+    @Autowired
+    private DataQueryService dataQueryService;
+    
+    @Autowired
     private AnalyticsService analyticsService;
-    
-    public void setAnalyticsService( AnalyticsService analyticsService )
-    {
-        this.analyticsService = analyticsService;
-    }
-    
+        
     // -------------------------------------------------------------------------
     // DataSetReportStore implementation
     // -------------------------------------------------------------------------
@@ -92,7 +93,7 @@
         
         if ( dimensions != null )
         {
-            params.setFilters( analyticsService.getDimensionalObjects( dimensions, null, null, null ) );
+            params.setFilters( dataQueryService.getDimensionalObjects( dimensions, null, null, null ) );
         }
         
         Map<String, Object> map = analyticsService.getAggregatedDataValueMapping( params );
@@ -147,7 +148,7 @@
 
                 if ( dimensions != null )
                 {
-                    params.setFilters( analyticsService.getDimensionalObjects( dimensions, null, null, null ) );
+                    params.setFilters( dataQueryService.getDimensionalObjects( dimensions, null, null, null ) );
                 }
                 
                 Map<String, Object> map = analyticsService.getAggregatedDataValueMapping( params );
@@ -183,7 +184,7 @@
 
         if ( dimensions != null )
         {
-            params.setFilters( analyticsService.getDimensionalObjects( dimensions, null, null, null ) );
+            params.setFilters( dataQueryService.getDimensionalObjects( dimensions, null, null, null ) );
         }
         
         Map<String, Object> map = analyticsService.getAggregatedDataValueMapping( params );
@@ -217,7 +218,7 @@
 
         if ( dimensions != null )
         {
-            params.setFilters( analyticsService.getDimensionalObjects( dimensions, null, null, null ) );
+            params.setFilters( dataQueryService.getDimensionalObjects( dimensions, null, null, null ) );
         }
         
         Map<String, Object> map = analyticsService.getAggregatedDataValueMapping( params );

=== modified file 'dhis-2/dhis-services/dhis-service-reporting/src/main/java/org/hisp/dhis/mapgeneration/GeoToolsMapGenerationService.java'
--- dhis-2/dhis-services/dhis-service-reporting/src/main/java/org/hisp/dhis/mapgeneration/GeoToolsMapGenerationService.java	2015-09-13 21:54:23 +0000
+++ dhis-2/dhis-services/dhis-service-reporting/src/main/java/org/hisp/dhis/mapgeneration/GeoToolsMapGenerationService.java	2015-11-05 02:57:57 +0000
@@ -40,7 +40,6 @@
 
 import org.apache.commons.lang3.StringUtils;
 import org.hisp.dhis.analytics.AnalyticsService;
-import org.hisp.dhis.analytics.DataQueryParams;
 import org.hisp.dhis.common.Grid;
 import org.hisp.dhis.i18n.I18nManager;
 import org.hisp.dhis.mapping.Map;
@@ -316,9 +315,7 @@
      */
     private List<MapValue> getAggregatedMapValues( MapView mapView )
     {
-        DataQueryParams params = analyticsService.getFromAnalyticalObject( mapView, null );
-        
-        Grid grid = analyticsService.getAggregatedDataValues( params );
+        Grid grid = analyticsService.getAggregatedDataValues( mapView, null );
 
         return getMapValues( grid );
     }

=== modified file 'dhis-2/dhis-services/dhis-service-reporting/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-services/dhis-service-reporting/src/main/resources/META-INF/dhis/beans.xml	2015-10-13 07:21:44 +0000
+++ dhis-2/dhis-services/dhis-service-reporting/src/main/resources/META-INF/dhis/beans.xml	2015-11-05 02:57:57 +0000
@@ -103,9 +103,7 @@
     <property name="dataSetReportStore" ref="org.hisp.dhis.datasetreport.DataSetReportStore" />
   </bean>
 
-  <bean id="org.hisp.dhis.datasetreport.DataSetReportStore" class="org.hisp.dhis.datasetreport.jdbc.AnalyticsDataSetReportStore">
-    <property name="analyticsService" ref="org.hisp.dhis.analytics.AnalyticsService" />
-  </bean>
+  <bean id="org.hisp.dhis.datasetreport.DataSetReportStore" class="org.hisp.dhis.datasetreport.jdbc.AnalyticsDataSetReportStore" />
 
   <!-- Dashboard -->
 

=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AnalyticsController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AnalyticsController.java	2015-09-08 18:09:34 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AnalyticsController.java	2015-11-05 02:57:57 +0000
@@ -39,6 +39,7 @@
 import org.hisp.dhis.analytics.AnalyticsService;
 import org.hisp.dhis.analytics.AnalyticsUtils;
 import org.hisp.dhis.analytics.DataQueryParams;
+import org.hisp.dhis.analytics.DataQueryService;
 import org.hisp.dhis.common.DisplayProperty;
 import org.hisp.dhis.common.Grid;
 import org.hisp.dhis.common.IdentifiableProperty;
@@ -63,8 +64,11 @@
     private static final String RESOURCE_PATH = "/analytics";
 
     @Autowired
+    private DataQueryService dataQueryService;
+    
+    @Autowired
     private AnalyticsService analyticsService;
-    
+        
     @Autowired
     private ContextUtils contextUtils;
 
@@ -102,7 +106,7 @@
         Model model,
         HttpServletResponse response ) throws Exception
     {
-        DataQueryParams params = analyticsService.getFromUrl( dimension, filter, aggregationType, measureCriteria, skipMeta, skipData, skipRounding, completedOnly, hierarchyMeta, 
+        DataQueryParams params = dataQueryService.getFromUrl( dimension, filter, aggregationType, measureCriteria, skipMeta, skipData, skipRounding, completedOnly, hierarchyMeta, 
             ignoreLimit, hideEmptyRows, showHierarchy, displayProperty, outputIdScheme, approvalLevel, relativePeriodDate, userOrgUnit, program, stage, i18nManager.getI18nFormat() );
 
         contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_JSON, CacheStrategy.RESPECT_SYSTEM_SETTING );
@@ -139,7 +143,7 @@
         Model model,
         HttpServletResponse response ) throws Exception
     {
-        DataQueryParams params = analyticsService.getFromUrl( dimension, filter, aggregationType, measureCriteria, skipMeta, skipData, skipRounding, completedOnly, hierarchyMeta, 
+        DataQueryParams params = dataQueryService.getFromUrl( dimension, filter, aggregationType, measureCriteria, skipMeta, skipData, skipRounding, completedOnly, hierarchyMeta, 
             ignoreLimit, hideEmptyRows, showHierarchy, displayProperty, outputIdScheme, approvalLevel, relativePeriodDate, userOrgUnit, program, stage, i18nManager.getI18nFormat() );
 
         contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_XML, CacheStrategy.RESPECT_SYSTEM_SETTING );
@@ -174,7 +178,7 @@
         Model model,
         HttpServletResponse response ) throws Exception
     {
-        DataQueryParams params = analyticsService.getFromUrl( dimension, filter, aggregationType, measureCriteria, skipMeta, skipData, skipRounding, completedOnly, hierarchyMeta, 
+        DataQueryParams params = dataQueryService.getFromUrl( dimension, filter, aggregationType, measureCriteria, skipMeta, skipData, skipRounding, completedOnly, hierarchyMeta, 
             ignoreLimit, hideEmptyRows, showHierarchy, displayProperty, outputIdScheme, approvalLevel, relativePeriodDate, userOrgUnit, program, stage, i18nManager.getI18nFormat() );
 
         contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_HTML, CacheStrategy.RESPECT_SYSTEM_SETTING );
@@ -209,7 +213,7 @@
         Model model,
         HttpServletResponse response ) throws Exception
     {
-        DataQueryParams params = analyticsService.getFromUrl( dimension, filter, aggregationType, measureCriteria, skipMeta, skipData, skipRounding, completedOnly, hierarchyMeta, 
+        DataQueryParams params = dataQueryService.getFromUrl( dimension, filter, aggregationType, measureCriteria, skipMeta, skipData, skipRounding, completedOnly, hierarchyMeta, 
             ignoreLimit, hideEmptyRows, showHierarchy, displayProperty, outputIdScheme, approvalLevel, relativePeriodDate, userOrgUnit, program, stage, i18nManager.getI18nFormat() );
 
         contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_HTML, CacheStrategy.RESPECT_SYSTEM_SETTING );
@@ -244,7 +248,7 @@
         Model model,
         HttpServletResponse response ) throws Exception
     {
-        DataQueryParams params = analyticsService.getFromUrl( dimension, filter, aggregationType, measureCriteria, skipMeta, skipData, skipRounding, completedOnly, hierarchyMeta, 
+        DataQueryParams params = dataQueryService.getFromUrl( dimension, filter, aggregationType, measureCriteria, skipMeta, skipData, skipRounding, completedOnly, hierarchyMeta, 
             ignoreLimit, hideEmptyRows, showHierarchy, displayProperty, outputIdScheme, approvalLevel, relativePeriodDate, userOrgUnit, program, stage, i18nManager.getI18nFormat() );
 
         contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_CSV, CacheStrategy.RESPECT_SYSTEM_SETTING, "data.csv", true );
@@ -279,7 +283,7 @@
         Model model,
         HttpServletResponse response ) throws Exception
     {
-        DataQueryParams params = analyticsService.getFromUrl( dimension, filter, aggregationType, measureCriteria, skipMeta, skipData, skipRounding, completedOnly, hierarchyMeta, 
+        DataQueryParams params = dataQueryService.getFromUrl( dimension, filter, aggregationType, measureCriteria, skipMeta, skipData, skipRounding, completedOnly, hierarchyMeta, 
             ignoreLimit, hideEmptyRows, showHierarchy, displayProperty, outputIdScheme, approvalLevel, relativePeriodDate, userOrgUnit, program, stage, i18nManager.getI18nFormat() );
 
         contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_EXCEL, CacheStrategy.RESPECT_SYSTEM_SETTING, "data.xls", true );
@@ -314,7 +318,7 @@
         Model model,
         HttpServletResponse response ) throws Exception
     {
-        DataQueryParams params = analyticsService.getFromUrl( dimension, filter, null, null,
+        DataQueryParams params = dataQueryService.getFromUrl( dimension, filter, null, null,
             true, false, false, false, false, false, false, false, null, null, null, null, null, null, null, i18nManager.getI18nFormat() );
 
         contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_XML, CacheStrategy.RESPECT_SYSTEM_SETTING, "data.jrxml", false );
@@ -350,7 +354,7 @@
         Model model,
         HttpServletResponse response ) throws Exception
     {
-        DataQueryParams params = analyticsService.getFromUrl( dimension, filter, aggregationType, measureCriteria, skipMeta, skipData, skipRounding, completedOnly, hierarchyMeta, 
+        DataQueryParams params = dataQueryService.getFromUrl( dimension, filter, aggregationType, measureCriteria, skipMeta, skipData, skipRounding, completedOnly, hierarchyMeta, 
             ignoreLimit, hideEmptyRows, showHierarchy, displayProperty, outputIdScheme, approvalLevel, relativePeriodDate, userOrgUnit, program, stage, i18nManager.getI18nFormat() );
 
         contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_TEXT, CacheStrategy.NO_CACHE, "debug.sql", false );

=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/EventAnalyticsController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/EventAnalyticsController.java	2015-09-17 16:41:41 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/EventAnalyticsController.java	2015-11-05 02:57:57 +0000
@@ -39,6 +39,7 @@
 import org.hisp.dhis.analytics.EventOutputType;
 import org.hisp.dhis.analytics.SortOrder;
 import org.hisp.dhis.analytics.event.EventAnalyticsService;
+import org.hisp.dhis.analytics.event.EventDataQueryService;
 import org.hisp.dhis.analytics.event.EventQueryParams;
 import org.hisp.dhis.common.DisplayProperty;
 import org.hisp.dhis.common.Grid;
@@ -63,6 +64,9 @@
     private static final String RESOURCE_PATH = "/analytics/events";
 
     @Autowired
+    private EventDataQueryService eventDataQueryService;
+    
+    @Autowired
     private EventAnalyticsService analyticsService;
 
     @Autowired
@@ -101,7 +105,7 @@
         Model model,
         HttpServletResponse response ) throws Exception
     {
-        EventQueryParams params = analyticsService.getFromUrl( program, stage, startDate, endDate, dimension, filter,
+        EventQueryParams params = eventDataQueryService.getFromUrl( program, stage, startDate, endDate, dimension, filter,
             value, aggregationType, skipMeta, skipData, skipRounding, completedOnly, hierarchyMeta, showHierarchy, sortOrder, limit, outputType,
             collapseDataDimensions, aggregateData, displayProperty, userOrgUnit, i18nManager.getI18nFormat() );
 
@@ -138,7 +142,7 @@
         Model model,
         HttpServletResponse response ) throws Exception
     {
-        EventQueryParams params = analyticsService.getFromUrl( program, stage, startDate, endDate, dimension, filter,
+        EventQueryParams params = eventDataQueryService.getFromUrl( program, stage, startDate, endDate, dimension, filter,
             value, aggregationType, skipMeta, skipData, skipRounding, completedOnly, hierarchyMeta, showHierarchy, sortOrder, limit, outputType,
             collapseDataDimensions, aggregateData, displayProperty, userOrgUnit, i18nManager.getI18nFormat() );
 
@@ -173,7 +177,7 @@
         Model model,
         HttpServletResponse response ) throws Exception
     {
-        EventQueryParams params = analyticsService.getFromUrl( program, stage, startDate, endDate, dimension, filter,
+        EventQueryParams params = eventDataQueryService.getFromUrl( program, stage, startDate, endDate, dimension, filter,
             value, aggregationType, skipMeta, skipData, skipRounding, completedOnly, hierarchyMeta, showHierarchy, sortOrder, limit, outputType,
             collapseDataDimensions, aggregateData, displayProperty, userOrgUnit, i18nManager.getI18nFormat() );
 
@@ -208,7 +212,7 @@
         Model model,
         HttpServletResponse response ) throws Exception
     {
-        EventQueryParams params = analyticsService.getFromUrl( program, stage, startDate, endDate, dimension, filter,
+        EventQueryParams params = eventDataQueryService.getFromUrl( program, stage, startDate, endDate, dimension, filter,
             value, aggregationType, skipMeta, skipData, skipRounding, completedOnly, hierarchyMeta, showHierarchy, sortOrder, limit, outputType,
             collapseDataDimensions, aggregateData, displayProperty, userOrgUnit, i18nManager.getI18nFormat() );
 
@@ -243,7 +247,7 @@
         Model model,
         HttpServletResponse response ) throws Exception
     {
-        EventQueryParams params = analyticsService.getFromUrl( program, stage, startDate, endDate, dimension, filter,
+        EventQueryParams params = eventDataQueryService.getFromUrl( program, stage, startDate, endDate, dimension, filter,
             value, aggregationType, skipMeta, skipData, skipRounding, completedOnly, hierarchyMeta, showHierarchy, sortOrder, limit, outputType,
             collapseDataDimensions, aggregateData, displayProperty, userOrgUnit, i18nManager.getI18nFormat() );
 
@@ -278,7 +282,7 @@
         Model model,
         HttpServletResponse response ) throws Exception
     {
-        EventQueryParams params = analyticsService.getFromUrl( program, stage, startDate, endDate, dimension, filter,
+        EventQueryParams params = eventDataQueryService.getFromUrl( program, stage, startDate, endDate, dimension, filter,
             value, aggregationType, skipMeta, skipData, skipRounding, completedOnly, hierarchyMeta, showHierarchy, sortOrder, limit, outputType,
             collapseDataDimensions, aggregateData, displayProperty, userOrgUnit, i18nManager.getI18nFormat() );
 
@@ -314,7 +318,7 @@
         Model model,
         HttpServletResponse response ) throws Exception
     {
-        EventQueryParams params = analyticsService.getFromUrl( program, stage, startDate, endDate, dimension, filter, 
+        EventQueryParams params = eventDataQueryService.getFromUrl( program, stage, startDate, endDate, dimension, filter, 
             ouMode, asc, desc, skipMeta, skipData, completedOnly, hierarchyMeta, coordinatesOnly, displayProperty, userOrgUnit, page, pageSize, i18nManager.getI18nFormat() );
 
         contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_JSON, CacheStrategy.RESPECT_SYSTEM_SETTING );
@@ -347,7 +351,7 @@
         Model model,
         HttpServletResponse response ) throws Exception
     {
-        EventQueryParams params = analyticsService.getFromUrl( program, stage, startDate, endDate, dimension, filter,
+        EventQueryParams params = eventDataQueryService.getFromUrl( program, stage, startDate, endDate, dimension, filter,
             ouMode, asc, desc, skipMeta, skipData, completedOnly, hierarchyMeta, coordinatesOnly, displayProperty, userOrgUnit, page, pageSize, i18nManager.getI18nFormat() );
 
         contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_XML, CacheStrategy.RESPECT_SYSTEM_SETTING, "events.xml", false );
@@ -378,7 +382,7 @@
         Model model,
         HttpServletResponse response ) throws Exception
     {
-        EventQueryParams params = analyticsService.getFromUrl( program, stage, startDate, endDate, dimension, filter,
+        EventQueryParams params = eventDataQueryService.getFromUrl( program, stage, startDate, endDate, dimension, filter,
             ouMode, asc, desc, skipMeta, skipData, completedOnly, hierarchyMeta, coordinatesOnly, displayProperty, userOrgUnit, page, pageSize, i18nManager.getI18nFormat() );
 
         contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_EXCEL, CacheStrategy.RESPECT_SYSTEM_SETTING, "events.xls", true );
@@ -409,7 +413,7 @@
         Model model,
         HttpServletResponse response ) throws Exception
     {
-        EventQueryParams params = analyticsService.getFromUrl( program, stage, startDate, endDate, dimension, filter,
+        EventQueryParams params = eventDataQueryService.getFromUrl( program, stage, startDate, endDate, dimension, filter,
             ouMode, asc, desc, skipMeta, skipData, completedOnly, hierarchyMeta, coordinatesOnly, displayProperty, userOrgUnit, page, pageSize, i18nManager.getI18nFormat() );
 
         contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_CSV, CacheStrategy.RESPECT_SYSTEM_SETTING, "events.csv", true );
@@ -440,7 +444,7 @@
         Model model,
         HttpServletResponse response ) throws Exception
     {
-        EventQueryParams params = analyticsService.getFromUrl( program, stage, startDate, endDate, dimension, filter,
+        EventQueryParams params = eventDataQueryService.getFromUrl( program, stage, startDate, endDate, dimension, filter,
             ouMode, asc, desc, skipMeta, skipData, completedOnly, hierarchyMeta, coordinatesOnly, displayProperty, userOrgUnit, page, pageSize, i18nManager.getI18nFormat() );
 
         contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_HTML, CacheStrategy.RESPECT_SYSTEM_SETTING, "events.html", false );
@@ -471,7 +475,7 @@
         Model model,
         HttpServletResponse response ) throws Exception
     {
-        EventQueryParams params = analyticsService.getFromUrl( program, stage, startDate, endDate, dimension, filter,
+        EventQueryParams params = eventDataQueryService.getFromUrl( program, stage, startDate, endDate, dimension, filter,
             ouMode, asc, desc, skipMeta, skipData, completedOnly, hierarchyMeta, coordinatesOnly, displayProperty, userOrgUnit, page, pageSize, i18nManager.getI18nFormat() );
 
         contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_HTML, CacheStrategy.RESPECT_SYSTEM_SETTING, "events.html", false );

=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/mapping/GeoFeatureController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/mapping/GeoFeatureController.java	2015-09-17 04:29:29 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/mapping/GeoFeatureController.java	2015-11-05 02:57:57 +0000
@@ -30,8 +30,8 @@
 
 import com.google.common.collect.ImmutableMap;
 import org.hisp.dhis.analytics.AggregationType;
-import org.hisp.dhis.analytics.AnalyticsService;
 import org.hisp.dhis.analytics.DataQueryParams;
+import org.hisp.dhis.analytics.DataQueryService;
 import org.hisp.dhis.common.DimensionalObject;
 import org.hisp.dhis.common.DisplayProperty;
 import org.hisp.dhis.common.NameableObjectUtils;
@@ -81,7 +81,7 @@
         put( FeatureType.POLYGON, GeoFeature.TYPE_POLYGON ).build();
 
     @Autowired
-    private AnalyticsService analyticsService;
+    private DataQueryService dataQueryService;
 
     @Autowired
     private OrganisationUnitGroupService organisationUnitGroupService;
@@ -168,7 +168,7 @@
         Set<String> set = new HashSet<>();
         set.add( ou );
 
-        DataQueryParams params = analyticsService.getFromUrl( set, null, AggregationType.SUM, null,
+        DataQueryParams params = dataQueryService.getFromUrl( set, null, AggregationType.SUM, null,
             false, false, false, false, false, false, false, false, displayProperty, null, null, relativePeriodDate, userOrgUnit, null, null, null );
 
         DimensionalObject dim = params.getDimension( DimensionalObject.ORGUNIT_DIM_ID );