=== 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 2013-01-28 15:55:56 +0000 +++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/AnalyticsService.java 2013-02-01 14:57:34 +0000 @@ -35,9 +35,11 @@ public interface AnalyticsService { - Grid getAggregatedDataValues( DataQueryParams params ) throws Exception; + Grid getAggregatedDataValues( DataQueryParams params ) + throws IllegalQueryException, Exception; - Map getAggregatedDataValueMap( DataQueryParams params, String tableName ) throws Exception; + Map getAggregatedDataValueMap( DataQueryParams params, String tableName ) + throws IllegalQueryException, Exception; DataQueryParams getFromUrl( Set dimensionParams, Set filterParams, AggregationType aggregationType, String measureCriteria, I18nFormat format ); === modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/DataQueryParams.java' --- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/DataQueryParams.java 2013-02-01 11:13:47 +0000 +++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/DataQueryParams.java 2013-02-01 14:57:34 +0000 @@ -270,7 +270,7 @@ if ( dataPeriodType != null ) { - for ( IdentifiableObject aggregatePeriod : getPeriods() ) + for ( IdentifiableObject aggregatePeriod : getDimensionOrFilter( PERIOD_DIM_ID ) ) { Period dataPeriod = dataPeriodType.createPeriod( ((Period) aggregatePeriod).getStartDate() ); @@ -293,7 +293,14 @@ { this.periodType = this.dataPeriodType.getName(); - setPeriods( new ArrayList( getDataPeriodAggregationPeriodMap().keySet() ) ); + if ( getPeriods() != null ) // Period is dimension + { + setPeriods( new ArrayList( dataPeriodAggregationPeriodMap.keySet() ) ); + } + else // Period is filter + { + setFilterPeriods( new ArrayList( dataPeriodAggregationPeriodMap.keySet() ) ); + } } } === modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/QueryPlanner.java' --- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/QueryPlanner.java 2013-01-17 17:49:13 +0000 +++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/QueryPlanner.java 2013-02-01 14:57:34 +0000 @@ -32,6 +32,17 @@ public interface QueryPlanner { /** + * Validates the given query. Throws an IllegalQueryException if the query + * is not valid with a descriptive message. Returns normally if the query is + * valid. + * + * @param params the query. + * @throws IllegalQueryException if the query is invalid. + */ + void validate( DataQueryParams params ) + throws IllegalQueryException; + + /** * Creates a list of DataQueryParams. It is mandatory to group the queries by * the following criteria: 1) partition / year 2) period type 3) organisation * unit level. If the number of queries produced by this grouping is equal or @@ -48,5 +59,6 @@ * @param tableName the base table name. * @return list of data query params. */ - List planQuery( DataQueryParams params, int optimalQueries, String tableName ); + List planQuery( DataQueryParams params, int optimalQueries, String tableName ) + throws IllegalQueryException; } === 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 2013-02-01 11:45:27 +0000 +++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultAnalyticsService.java 2013-02-01 14:57:34 +0000 @@ -90,7 +90,6 @@ import org.hisp.dhis.system.util.SystemUtils; import org.hisp.dhis.system.util.Timer; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.util.Assert; public class DefaultAnalyticsService implements AnalyticsService @@ -134,10 +133,13 @@ // Implementation // ------------------------------------------------------------------------- - public Grid getAggregatedDataValues( DataQueryParams params ) throws Exception + public Grid getAggregatedDataValues( DataQueryParams params ) + throws IllegalQueryException, Exception { log.info( "Query: " + params ); + queryPlanner.validate( params ); + Grid grid = new ListGrid(); // --------------------------------------------------------------------- @@ -188,8 +190,6 @@ { Period period = (Period) DimensionOption.getPeriodOption( options ); - Assert.notNull( period ); - Double value = expressionService.getIndicatorValue( indicator, period, valueMap, constantMap, null ); if ( value != null ) @@ -268,8 +268,11 @@ return grid; } - public Map getAggregatedDataValueMap( DataQueryParams params, String tableName ) throws Exception + public Map getAggregatedDataValueMap( DataQueryParams params, String tableName ) + throws IllegalQueryException, Exception { + queryPlanner.validate( params ); + Timer t = new Timer().start(); int optimalQueries = MathUtils.getWithin( SystemUtils.getCpuCores(), 1, 6 ); === 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 2013-01-30 20:37:26 +0000 +++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultQueryPlanner.java 2013-02-01 14:57:34 +0000 @@ -31,8 +31,7 @@ import static org.hisp.dhis.analytics.AggregationType.AVERAGE_INT; import static org.hisp.dhis.analytics.AggregationType.AVERAGE_INT_DISAGGREGATION; import static org.hisp.dhis.analytics.AggregationType.SUM; -import static org.hisp.dhis.analytics.DataQueryParams.ORGUNIT_DIM_ID; -import static org.hisp.dhis.analytics.DataQueryParams.PERIOD_DIM_ID; +import static org.hisp.dhis.analytics.DataQueryParams.INDICATOR_DIM_ID; import static org.hisp.dhis.dataelement.DataElement.AGGREGATION_OPERATOR_AVERAGE; import static org.hisp.dhis.dataelement.DataElement.AGGREGATION_OPERATOR_SUM; import static org.hisp.dhis.dataelement.DataElement.VALUE_TYPE_BOOL; @@ -44,7 +43,7 @@ import org.hisp.dhis.analytics.AggregationType; import org.hisp.dhis.analytics.DataQueryParams; import org.hisp.dhis.analytics.Dimension; -import org.hisp.dhis.analytics.DimensionType; +import org.hisp.dhis.analytics.IllegalQueryException; import org.hisp.dhis.analytics.QueryPlanner; import org.hisp.dhis.analytics.table.PartitionUtils; import org.hisp.dhis.common.IdentifiableObject; @@ -58,13 +57,12 @@ import org.hisp.dhis.system.util.MathUtils; import org.hisp.dhis.system.util.PaginatedList; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.util.Assert; public class DefaultQueryPlanner implements QueryPlanner { - //TODO call getLevelOrgUnitMap once - //TODO shortcut group by methods when only 1 option + //TODO call getLevelOrgUnitMap once? + //TODO shortcut group by methods when only 1 option? @Autowired private OrganisationUnitService organisationUnitService; @@ -72,12 +70,36 @@ // ------------------------------------------------------------------------- // DefaultQueryPlanner implementation // ------------------------------------------------------------------------- + + public void validate( DataQueryParams params ) + throws IllegalQueryException + { + if ( params == null || params.getDimensions().isEmpty() ) + { + throw new IllegalQueryException( "At least one dimension must be specified" ); + } + + if ( !params.dimensionsAsFilters().isEmpty() ) + { + throw new IllegalQueryException( "Dimensions cannot be specified as dimension and filter simultaneously: " + params.dimensionsAsFilters() ); + } + + if ( !params.hasPeriods() ) + { + throw new IllegalQueryException( "At least one period must be specified as dimension or filter" ); + } + + if ( params.getFilters() != null && params.getFilters().contains( new Dimension( INDICATOR_DIM_ID ) ) ) + { + throw new IllegalQueryException( "Indicators cannot be specified as filter" ); + } + + //TODO check if any dimension occur more than once + } public List planQuery( DataQueryParams params, int optimalQueries, String tableName ) { - Assert.isTrue( !params.getDimensions().isEmpty() ); - Assert.isTrue( params.dimensionsAsFilters().isEmpty() ); - Assert.isTrue( params.hasPeriods() ); + validate( params ); // --------------------------------------------------------------------- // Group queries by partition, period type and organisation unit level @@ -130,13 +152,6 @@ } } - // --------------------------------------------------------------------- - // Set filters for each period type and organisation unit level - // --------------------------------------------------------------------- - - queries = setFilterByPeriodType( queries ); - queries = setFilterByOrgUnitLevel( queries ); - if ( queries.size() >= optimalQueries ) { return queries; @@ -222,7 +237,7 @@ queries.add( query ); } } - else + else if ( params.getFilterPeriods() != null && !params.getFilterPeriods().isEmpty() ) { ListMap tablePeriodMap = PartitionUtils.getTablePeriodMap( params.getFilterPeriods(), tableName ); @@ -234,6 +249,10 @@ queries.add( query ); } } + else + { + throw new IllegalQueryException( "Query does not contain any period dimension options" ); + } return queries; } @@ -246,20 +265,33 @@ { List queries = new ArrayList(); - if ( params.getPeriods() == null || params.getPeriods().isEmpty() ) - { - queries.add( new DataQueryParams( params ) ); - return queries; - } - - ListMap periodTypePeriodMap = getPeriodTypePeriodMap( params.getPeriods() ); - - for ( String periodType : periodTypePeriodMap.keySet() ) - { - DataQueryParams query = new DataQueryParams( params ); - query.setPeriods( periodTypePeriodMap.get( periodType ) ); - query.setPeriodType( periodType ); - queries.add( query ); + if ( params.getPeriods() != null && !params.getPeriods().isEmpty() ) + { + ListMap periodTypePeriodMap = getPeriodTypePeriodMap( params.getPeriods() ); + + for ( String periodType : periodTypePeriodMap.keySet() ) + { + DataQueryParams query = new DataQueryParams( params ); + query.setPeriods( periodTypePeriodMap.get( periodType ) ); + query.setPeriodType( periodType ); + queries.add( query ); + } + } + else if ( params.getFilterPeriods() != null && !params.getFilterPeriods().isEmpty() ) + { + ListMap periodTypePeriodMap = getPeriodTypePeriodMap( params.getFilterPeriods() ); + + for ( String periodType : periodTypePeriodMap.keySet() ) + { + DataQueryParams query = new DataQueryParams( params ); + query.setFilterPeriods( periodTypePeriodMap.get( periodType ) ); + query.setPeriodType( periodType ); + queries.add( query ); + } + } + else + { + throw new IllegalQueryException( "Query does not contain any period dimension options" ); } return queries; @@ -273,22 +305,36 @@ { List queries = new ArrayList(); - if ( params.getOrganisationUnits() == null || params.getOrganisationUnits().isEmpty() ) + if ( params.getOrganisationUnits() != null && !params.getOrganisationUnits().isEmpty() ) + { + ListMap levelOrgUnitMap = getLevelOrgUnitMap( params.getOrganisationUnits() ); + + for ( Integer level : levelOrgUnitMap.keySet() ) + { + DataQueryParams query = new DataQueryParams( params ); + query.setOrganisationUnits( levelOrgUnitMap.get( level ) ); + query.setOrganisationUnitLevel( level ); + queries.add( query ); + } + } + else if ( params.getFilterOrganisationUnits() != null && !params.getFilterOrganisationUnits().isEmpty() ) + { + ListMap levelOrgUnitMap = getLevelOrgUnitMap( params.getFilterOrganisationUnits() ); + + for ( Integer level : levelOrgUnitMap.keySet() ) + { + DataQueryParams query = new DataQueryParams( params ); + query.setFilterOrganisationUnits( levelOrgUnitMap.get( level ) ); + query.setOrganisationUnitLevel( level ); + queries.add( query ); + } + } + else { queries.add( new DataQueryParams( params ) ); return queries; } - ListMap levelOrgUnitMap = getLevelOrgUnitMap( params.getOrganisationUnits() ); - - for ( Integer level : levelOrgUnitMap.keySet() ) - { - DataQueryParams query = new DataQueryParams( params ); - query.setOrganisationUnits( levelOrgUnitMap.get( level ) ); - query.setOrganisationUnitLevel( level ); - queries.add( query ); - } - return queries; } @@ -324,6 +370,8 @@ queries.add( new DataQueryParams( params ) ); return queries; } + + Dimension groupSet = null; if ( params.getDataElements() != null && !params.getDataElements().isEmpty() ) { @@ -338,13 +386,8 @@ query.setAggregationType( aggregationType ); queries.add( query ); } - - return queries; } - - Dimension groupSet = null; - - if ( params.getDataElementGroupSets() != null && !params.getDataElementGroupSets().isEmpty() && + else if ( params.getDataElementGroupSets() != null && !params.getDataElementGroupSets().isEmpty() && ( groupSet = params.getDataElementGroupSets().iterator().next() ).getOptions() != null && !groupSet.getOptions().isEmpty() ) { PeriodType periodType = PeriodType.getPeriodTypeByName( params.getPeriodType() ); @@ -358,13 +401,14 @@ query.setAggregationType( aggregationType ); queries.add( query ); } - - return queries; } + else + { + DataQueryParams query = new DataQueryParams( params ); + query.setAggregationType( SUM ); + queries.add( query ); + } - DataQueryParams query = new DataQueryParams( params ); - query.setAggregationType( SUM ); - queries.add( query ); return queries; } @@ -396,55 +440,6 @@ } /** - * Replaces the period filter with individual filters for each period type. - */ - private List setFilterByPeriodType( List queries ) - { - for ( DataQueryParams params : queries ) - { - if ( params.getFilterPeriods() != null && !params.getFilterPeriods().isEmpty() ) - { - ListMap map = getPeriodTypePeriodMap( params.getFilterPeriods() ); - - params.getFilters().remove( new Dimension( PERIOD_DIM_ID ) ); - - for ( String periodType : map.keySet() ) - { - params.getFilters().add( new Dimension( PERIOD_DIM_ID, DimensionType.PERIOD, map.get( periodType ) ) ); - params.setPeriodType( periodType ); - } - } - } - - return queries; - } - - /** - * Replaces the organisation unit filter with individual filters for each - * organisation unit level. - */ - private List setFilterByOrgUnitLevel( List queries ) - { - for ( DataQueryParams params : queries ) - { - if ( params.getFilterOrganisationUnits() != null && !params.getFilterOrganisationUnits().isEmpty() ) - { - ListMap map = getLevelColumnOrgUnitMap( params.getFilterOrganisationUnits() ); - - params.getFilters().remove( new Dimension( ORGUNIT_DIM_ID ) ); - - for ( Integer level : map.keySet() ) - { - params.getFilters().add( new Dimension( ORGUNIT_DIM_ID, DimensionType.ORGANISATIONUNIT, map.get( level ) ) ); - params.setOrganisationUnitLevel( level ); - } - } - } - - return queries; - } - - /** * Creates a mapping between period type name and period for the given periods. */ private ListMap getPeriodTypePeriodMap( Collection periods ) @@ -478,25 +473,7 @@ return map; } - - /** - * Creates a mapping between the level column and organisation unit for the - * given organisation units. - */ - private ListMap getLevelColumnOrgUnitMap( Collection orgUnits ) - { - ListMap map = new ListMap(); - - for ( IdentifiableObject orgUnit : orgUnits ) - { - int level = organisationUnitService.getLevelOfOrganisationUnit( ((OrganisationUnit) orgUnit).getUid() ); - - map.putValue( level, orgUnit ); - } - - return map; - } - + /** * Creates a mapping between the aggregation type and data element for the * given data elements and period type. @@ -552,7 +529,7 @@ } else { - if ( dataPeriodType == null || aggregationPeriodType.getFrequencyOrder() >= dataPeriodType.getFrequencyOrder() ) + if ( dataPeriodType == null || aggregationPeriodType == null || aggregationPeriodType.getFrequencyOrder() >= dataPeriodType.getFrequencyOrder() ) { map.putValue( AVERAGE_INT, element ); } === modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/JdbcAnalyticsManager.java' --- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/JdbcAnalyticsManager.java 2013-01-28 15:55:56 +0000 +++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/JdbcAnalyticsManager.java 2013-02-01 14:57:34 +0000 @@ -177,6 +177,11 @@ { int periodIndex = params.getPeriodDimensionIndex(); + if ( periodIndex == -1 ) + { + return; // Period is filter, nothing to replace + } + Set keys = new HashSet( dataValueMap.keySet() ); for ( String key : keys ) === modified file 'dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/data/QueryPlannerTest.java' --- dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/data/QueryPlannerTest.java 2013-01-30 13:46:01 +0000 +++ dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/data/QueryPlannerTest.java 2013-02-01 14:57:34 +0000 @@ -46,6 +46,7 @@ import org.hisp.dhis.analytics.DataQueryParams; import org.hisp.dhis.analytics.Dimension; import org.hisp.dhis.analytics.DimensionOption; +import org.hisp.dhis.analytics.IllegalQueryException; import org.hisp.dhis.analytics.QueryPlanner; import org.hisp.dhis.common.IdentifiableObject; import org.hisp.dhis.dataelement.DataElement; @@ -103,6 +104,8 @@ private OrganisationUnit ouD; private OrganisationUnit ouE; + //TODO test for indicators, periods in filter + @Override public void setUpTest() { @@ -480,7 +483,7 @@ /** * Expected to fail because of no periods specified. */ - @Test( expected = IllegalArgumentException.class ) + @Test( expected = IllegalQueryException.class ) public void planQueryG() { DataQueryParams params = new DataQueryParams(); @@ -539,6 +542,19 @@ assertDimensionNameNotNull( query ); } } + + /** + * No periods specified, illegal query. + */ + @Test( expected=IllegalQueryException.class ) + public void planQueryJ() + { + DataQueryParams params = new DataQueryParams(); + params.setDataElements( getList( deA, deB, deC, deD ) ); + params.setOrganisationUnits( getList( ouA, ouB, ouC, ouD, ouE ) ); + + queryPlanner.planQuery( params, 4, ANALYTICS_TABLE_NAME ); + } // ------------------------------------------------------------------------- // Supportive methods === modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/expression/DefaultExpressionService.java' --- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/expression/DefaultExpressionService.java 2013-01-15 11:43:12 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/expression/DefaultExpressionService.java 2013-02-01 14:57:34 +0000 @@ -150,7 +150,7 @@ { final double numeratorValue = calculateExpression( generateExpression( indicator.getNumerator(), valueMap, constantMap, days, false ) ); - final double annualizationFactor = DateUtils.getAnnualizationFactor( indicator, period.getStartDate(), period.getEndDate() ); + final double annualizationFactor = period != null ? DateUtils.getAnnualizationFactor( indicator, period.getStartDate(), period.getEndDate() ) : 1d; final double factor = indicator.getIndicatorType().getFactor(); final double aggregatedValue = ( numeratorValue / denominatorValue ) * factor * annualizationFactor; === modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/AnalyticsController.java' --- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/AnalyticsController.java 2013-01-31 10:59:22 +0000 +++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/AnalyticsController.java 2013-02-01 14:57:34 +0000 @@ -35,7 +35,6 @@ import org.hisp.dhis.analytics.AggregationType; import org.hisp.dhis.analytics.AnalyticsService; import org.hisp.dhis.analytics.DataQueryParams; -import org.hisp.dhis.analytics.Dimension; import org.hisp.dhis.analytics.IllegalQueryException; import org.hisp.dhis.api.utils.ContextUtils; import org.hisp.dhis.api.utils.ContextUtils.CacheStrategy; @@ -50,8 +49,6 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; -import static org.hisp.dhis.analytics.DataQueryParams.*; - @Controller public class AnalyticsController { @@ -81,11 +78,6 @@ { DataQueryParams params = analyticsService.getFromUrl( dimension, filter, aggregationType, measureCriteria, i18nManager.getI18nFormat() ); - if ( !valid( params, response ) ) - { - return null; - } - contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_JSON, CacheStrategy.NO_CACHE ); //TODO Grid grid = analyticsService.getAggregatedDataValues( params ); model.addAttribute( "model", grid ); @@ -104,11 +96,6 @@ { DataQueryParams params = analyticsService.getFromUrl( dimension, filter, aggregationType, measureCriteria, i18nManager.getI18nFormat() ); - if ( !valid( params, response ) ) - { - return; - } - contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_XML, CacheStrategy.NO_CACHE ); //TODO Grid grid = analyticsService.getAggregatedDataValues( params ); GridUtils.toXml( grid, response.getOutputStream() ); @@ -125,11 +112,6 @@ { DataQueryParams params = analyticsService.getFromUrl( dimension, filter, aggregationType, measureCriteria, i18nManager.getI18nFormat() ); - if ( !valid( params, response ) ) - { - return; - } - contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_CSV, CacheStrategy.NO_CACHE ); //TODO Grid grid = analyticsService.getAggregatedDataValues( params ); GridUtils.toCsv( grid, response.getOutputStream() ); @@ -146,55 +128,19 @@ { DataQueryParams params = analyticsService.getFromUrl( dimension, filter, aggregationType, measureCriteria, i18nManager.getI18nFormat() ); - if ( !valid( params, response ) ) - { - return; - } - contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_HTML, CacheStrategy.NO_CACHE ); //TODO Grid grid = analyticsService.getAggregatedDataValues( params ); GridUtils.toHtml( grid, response.getWriter() ); } - + + // ------------------------------------------------------------------------- + // Exception handling + // ------------------------------------------------------------------------- + @ExceptionHandler(IllegalQueryException.class) public void handleError( IllegalQueryException ex, HttpServletResponse response ) throws IOException { ContextUtils.conflictResponse( response, ex.getMessage() ); } - - // ------------------------------------------------------------------------- - // Supportive methods - // ------------------------------------------------------------------------- - - private boolean valid( DataQueryParams params, HttpServletResponse response ) - { - if ( params == null || params.getDimensions().isEmpty() ) - { - ContextUtils.conflictResponse( response, "At least one dimension must be specified" ); - return false; - } - - if ( !params.dimensionsAsFilters().isEmpty() ) - { - ContextUtils.conflictResponse( response, "Dimensions cannot be specified as dimension and filter simultaneously: " + params.dimensionsAsFilters() ); - return false; - } - - if ( !params.hasPeriods() ) - { - ContextUtils.conflictResponse( response, "At least one period must be specified as dimension or filter" ); - return false; - } - - if ( params.getFilters() != null && params.getFilters().contains( new Dimension( INDICATOR_DIM_ID ) ) ) - { - ContextUtils.conflictResponse( response, "Indicators cannot be specified as filter" ); - return false; - } - - //TODO check if any dimension occur more than once - - return true; - } }