← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 11739: First cut of event data analytics Web API

 

------------------------------------------------------------
revno: 11739
committer: Lars Helge Øverland <larshelge@xxxxxxxxx>
branch nick: dhis2
timestamp: Wed 2013-08-21 20:09:08 +0200
message:
  First cut of event data analytics Web API
added:
  dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/
  dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/EventAnalyticsManager.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/EventQueryParams.java
  dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/QueryItem.java
  dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/
  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/EventQueryPlanner.java
  dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/JdbcEventAnalyticsManager.java
  dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/event/
  dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/event/data/
  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/EventQueryPlannerTest.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/EventAnalyticsController.java
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/period/Cal.java
  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/table/PartitionUtils.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/table/PartitionUtilsTest.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-api/src/main/java/org/hisp/dhis/period/Cal.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/period/Cal.java	2013-03-04 14:44:15 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/period/Cal.java	2013-08-21 18:09:08 +0000
@@ -55,6 +55,16 @@
         calendar.clear();
         set( year, month, day );
     }
+    
+    /**
+     * @param date the date.
+     */
+    public Cal( Date date )
+    {
+        calendar = new GregorianCalendar();
+        calendar.clear();
+        calendar.setTime( date );
+    }
 
     /**
      * Sets the time of the calendar to now.

=== 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-08-17 09:24:30 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/DataQueryParams.java	2013-08-21 18:09:08 +0000
@@ -88,9 +88,9 @@
     public static final String DISPLAY_NAME_PERIOD = "Period";
     public static final String DISPLAY_NAME_ORGUNIT = "Organisation unit";    
     
-    private static final String DIMENSION_NAME_SEP = ":";
-    private static final String OPTION_SEP = ";";
-    private static final String ITEM_SEP = "-";
+    public static final String DIMENSION_NAME_SEP = ":";
+    public static final String OPTION_SEP = ";";
+    public static final String ITEM_SEP = "-";
 
     public static final List<String> DATA_DIMS = Arrays.asList( INDICATOR_DIM_ID, DATAELEMENT_DIM_ID, DATAELEMENT_OPERAND_ID, DATASET_DIM_ID );
     public static final List<String> FIXED_DIMS = Arrays.asList( DATA_X_DIM_ID, INDICATOR_DIM_ID, DATAELEMENT_DIM_ID, DATASET_DIM_ID, PERIOD_DIM_ID, ORGUNIT_DIM_ID );

=== added directory 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event'
=== added file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/EventAnalyticsManager.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/EventAnalyticsManager.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/EventAnalyticsManager.java	2013-08-21 18:09:08 +0000
@@ -0,0 +1,38 @@
+package org.hisp.dhis.analytics.event;
+
+/*
+ * Copyright (c) 2004-2012, 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 org.hisp.dhis.common.Grid;
+
+/**
+ * @author Lars Helge Overland
+ */
+public interface EventAnalyticsManager
+{
+    Grid getEvents( EventQueryParams params, Grid grid );
+}

=== added 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	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/EventAnalyticsService.java	2013-08-21 18:09:08 +0000
@@ -0,0 +1,42 @@
+package org.hisp.dhis.analytics.event;
+
+/*
+ * Copyright (c) 2004-2012, 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.common.Grid;
+
+/**
+ * @author Lars Helge Overland
+ */
+public interface EventAnalyticsService
+{
+    Grid getEvents( EventQueryParams params );
+
+    EventQueryParams getFromUrl( String program, String stage, String startDate, String endDate, Set<String> item, Set<String> orgUnits );
+}

