← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 2568: Improved Grid and results

 

------------------------------------------------------------
revno: 2568
committer: Lars Helge Overland <larshelge@xxxxxxxxx>
branch nick: dhis2
timestamp: Fri 2011-01-14 17:14:22 +0100
message:
  Improved Grid and results
added:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/GridHeader.java
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/Grid.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/Program.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/reporttable/ReportTable.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/reporttable/ReportTableService.java
  dhis-2/dhis-services/dhis-service-reporting/src/main/java/org/hisp/dhis/orgunitdistribution/impl/DefaultOrgUnitDistributionService.java
  dhis-2/dhis-services/dhis-service-reporting/src/main/java/org/hisp/dhis/reporttable/impl/DefaultReportTableService.java
  dhis-2/dhis-services/dhis-service-reporting/src/main/java/org/hisp/dhis/reporttable/jdbc/JDBCReportTableManager.java
  dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/grid/ListGrid.java
  dhis-2/dhis-support/dhis-support-system/src/test/java/org/hisp/dhis/system/grid/GridTest.java
  dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/ajax/htmlGrid.vm
  dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/result/GridCsvResult.java
  dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/result/GridPdfResult.java
  dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/result/GridXlsResult.java
  dhis-2/dhis-web/dhis-web-reporting/src/main/java/org/hisp/dhis/reporting/completeness/action/GetDataCompletenessAction.java
  dhis-2/dhis-web/dhis-web-reporting/src/main/java/org/hisp/dhis/reporting/tablecreator/action/ExportTableAction.java
  dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/ExportValidationResultAction.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/common/Grid.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/Grid.java	2010-12-26 15:38:45 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/Grid.java	2011-01-14 16:14:22 +0000
@@ -27,8 +27,6 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import java.sql.ResultSet;
-import java.sql.SQLException;
 import java.util.List;
 
 /**
@@ -55,23 +53,22 @@
      * Sets the grid subtitle.
      */
     Grid setSubtitle( String subtitle );
-    
+
     /**
      * Returns all header values.
      */
-    List<String> getHeaders();
+    List<GridHeader> getHeaders();
+    
+    /**
+     * Returns all visible headers, ie. headers which are not hidden.
+     */
+    List<GridHeader> getVisibleHeaders();
     
     /**
      * Adds a header value.
      */
-    Grid addHeader( String value );
-    
-    /**
-     * Replaces the header String given in the first argument with the header
-     * String given in the second argument if the former exists.
-     */
-    Grid replaceHeader( String currentHeader, String newHeader );
-    
+    Grid addHeader( GridHeader header );
+        
     /**
      * Returns the current height / number of rows in the grid.
      */
@@ -81,6 +78,11 @@
      * Returns the current width / number of columns in the grid.
      */
     int getWidth();
+    
+    /**
+     * Returns the current width / number of visible columns in the grid.
+     */
+    int getVisibleWidth();
 
     /**
      * Adds a new row the the grid and moves the cursor accordingly.
@@ -105,6 +107,12 @@
      * Returns all rows.
      */
     List<List<String>> getRows();
+    
+    /**
+     * Returns all visible rows, ie. rows with a corresponding header that is
+     * not hidden.
+     */
+    List<List<String>> getVisibleRows();
 
     /**
      * Returns the column with the given index.
@@ -141,7 +149,7 @@
      * Removes the header and the column at the index of the given header if it
      * exists.
      */
-    Grid removeColumn( String header );
+    Grid removeColumn( GridHeader header );
     
     /**
      * Adds a regression column to the grid. Column must hold numeric data.
@@ -149,12 +157,4 @@
      * @param columnIndex the index of the base column.
      */
     Grid addRegressionColumn( int columnIndex );
-    
-    /**
-     * Instantiates and populates a Grid based on the given result set. The
-     * column names are used as headers and result rows are represented as grid
-     * rows.
-     */
-    Grid fromResultSet( ResultSet resultSet )
-        throws SQLException;
 }

