=== 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 2011-02-23 14:27:49 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/Grid.java 2011-02-23 23:26:47 +0000 @@ -184,6 +184,7 @@ * Adds a regression column to the grid. Column must hold numeric data. * * @param columnIndex the index of the base column. + * @oaram addHeader indicates whether to add a grid header for the regression column. */ - Grid addRegressionColumn( int columnIndex ); + Grid addRegressionColumn( int columnIndex, boolean addHeader ); } === 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-02-18 19:27:56 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/reporttable/ReportTable.java 2011-02-23 23:26:47 +0000 @@ -33,8 +33,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import org.apache.commons.lang.StringUtils; import org.hisp.dhis.common.CombinationGenerator; @@ -81,13 +79,10 @@ public static final String ORGANISATION_UNIT_IS_PARENT_COLUMN_NAME = "organisation_unit_is_parent"; public static final String SEPARATOR = "_"; - public static final String SPACE = " "; - + public static final String SPACE = " "; public static final String TOTAL_COLUMN_NAME = "total"; public static final String TOTAL_COLUMN_PRETTY_NAME = "Total"; - public static final String REGRESSION_COLUMN_PREFIX = "regression_"; - public static final int ASC = -1; public static final int DESC = 1; public static final int NONE = 0; @@ -110,11 +105,6 @@ put( ORGANISATION_UNIT_IS_PARENT_COLUMN_NAME, "Organisation unit is parent" ); } }; - private static final String EMPTY_REPLACEMENT = "_"; - private static final String EMPTY = ""; - private static final String TABLE_PREFIX = "_report_"; - private static final String REGEX_NUMERIC = "([0-9]*)"; - public static final Map, String> CLASS_ID_MAP = new HashMap, String>() { { put( Indicator.class, INDICATOR_ID ); put( DataElement.class, DATAELEMENT_ID ); @@ -124,9 +114,12 @@ put( Period.class, PERIOD_ID ); put( OrganisationUnit.class, ORGANISATIONUNIT_ID ); } }; - + + private static final String EMPTY = ""; + private static final String TABLE_PREFIX = "_report_"; private static final IdentifiableObject[] IRT = new IdentifiableObject[0]; - private static final String[] SRT = new String[0]; + private static final String[] SRT = new String[0]; + private static final String ILLEGAL_FILENAME_CHARS_REGEX = "[/\\?%*:|\"<>.]"; // ------------------------------------------------------------------------- // Persisted properties @@ -363,6 +356,7 @@ verify( nonEmptyLists( dataElements, indicators, dataSets ) > 0, "Must contain dataelements, indicators or datasets" ); verify( nonEmptyLists( periods, relativePeriods ) > 0, "Must contain periods or relative periods" ); verify( nonEmptyLists( units, relativeUnits ) > 0, "Must contain organisation units or relative organisation units" ); + verify( !( doTotal() && regression ), "Cannot have regression columns with total columns" ); verify( i18nFormat != null, "I18n format must be set" ); // --------------------------------------------------------------------- @@ -466,7 +460,7 @@ { if ( object != null && object instanceof Period ) { - buffer.append( object.getName() + SEPARATOR ); // Relative periods must have static names when crosstabbed which are set on name property + buffer.append( object.getName() + SEPARATOR ); // Relative periods must have static names when crosstabbed - which are set on name property } else { @@ -474,7 +468,7 @@ } } - String column = databaseEncode( buffer.toString() ); + String column = columnEncode( buffer.toString() ); return column.length() > 0 ? column.substring( 0, column.lastIndexOf( SEPARATOR ) ) : TOTAL_COLUMN_NAME; } @@ -571,51 +565,15 @@ } /** - * Database encodes the argument string. Remove non-character data from the - * string, prefixes the string if it starts with a numeric character and - * truncates the string if it is longer than 255 characters. + * Generates a string which is acceptable as a filename. */ - public static String databaseEncode( String string ) + public static String columnEncode( String string ) { if ( string != null ) { + string = string.replaceAll( ILLEGAL_FILENAME_CHARS_REGEX, EMPTY ); + string = string.length() > 255 ? string.substring( 0, 255 ) : string; string = string.toLowerCase(); - - string = string.replaceAll( " ", EMPTY_REPLACEMENT ); - string = string.replaceAll( "-", EMPTY ); - string = string.replaceAll( "<", EMPTY_REPLACEMENT + "lt" + EMPTY_REPLACEMENT ); - string = string.replaceAll( ">", EMPTY_REPLACEMENT + "gt" + EMPTY_REPLACEMENT ); - - StringBuffer buffer = new StringBuffer(); - - Pattern pattern = Pattern.compile( "[a-zA-Z0-9_]" ); - Matcher matcher = pattern.matcher( string ); - - while ( matcher.find() ) - { - buffer.append( matcher.group() ); - } - - string = buffer.toString(); - string = string.replaceAll( EMPTY_REPLACEMENT + "+", EMPTY_REPLACEMENT ); - - // ----------------------------------------------------------------- - // Cannot start with numeric character - // ----------------------------------------------------------------- - - if ( string.length() > 0 && string.substring( 0, 1 ).matches( REGEX_NUMERIC ) ) - { - string = SEPARATOR + string; - } - - // ----------------------------------------------------------------- - // Cannot be longer than 255 characters - // ----------------------------------------------------------------- - - if ( string.length() > 255 ) - { - string = string.substring( 0, 255 ); - } } return string; @@ -673,7 +631,7 @@ */ private static String generateTableName( String name ) { - return TABLE_PREFIX + databaseEncode( name ); + return TABLE_PREFIX + columnEncode( name ); } /** === 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-02-23 21:08:31 +0000 +++ dhis-2/dhis-services/dhis-service-reporting/src/main/java/org/hisp/dhis/reporttable/impl/DefaultReportTableService.java 2011-02-23 23:26:47 +0000 @@ -34,7 +34,7 @@ import static org.hisp.dhis.reporttable.ReportTable.SPACE; import static org.hisp.dhis.reporttable.ReportTable.TOTAL_COLUMN_NAME; import static org.hisp.dhis.reporttable.ReportTable.TOTAL_COLUMN_PRETTY_NAME; -import static org.hisp.dhis.reporttable.ReportTable.databaseEncode; +import static org.hisp.dhis.reporttable.ReportTable.columnEncode; import static org.hisp.dhis.reporttable.ReportTable.getColumnName; import static org.hisp.dhis.reporttable.ReportTable.getIdentifier; import static org.hisp.dhis.reporttable.ReportTable.getPrettyColumnName; @@ -343,28 +343,6 @@ } /** - * Adds columns with regression values to the given grid. - * - * @param grid the grid. - * @param startColumnIndex the start column index. - * @param numberOfColumns the number of columns. - * @return a grid. - */ - private Grid addRegressionToGrid( Grid grid, int numberOfColumns ) - { - int startColumnIndex = grid.getWidth() - numberOfColumns; - - for ( int i = 0; i < numberOfColumns; i++ ) - { - int columnIndex = i + startColumnIndex; - - grid.addRegressionColumn( columnIndex ); - } - - return grid; - } - - /** * Generates a grid based on the given report table. * * @param reportTable the report table. @@ -405,7 +383,7 @@ { for ( DataElementCategoryOption categoryOption : reportTable.getCategoryCombo().getCategoryOptions() ) // TOTO skip if only one category? { - grid.addHeader( new GridHeader( categoryOption.getShortName(), databaseEncode( categoryOption.getShortName() ), String.class.getName(), false, false ) ); + grid.addHeader( new GridHeader( categoryOption.getShortName(), columnEncode( categoryOption.getShortName() ), String.class.getName(), false, false ) ); } grid.addHeader( new GridHeader( TOTAL_COLUMN_PRETTY_NAME, TOTAL_COLUMN_NAME, String.class.getName(), false, false ) ); @@ -419,7 +397,7 @@ { grid.addRow(); - for ( IdentifiableObject object : row ) // TODO change order and get one loop? + for ( IdentifiableObject object : row ) { grid.addValue( object.getId() ); // Index columns } @@ -449,6 +427,11 @@ } } + if ( reportTable.isRegression() && !reportTable.doTotal() ) + { + addRegressionToGrid( grid, reportTable.getColumns().size() ); + } + // --------------------------------------------------------------------- // Sort first and then limit // --------------------------------------------------------------------- @@ -465,6 +448,26 @@ return grid; } + + /** + * Adds columns with regression values to the given grid. + * + * @param grid the grid. + * @param numberOfColumns the number of columns. + */ + private Grid addRegressionToGrid( Grid grid, int numberOfColumns ) + { + int startColumnIndex = grid.getWidth() - numberOfColumns; + + for ( int i = 0; i < numberOfColumns; i++ ) + { + int columnIndex = i + startColumnIndex; + + grid.addRegressionColumn( columnIndex, true ); + } + + return grid; + } /** * Checks whether the given List of IdentifiableObjects contains an object === modified file 'dhis-2/dhis-services/dhis-service-reporting/src/test/java/org/hisp/dhis/reporttable/ReportTableGridTest.java' --- dhis-2/dhis-services/dhis-service-reporting/src/test/java/org/hisp/dhis/reporttable/ReportTableGridTest.java 2011-02-23 14:27:49 +0000 +++ dhis-2/dhis-services/dhis-service-reporting/src/test/java/org/hisp/dhis/reporttable/ReportTableGridTest.java 2011-02-23 23:26:47 +0000 @@ -948,4 +948,36 @@ assertEquals( 11.0, grid.getRow( 3 ).get( 7 ) ); assertEquals( 12.0, grid.getRow( 3 ).get( 8 ) ); } + + @Test + public void testGetDataElementReportTableRegression() + { + ReportTable reportTable = new ReportTable( "Embezzlement", true, + dataElements, new ArrayList(), new ArrayList(), periods, relativePeriods, units, new ArrayList(), + null, true, false, true, new RelativePeriods(), null, i18nFormat, "january_2000" ); + + int id = reportTableService.saveReportTable( reportTable ); + + Grid grid = reportTableService.getReportTableGrid( id, i18nFormat, 0, 0 ); + + assertEquals( 11.0, grid.getRow( 0 ).get( 5 ) ); + assertEquals( 12.0, grid.getRow( 0 ).get( 6 ) ); + assertEquals( 15.0, grid.getRow( 0 ).get( 7 ) ); + assertEquals( 16.0, grid.getRow( 0 ).get( 8 ) ); + + assertEquals( 11.0, grid.getRow( 0 ).get( 9 ) ); + assertEquals( 12.0, grid.getRow( 0 ).get( 10 ) ); + assertEquals( 15.0, grid.getRow( 0 ).get( 11 ) ); + assertEquals( 16.0, grid.getRow( 0 ).get( 12 ) ); + + assertEquals( 13.0, grid.getRow( 1 ).get( 5 ) ); + assertEquals( 14.0, grid.getRow( 1 ).get( 6 ) ); + assertEquals( 17.0, grid.getRow( 1 ).get( 7 ) ); + assertEquals( 18.0, grid.getRow( 1 ).get( 8 ) ); + + assertEquals( 13.0, grid.getRow( 1 ).get( 9 ) ); + assertEquals( 14.0, grid.getRow( 1 ).get( 10 ) ); + assertEquals( 17.0, grid.getRow( 1 ).get( 11 ) ); + assertEquals( 18.0, grid.getRow( 1 ).get( 12 ) ); + } } === 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 2011-02-23 21:26:24 +0000 +++ dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/grid/ListGrid.java 2011-02-23 23:26:47 +0000 @@ -50,6 +50,8 @@ public class ListGrid implements Grid { + private static final String REGRESSION_SUFFIX = "_regression"; + /** * The title of the grid. */ @@ -148,7 +150,7 @@ return this; } - + public List getHeaders() { return headers; @@ -338,7 +340,7 @@ return this; } - public Grid addRegressionColumn( int columnIndex ) + public Grid addRegressionColumn( int columnIndex, boolean addHeader ) { verifyGridState(); @@ -350,21 +352,17 @@ for ( Object value : column ) { - index++; - if ( Double.parseDouble( String.valueOf( value ) ) != 0.0 ) // 0 omitted from regression { - regression.addData( index, Double.parseDouble( String.valueOf( value ) ) ); + regression.addData( index++, Double.parseDouble( String.valueOf( value ) ) ); } } List regressionColumn = new ArrayList(); - index = 0; - for ( int i = 0; i < column.size(); i++ ) { - final double predicted = regression.predict( index++ ); + final double predicted = regression.predict( i ); if ( !Double.isNaN( predicted ) ) // Enough values must exist for regression { @@ -378,6 +376,19 @@ addColumn( regressionColumn ); + if ( addHeader && columnIndex < headers.size() ) + { + GridHeader header = headers.get( columnIndex ); + + if ( header != null ) + { + GridHeader regressionHeader = new GridHeader( header.getName() + REGRESSION_SUFFIX, + header.getColumn() + REGRESSION_SUFFIX, header.getType(), header.isHidden(), header.isMeta() ); + + addHeader( regressionHeader ); + } + } + return this; } @@ -417,17 +428,11 @@ { if ( rowLength != null && rowLength != row.size() ) { - throw new IllegalStateException( "Grid rows do not have the same number of cells" ); + throw new IllegalStateException( "Grid rows do not have the same number of cells, previous: " + rowLength + ", this: " + row.size() ); } rowLength = row.size(); } - - 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 (headers: " + headers.size() + ", cols: " + rowLength + ")" ); - } } /** === 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 2011-02-23 14:27:49 +0000 +++ dhis-2/dhis-support/dhis-support-system/src/test/java/org/hisp/dhis/system/grid/GridTest.java 2011-02-23 23:26:47 +0000 @@ -365,15 +365,15 @@ grid.addRow(); grid.addValue( 60.0 ); - grid.addRegressionColumn( 0 ); + grid.addRegressionColumn( 0, true ); List column = grid.getColumn( 1 ); assertTrue( column.size() == 4 ); - assertTrue( column.contains( 5.0 ) ); assertTrue( column.contains( 17.0 ) ); assertTrue( column.contains( 29.0 ) ); assertTrue( column.contains( 41.0 ) ); + assertTrue( column.contains( 53.0 ) ); } @Test