=== added file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/EventQueryParams.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/EventQueryParams.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/EventQueryParams.java	2013-08-21 18:09:08 +0000
@@ -0,0 +1,158 @@
+package org.hisp.dhis.analytics.event;
+
+/*
+ * Copyright (c) 2004-2009, 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.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.hisp.dhis.organisationunit.OrganisationUnit;
+import org.hisp.dhis.program.Program;
+import org.hisp.dhis.program.ProgramStage;
+
+/**
+ * @author Lars Helge Overland
+ */
+public class EventQueryParams
+{
+    private Program program;
+    
+    private ProgramStage programStage;
+    
+    private Date startDate;
+    
+    private Date endDate;
+    
+    private List<QueryItem> items = new ArrayList<QueryItem>();
+    
+    private List<OrganisationUnit> organisationUnits = new ArrayList<OrganisationUnit>();
+    
+    private String tableName;
+
+    // -------------------------------------------------------------------------
+    // Constructors
+    // -------------------------------------------------------------------------
+
+    public EventQueryParams()
+    {
+    }
+    
+    public EventQueryParams( EventQueryParams params )
+    {
+        this.program = params.getProgram();
+        this.programStage = params.getProgramStage();
+        this.startDate = params.getStartDate();
+        this.endDate = params.getEndDate();
+        this.items = new ArrayList<QueryItem>( params.getItems() );
+        this.organisationUnits = new ArrayList<OrganisationUnit>( params.getOrganisationUnits() );
+        this.tableName = params.getTableName();
+    }
+
+    // -------------------------------------------------------------------------
+    // Logic
+    // -------------------------------------------------------------------------
+
+    public boolean hasOrganisationUnits()
+    {
+        return organisationUnits != null && !organisationUnits.isEmpty();
+    }
+    
+    // -------------------------------------------------------------------------
+    // Getters and setters
+    // -------------------------------------------------------------------------
+
+    public Program getProgram()
+    {
+        return program;
+    }
+
+    public void setProgram( Program program )
+    {
+        this.program = program;
+    }
+
+    public ProgramStage getProgramStage()
+    {
+        return programStage;
+    }
+
+    public void setProgramStage( ProgramStage programStage )
+    {
+        this.programStage = programStage;
+    }
+
+    public Date getStartDate()
+    {
+        return startDate;
+    }
+
+    public void setStartDate( Date startDate )
+    {
+        this.startDate = startDate;
+    }
+
+    public Date getEndDate()
+    {
+        return endDate;
+    }
+
+    public void setEndDate( Date endDate )
+    {
+        this.endDate = endDate;
+    }
+
+    public List<QueryItem> getItems()
+    {
+        return items;
+    }
+
+    public void setItems( List<QueryItem> items )
+    {
+        this.items = items;
+    }
+
+    public List<OrganisationUnit> getOrganisationUnits()
+    {
+        return organisationUnits;
+    }
+
+    public void setOrganisationUnits( List<OrganisationUnit> organisationUnits )
+    {
+        this.organisationUnits = organisationUnits;
+    }
+
+    public String getTableName()
+    {
+        return tableName;
+    }
+
+    public void setTableName( String tableName )
+    {
+        this.tableName = tableName;
+    }
+}

=== added file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/QueryItem.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/QueryItem.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/QueryItem.java	2013-08-21 18:09:08 +0000
@@ -0,0 +1,101 @@
+package org.hisp.dhis.analytics.event;
+
+/*
+ * Copyright (c) 2004-2012, 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 org.hisp.dhis.common.IdentifiableObject;
+
+/**
+ * @author Lars Helge Overland
+ */
+public class QueryItem
+{
+    private IdentifiableObject item;
+
+    private String operator;
+
+    private String filter;
+
+    // -------------------------------------------------------------------------
+    // Constructors
+    // -------------------------------------------------------------------------
+
+    public QueryItem( IdentifiableObject item )
+    {
+        this.item = item;
+    }
+    
+    public QueryItem( IdentifiableObject item, String operator, String filter )
+    {
+        this.item = item;
+        this.operator = operator;
+        this.filter = filter;
+    }
+
+    // -------------------------------------------------------------------------
+    // Logic
+    // -------------------------------------------------------------------------
+
+    public boolean hasFilter()
+    {
+        return operator != null && !operator.isEmpty() && filter != null && !filter.isEmpty();
+    }
+    
+    // -------------------------------------------------------------------------
+    // Getters and setters
+    // -------------------------------------------------------------------------
+
+    public IdentifiableObject getItem()
+    {
+        return item;
+    }
+
+    public void setItem( IdentifiableObject item )
+    {
+        this.item = item;
+    }
+
+    public String getOperator()
+    {
+        return operator;
+    }
+
+    public void setOperator( String operator )
+    {
+        this.operator = operator;
+    }
+
+    public String getFilter()
+    {
+        return filter;
+    }
+
+    public void setFilter( String filter )
+    {
+        this.filter = filter;
+    }
+}