=== added file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/GridHeader.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/GridHeader.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/GridHeader.java	2011-01-14 16:14:22 +0000
@@ -0,0 +1,145 @@
+package org.hisp.dhis.common;
+
+/*
+ * Copyright (c) 2004-2010, 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.
+ */
+
+/**
+ * @author Lars Helge Overland
+ */
+public class GridHeader
+{
+    private String name;
+    
+    private String column;
+    
+    private String type;
+    
+    private boolean hidden;
+    
+    private boolean meta;
+    
+    public GridHeader()
+    {
+    }
+
+    public GridHeader( String name, boolean hidden, boolean meta )
+    {
+        this.name = name;
+        this.column = name;
+        this.type = null;
+        this.hidden = hidden;
+        this.meta = meta;
+    }
+
+    public GridHeader( String name, String column, String type, boolean hidden, boolean meta )
+    {
+        this.name = name;
+        this.column = column;
+        this.type = type;
+        this.hidden = hidden;
+        this.meta = meta;
+    }
+
+    public String getName()
+    {
+        return name;
+    }
+
+    public void setName( String name )
+    {
+        this.name = name;
+    }
+
+    public String getColumn()
+    {
+        return column;
+    }
+
+    public void setColumn( String column )
+    {
+        this.column = column;
+    }
+
+    public String getType()
+    {
+        return type;
+    }
+
+    public void setType( String type )
+    {
+        this.type = type;
+    }
+
+    public boolean isHidden()
+    {
+        return hidden;
+    }
+
+    public void setHidden( boolean hidden )
+    {
+        this.hidden = hidden;
+    }
+
+    public boolean isMeta()
+    {
+        return meta;
+    }
+
+    public void setMeta( boolean meta )
+    {
+        this.meta = meta;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return name.hashCode();
+    }
+
+    @Override
+    public boolean equals( Object object )
+    {
+        if ( this == object )
+        {
+            return true;
+        }
+        
+        if ( object == null )
+        {
+            return false;
+        }
+        
+        if ( getClass() != object.getClass() )
+        {
+            return false;
+        }
+        
+        final GridHeader other = (GridHeader) object;
+        
+        return name.equals( other.name );
+    }
+}

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/Program.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/Program.java	2010-12-29 16:17:28 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/Program.java	2011-01-14 16:14:22 +0000
@@ -270,7 +270,7 @@
         return null;
     }
 
