class AbstractJdbcEventAnalyticsManager {

    protected String getAggregateClause( EventQueryParams params )
    {
        EventOutputType outputType = params.getOutputType();

        if ( params.hasValueDimension() ) // TODO && isNumeric
        {
            Assert.isTrue( params.getAggregationTypeFallback().getAggregationType().isAggregateable(), "Event query aggregation type must be aggregatable" );

            String function = params.getAggregationTypeFallback().getAggregationType().getValue();

            String expression = quoteAlias( params.getValue().getUid() );

            return function + "(" + expression + ")";
        }
        else if ( params.hasProgramIndicatorDimension() )
        {
            String function = params.getProgramIndicator().getAggregationTypeFallback().getValue();

            function = TextUtils.emptyIfEqual( function, AggregationType.CUSTOM.getValue() );

            String expression = programIndicatorService.getAnalyticsSql( params.getProgramIndicator().getExpression(),
                params.getProgramIndicator(), params.getEarliestStartDate(), params.getLatestEndDate() );

            return function + "(" + expression + ")";
        }
        else
        {
            if ( params.hasEnrollmentProgramIndicatorDimension() )
            {
                if ( EventOutputType.TRACKED_ENTITY_INSTANCE.equals( outputType ) && params.isProgramRegistration() )
                {
                    return "count(distinct tei)";
                }
                else // EVENT
                {
                    return "count(pi)";
                }
            }
            else
            {
                if ( EventOutputType.TRACKED_ENTITY_INSTANCE.equals( outputType ) && params.isProgramRegistration() )
                {
                    return "count(distinct " + quoteAlias( "tei") + ")";
                }
                else if ( EventOutputType.ENROLLMENT.equals( outputType ) )
                {
                    return "count(distinct " + quoteAlias( "pi") + ")";
                }
                else // EVENT
                {
                    return "count(" + quoteAlias( "psi") + ")";
                }
            }
        }
    }

    public  AbstractJdbcEventAnalyticsManager( @Qualifier( "readOnlyJdbcTemplate" ) JdbcTemplate jdbcTemplate,
        StatementBuilder statementBuilder, ProgramIndicatorService programIndicatorService,
        ProgramIndicatorSubqueryBuilder programIndicatorSubqueryBuilder );

}