=== added directory 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data'
=== added 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	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/DefaultEventAnalyticsService.java	2013-08-21 18:09:08 +0000
@@ -0,0 +1,224 @@
+package org.hisp.dhis.analytics.event.data;
+
+/*
+ * Copyright (c) 2004-2012, 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.OPTION_SEP;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+import org.hisp.dhis.analytics.IllegalQueryException;
+import org.hisp.dhis.analytics.event.EventAnalyticsManager;
+import org.hisp.dhis.analytics.event.EventAnalyticsService;
+import org.hisp.dhis.analytics.event.EventQueryParams;
+import org.hisp.dhis.analytics.event.QueryItem;
+import org.hisp.dhis.common.Grid;
+import org.hisp.dhis.common.GridHeader;
+import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.dataelement.DataElement;
+import org.hisp.dhis.dataelement.DataElementService;
+import org.hisp.dhis.organisationunit.OrganisationUnit;
+import org.hisp.dhis.organisationunit.OrganisationUnitService;
+import org.hisp.dhis.patient.PatientAttribute;
+import org.hisp.dhis.patient.PatientAttributeService;
+import org.hisp.dhis.patient.PatientIdentifierType;
+import org.hisp.dhis.patient.PatientIdentifierTypeService;
+import org.hisp.dhis.program.Program;
+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.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * @author Lars Helge Overland
+ */
+public class DefaultEventAnalyticsService
+    implements EventAnalyticsService
+{
+    @Autowired
+    private ProgramService programService;
+    
+    @Autowired
+    private ProgramStageService programStageService;
+
+    @Autowired
+    private DataElementService dataElementService;
+    
+    @Autowired
+    private PatientAttributeService attributeService;
+
+    @Autowired
+    private PatientIdentifierTypeService identifierTypeService;
+    
+    @Autowired
+    private OrganisationUnitService organisationUnitService;
+    
+    @Autowired
+    private EventAnalyticsManager analyticsManager;
+
+    // -------------------------------------------------------------------------
+    // EventAnalyticsService implementation
+    // -------------------------------------------------------------------------
+
+    //TODO table name
+    //TODO org unit children / descendants
+    
+    public Grid getEvents( EventQueryParams params )
+    {
+        Grid grid = new ListGrid();
+                
+        grid.addHeader( new GridHeader( "Event", "psi" ) );
+        grid.addHeader( new GridHeader( "Program stage", "ps" ) );
+        grid.addHeader( new GridHeader( "Executiondate", "executiondate" ) );
+        grid.addHeader( new GridHeader( "Organisation unit", "ou" ) );
+        
+        for ( QueryItem queryItem : params.getItems() )
+        {
+            IdentifiableObject item = queryItem.getItem();
+            
+            grid.addHeader( new GridHeader( item.getName(), item.getUid() ) );
+        }
+        
+        List<EventQueryParams> queries = EventQueryPlanner.planQuery( params );
+        
+        for ( EventQueryParams query : queries )
+        {
+            analyticsManager.getEvents( query, grid );
+        }
+        
+        return grid;
+    }
+    
+    public EventQueryParams getFromUrl( String program, String stage, String startDate, String endDate, Set<String> item, Set<String> orgUnits )
+    {
+        EventQueryParams params = new EventQueryParams();
+        
+        Program pr = programService.getProgram( program );
+        
+        if ( pr == null )
+        {
+            throw new IllegalQueryException( "Program does not exist: " + program );
+        }
+        
+        ProgramStage ps = programStageService.getProgramStage( stage );
+        
+        if ( stage != null && !stage.isEmpty() && ps == null )
+        {
+            throw new IllegalQueryException( "Program stage is specified but does not exist: " + stage );
+        }
+        
+        Date start = null;
+        Date end = 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 ( start.after( end ) )
+        {
+            throw new IllegalQueryException( "Start date is after end date: " + startDate + " - " + endDate );
+        }
+        
+        if ( item != null )
+        {
+            for ( String it : item )
+            {
+                if ( it != null && !it.contains( OPTION_SEP ) )
+                {
+                    params.getItems().add( new QueryItem( getItem( it ) ) );
+                }
+                else if ( it != null )
+                {
+                    String[] split = it.split( OPTION_SEP );
+                    
+                    if ( split == null || split.length != 3 )
+                    {
+                        throw new IllegalQueryException( "Item filter has invalid format: " + it );
+                    }
+                    
+                    params.getItems().add( new QueryItem( getItem( split[0] ), split[1], split[2] ) );
+                }
+            }
+        }
+        
+        if ( orgUnits != null )
+        {
+            for ( String orgUnit : orgUnits )
+            {
+                OrganisationUnit ou = organisationUnitService.getOrganisationUnit( orgUnit );
+                
+                if ( ou != null )
+                {
+                    params.getOrganisationUnits().add( ou );
+                }
+            }
+        }
+        
+        params.setProgram( pr );
+        params.setProgramStage( ps );
+        params.setStartDate( start );
+        params.setEndDate( end );
+        
+        return params;
+    }
+    
+    private IdentifiableObject getItem( String item )
+    {
+        DataElement de = dataElementService.getDataElement( item );
+        
+        if ( de != null )
+        {
+            return de;
+        }
+        
+        PatientAttribute at = attributeService.getPatientAttribute( item );
+        
+        if ( at != null )
+        {
+            return at;
+        }
+        
+        PatientIdentifierType it = identifierTypeService.getPatientIdentifierType( item );
+        
+        if ( it != null )
+        {
+            return it;
+        }
+        
+        throw new IllegalQueryException( "Item identifier does not reference any item: " + item );           
+    }
+}