-    @SuppressWarnings( { "unchecked", "rawtypes" } )
+    @SuppressWarnings( "unchecked" )
     public ValidationCriteria isValid( Patient patient )
     {
         try

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/reporttable/ReportTable.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/reporttable/ReportTable.java	2011-01-13 18:38:38 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/reporttable/ReportTable.java	2011-01-14 16:14:22 +0000
@@ -28,7 +28,6 @@
  */
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
@@ -92,16 +91,22 @@
     
     public static final String REGRESSION_COLUMN_PREFIX = "regression_";
     
-    public static final List<String> DB_COLUMNS = Arrays.asList( DATAELEMENT_ID, CATEGORYCOMBO_ID, INDICATOR_ID, DATASET_ID, 
-        PERIOD_ID, ORGANISATIONUNIT_ID, REPORTING_MONTH_COLUMN_NAME, PARAM_ORGANISATIONUNIT_COLUMN_NAME, ORGANISATION_UNIT_IS_PARENT_COLUMN_NAME );
-    
     public static final Map<String, String> PRETTY_COLUMNS = new HashMap<String, String>() { {
+        put( DATAELEMENT_ID, "Data element ID" );
         put( DATAELEMENT_NAME, "Data element" );
+        put( CATEGORYCOMBO_ID, "Category combination ID" );
         put( CATEGORYCOMBO_NAME, "Category combination" );
+        put( INDICATOR_ID, "Indicator ID" );
         put( INDICATOR_NAME, "Indicator" );
+        put( DATASET_ID, "Data set ID" );
         put( DATASET_NAME, "Data set" );
-        put( PERIOD_NAME, "Period" );
-        put( ORGANISATIONUNIT_NAME, "Organisation unit" );
+        put( PERIOD_ID, "Period ID" );
+        put( PERIOD_NAME, "Period" );        
+        put( ORGANISATIONUNIT_ID, "Organisation unit ID" );
+        put( ORGANISATIONUNIT_NAME, "Organisation unit" );        
+        put( REPORTING_MONTH_COLUMN_NAME, "Reporting month" );
+        put( PARAM_ORGANISATIONUNIT_COLUMN_NAME, "Organisation unit parameter" );        
+        put( ORGANISATION_UNIT_IS_PARENT_COLUMN_NAME, "Organisation unit is parent" );
     } };
     
     private static final String EMPTY_REPLACEMENT = "_";

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/reporttable/ReportTableService.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/reporttable/ReportTableService.java	2010-12-26 15:38:45 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/reporttable/ReportTableService.java	2011-01-14 16:14:22 +0000
@@ -134,7 +134,7 @@
      * @param format the I18nFormat.
      * @return a Grid.
      */
-    Grid getPrettyReportTableGrid( int id, I18nFormat format );
+    Grid getReportTableGrid( int id, I18nFormat format );
     
     /**
      * Tests whether the report table has been generated in the database.

=== modified file 'dhis-2/dhis-services/dhis-service-reporting/src/main/java/org/hisp/dhis/orgunitdistribution/impl/DefaultOrgUnitDistributionService.java'
--- dhis-2/dhis-services/dhis-service-reporting/src/main/java/org/hisp/dhis/orgunitdistribution/impl/DefaultOrgUnitDistributionService.java	2010-12-26 18:47:16 +0000
+++ dhis-2/dhis-services/dhis-service-reporting/src/main/java/org/hisp/dhis/orgunitdistribution/impl/DefaultOrgUnitDistributionService.java	2011-01-14 16:14:22 +0000
@@ -39,6 +39,7 @@
 import org.apache.commons.collections.CollectionUtils;
 import org.hisp.dhis.chart.ChartService;
 import org.hisp.dhis.common.Grid;
+import org.hisp.dhis.common.GridHeader;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
 import org.hisp.dhis.organisationunit.OrganisationUnitGroup;
 import org.hisp.dhis.organisationunit.OrganisationUnitGroupSet;
@@ -63,6 +64,7 @@
     private static final Comparator<OrganisationUnitGroup> ORGUNIT_GROUP_COMPARATOR = new OrganisationUnitGroupNameComparator();
 
     private static final String TITLE_SEP = " - ";
+    private static final String FIRST_COLUMN_TEXT = "Organisation unit";
     
     // -------------------------------------------------------------------------
     // Dependencies
@@ -96,7 +98,7 @@
         
         for ( int i = 1; i < grid.getWidth(); i++ ) // Skip name column
         {
-            categoryValues.put( grid.getHeaders().get( i ), Double.valueOf( grid.getRow( 0 ).get( i ) ) );
+            categoryValues.put( grid.getHeaders().get( i ).getName(), Double.valueOf( grid.getRow( 0 ).get( i ) ) );
         }
         
         String title = groupSet.getName() + TITLE_SEP + organisationUnit.getName();
@@ -120,11 +122,11 @@
         Collections.sort( units, ORGUNIT_COMPARATOR );
         Collections.sort( groups, ORGUNIT_GROUP_COMPARATOR );
         
-        grid.addHeader( null ); // First header row column is empty
+        grid.addHeader( new GridHeader( FIRST_COLUMN_TEXT, FIRST_COLUMN_TEXT, null, false, true ) );
         
         for ( OrganisationUnitGroup group : groups )
         {
-            grid.addHeader( group.getName() );
+            grid.addHeader( new GridHeader( group.getName(), false, false )  );
         }
         
         for ( OrganisationUnit unit : units )

=== modified file 'dhis-2/dhis-services/dhis-service-reporting/src/main/java/org/hisp/dhis/reporttable/impl/DefaultReportTableService.java'
--- dhis-2/dhis-services/dhis-service-reporting/src/main/java/org/hisp/dhis/reporttable/impl/DefaultReportTableService.java	2011-01-13 18:38:38 +0000
+++ dhis-2/dhis-services/dhis-service-reporting/src/main/java/org/hisp/dhis/reporttable/impl/DefaultReportTableService.java	2011-01-14 16:14:22 +0000
@@ -366,33 +366,14 @@
     }
 
     @Transactional
-    public Grid getPrettyReportTableGrid( int id, I18nFormat format )
+    public Grid getReportTableGrid( int id, I18nFormat format )
     {
         ReportTable reportTable = getReportTable( id );
         
         reportTable.setI18nFormat( format );
         reportTable.init();
         
-        Grid grid = reportTableManager.getReportTableGrid( reportTable );
-        
-        grid.setTitle( reportTable.getName() );        
-                
-        for ( String col : ReportTable.DB_COLUMNS )
-        {
-            grid.removeColumn( col );
-        }
-        
-        for ( String col : ReportTable.PRETTY_COLUMNS.keySet() )
-        {
-            grid.replaceHeader( col, ReportTable.PRETTY_COLUMNS.get( col ) );
-        }
-        
-        for ( String col : reportTable.getPrettyCrossTabColumns().keySet() )
-        {
-            grid.replaceHeader( col, reportTable.getPrettyCrossTabColumns().get( col ) );
-        }
-        
-        return grid;
+        return reportTableManager.getReportTableGrid( reportTable );
     }
     
     public boolean reportTableIsGenerated( int id )

=== modified file 'dhis-2/dhis-services/dhis-service-reporting/src/main/java/org/hisp/dhis/reporttable/jdbc/JDBCReportTableManager.java'
--- dhis-2/dhis-services/dhis-service-reporting/src/main/java/org/hisp/dhis/reporttable/jdbc/JDBCReportTableManager.java	2010-12-26 15:38:45 +0000
+++ dhis-2/dhis-services/dhis-service-reporting/src/main/java/org/hisp/dhis/reporttable/jdbc/JDBCReportTableManager.java	2011-01-14 16:14:22 +0000
@@ -27,7 +27,7 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import static org.hisp.dhis.reporttable.ReportTable.SEPARATOR;
+import static org.hisp.dhis.reporttable.ReportTable.*;
 
 import java.sql.ResultSet;
 import java.util.HashMap;
@@ -38,6 +38,7 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.hisp.dhis.common.Grid;
+import org.hisp.dhis.common.GridHeader;
 import org.hisp.dhis.common.IdentifiableObject;
 import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo;
 import org.hisp.dhis.jdbc.StatementBuilder;
@@ -209,7 +210,60 @@
         {
             ResultSet resultSet = holder.getStatement().executeQuery( "SELECT * FROM " + reportTable.getExistingTableName() );
             
-            return new ListGrid().fromResultSet( resultSet );
+            Grid grid = new ListGrid().setTitle( reportTable.getName() );
+
+            // -----------------------------------------------------------------
+            // Columns
+            // -----------------------------------------------------------------
+
+            for ( String column : reportTable.getIndexColumns() )
+            {
+                grid.addHeader( new GridHeader( PRETTY_COLUMNS.get( column ), column, Integer.class.getName(), true, true ) );
+            }
+            
+            for ( String column : reportTable.getIndexNameColumns() )
+            {
+                grid.addHeader( new GridHeader( PRETTY_COLUMNS.get( column ), column, String.class.getName(), false, true ) );
+            }
+            
+            grid.addHeader( new GridHeader( PRETTY_COLUMNS.get( REPORTING_MONTH_COLUMN_NAME ), REPORTING_MONTH_COLUMN_NAME, String.class.getName(), true, true ) );
+            grid.addHeader( new GridHeader( PRETTY_COLUMNS.get( PARAM_ORGANISATIONUNIT_COLUMN_NAME ), PARAM_ORGANISATIONUNIT_COLUMN_NAME, String.class.getName(), true, true ) );
+            grid.addHeader( new GridHeader( PRETTY_COLUMNS.get( ORGANISATION_UNIT_IS_PARENT_COLUMN_NAME ), ORGANISATION_UNIT_IS_PARENT_COLUMN_NAME, String.class.getName(), true, true ) );
+            
+            for ( String column : reportTable.getPrettyCrossTabColumns().keySet() )
+            {
+                grid.addHeader( new GridHeader( reportTable.getPrettyCrossTabColumns().get( column ), column, Double.class.getName(), false, false ) );
+            }
+
+            // -----------------------------------------------------------------
+            // Values
+            // -----------------------------------------------------------------
+
+            while ( resultSet.next() )
+            {
+                grid.nextRow();
+                
+                for ( String column : reportTable.getIndexColumns() )
+                {
+                    grid.addValue( String.valueOf( resultSet.getInt( column ) ) );
+                }
+                
+                for ( String column : reportTable.getIndexNameColumns() )
+                {
+                    grid.addValue( resultSet.getString( column ) );
+                }
+                
+                grid.addValue( resultSet.getString( REPORTING_MONTH_COLUMN_NAME ) );
+                grid.addValue( resultSet.getString( PARAM_ORGANISATIONUNIT_COLUMN_NAME ) );
+                grid.addValue( resultSet.getString( ORGANISATION_UNIT_IS_PARENT_COLUMN_NAME ) );
+                
+                for ( String column : reportTable.getPrettyCrossTabColumns().keySet() )
+                {
+                    grid.addValue( String.valueOf( resultSet.getDouble( column ) ) );
+                }
+            }
+            
+            return grid;
         }
         catch ( Exception ex )
         {

=== modified file 'dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/grid/ListGrid.java'
--- dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/grid/ListGrid.java	2010-12-26 15:38:45 +0000
+++ dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/grid/ListGrid.java	2011-01-14 16:14:22 +0000
@@ -29,14 +29,12 @@
 
 import static org.hisp.dhis.system.util.MathUtils.getRounded;
 
-import java.sql.ResultSet;
-import java.sql.ResultSetMetaData;
-import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.commons.math.stat.regression.SimpleRegression;
 import org.hisp.dhis.common.Grid;
+import org.hisp.dhis.common.GridHeader;
 
 /**
  * @author Lars Helge Overland
@@ -58,7 +56,7 @@
     /**
      * A List which represents the column headers of the grid.
      */
-    private List<String> headers;
+    private List<GridHeader> headers;
     
     /**
      * A two dimensional List which simulates a grid where the first list
@@ -76,10 +74,10 @@
      */
     public ListGrid()
     {
-        headers = new ArrayList<String>();
+        headers = new ArrayList<GridHeader>();
         grid = new ArrayList<List<String>>();
     }
-
+    
     // ---------------------------------------------------------------------
     // Public methods
     // ---------------------------------------------------------------------
@@ -107,29 +105,34 @@
         
         return this;
     }