=== added file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/EventQueryPlanner.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/EventQueryPlanner.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/EventQueryPlanner.java	2013-08-21 18:09:08 +0000
@@ -0,0 +1,75 @@
+package org.hisp.dhis.analytics.event.data;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.hisp.dhis.analytics.event.EventQueryParams;
+import org.hisp.dhis.period.Cal;
+import org.hisp.dhis.program.Program;
+
+public class EventQueryPlanner
+{
+    private static final String TABLE_BASE_NAME = "analytics_event_";
+    
+    public static List<EventQueryParams> planQuery( EventQueryParams params )
+    {
+        return splitByPartition( params );
+    }
+    
+    private static List<EventQueryParams> splitByPartition( EventQueryParams params )
+    {
+        List<EventQueryParams> list = new ArrayList<EventQueryParams>();
+        
+        Program program = params.getProgram();
+        
+        Date startDate = params.getStartDate();
+        Date endDate = params.getEndDate();
+        
+        Date currentStartDate = startDate;
+        Date currentEndDate = endDate;
+        
+        while ( true )
+        {
+            if ( year( currentStartDate ) < year( endDate ) ) // Spans multiple
+            {
+                // Set end date to max of current year
+                
+                currentEndDate = maxOfYear( currentStartDate ); 
+                
+                list.add( getQuery( params, currentStartDate, currentEndDate, program ) );
+                
+                // Set start date to start of next year
+                
+                currentStartDate = new Cal( ( year( currentStartDate ) + 1 ), 1, 1 ).time();                 
+            }
+            else
+            {
+                list.add( getQuery( params, currentStartDate, endDate, program ) );
+                
+                break;
+            }
+        }
+        
+        return list;
+    }
+    
+    private static EventQueryParams getQuery( EventQueryParams params, Date startDate, Date endDate, Program program )
+    {
+        EventQueryParams query = new EventQueryParams( params );
+        query.setStartDate( startDate );
+        query.setEndDate( endDate );
+        query.setTableName( TABLE_BASE_NAME + year( startDate ) + "_" + program.getUid() );
+        return query;
+    }
+    
+    private static int year( Date date )
+    {
+        return new Cal( date ).getYear();
+    }
+    
+    private static Date maxOfYear( Date date )
+    {
+        return new Cal( year( date ), 12, 31 ).time();
+    }
+}