-
-    public List<String> getHeaders()
+    
+    public List<GridHeader> getHeaders()
     {
         return headers;
     }
-    
-    public Grid addHeader( String value )
+
+    public List<GridHeader> getVisibleHeaders()
     {
-        headers.add( value );
+        List<GridHeader> tempHeaders = new ArrayList<GridHeader>();
         
-        return this;
-    }
-    
-    public Grid replaceHeader( String currentHeader, String newHeader )
-    {
-        if ( headers.contains( currentHeader ) )
+        for ( GridHeader header : headers )
         {
-            headers.set( headers.indexOf( currentHeader ), newHeader );
+            if ( !header.isHidden() )
+            {
+                tempHeaders.add( header );
+            }
         }
         
+        return tempHeaders;
+    }
+    
+    public Grid addHeader( GridHeader header )
+    {
+        headers.add( header );
+        
         return this;
     }
-    
+        
     public int getHeight()
     {        
         return ( grid != null && grid.size() > 0 ) ? grid.size() : 0;
@@ -142,6 +145,13 @@
         return ( grid != null && grid.size() > 0 ) ? grid.get( 0 ).size() : 0;
     }
     
+    public int getVisibleWidth()
+    {
+        verifyGridState();
+        
+        return ( grid != null && grid.size() > 0 )  ? getVisibleRows().get( 0 ).size() : 0;
+    }
+    
     public Grid nextRow()
     {
         grid.add( new ArrayList<String>() );
@@ -168,6 +178,33 @@
         return grid;
     }
     