=== added file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/JdbcEventAnalyticsManager.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/JdbcEventAnalyticsManager.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/JdbcEventAnalyticsManager.java	2013-08-21 18:09:08 +0000
@@ -0,0 +1,110 @@
+package org.hisp.dhis.analytics.event.data;
+
+/*
+ * Copyright (c) 2004-2012, 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.IdentifiableObjectUtils.getUids;
+import static org.hisp.dhis.system.util.DateUtils.getMediumDateString;
+import static org.hisp.dhis.system.util.TextUtils.getQuotedCommaDelimitedString;
+import static org.hisp.dhis.system.util.TextUtils.removeLast;
+
+import org.hisp.dhis.analytics.event.EventAnalyticsManager;
+import org.hisp.dhis.analytics.event.EventQueryParams;
+import org.hisp.dhis.analytics.event.QueryItem;
+import org.hisp.dhis.common.Grid;
+import org.hisp.dhis.common.IdentifiableObject;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.support.rowset.SqlRowSet;
+
+/**
+ * @author Lars Helge Overland
+ */
+public class JdbcEventAnalyticsManager
+    implements EventAnalyticsManager
+{
+    @Autowired
+    private JdbcTemplate jdbcTemplate;
+
+    // -------------------------------------------------------------------------
+    // EventAnalyticsManager implementation
+    // -------------------------------------------------------------------------
+
+    public Grid getEvents( EventQueryParams params, Grid grid )
+    {
+        String sql = "select psi,ps,executiondate,ou,";
+        
+        for ( QueryItem queryItem : params.getItems() )
+        {
+            IdentifiableObject item = queryItem.getItem();
+            
+            sql += item.getUid() + ",";
+        }
+        
+        sql = removeLast( sql, 1 ) + " ";
+        
+        sql += "from " + params.getTableName() + " ";        
+        sql += "where executiondate >= '" + getMediumDateString( params.getStartDate() ) + "' ";
+        sql += "and executiondate <= '" + getMediumDateString( params.getEndDate() ) + "' ";
+        
+        if ( params.hasOrganisationUnits() )
+        {
+            sql += "and ou in (" + getQuotedCommaDelimitedString( getUids( params.getOrganisationUnits() ) ) + ") ";
+        }
+        
+        if ( params.getProgramStage() != null )
+        {
+            sql += "and ps = '" + params.getProgramStage() + "' ";
+        }
+        
+        for ( QueryItem filter : params.getItems() )
+        {
+            if ( filter.hasFilter() )
+            {
+                sql += "and " + filter.getFilter() + " " + filter.getOperator() + " '" + filter.getFilter() + "' ";
+            }
+        }
+
+        int rowLength = grid.getHeaders().size();
+        
+        SqlRowSet rowSet = jdbcTemplate.queryForRowSet( sql );
+
+        while ( rowSet.next() )
+        {
+            grid.addRow();
+            
+            for ( int i = 0; i < rowLength; i++ )
+            {
+                int index = i + 1;
+                
+                grid.addValue( rowSet.getString( index ) );
+            }
+        }
+        
+        return grid;
+    }
+}