+    public List<List<String>> getVisibleRows()
+    {
+        verifyGridState();
+        
+        List<List<String>> tempGrid = new ArrayList<List<String>>();
+        
+        if ( headers != null && headers.size() > 0 )
+        {
+            for ( List<String> row : grid )
+            {
+                List<String> tempRow = new ArrayList<String>();
+                
+                for ( int i = 0; i < row.size(); i++ )
+                {
+                    if ( !headers.get( i ).isHidden() )
+                    {
+                        tempRow.add( row.get( i ) );
+                    }
+                }
+                
+                tempGrid.add( tempRow );
+            }
+        }
+        
+        return tempGrid;
+    }
+        
     public List<String> getColumn( int columnIndex )
     {
         List<String> column = new ArrayList<String>();
@@ -227,7 +264,7 @@
         return this;
     }
     
-    public Grid removeColumn( String header )
+    public Grid removeColumn( GridHeader header )
     {
         int index = headers.indexOf( header );
         
@@ -282,34 +319,6 @@
         return this;
     }
     
-    public Grid fromResultSet( ResultSet resultSet )
-        throws SQLException
-    {
-        headers = new ArrayList<String>();
-        grid = new ArrayList<List<String>>();
-                
-        ResultSetMetaData metaData = resultSet.getMetaData();
-        
-        int cols = metaData.getColumnCount();
-        
-        for ( int i = 0; i < cols; i++ )
-        {
-            this.addHeader( String.valueOf( metaData.getColumnName( i + 1 ) ) );
-        }
-        
-        while ( resultSet.next() )
-        {
-            this.nextRow();
-            
-            for ( int i = 0; i < cols; i++ )
-            {
-                this.addValue( String.valueOf( resultSet.getObject( i + 1 ) ) );
-            }
-        }
-        
-        return this;
-    }
-
     // ---------------------------------------------------------------------
     // Supportive methods
     // ---------------------------------------------------------------------
@@ -334,10 +343,11 @@
         
         if ( rowLength != null && headers.size() != 0 && headers.size() != rowLength )
         {
-            throw new IllegalStateException( "Number of headers is not 0 and not equal to the number of columns" );
+            throw new IllegalStateException( 
+                "Number of headers is not 0 and not equal to the number of columns (headers: " + headers.size() + ", cols: " + rowLength + ")" );
         }
     }
-
+    
     // ---------------------------------------------------------------------
     // toString
     // ---------------------------------------------------------------------
@@ -347,6 +357,18 @@
     {
         StringBuffer buffer = new StringBuffer( "[" );
         
+        if ( headers != null && headers.size() > 0 )
+        {
+            List<String> headerNames = new ArrayList<String>();
+            
+            for ( GridHeader header : headers )
+            {
+                headerNames.add( header.getName() );
+            }
+            
+            buffer.append( headerNames );
+        }
+        
         for ( List<String> row : grid )
         {
             buffer.append( row );

=== modified file 'dhis-2/dhis-support/dhis-support-system/src/test/java/org/hisp/dhis/system/grid/GridTest.java'
--- dhis-2/dhis-support/dhis-support-system/src/test/java/org/hisp/dhis/system/grid/GridTest.java	2010-12-26 15:38:45 +0000
+++ dhis-2/dhis-support/dhis-support-system/src/test/java/org/hisp/dhis/system/grid/GridTest.java	2011-01-14 16:14:22 +0000
@@ -27,30 +27,41 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+
 import java.util.ArrayList;
 import java.util.List;
 
+import org.hisp.dhis.common.Grid;
+import org.hisp.dhis.common.GridHeader;
 import org.junit.Before;
 import org.junit.Test;
 
-import static junit.framework.Assert.*;
-
 /**
  * @author Lars Helge Overland
  * @version $Id$
  */
 public class GridTest
 {
-    private ListGrid grid;
+    private Grid grid;
+    
+    private GridHeader headerA;
+    private GridHeader headerB;
+    private GridHeader headerC;
     
     @Before
     public void setUp()
     {
         grid = new ListGrid();
-
-        grid.addHeader( "col1" );
-        grid.addHeader( "col2" );
-        grid.addHeader( "col3" );
+        
+        headerA = new GridHeader( "ColA", "colA", String.class.getName(), false, false );
+        headerB = new GridHeader( "ColB", "colB", String.class.getName(), false, false );
+        headerC = new GridHeader( "ColC", "colC", String.class.getName(), true, false );
+        
+        grid.addHeader( headerA );
+        grid.addHeader( headerB );
+        grid.addHeader( headerC );
         
         grid.nextRow();        
         grid.addValue( "11" );
@@ -66,12 +77,17 @@
         grid.addValue( "31" );
         grid.addValue( "32" );
         grid.addValue( "33" );
+
+        grid.nextRow();        
+        grid.addValue( "41" );
+        grid.addValue( "42" );
+        grid.addValue( "43" );
     }
     
     @Test
     public void testGetHeight()
     {
-        assertEquals( 3, grid.getHeight() );
+        assertEquals( 4, grid.getHeight() );
     }
     
     @Test
@@ -79,18 +95,7 @@
     {
         assertEquals( 3, grid.getWidth() );
     }
-    
-    @Test
-    public void testReplaceHeader()
-    {
-        assertTrue( grid.getHeaders().contains( "col2" ) );
         
-        grid.replaceHeader( "col2", "Column2" );
-
-        assertFalse( grid.getHeaders().contains( "col2" ) );
-        assertTrue( grid.getHeaders().contains( "Column2" ) );
-    }
-    
     @Test
     public void testGetRow()
     {
@@ -108,55 +113,84 @@
         assertTrue( rowB.contains( "22" ) );
         assertTrue( rowB.contains( "23" ) );
     }
+
+    @Test
+    public void testGetHeaders()
+    {
+        assertEquals( 3, grid.getHeaders().size() );
+    }
     
     @Test
+    public void tetsGetVisibleHeaders()
+    {
+        assertEquals( 2, grid.getVisibleHeaders().size() );
+        assertTrue( grid.getVisibleHeaders().contains( headerA ) );
+        assertTrue( grid.getVisibleHeaders().contains( headerB ) );
+    }
+
+    @Test
     public void testGetRows()
     {
-        assertEquals( 3, grid.getRows().size() );
+        assertEquals( 4, grid.getRows().size() );
+        assertEquals( 3, grid.getWidth() );
+    }
+
+    @Test
+    public void testGetGetVisibleRows()
+    {
+        assertEquals( 4, grid.getVisibleRows().size() );
+        assertEquals( 2, grid.getVisibleRows().get( 0 ).size() );
+        assertEquals( 2, grid.getVisibleRows().get( 1 ).size() );
+        assertEquals( 2, grid.getVisibleRows().get( 2 ).size() );
+        assertEquals( 2, grid.getVisibleRows().get( 3 ).size() );
     }
     
     @Test
     public void testGetColumn()
     {        
-        List<String> columnB = grid.getColumn( 1 );
+        List<String> column1 = grid.getColumn( 1 );
         
-        assertTrue( columnB.size() == 3 );
-        assertTrue( columnB.contains( "12" ) );
-        assertTrue( columnB.contains( "22" ) );
-        assertTrue( columnB.contains( "32" ) );
+        assertEquals( 4, column1.size() );
+        assertTrue( column1.contains( "12" ) );
+        assertTrue( column1.contains( "22" ) );
+        assertTrue( column1.contains( "32" ) );
+        assertTrue( column1.contains( "42" ) );
 
-        List<String> columnC = grid.getColumn( 2 );
+        List<String> column2 = grid.getColumn( 2 );
         
-        assertTrue( columnC.size() == 3 );
-        assertTrue( columnC.contains( "13" ) );
-        assertTrue( columnC.contains( "23" ) );
-        assertTrue( columnC.contains( "33" ) ); 
+        assertEquals( 4, column2.size() );
+        assertTrue( column2.contains( "13" ) );
+        assertTrue( column2.contains( "23" ) );
+        assertTrue( column2.contains( "33" ) );
+        assertTrue( column2.contains( "43" ) );
     }
     
     @Test
     public void testAddColumn()
     {
-        List<String> columnValues = new ArrayList<String>( 3 );
+        List<String> columnValues = new ArrayList<String>();
         columnValues.add( "14" );
         columnValues.add( "24" );
-        columnValues.add( "34" );        
+        columnValues.add( "34" );
+        columnValues.add( "44" );
         
         grid.addColumn( columnValues );
         
-        List<String> columnD = grid.getColumn( 3 );
-        
-        assertTrue( columnD.size() == 3 );
-        assertTrue( columnD.contains( "14" ) );
-        assertTrue( columnD.contains( "24" ) );
-        assertTrue( columnD.contains( "34" ) );
-        
-        List<String> rowB = grid.getRow( 1 );
-        
-        assertTrue( rowB.size() == 4 );
-        assertTrue( rowB.contains( "21" ) );
-        assertTrue( rowB.contains( "22" ) );
-        assertTrue( rowB.contains( "23" ) );
-        assertTrue( rowB.contains( "24" ) );
+        List<String> column3 = grid.getColumn( 3 );
+        
+        assertEquals( 4, column3.size() );
+        assertTrue( column3.contains( "14" ) );
+        assertTrue( column3.contains( "24" ) );
+        assertTrue( column3.contains( "34" ) );
+        assertTrue( column3.contains( "44" ) );
+        
+        List<String> row2 = grid.getRow( 1 );
+        
+        assertEquals( 4, row2.size() );
+        assertTrue( row2.contains( "21" ) );
+        assertTrue( row2.contains( "22" ) );
+        assertTrue( row2.contains( "23" ) );
+        assertTrue( row2.contains( "24" ) );
     }
     
     @Test
@@ -174,7 +208,7 @@
     {
         assertEquals( 3, grid.getWidth() );
         
-        grid.removeColumn( "col2" );
+        grid.removeColumn( headerB );
         
         assertEquals( 2, grid.getWidth() );
     }

=== modified file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/ajax/htmlGrid.vm'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/ajax/htmlGrid.vm	2010-12-26 15:38:45 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/ajax/htmlGrid.vm	2011-01-14 16:14:22 +0000
@@ -19,17 +19,18 @@
 
 <thead>
 <tr>
-#foreach( $header in $grid.getHeaders() )
-<th>$!encoder.htmlEncode( $header )</th>
+#foreach( $header in $grid.getVisibleHeaders() )
+<th #if( $header.meta )style="text-align:left"#end>$!encoder.htmlEncode( $header.name )</th>
 #end
 </tr>
 </thead>
 
 <tbody>
-#foreach( $row in $grid.getRows() )
+#foreach( $row in $grid.getVisibleRows() )
 <tr>
 #foreach( $col in $row )
-<td #if( $velocityCount == 1 )style="text-align:left"#end>$!encoder.htmlEncode( $col )</td>
+#set( $index = ( $velocityCount - 1 ) )
+<td #if( $grid.getVisibleHeaders().get( $index ).meta )style="text-align:left"#end>$!encoder.htmlEncode( $col )</td>
 #end
 </tr>
 #end

=== modified file 'dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/result/GridCsvResult.java'
--- dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/result/GridCsvResult.java	2011-01-11 15:07:13 +0000
+++ dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/result/GridCsvResult.java	2011-01-14 16:14:22 +0000
@@ -36,6 +36,7 @@
 import org.apache.commons.lang.StringUtils;
 import org.apache.struts2.ServletActionContext;
 import org.hisp.dhis.common.Grid;
+import org.hisp.dhis.common.GridHeader;
 import org.hisp.dhis.system.util.CodecUtils;
 import org.hisp.dhis.util.ContextUtils;
 
@@ -95,11 +96,11 @@
         // Write CSV to output stream
         // ---------------------------------------------------------------------
 
-        Iterator<String> headers = grid.getHeaders().iterator();
+        Iterator<GridHeader> headers = grid.getHeaders().iterator();
         
         while ( headers.hasNext() )
         {
-            out.write( csvEncode( headers.next() ).getBytes() );
+            out.write( csvEncode( headers.next().getName() ).getBytes() );
             
             if ( headers.hasNext() )
             {

=== modified file 'dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/result/GridPdfResult.java'
--- dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/result/GridPdfResult.java	2011-01-11 15:07:13 +0000
+++ dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/result/GridPdfResult.java	2011-01-14 16:14:22 +0000
@@ -35,6 +35,7 @@
 import org.apache.commons.lang.StringUtils;
 import org.apache.struts2.ServletActionContext;
 import org.hisp.dhis.common.Grid;
+import org.hisp.dhis.common.GridHeader;
 import org.hisp.dhis.system.util.CodecUtils;
 import org.hisp.dhis.util.ContextUtils;
 
@@ -98,23 +99,23 @@
         
         Document document = openDocument( out );
         
-        PdfPTable table = new PdfPTable( grid.getWidth() );
+        PdfPTable table = new PdfPTable( grid.getVisibleWidth() );
         
         table.setHeaderRows( 1 );
 
-        table.addCell( getTitleCell( grid.getTitle(), grid.getWidth() ) );
-        table.addCell( getEmptyCell( grid.getWidth(), 30 ) );
-        table.addCell( getSubtitleCell( grid.getSubtitle(), grid.getWidth() ) );
-        table.addCell( getEmptyCell( grid.getWidth(), 30 ) );
+        table.addCell( getTitleCell( grid.getTitle(), grid.getVisibleWidth() ) );
+        table.addCell( getEmptyCell( grid.getVisibleWidth(), 30 ) );
+        table.addCell( getSubtitleCell( grid.getSubtitle(), grid.getVisibleWidth() ) );
+        table.addCell( getEmptyCell( grid.getVisibleWidth(), 30 ) );
         
-        for ( String header : grid.getHeaders() )
+        for ( GridHeader header : grid.getVisibleHeaders() )
         {
-            table.addCell( getItalicCell( header ) );
+            table.addCell( getItalicCell( header.getName() ) );
         }
 
-        table.addCell( getEmptyCell( grid.getWidth(), 10 ) );
+        table.addCell( getEmptyCell( grid.getVisibleWidth(), 10 ) );
         
-        for ( List<String> row : grid.getRows() )
+        for ( List<String> row : grid.getVisibleRows() )
         {
             for ( String col : row )
             {

=== modified file 'dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/result/GridXlsResult.java'
--- dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/result/GridXlsResult.java	2011-01-11 15:07:13 +0000
+++ dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/result/GridXlsResult.java	2011-01-14 16:14:22 +0000
@@ -45,6 +45,7 @@
 import org.apache.commons.lang.StringUtils;
 import org.apache.struts2.ServletActionContext;
 import org.hisp.dhis.common.Grid;
+import org.hisp.dhis.common.GridHeader;
 import org.hisp.dhis.system.util.CodecUtils;
 import org.hisp.dhis.util.ContextUtils;
 
@@ -126,14 +127,14 @@
 
         rowNumber++;
 
-        for ( String header : grid.getHeaders() )
+        for ( GridHeader header : grid.getVisibleHeaders() )
         {
-            sheet.addCell( new Label( columnIndex++, rowNumber, header, FORMAT_LABEL ) );
+            sheet.addCell( new Label( columnIndex++, rowNumber, header.getName(), FORMAT_LABEL ) );
         }
 
         rowNumber++;
 
-        for ( List<String> row : grid.getRows() )
+        for ( List<String> row : grid.getVisibleRows() )
         {
             columnIndex = 0;
 

=== modified file 'dhis-2/dhis-web/dhis-web-reporting/src/main/java/org/hisp/dhis/reporting/completeness/action/GetDataCompletenessAction.java'
--- dhis-2/dhis-web/dhis-web-reporting/src/main/java/org/hisp/dhis/reporting/completeness/action/GetDataCompletenessAction.java	2010-12-26 23:25:10 +0000
+++ dhis-2/dhis-web/dhis-web-reporting/src/main/java/org/hisp/dhis/reporting/completeness/action/GetDataCompletenessAction.java	2011-01-14 16:14:22 +0000
@@ -32,6 +32,7 @@
 import java.util.List;
 
 import org.hisp.dhis.common.Grid;
+import org.hisp.dhis.common.GridHeader;
 import org.hisp.dhis.common.ServiceProvider;
 import org.hisp.dhis.completeness.DataSetCompletenessResult;
 import org.hisp.dhis.completeness.DataSetCompletenessService;
@@ -199,12 +200,12 @@
         
         Grid grid = new ListGrid().setTitle( title ).setSubtitle( subtitle );
         
-        grid.addHeader( i18n.getString( "name" ) );
-        grid.addHeader( i18n.getString( "actual" ) );
-        grid.addHeader( i18n.getString( "target" ) );
-        grid.addHeader( i18n.getString( "percent" ) );
-        grid.addHeader( i18n.getString( "on_time" ) );
-        grid.addHeader( i18n.getString( "percent" ) );
+        grid.addHeader( new GridHeader( i18n.getString( "name" ), false, true ) );
+        grid.addHeader( new GridHeader( i18n.getString( "actual" ), false, false ) );
+        grid.addHeader( new GridHeader( i18n.getString( "target" ), false, false ) );
+        grid.addHeader( new GridHeader( i18n.getString( "percent" ), false, false ) );
+        grid.addHeader( new GridHeader( i18n.getString( "on_time" ), false, false ) );
+        grid.addHeader( new GridHeader( i18n.getString( "percent" ), false, false ) );
         
         for ( DataSetCompletenessResult result : results )
         {

=== modified file 'dhis-2/dhis-web/dhis-web-reporting/src/main/java/org/hisp/dhis/reporting/tablecreator/action/ExportTableAction.java'
--- dhis-2/dhis-web/dhis-web-reporting/src/main/java/org/hisp/dhis/reporting/tablecreator/action/ExportTableAction.java	2011-01-06 12:40:57 +0000
+++ dhis-2/dhis-web/dhis-web-reporting/src/main/java/org/hisp/dhis/reporting/tablecreator/action/ExportTableAction.java	2011-01-14 16:14:22 +0000
@@ -110,7 +110,7 @@
         }
         else
         {
-            grid = reportTableService.getPrettyReportTableGrid( id, format );            
+            grid = reportTableService.getReportTableGrid( id, format );            
         }
         
         SessionUtils.setSessionVar( SessionUtils.KEY_REPORT_TABLE_GRID, grid );

=== modified file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/ExportValidationResultAction.java'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/ExportValidationResultAction.java	2010-12-29 10:06:33 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/ExportValidationResultAction.java	2011-01-14 16:14:22 +0000
@@ -31,6 +31,7 @@
 
 import org.apache.commons.lang.xwork.StringUtils;
 import org.hisp.dhis.common.Grid;
+import org.hisp.dhis.common.GridHeader;
 import org.hisp.dhis.i18n.I18n;
 import org.hisp.dhis.i18n.I18nFormat;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
@@ -114,15 +115,14 @@
         Grid grid = new ListGrid();
         
         grid.setTitle( i18n.getString( "data_quality_report" ) );
-        //TODO subtitle
         
-        grid.addHeader( i18n.getString( "source" ) );
-        grid.addHeader( i18n.getString( "period" ) );
-        grid.addHeader( i18n.getString( "left_side_description" ) );
-        grid.addHeader( i18n.getString( "value" ) );
-        grid.addHeader( i18n.getString( "operator" ) );
-        grid.addHeader( i18n.getString( "value" ) );
-        grid.addHeader( i18n.getString( "right_side_description" ) );
+        grid.addHeader( new GridHeader( i18n.getString( "source" ), false, true ) );
+        grid.addHeader( new GridHeader( i18n.getString( "period" ), false, true ) );
+        grid.addHeader( new GridHeader( i18n.getString( "left_side_description" ), false, true ) );
+        grid.addHeader( new GridHeader( i18n.getString( "value" ), false, false ) );
+        grid.addHeader( new GridHeader( i18n.getString( "operator" ), false, false ) );
+        grid.addHeader( new GridHeader( i18n.getString( "value" ), false, false ) );
+        grid.addHeader( new GridHeader( i18n.getString( "right_side_description" ), false, true ) );
     
         for ( ValidationResult validationResult : results )
         {