=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/PartitionUtils.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/PartitionUtils.java	2013-08-20 22:48:23 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/PartitionUtils.java	2013-08-21 18:09:08 +0000
@@ -34,7 +34,6 @@
 import org.hisp.dhis.common.ListMap;
 import org.hisp.dhis.common.NameableObject;
 import org.hisp.dhis.period.Period;
-import org.hisp.dhis.period.PeriodType;
 import org.hisp.dhis.period.YearlyPeriodType;
 
 /**
@@ -67,19 +66,6 @@
         
         return tableName + SEP + year.getIsoDate();
     }
-
-    public static Period getPeriod( String tableName )
-    {
-        if ( tableName == null || tableName.indexOf( SEP ) == -1 )
-        {
-            return null;
-        }
-        
-        String[] split = tableName.split( SEP );
-        String isoPeriod = split[split.length - 1];
-        
-        return PeriodType.getPeriodFromIsoString( isoPeriod );
-    }
     
     public static ListMap<String, NameableObject> getTableNamePeriodMap( List<NameableObject> periods, String tableName )
     {

=== 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	2013-08-21 10:08:02 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/resources/META-INF/dhis/beans.xml	2013-08-21 18:09:08 +0000
@@ -2,6 +2,8 @@
 <beans xmlns="http://www.springframework.org/schema/beans"; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd";>
 
+  <!-- Table -->
+
   <bean id="org.hisp.dhis.analytics.AnalyticsTableManager" class="org.hisp.dhis.analytics.table.JdbcAnalyticsTableManager" />
   
   <bean id="org.hisp.dhis.analytics.CompletenessTableManager" class="org.hisp.dhis.analytics.table.JdbcCompletenessTableManager" />
@@ -26,12 +28,20 @@
     <property name="tableManager" ref="org.hisp.dhis.analytics.EventAnalyticsTableManager" />
   </bean>
   
+  <!-- Routine analytics -->
+  
   <bean id="org.hisp.dhis.analytics.AnalyticsManager" class="org.hisp.dhis.analytics.data.JdbcAnalyticsManager" />
   
   <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" />
 
+  <!-- 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.EventAnalyticsService" class="org.hisp.dhis.analytics.event.data.DefaultEventAnalyticsService" />
+
   <!-- Scheduled tasks -->
   
   <bean id="analyticsAllTask" class="org.hisp.dhis.analytics.scheduling.AnalyticsTableTask">

=== added directory 'dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/event'
=== added directory 'dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/event/data'
=== added 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/EventAnalyticsServiceTest.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/event/data/EventAnalyticsServiceTest.java	2013-08-21 18:09:08 +0000
@@ -0,0 +1,84 @@
+package org.hisp.dhis.analytics.event.data;
+
+/*
+ * Copyright (c) 2004-2012, 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 org.hisp.dhis.DhisSpringTest;
+import org.hisp.dhis.analytics.event.EventAnalyticsService;
+import org.hisp.dhis.dataelement.DataElement;
+import org.hisp.dhis.dataelement.DataElementService;
+import org.hisp.dhis.patient.PatientAttribute;
+import org.hisp.dhis.patient.PatientAttributeService;
+import org.hisp.dhis.patient.PatientIdentifierType;
+import org.hisp.dhis.patient.PatientIdentifierTypeService;
+import org.hisp.dhis.program.Program;
+import org.hisp.dhis.program.ProgramService;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * @author Lars Helge Overland
+ */
+public class EventAnalyticsServiceTest
+    extends DhisSpringTest
+{
+    @Autowired
+    private EventAnalyticsService analyticsService;
+    
+    @Autowired
+    private ProgramService programService;
+    
+    @Autowired
+    private DataElementService dataElementService;
+    
+    @Autowired
+    private PatientAttributeService attributeService;
+
+    @Autowired
+    private PatientIdentifierTypeService identifierTypeService;
+    
+    private Program prA;
+    private DataElement deA;
+    private DataElement deB;
+    private PatientAttribute atA;
+    private PatientAttribute atB;
+    private PatientIdentifierType itA;
+    private PatientIdentifierType itB;
+
+    @Override
+    public void setUpTest()
+    {
+        prA = createProgram( 'A', null, null );
+        
+    }
+    
+    @Test
+    public void testGetFromUrl()
+    {
+        
+    }
+}

=== added file 'dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/event/data/EventQueryPlannerTest.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/event/data/EventQueryPlannerTest.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/event/data/EventQueryPlannerTest.java	2013-08-21 18:09:08 +0000
@@ -0,0 +1,91 @@
+package org.hisp.dhis.analytics.event.data;
+
+/*
+ * Copyright (c) 2004-2012, 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.junit.Assert.assertEquals;
+
+import java.util.List;
+
+import org.hisp.dhis.analytics.event.EventQueryParams;
+import org.hisp.dhis.period.Cal;
+import org.hisp.dhis.program.Program;
+import org.junit.Test;
+
+/**
+ * @author Lars Helge Overland
+ */
+public class EventQueryPlannerTest
+{
+    @Test
+    public void testPlanQueryA()
+    {
+        Program prA = new Program();
+        prA.setUid( "programuidA" );
+        
+        EventQueryParams params = new EventQueryParams();
+        params.setProgram( prA );
+        params.setStartDate( new Cal( 2010, 6, 1 ).time() );
+        params.setEndDate( new Cal( 2012, 3, 20 ).time() );
+        
+        List<EventQueryParams> queries = EventQueryPlanner.planQuery( params );
+        
+        assertEquals( 3, queries.size() );
+        
+        assertEquals( new Cal( 2010, 6, 1 ).time(), queries.get( 0 ).getStartDate() );
+        assertEquals( new Cal( 2010, 12, 31 ).time(), queries.get( 0 ).getEndDate() );
+        assertEquals( new Cal( 2011, 1, 1 ).time(), queries.get( 1 ).getStartDate() );
+        assertEquals( new Cal( 2011, 12, 31 ).time(), queries.get( 1 ).getEndDate() );
+        assertEquals( new Cal( 2012, 1, 1 ).time(), queries.get( 2 ).getStartDate() );
+        assertEquals( new Cal( 2012, 3, 20 ).time(), queries.get( 2 ).getEndDate() );
+        
+        assertEquals( "analytics_event_2010_programuidA", queries.get( 0 ).getTableName() );
+        assertEquals( "analytics_event_2011_programuidA", queries.get( 1 ).getTableName() );
+        assertEquals( "analytics_event_2012_programuidA", queries.get( 2 ).getTableName() );
+    }
+
+    @Test
+    public void testPlanQueryB()
+    {
+        Program prA = new Program();
+        prA.setUid( "programuidA" );
+        
+        EventQueryParams params = new EventQueryParams();
+        params.setProgram( prA );
+        params.setStartDate( new Cal( 2010, 3, 1 ).time() );
+        params.setEndDate( new Cal( 2010, 9, 20 ).time() );
+        
+        List<EventQueryParams> queries = EventQueryPlanner.planQuery( params );
+
+        assertEquals( 1, queries.size() );
+        
+        assertEquals( new Cal( 2010, 3, 1 ).time(), queries.get( 0 ).getStartDate() );
+        assertEquals( new Cal( 2010, 9, 20 ).time(), queries.get( 0 ).getEndDate() );
+
+        assertEquals( "analytics_event_2010_programuidA", queries.get( 0 ).getTableName() );
+    }        
+}

=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/table/PartitionUtilsTest.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/table/PartitionUtilsTest.java	2013-08-20 22:48:23 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/table/PartitionUtilsTest.java	2013-08-21 18:09:08 +0000
@@ -29,16 +29,12 @@
 
 import static org.hisp.dhis.DhisConvenienceTest.createPeriod;
 import static org.hisp.dhis.analytics.AnalyticsTableManager.ANALYTICS_TABLE_NAME;
-import static org.hisp.dhis.analytics.AnalyticsTableManager.TABLE_TEMP_SUFFIX;
 import static org.hisp.dhis.common.NameableObjectUtils.getList;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
 import org.hisp.dhis.common.ListMap;
 import org.hisp.dhis.common.NameableObject;
-import org.hisp.dhis.period.Cal;
-import org.hisp.dhis.period.Period;
-import org.hisp.dhis.period.YearlyPeriodType;
 import org.junit.Test;
 
 /**
@@ -46,7 +42,6 @@
  */
 public class PartitionUtilsTest
 {
-    private static final String TABLE_NAME_TEMP = ANALYTICS_TABLE_NAME + TABLE_TEMP_SUFFIX;
     private static final String TABLE_NAME = ANALYTICS_TABLE_NAME;
         
     @Test
@@ -57,19 +52,7 @@
         assertEquals( TABLE_NAME + "_2002", PartitionUtils.getTableName( createPeriod( "2002Q2" ), TABLE_NAME ) );
         assertEquals( TABLE_NAME + "_2003", PartitionUtils.getTableName( createPeriod( "2003S2" ), TABLE_NAME ) );
     }
-    
-    @Test
-    public void testGetPeriod()
-    {
-        Cal cal = new Cal();
-        
-        Period p1 = new YearlyPeriodType().createPeriod( cal.set( 2000, 4, 1 ).time() );
-        Period p2 = new YearlyPeriodType().createPeriod( cal.set( 2001, 10, 1 ).time() );
-        
-        assertEquals( p1, PartitionUtils.getPeriod( TABLE_NAME_TEMP + "_2000" ) );
-        assertEquals( p2, PartitionUtils.getPeriod( TABLE_NAME_TEMP + "_2001" ) );
-    }
-    
+        
     @Test
     public void testGetTablePeriodMap()
     {        

=== added file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/EventAnalyticsController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/EventAnalyticsController.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/EventAnalyticsController.java	2013-08-21 18:09:08 +0000
@@ -0,0 +1,81 @@
+package org.hisp.dhis.api.controller;
+
+/*
+ * Copyright (c) 2004-2012, 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 javax.servlet.http.HttpServletResponse;
+
+import org.hisp.dhis.analytics.event.EventAnalyticsService;
+import org.hisp.dhis.analytics.event.EventQueryParams;
+import org.hisp.dhis.api.utils.ContextUtils;
+import org.hisp.dhis.api.utils.ContextUtils.CacheStrategy;
+import org.hisp.dhis.common.Grid;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+
+@Controller
+public class EventAnalyticsController
+{
+    private static final String RESOURCE_PATH = "/analytics/events";
+
+    @Autowired
+    private EventAnalyticsService analyticsService;
+
+    @Autowired
+    private ContextUtils contextUtils;
+
+    // -------------------------------------------------------------------------
+    // Resources
+    // -------------------------------------------------------------------------
+    
+    @RequestMapping( value = RESOURCE_PATH + "/{program}", method = RequestMethod.GET, produces = { "application/json", "application/javascript" } )
+    public String getJson( // JSON, JSONP
+        @PathVariable String program,
+        @RequestParam(required=false) String stage,
+        @RequestParam String startDate,
+        @RequestParam String endDate,
+        @RequestParam Set<String> item,
+        @RequestParam(required=false) Set<String> orgUnits,
+        Model model,
+        HttpServletResponse response ) throws Exception
+    {
+        EventQueryParams params = analyticsService.getFromUrl( program, stage, startDate, endDate, item, orgUnits );
+        
+        contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_JSON, CacheStrategy.RESPECT_SYSTEM_SETTING );
+        Grid grid = analyticsService.getEvents( params );
+        model.addAttribute( "model", grid );
+        model.addAttribute( "viewClass", "detailed" );
+        return "grid";
+    }
+}