=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/AbstractCalendar.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/AbstractCalendar.java 2014-08-29 15:45:21 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/AbstractCalendar.java 2014-09-21 07:49:12 +0000 @@ -249,4 +249,10 @@ return DEFAULT_I18N_DAY_SHORT_NAMES[day - 1]; } + + @Override + public boolean isIso8601() + { + return false; + } } === modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/Calendar.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/Calendar.java 2014-08-29 10:02:21 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/Calendar.java 2014-09-21 07:49:12 +0000 @@ -73,7 +73,7 @@ /** * Formats dateUnit using supplied date format * - * @param dateFormat Date format to use + * @param dateFormat Date format to use * @param dateTimeUnit DateUnit representing local year, month, day * @return Default date format * @see #getDateFormat() @@ -142,9 +142,9 @@ * Gets interval of type based on DateUnit * * @param dateTimeUnit DateUnit representing local year, month, day - * @param type Interval type to get - * @param offset Offset to start at, can be negative of positive - * @param length How many periods to asks for, i.e. type = MONTH, length = 2, two months + * @param type Interval type to get + * @param offset Offset to start at, can be negative of positive + * @param length How many periods to asks for, i.e. type = MONTH, length = 2, two months * @return Interval for interval type based on dateUnit * @see DateIntervalType */ @@ -154,7 +154,7 @@ * Gets interval of type based on DateUnit using default options, 0 for offset, 1 for length * * @param dateTimeUnit DateUnit representing local year, month, day - * @param type Interval type to get + * @param type Interval type to get * @return Interval for interval type based on dateUnit * @see DateIntervalType */ @@ -184,10 +184,10 @@ * Gets interval of type based on DateUnit * * @param dateTimeUnit DateUnit representing local year, month, day - * @param type Interval type to get - * @param offset Offset to start at, can be negative of positive - * @param length How many periods to asks for, i.e. type = MONTH, length = 2, two months - * @param periods How many periods to generate + * @param type Interval type to get + * @param offset Offset to start at, can be negative of positive + * @param length How many periods to asks for, i.e. type = MONTH, length = 2, two months + * @param periods How many periods to generate * @return Interval for interval type based on dateUnit * @see DateIntervalType */ @@ -316,7 +316,7 @@ * Returns a new dateUnit with specified number of days added * * @param dateTimeUnit DateUnit representing local year, month, day - * @param days Days to add + * @param days Days to add * @return dateUnit + days */ DateTimeUnit plusDays( DateTimeUnit dateTimeUnit, int days ); @@ -325,7 +325,7 @@ * Returns a new dateUnit with specified number of days subtracted * * @param dateTimeUnit DateUnit representing local year, month, day - * @param days Days to subtract + * @param days Days to subtract * @return dateUnit - days */ DateTimeUnit minusDays( DateTimeUnit dateTimeUnit, int days ); @@ -334,7 +334,7 @@ * Returns a new dateUnit with specified number of weeks added * * @param dateTimeUnit DateUnit representing local year, month, day - * @param weeks Weeks to add + * @param weeks Weeks to add * @return dateUnit + weeks */ DateTimeUnit plusWeeks( DateTimeUnit dateTimeUnit, int weeks ); @@ -343,7 +343,7 @@ * Returns a new dateUnit with specified number of weeks subtracted * * @param dateTimeUnit DateUnit representing local year, month, day - * @param weeks Weeks to subtract + * @param weeks Weeks to subtract * @return dateUnit - weeks */ DateTimeUnit minusWeeks( DateTimeUnit dateTimeUnit, int weeks ); @@ -352,7 +352,7 @@ * Returns a new dateUnit with specified number of months added * * @param dateTimeUnit DateUnit representing local year, month, day - * @param months Months to add + * @param months Months to add * @return dateUnit + months */ DateTimeUnit plusMonths( DateTimeUnit dateTimeUnit, int months ); @@ -361,7 +361,7 @@ * Returns a new dateUnit with specified number of months subtracted * * @param dateTimeUnit DateUnit representing local year, month, day - * @param months Months to subtract + * @param months Months to subtract * @return dateUnit - months */ DateTimeUnit minusMonths( DateTimeUnit dateTimeUnit, int months ); @@ -370,7 +370,7 @@ * Returns a new dateUnit with specified number of years added * * @param dateTimeUnit DateUnit representing local year, month, day - * @param years Years to add + * @param years Years to add * @return dateUnit + years */ DateTimeUnit plusYears( DateTimeUnit dateTimeUnit, int years ); @@ -379,8 +379,15 @@ * Returns a new dateUnit with specified number of years subtracted * * @param dateTimeUnit DateUnit representing local year, month, day - * @param years Years to subtract + * @param years Years to subtract * @return dateUnit - years */ DateTimeUnit minusYears( DateTimeUnit dateTimeUnit, int years ); + + /** + * Is this calendar based on ISO 8601 (Iso8601 / Gregorian) + * + * @return is iso8601 based + */ + boolean isIso8601(); } === modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/ChronologyBasedCalendar.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/ChronologyBasedCalendar.java 2014-09-01 06:16:29 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/ChronologyBasedCalendar.java 2014-09-21 07:49:12 +0000 @@ -253,55 +253,55 @@ public DateTimeUnit plusDays( DateTimeUnit dateTimeUnit, int days ) { DateTime dateTime = dateTimeUnit.toJodaDateTime( chronology ); - return DateTimeUnit.fromJodaDateTime( dateTime.plusDays( days ) ); + return DateTimeUnit.fromJodaDateTime( dateTime.plusDays( days ), dateTimeUnit.isIso8601() ); } @Override public DateTimeUnit minusDays( DateTimeUnit dateTimeUnit, int days ) { DateTime dateTime = dateTimeUnit.toJodaDateTime( chronology ); - return DateTimeUnit.fromJodaDateTime( dateTime.minusDays( days ) ); + return DateTimeUnit.fromJodaDateTime( dateTime.minusDays( days ), dateTimeUnit.isIso8601() ); } @Override public DateTimeUnit plusWeeks( DateTimeUnit dateTimeUnit, int weeks ) { DateTime dateTime = dateTimeUnit.toJodaDateTime( chronology ); - return DateTimeUnit.fromJodaDateTime( dateTime.plusWeeks( weeks ) ); + return DateTimeUnit.fromJodaDateTime( dateTime.plusWeeks( weeks ), dateTimeUnit.isIso8601() ); } @Override public DateTimeUnit minusWeeks( DateTimeUnit dateTimeUnit, int weeks ) { DateTime dateTime = dateTimeUnit.toJodaDateTime( chronology ); - return DateTimeUnit.fromJodaDateTime( dateTime.minusWeeks( weeks ) ); + return DateTimeUnit.fromJodaDateTime( dateTime.minusWeeks( weeks ), dateTimeUnit.isIso8601() ); } @Override public DateTimeUnit plusMonths( DateTimeUnit dateTimeUnit, int months ) { DateTime dateTime = dateTimeUnit.toJodaDateTime( chronology ); - return DateTimeUnit.fromJodaDateTime( dateTime.plusMonths( months ) ); + return DateTimeUnit.fromJodaDateTime( dateTime.plusMonths( months ), dateTimeUnit.isIso8601() ); } @Override public DateTimeUnit minusMonths( DateTimeUnit dateTimeUnit, int months ) { DateTime dateTime = dateTimeUnit.toJodaDateTime( chronology ); - return DateTimeUnit.fromJodaDateTime( dateTime.minusMonths( months ) ); + return DateTimeUnit.fromJodaDateTime( dateTime.minusMonths( months ), dateTimeUnit.isIso8601() ); } @Override public DateTimeUnit plusYears( DateTimeUnit dateTimeUnit, int years ) { DateTime dateTime = dateTimeUnit.toJodaDateTime( chronology ); - return DateTimeUnit.fromJodaDateTime( dateTime.plusYears( years ) ); + return DateTimeUnit.fromJodaDateTime( dateTime.plusYears( years ), dateTimeUnit.isIso8601() ); } @Override public DateTimeUnit minusYears( DateTimeUnit dateTimeUnit, int years ) { DateTime dateTime = dateTimeUnit.toJodaDateTime( chronology ); - return DateTimeUnit.fromJodaDateTime( dateTime.minusYears( years ) ); + return DateTimeUnit.fromJodaDateTime( dateTime.minusYears( years ), dateTimeUnit.isIso8601() ); } } === modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/DateUnitPeriodTypeParser.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/DateUnitPeriodTypeParser.java 2014-08-29 15:45:21 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/DateUnitPeriodTypeParser.java 2014-09-21 07:49:12 +0000 @@ -68,6 +68,12 @@ @Override public DateInterval parse( String period ) { + return parse( getCalendar(), period ); + } + + @Override + public DateInterval parse( Calendar calendar, String period ) + { DateUnitType type = DateUnitType.find( period ); if ( type == null ) @@ -97,15 +103,13 @@ return null; } - Calendar calendar = getCalendar(); - if ( DateUnitType.DAILY.equals( type ) ) { int year = Integer.parseInt( matcher.group( 1 ) ); int month = Integer.parseInt( matcher.group( 2 ) ); int day = Integer.parseInt( matcher.group( 3 ) ); - DateTimeUnit dateTimeUnit = new DateTimeUnit( year, month, day ); + DateTimeUnit dateTimeUnit = new DateTimeUnit( year, month, day, calendar.isIso8601() ); dateTimeUnit.setDayOfWeek( calendar.weekday( dateTimeUnit ) ); return new DateInterval( dateTimeUnit, dateTimeUnit ); @@ -120,7 +124,7 @@ return null; } - DateTimeUnit start = new DateTimeUnit( year, 1, 1 ); + DateTimeUnit start = new DateTimeUnit( year, 1, 1, calendar.isIso8601() ); start = calendar.minusDays( start, calendar.weekday( start ) - 1 ); // rewind to start of week // since we rewind to start of week, we might end up in the previous years weeks, so we check and forward if needed @@ -144,8 +148,8 @@ int year = Integer.parseInt( matcher.group( 1 ) ); int month = Integer.parseInt( matcher.group( 2 ) ); - DateTimeUnit start = new DateTimeUnit( year, month, 1 ); - DateTimeUnit end = new DateTimeUnit( year, month, calendar.daysInMonth( start.getYear(), start.getMonth() ) ); + DateTimeUnit start = new DateTimeUnit( year, month, 1, calendar.isIso8601() ); + DateTimeUnit end = new DateTimeUnit( year, month, calendar.daysInMonth( start.getYear(), start.getMonth() ), calendar.isIso8601() ); start.setDayOfWeek( calendar.weekday( start ) ); end.setDayOfWeek( calendar.weekday( end ) ); @@ -162,7 +166,7 @@ return null; } - DateTimeUnit start = new DateTimeUnit( year, (month * 2) - 1, 1 ); + DateTimeUnit start = new DateTimeUnit( year, (month * 2) - 1, 1, calendar.isIso8601() ); DateTimeUnit end = new DateTimeUnit( start ); end = calendar.plusMonths( end, 2 ); end = calendar.minusDays( end, 1 ); @@ -183,7 +187,7 @@ return null; } - DateTimeUnit start = new DateTimeUnit( year, ((quarter - 1) * 3) + 1, 1 ); + DateTimeUnit start = new DateTimeUnit( year, ((quarter - 1) * 3) + 1, 1, calendar.isIso8601() ); DateTimeUnit end = new DateTimeUnit( start ); end = calendar.plusMonths( end, 3 ); end = calendar.minusDays( end, 1 ); @@ -204,7 +208,7 @@ return null; } - DateTimeUnit start = new DateTimeUnit( year, semester == 1 ? 1 : 7, 1 ); + DateTimeUnit start = new DateTimeUnit( year, semester == 1 ? 1 : 7, 1, calendar.isIso8601() ); DateTimeUnit end = new DateTimeUnit( start ); end = calendar.plusMonths( end, 6 ); end = calendar.minusDays( end, 1 ); @@ -225,7 +229,7 @@ return null; } - DateTimeUnit start = new DateTimeUnit( year, semester == 1 ? 4 : 10, 1 ); + DateTimeUnit start = new DateTimeUnit( year, semester == 1 ? 4 : 10, 1, calendar.isIso8601() ); DateTimeUnit end = new DateTimeUnit( start ); end = calendar.plusMonths( end, 6 ); end = calendar.minusDays( end, 1 ); @@ -239,9 +243,9 @@ { int year = Integer.parseInt( matcher.group( 1 ) ); - DateTimeUnit start = new DateTimeUnit( year, 1, 1 ); + DateTimeUnit start = new DateTimeUnit( year, 1, 1, calendar.isIso8601() ); DateTimeUnit end = new DateTimeUnit( year, calendar.monthsInYear(), - calendar.daysInMonth( start.getYear(), calendar.monthsInYear() ) ); + calendar.daysInMonth( start.getYear(), calendar.monthsInYear() ), calendar.isIso8601()); start.setDayOfWeek( calendar.weekday( start ) ); end.setDayOfWeek( calendar.weekday( end ) ); @@ -252,7 +256,7 @@ { int year = Integer.parseInt( matcher.group( 1 ) ); - DateTimeUnit start = new DateTimeUnit( year, 4, 1 ); + DateTimeUnit start = new DateTimeUnit( year, 4, 1, calendar.isIso8601() ); DateTimeUnit end = new DateTimeUnit( start ); end = calendar.plusYears( end, 1 ); end = calendar.minusDays( end, 1 ); @@ -266,7 +270,7 @@ { int year = Integer.parseInt( matcher.group( 1 ) ); - DateTimeUnit start = new DateTimeUnit( year, 7, 1 ); + DateTimeUnit start = new DateTimeUnit( year, 7, 1, calendar.isIso8601() ); DateTimeUnit end = new DateTimeUnit( start ); end = calendar.plusYears( end, 1 ); end = calendar.minusDays( end, 1 ); @@ -280,7 +284,7 @@ { int year = Integer.parseInt( matcher.group( 1 ) ); - DateTimeUnit start = new DateTimeUnit( year, 10, 1 ); + DateTimeUnit start = new DateTimeUnit( year, 10, 1, calendar.isIso8601() ); DateTimeUnit end = new DateTimeUnit( start ); end = calendar.plusYears( end, 1 ); end = calendar.minusDays( end, 1 ); === modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/PeriodTypeParser.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/PeriodTypeParser.java 2014-05-21 07:25:28 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/PeriodTypeParser.java 2014-09-21 07:49:12 +0000 @@ -34,4 +34,6 @@ public interface PeriodTypeParser { public DateInterval parse( String period ); + + public DateInterval parse( Calendar calendar, String period ); } === modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/impl/GregorianCalendar.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/impl/GregorianCalendar.java 2014-04-25 12:25:39 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/impl/GregorianCalendar.java 2014-09-21 07:49:12 +0000 @@ -56,4 +56,10 @@ { return "gregorian"; } + + @Override + public boolean isIso8601() + { + return true; + } } === modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/impl/Iso8601Calendar.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/impl/Iso8601Calendar.java 2014-04-25 12:25:39 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/impl/Iso8601Calendar.java 2014-09-21 07:49:12 +0000 @@ -56,4 +56,10 @@ { return "iso8601"; } + + @Override + public boolean isIso8601() + { + return true; + } } === modified file 'dhis-2/dhis-api/src/test/java/org/hisp/dhis/calendar/DateTimeUnitPeriodTypeParserTest.java' --- dhis-2/dhis-api/src/test/java/org/hisp/dhis/calendar/DateTimeUnitPeriodTypeParserTest.java 2014-08-29 10:02:21 +0000 +++ dhis-2/dhis-api/src/test/java/org/hisp/dhis/calendar/DateTimeUnitPeriodTypeParserTest.java 2014-09-21 07:49:12 +0000 @@ -50,66 +50,66 @@ public void testDateUnitFormatParser() { // daily - assertEquals( new DateInterval( new DateTimeUnit( 2014, 2, 4 ), new DateTimeUnit( 2014, 2, 4 ) ), format.parse( "20140204" ) ); + assertEquals( new DateInterval( new DateTimeUnit( 2014, 2, 4, true ), new DateTimeUnit( 2014, 2, 4, true ) ), format.parse( "20140204" ) ); // weekly - assertEquals( new DateInterval( new DateTimeUnit( 2013, 12, 30 ), new DateTimeUnit( 2014, 1, 5 ) ), format.parse( "2014W1" ) ); - assertEquals( new DateInterval( new DateTimeUnit( 2014, 1, 6 ), new DateTimeUnit( 2014, 1, 12 ) ), format.parse( "2014W2" ) ); + assertEquals( new DateInterval( new DateTimeUnit( 2013, 12, 30, true ), new DateTimeUnit( 2014, 1, 5, true ) ), format.parse( "2014W1" ) ); + assertEquals( new DateInterval( new DateTimeUnit( 2014, 1, 6, true ), new DateTimeUnit( 2014, 1, 12, true ) ), format.parse( "2014W2" ) ); // monthly assertNull( format.parse( "2014W0" ) ); assertNull( format.parse( "2014W53" ) ); assertNotNull( format.parse( "2009W53" ) ); // 2009 has 53 weeks assertNull( format.parse( "2009W54" ) ); - assertEquals( new DateInterval( new DateTimeUnit( 2014, 2, 1 ), new DateTimeUnit( 2014, 2, 28 ) ), format.parse( "201402" ) ); - assertEquals( new DateInterval( new DateTimeUnit( 2014, 4, 1 ), new DateTimeUnit( 2014, 4, 30 ) ), format.parse( "201404" ) ); - assertEquals( new DateInterval( new DateTimeUnit( 2014, 3, 1 ), new DateTimeUnit( 2014, 3, 31 ) ), format.parse( "2014-03" ) ); - assertEquals( new DateInterval( new DateTimeUnit( 2014, 5, 1 ), new DateTimeUnit( 2014, 5, 31 ) ), format.parse( "2014-05" ) ); + assertEquals( new DateInterval( new DateTimeUnit( 2014, 2, 1, true ), new DateTimeUnit( 2014, 2, 28, true ) ), format.parse( "201402" ) ); + assertEquals( new DateInterval( new DateTimeUnit( 2014, 4, 1, true ), new DateTimeUnit( 2014, 4, 30, true ) ), format.parse( "201404" ) ); + assertEquals( new DateInterval( new DateTimeUnit( 2014, 3, 1, true ), new DateTimeUnit( 2014, 3, 31, true ) ), format.parse( "2014-03" ) ); + assertEquals( new DateInterval( new DateTimeUnit( 2014, 5, 1, true ), new DateTimeUnit( 2014, 5, 31, true ) ), format.parse( "2014-05" ) ); // bi-monthly assertNull( format.parse( "201400B" ) ); assertNull( format.parse( "201407B" ) ); - assertEquals( new DateInterval( new DateTimeUnit( 2014, 1, 1 ), new DateTimeUnit( 2014, 2, 28 ) ), format.parse( "201401B" ) ); - assertEquals( new DateInterval( new DateTimeUnit( 2014, 3, 1 ), new DateTimeUnit( 2014, 4, 30 ) ), format.parse( "201402B" ) ); - assertEquals( new DateInterval( new DateTimeUnit( 2014, 5, 1 ), new DateTimeUnit( 2014, 6, 30 ) ), format.parse( "201403B" ) ); - assertEquals( new DateInterval( new DateTimeUnit( 2014, 7, 1 ), new DateTimeUnit( 2014, 8, 31 ) ), format.parse( "201404B" ) ); - assertEquals( new DateInterval( new DateTimeUnit( 2014, 9, 1 ), new DateTimeUnit( 2014, 10, 31 ) ), format.parse( "201405B" ) ); - assertEquals( new DateInterval( new DateTimeUnit( 2014, 11, 1 ), new DateTimeUnit( 2014, 12, 31 ) ), format.parse( "201406B" ) ); + assertEquals( new DateInterval( new DateTimeUnit( 2014, 1, 1, true ), new DateTimeUnit( 2014, 2, 28, true ) ), format.parse( "201401B" ) ); + assertEquals( new DateInterval( new DateTimeUnit( 2014, 3, 1, true ), new DateTimeUnit( 2014, 4, 30, true ) ), format.parse( "201402B" ) ); + assertEquals( new DateInterval( new DateTimeUnit( 2014, 5, 1, true ), new DateTimeUnit( 2014, 6, 30, true ) ), format.parse( "201403B" ) ); + assertEquals( new DateInterval( new DateTimeUnit( 2014, 7, 1, true ), new DateTimeUnit( 2014, 8, 31, true ) ), format.parse( "201404B" ) ); + assertEquals( new DateInterval( new DateTimeUnit( 2014, 9, 1, true ), new DateTimeUnit( 2014, 10, 31, true ) ), format.parse( "201405B" ) ); + assertEquals( new DateInterval( new DateTimeUnit( 2014, 11, 1, true ), new DateTimeUnit( 2014, 12, 31, true ) ), format.parse( "201406B" ) ); // quarter assertNull( format.parse( "2014Q0" ) ); assertNull( format.parse( "2014Q5" ) ); - assertEquals( new DateInterval( new DateTimeUnit( 2014, 1, 1 ), new DateTimeUnit( 2014, 3, 31 ) ), format.parse( "2014Q1" ) ); - assertEquals( new DateInterval( new DateTimeUnit( 2014, 4, 1 ), new DateTimeUnit( 2014, 6, 30 ) ), format.parse( "2014Q2" ) ); - assertEquals( new DateInterval( new DateTimeUnit( 2014, 7, 1 ), new DateTimeUnit( 2014, 9, 30 ) ), format.parse( "2014Q3" ) ); - assertEquals( new DateInterval( new DateTimeUnit( 2014, 10, 1 ), new DateTimeUnit( 2014, 12, 31 ) ), format.parse( "2014Q4" ) ); + assertEquals( new DateInterval( new DateTimeUnit( 2014, 1, 1, true ), new DateTimeUnit( 2014, 3, 31, true ) ), format.parse( "2014Q1" ) ); + assertEquals( new DateInterval( new DateTimeUnit( 2014, 4, 1, true ), new DateTimeUnit( 2014, 6, 30, true ) ), format.parse( "2014Q2" ) ); + assertEquals( new DateInterval( new DateTimeUnit( 2014, 7, 1, true ), new DateTimeUnit( 2014, 9, 30, true ) ), format.parse( "2014Q3" ) ); + assertEquals( new DateInterval( new DateTimeUnit( 2014, 10, 1, true ), new DateTimeUnit( 2014, 12, 31, true ) ), format.parse( "2014Q4" ) ); // six-monthly assertNull( format.parse( "2014S0" ) ); assertNull( format.parse( "2014S3" ) ); - assertEquals( new DateInterval( new DateTimeUnit( 2014, 1, 1 ), new DateTimeUnit( 2014, 6, 30 ) ), format.parse( "2014S1" ) ); - assertEquals( new DateInterval( new DateTimeUnit( 2014, 7, 1 ), new DateTimeUnit( 2014, 12, 31 ) ), format.parse( "2014S2" ) ); + assertEquals( new DateInterval( new DateTimeUnit( 2014, 1, 1, true ), new DateTimeUnit( 2014, 6, 30, true ) ), format.parse( "2014S1" ) ); + assertEquals( new DateInterval( new DateTimeUnit( 2014, 7, 1, true ), new DateTimeUnit( 2014, 12, 31, true ) ), format.parse( "2014S2" ) ); // six-monthly april assertNull( format.parse( "2014AprilS0" ) ); assertNull( format.parse( "2014AprilS3" ) ); - assertEquals( new DateInterval( new DateTimeUnit( 2014, 4, 1 ), new DateTimeUnit( 2014, 9, 30 ) ), format.parse( "2014AprilS1" ) ); - assertEquals( new DateInterval( new DateTimeUnit( 2014, 10, 1 ), new DateTimeUnit( 2015, 3, 31 ) ), format.parse( "2014AprilS2" ) ); + assertEquals( new DateInterval( new DateTimeUnit( 2014, 4, 1, true ), new DateTimeUnit( 2014, 9, 30, true ) ), format.parse( "2014AprilS1" ) ); + assertEquals( new DateInterval( new DateTimeUnit( 2014, 10, 1, true ), new DateTimeUnit( 2015, 3, 31, true ) ), format.parse( "2014AprilS2" ) ); // yearly - assertEquals( new DateInterval( new DateTimeUnit( 2013, 1, 1 ), new DateTimeUnit( 2013, 12, 31 ) ), format.parse( "2013" ) ); - assertEquals( new DateInterval( new DateTimeUnit( 2014, 1, 1 ), new DateTimeUnit( 2014, 12, 31 ) ), format.parse( "2014" ) ); + assertEquals( new DateInterval( new DateTimeUnit( 2013, 1, 1, true ), new DateTimeUnit( 2013, 12, 31, true ) ), format.parse( "2013" ) ); + assertEquals( new DateInterval( new DateTimeUnit( 2014, 1, 1, true ), new DateTimeUnit( 2014, 12, 31, true ) ), format.parse( "2014" ) ); // financial april - assertEquals( new DateInterval( new DateTimeUnit( 2013, 4, 1 ), new DateTimeUnit( 2014, 3, 31 ) ), format.parse( "2013April" ) ); - assertEquals( new DateInterval( new DateTimeUnit( 2014, 4, 1 ), new DateTimeUnit( 2015, 3, 31 ) ), format.parse( "2014April" ) ); + assertEquals( new DateInterval( new DateTimeUnit( 2013, 4, 1, true ), new DateTimeUnit( 2014, 3, 31, true ) ), format.parse( "2013April" ) ); + assertEquals( new DateInterval( new DateTimeUnit( 2014, 4, 1, true ), new DateTimeUnit( 2015, 3, 31, true ) ), format.parse( "2014April" ) ); // financial july - assertEquals( new DateInterval( new DateTimeUnit( 2013, 7, 1 ), new DateTimeUnit( 2014, 6, 30 ) ), format.parse( "2013July" ) ); - assertEquals( new DateInterval( new DateTimeUnit( 2014, 7, 1 ), new DateTimeUnit( 2015, 6, 30 ) ), format.parse( "2014July" ) ); + assertEquals( new DateInterval( new DateTimeUnit( 2013, 7, 1, true ), new DateTimeUnit( 2014, 6, 30, true ) ), format.parse( "2013July" ) ); + assertEquals( new DateInterval( new DateTimeUnit( 2014, 7, 1, true ), new DateTimeUnit( 2015, 6, 30, true ) ), format.parse( "2014July" ) ); // financial october - assertEquals( new DateInterval( new DateTimeUnit( 2013, 10, 1 ), new DateTimeUnit( 2014, 9, 30 ) ), format.parse( "2013Oct" ) ); - assertEquals( new DateInterval( new DateTimeUnit( 2014, 10, 1 ), new DateTimeUnit( 2015, 9, 30 ) ), format.parse( "2014Oct" ) ); + assertEquals( new DateInterval( new DateTimeUnit( 2013, 10, 1, true ), new DateTimeUnit( 2014, 9, 30, true ) ), format.parse( "2013Oct" ) ); + assertEquals( new DateInterval( new DateTimeUnit( 2014, 10, 1, true ), new DateTimeUnit( 2015, 9, 30, true ) ), format.parse( "2014Oct" ) ); } } === modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultAnalyticsService.java' --- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultAnalyticsService.java 2014-09-14 19:39:53 +0000 +++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultAnalyticsService.java 2014-09-21 07:49:12 +0000 @@ -86,6 +86,8 @@ import org.hisp.dhis.analytics.DataQueryParams; import org.hisp.dhis.analytics.DimensionItem; import org.hisp.dhis.analytics.QueryPlanner; +import org.hisp.dhis.calendar.Calendar; +import org.hisp.dhis.calendar.DateTimeUnit; import org.hisp.dhis.common.AnalyticalObject; import org.hisp.dhis.common.BaseDimensionalObject; import org.hisp.dhis.common.CodeGenerator; @@ -148,53 +150,53 @@ implements AnalyticsService { private static final Log log = LogFactory.getLog( DefaultAnalyticsService.class ); - + private static final String VALUE_HEADER_NAME = "Value"; private static final int PERCENT = 100; private static final int MAX_QUERIES = 8; //TODO make sure data x dims are successive //TODO completeness on time - + @Autowired private AnalyticsManager analyticsManager; - + @Autowired private AnalyticsSecurityManager securityManager; - + @Autowired private QueryPlanner queryPlanner; - + @Autowired private IndicatorService indicatorService; - + @Autowired private DataElementService dataElementService; - + @Autowired private DataElementCategoryService categoryService; - + @Autowired private DataSetService dataSetService; - + @Autowired private OrganisationUnitService organisationUnitService; - + @Autowired private OrganisationUnitGroupService organisationUnitGroupService; - + @Autowired private TrackedEntityAttributeService attributeService; - + @Autowired private ExpressionService expressionService; - + @Autowired private ConstantService constantService; @Autowired private DataElementOperandService operandService; - + @Autowired private SystemSettingManager systemSettingManager; @@ -212,19 +214,19 @@ @Override public Grid getAggregatedDataValues( DataQueryParams params ) - { + { // --------------------------------------------------------------------- // Security and validation // --------------------------------------------------------------------- securityManager.decideAccess( params ); - + securityManager.applyDataApprovalConstraints( params ); - + securityManager.applyDimensionConstraints( params ); - + queryPlanner.validate( params ); - + params.conform(); // --------------------------------------------------------------------- @@ -232,7 +234,7 @@ // --------------------------------------------------------------------- Grid grid = new ListGrid(); - + addHeaders( params, grid ); // --------------------------------------------------------------------- @@ -240,22 +242,22 @@ // --------------------------------------------------------------------- addIndicatorValues( params, grid ); - + addDataElementValues( params, grid ); - + addDataSetValues( params, grid ); - + addDynamicDimensionValues( params, grid ); - + // --------------------------------------------------------------------- // Meta-data // --------------------------------------------------------------------- addMetaData( params, grid ); - + return grid; } - + /** * Adds headers to the given grid based on the given data query parameters. */ @@ -265,24 +267,24 @@ { grid.addHeader( new GridHeader( col.getDimension(), col.getDisplayName(), String.class.getName(), false, true ) ); } - + grid.addHeader( new GridHeader( DataQueryParams.VALUE_ID, VALUE_HEADER_NAME, Double.class.getName(), false, false ) ); } /** - * Adds indicator values to the given grid based on the given data query + * Adds indicator values to the given grid based on the given data query * parameters. - * + * * @param params the data query parameters. * @param grid the grid. */ private void addIndicatorValues( DataQueryParams params, Grid grid ) { if ( params.getIndicators() != null ) - { + { int indicatorIndex = params.getIndicatorDimensionIndex(); List indicators = asTypedList( params.getIndicators() ); - + expressionService.explodeExpressions( indicators ); // ----------------------------------------------------------------- @@ -292,13 +294,13 @@ DataQueryParams dataSourceParams = params.instance(); dataSourceParams.removeDimension( DATAELEMENT_DIM_ID ); dataSourceParams.removeDimension( DATASET_DIM_ID ); - + dataSourceParams = replaceIndicatorsWithDataElements( dataSourceParams, indicatorIndex ); Map aggregatedDataMap = getAggregatedDataValueMap( dataSourceParams ); Map> permutationOperandValueMap = dataSourceParams.getPermutationOperandValueMap( aggregatedDataMap ); - + List> dimensionItemPermutations = dataSourceParams.getDimensionItemPermutations(); Map constantMap = constantService.getConstantMap(); @@ -306,7 +308,7 @@ Period filterPeriod = dataSourceParams.getFilterPeriod(); Map> permutationOrgUnitTargetMap = getOrgUnitTargetMap( dataSourceParams, indicators ); - + for ( Indicator indicator : indicators ) { for ( List options : dimensionItemPermutations ) @@ -314,28 +316,28 @@ String permKey = DimensionItem.asItemKey( options ); Map valueMap = permutationOperandValueMap.get( permKey ); - + if ( valueMap == null ) { continue; } - + Period period = filterPeriod != null ? filterPeriod : (Period) DimensionItem.getPeriodItem( options ); - + OrganisationUnit unit = (OrganisationUnit) DimensionItem.getOrganisationUnitItem( options ); - + String ou = unit != null ? unit.getUid() : null; - + Map orgUnitCountMap = permutationOrgUnitTargetMap != null ? permutationOrgUnitTargetMap.get( ou ) : null; - + Double value = expressionService.getIndicatorValue( indicator, period, valueMap, constantMap, orgUnitCountMap, period.getDaysInPeriod() ); if ( value != null ) { List row = new ArrayList<>( options ); - + row.add( indicatorIndex, new DimensionItem( INDICATOR_DIM_ID, indicator ) ); - + grid.addRow(); grid.addValues( DimensionItem.getItemIdentifiers( row ) ); grid.addValue( params.isSkipRounding() ? value : MathUtils.getRounded( value ) ); @@ -346,9 +348,9 @@ } /** - * Adds data element values to the given grid based on the given data query + * Adds data element values to the given grid based on the given data query * parameters. - * + * * @param params the data query parameters. * @param grid the grid. */ @@ -359,9 +361,9 @@ DataQueryParams dataSourceParams = params.instance(); dataSourceParams.removeDimension( INDICATOR_DIM_ID ); dataSourceParams.removeDimension( DATASET_DIM_ID ); - + Map aggregatedDataMap = getAggregatedDataValueMap( dataSourceParams ); - + for ( Map.Entry entry : aggregatedDataMap.entrySet() ) { grid.addRow(); @@ -372,9 +374,9 @@ } /** - * Adds data set values to the given grid based on the given data query + * Adds data set values to the given grid based on the given data query * parameters. - * + * * @param params the data query parameters. * @param grid the grid. */ @@ -400,7 +402,7 @@ List completenessDimIndexes = dataSourceParams.getCompletenessDimensionIndexes(); List completenessFilterIndexes = dataSourceParams.getCompletenessFilterIndexes(); - + DataQueryParams targetParams = dataSourceParams.instance(); targetParams.setDimensions( ListUtils.getAtIndexes( targetParams.getDimensions(), completenessDimIndexes ) ); @@ -415,7 +417,7 @@ Map dsPtMap = dataSourceParams.getDataSetPeriodTypeMap(); PeriodType filterPeriodType = dataSourceParams.getFilterPeriodType(); - + // ----------------------------------------------------------------- // Join data maps, calculate completeness and add to grid // ----------------------------------------------------------------- @@ -423,20 +425,20 @@ for ( Map.Entry entry : aggregatedDataMap.entrySet() ) { List dataRow = ListUtils.getList( entry.getKey().split( DIMENSION_SEP ) ); - + List targetRow = ListUtils.getAtIndexes( dataRow, completenessDimIndexes ); String targetKey = StringUtils.join( targetRow, DIMENSION_SEP ); Double target = targetMap.get( targetKey ); - + if ( target != null && entry.getValue() != null ) { PeriodType queryPt = filterPeriodType != null ? filterPeriodType : getPeriodTypeFromIsoString( dataRow.get( periodIndex ) ); PeriodType dataSetPt = dsPtMap.get( dataRow.get( dataSetIndex ) ); - + target = target * queryPt.getPeriodSpan( dataSetPt ); - + double value = entry.getValue() * PERCENT / target; - + grid.addRow(); grid.addValues( dataRow.toArray() ); grid.addValue( params.isSkipRounding() ? value : MathUtils.getRounded( value ) ); @@ -446,9 +448,9 @@ } /** - * Adds values to the given grid based on dynamic dimensions from the given + * Adds values to the given grid based on dynamic dimensions from the given * data query parameters. - * + * * @param params the data query parameters. * @param grid the grid. */ @@ -457,7 +459,7 @@ if ( params.getIndicators() == null && params.getDataElements() == null && params.getDataSets() == null ) { Map aggregatedDataMap = getAggregatedDataValueMap( params.instance() ); - + for ( Map.Entry entry : aggregatedDataMap.entrySet() ) { grid.addRow(); @@ -468,9 +470,9 @@ } /** - * Adds meta data values to the given grid based on the given data query + * Adds meta data values to the given grid based on the given data query * parameters. - * + * * @param params the data query parameters. * @param grid the grid. */ @@ -479,32 +481,51 @@ if ( !params.isSkipMeta() ) { Integer cocIndex = params.getCocIndex(); - + Map metaData = new HashMap<>(); - + Map uidNameMap = getUidNameMap( params ); - Map cocNameMap = getCocNameMap( grid, cocIndex ); + Map cocNameMap = getCocNameMap( grid, cocIndex ); uidNameMap.putAll( cocNameMap ); - + metaData.put( NAMES_META_KEY, uidNameMap ); - metaData.put( PERIOD_DIM_ID, getUids( params.getDimensionOrFilter( PERIOD_DIM_ID ) ) ); + + List periodUids = new ArrayList<>(); + + Calendar calendar = PeriodType.getCalendar(); + + if ( calendar.isIso8601() ) + { + periodUids = getUids( params.getDimensionOrFilter( PERIOD_DIM_ID ) ); + } + else + { + for ( NameableObject nameableObject : params.getDimensionOrFilter( PERIOD_DIM_ID ) ) + { + Period period = (Period) nameableObject; + DateTimeUnit dateTimeUnit = calendar.fromIso( DateTimeUnit.fromJdkDate( period.getStartDate() ) ); + periodUids.add( period.getPeriodType().getIsoDate( dateTimeUnit ) ); + } + } + + metaData.put( PERIOD_DIM_ID, periodUids ); metaData.put( ORGUNIT_DIM_ID, getUids( params.getDimensionOrFilter( ORGUNIT_DIM_ID ) ) ); metaData.put( CATEGORYOPTIONCOMBO_DIM_ID, cocNameMap.keySet() ); - + if ( params.isHierarchyMeta() ) { metaData.put( OU_HIERARCHY_KEY, getParentGraphMap( asTypedList( params.getDimensionOrFilter( ORGUNIT_DIM_ID ), OrganisationUnit.class ) ) ); } - + if ( params.isShowHierarchy() ) { metaData.put( OU_NAME_HIERARCHY_KEY, getParentNameGraphMap( asTypedList( params.getDimensionOrFilter( ORGUNIT_DIM_ID ), OrganisationUnit.class ), true ) ); } - + grid.setMetaData( metaData ); - } + } } - + @Override public Grid getAggregatedDataValues( DataQueryParams params, boolean tableLayout, List columns, List rows ) { @@ -512,33 +533,33 @@ { return getAggregatedDataValues( params ); } - + ListUtils.removeEmptys( columns ); ListUtils.removeEmptys( rows ); - + queryPlanner.validateTableLayout( params, columns, rows ); - + ReportTable reportTable = new ReportTable(); - + List tableColumns = new ArrayList<>(); List tableRows = new ArrayList<>(); if ( columns != null ) - { + { for ( String dimension : columns ) { reportTable.getColumnDimensions().add( dimension ); - + tableColumns.add( params.getDimensionArrayCollapseDxExplodeCoc( dimension ) ); } } - + if ( rows != null ) { for ( String dimension : rows ) { reportTable.getRowDimensions().add( dimension ); - + tableRows.add( params.getDimensionArrayCollapseDxExplodeCoc( dimension ) ); } } @@ -546,33 +567,33 @@ reportTable.setGridColumns( new CombinationGenerator<>( tableColumns.toArray( IRT2D ) ).getCombinations() ); reportTable.setGridRows( new CombinationGenerator<>( tableRows.toArray( IRT2D ) ).getCombinations() ); - addIfEmpty( reportTable.getGridColumns() ); + addIfEmpty( reportTable.getGridColumns() ); addIfEmpty( reportTable.getGridRows() ); - + reportTable.setTitle( IdentifiableObjectUtils.join( params.getFilterItems() ) ); reportTable.setHideEmptyRows( params.isHideEmptyRows() ); reportTable.setShowHierarchy( params.isShowHierarchy() ); Grid grid = getAggregatedDataValues( params ); - + Map valueMap = getAggregatedDataValueMapping( grid ); return reportTable.getGrid( new ListGrid( grid.getMetaData() ), valueMap, false ); } - + @Override public Map getAggregatedDataValueMapping( DataQueryParams params ) { Grid grid = getAggregatedDataValues( params ); - + return getAggregatedDataValueMapping( grid ); } - + @Override public Map getAggregatedDataValueMapping( AnalyticalObject object, I18nFormat format ) { DataQueryParams params = getFromAnalyticalObject( object, format ); - + return getAggregatedDataValueMapping( params ); } @@ -581,71 +602,71 @@ // ------------------------------------------------------------------------- /** - * Generates a mapping of permutations keys (organisation unit id or null) + * Generates a mapping of permutations keys (organisation unit id or null) * and mappings of organisation unit group and counts. - * + * * @param params the data query parameters. - * @param indicators the indicators for which formulas to scan for organisation + * @param indicators the indicators for which formulas to scan for organisation * unit groups. * @return a map of maps. */ private Map> getOrgUnitTargetMap( DataQueryParams params, Collection indicators ) { Set orgUnitGroups = expressionService.getOrganisationUnitGroupsInIndicators( indicators ); - + if ( orgUnitGroups == null || orgUnitGroups.isEmpty() ) { return null; } - + DataQueryParams orgUnitTargetParams = params.instance().pruneToDimensionType( DimensionType.ORGANISATIONUNIT ); orgUnitTargetParams.getDimensions().add( new BaseDimensionalObject( DimensionalObject.ORGUNIT_GROUP_DIM_ID, null, new ArrayList( orgUnitGroups ) ) ); orgUnitTargetParams.setSkipPartitioning( true ); - + Map orgUnitCountMap = getAggregatedOrganisationUnitTargetMap( orgUnitTargetParams ); - + return orgUnitTargetParams.getPermutationOrgUnitGroupCountMap( orgUnitCountMap ); } - + /** * Generates a mapping where the key represents the dimensional item identifiers * concatenated by "-" and the value is the corresponding aggregated data value * based on the given grid. - * + * * @param grid the grid. * @return a mapping between item identifiers and aggregated values. */ private Map getAggregatedDataValueMapping( Grid grid ) { Map map = new HashMap<>(); - + int metaCols = grid.getWidth() - 1; int valueIndex = grid.getWidth() - 1; - + for ( List row : grid.getRows() ) { StringBuilder key = new StringBuilder(); - + for ( int index = 0; index < metaCols; index++ ) { key.append( row.get( index ) ).append( DIMENSION_SEP ); } key.deleteCharAt( key.length() - 1 ); - + Double value = (Double) row.get( valueIndex ); - + map.put( key.toString(), value ); } - + return map; } /** - * Generates aggregated values for the given query. Creates a mapping between - * a dimension key and the aggregated value. The dimension key is a + * Generates aggregated values for the given query. Creates a mapping between + * a dimension key and the aggregated value. The dimension key is a * concatenation of the identifiers of the dimension items separated by "-". - * + * * @param params the data query parameters. * @return a mapping between a dimension key and the aggregated value. */ @@ -655,10 +676,10 @@ } /** - * Generates aggregated values for the given query. Creates a mapping between - * a dimension key and the aggregated value. The dimension key is a + * Generates aggregated values for the given query. Creates a mapping between + * a dimension key and the aggregated value. The dimension key is a * concatenation of the identifiers of the dimension items separated by "-". - * + * * @param params the data query parameters. * @return a mapping between a dimension key and the aggregated value. */ @@ -670,7 +691,7 @@ /** * Generates a mapping between the the data set dimension key and the count * of expected data sets to report. - * + * * @param params the data query parameters. * @return a mapping between the the data set dimension key and the count of * expected data sets to report. @@ -684,7 +705,7 @@ * Generates a mapping between the the org unit dimension key and the count * of org units inside the subtree of the given organisation units and * members of the given organisation unit groups. - * + * * @param params the data query parameters. * @return a mapping between the the data set dimension key and the count of * expected data sets to report. @@ -693,43 +714,43 @@ { return getAggregatedValueMap( params, ORGUNIT_TARGET_TABLE_NAME ); } - + /** * Generates a mapping between a dimension key and the aggregated value. The * dimension key is a concatenation of the identifiers of the dimension items * separated by "-". - * + * * @param params the data query parameters. */ - private Map getAggregatedValueMap( DataQueryParams params, String tableName ) + private Map getAggregatedValueMap( DataQueryParams params, String tableName ) { queryPlanner.validateMaintenanceMode(); - + int optimalQueries = MathUtils.getWithin( getProcessNo(), 1, MAX_QUERIES ); - + Timer t = new Timer().start(); - + DataQueryGroups queryGroups = queryPlanner.planQuery( params, optimalQueries, tableName ); - + t.getSplitTime( "Planned query, got: " + queryGroups.getLargestGroupSize() + " for optimal: " + optimalQueries ); Map map = new HashMap<>(); - + for ( List queries : queryGroups.getSequentialQueries() ) { List>> futures = new ArrayList<>(); - + for ( DataQueryParams query : queries ) { futures.add( analyticsManager.getAggregatedDataValues( query ) ); } - + for ( Future> future : futures ) { try { Map taskValues = future.get(); - + if ( taskValues != null ) { map.putAll( taskValues ); @@ -739,16 +760,16 @@ { log.error( DebugUtils.getStackTrace( ex ) ); log.error( DebugUtils.getStackTrace( ex.getCause() ) ); - + throw new RuntimeException( "Error during execution of aggregation query task", ex ); } } - + t.getSplitTime( "Got aggregated values for query group" ); } - + t.getTime( "Got aggregated values" ); - + return map; } @@ -757,21 +778,21 @@ // ------------------------------------------------------------------------- @Override - public DataQueryParams getFromUrl( Set dimensionParams, Set filterParams, AggregationType aggregationType, + public DataQueryParams getFromUrl( Set dimensionParams, Set filterParams, AggregationType aggregationType, String measureCriteria, boolean skipMeta, boolean skipRounding, boolean hierarchyMeta, boolean ignoreLimit, boolean hideEmptyRows, boolean showHierarchy, I18nFormat format ) { DataQueryParams params = new DataQueryParams(); params.setAggregationType( aggregationType ); params.setIgnoreLimit( ignoreLimit ); - + if ( dimensionParams != null && !dimensionParams.isEmpty() ) { for ( String param : dimensionParams ) { String dimension = DimensionalObjectUtils.getDimensionFromParam( param ); List options = DimensionalObjectUtils.getDimensionItemsFromParam( param ); - + if ( dimension != null && options != null ) { params.getDimensions().addAll( getDimension( dimension, options, null, format, false ) ); @@ -785,19 +806,19 @@ { String dimension = DimensionalObjectUtils.getDimensionFromParam( param ); List options = DimensionalObjectUtils.getDimensionItemsFromParam( param ); - + if ( dimension != null && options != null ) { params.getFilters().addAll( getDimension( dimension, options, null, format, false ) ); } } } - + if ( measureCriteria != null && !measureCriteria.isEmpty() ) { params.setMeasureCriteria( DataQueryParams.getMeasureCriteriaFromParam( measureCriteria ) ); } - + params.setSkipMeta( skipMeta ); params.setSkipRounding( skipRounding ); params.setHierarchyMeta( hierarchyMeta ); @@ -811,123 +832,123 @@ public DataQueryParams getFromAnalyticalObject( AnalyticalObject object, I18nFormat format ) { DataQueryParams params = new DataQueryParams(); - + if ( object != null ) { Date date = object.getRelativePeriodDate(); - + object.populateAnalyticalProperties(); - + for ( DimensionalObject column : object.getColumns() ) { params.getDimensions().addAll( getDimension( toDimension( column.getDimension() ), getUids( column.getItems() ), date, format, false ) ); } - + for ( DimensionalObject row : object.getRows() ) { params.getDimensions().addAll( getDimension( toDimension( row.getDimension() ), getUids( row.getItems() ), date, format, false ) ); } - + for ( DimensionalObject filter : object.getFilters() ) { params.getFilters().addAll( getDimension( toDimension( filter.getDimension() ), getUids( filter.getItems() ), date, format, false ) ); } } - + return params; } - + // TODO verify that current user can read each dimension and dimension item // TODO optimize so that org unit levels + boundary are used in query instead of fetching all org units one by one - + public List getDimension( String dimension, List items, Date relativePeriodDate, I18nFormat format, boolean allowNull ) - { + { if ( DATA_X_DIM_ID.equals( dimension ) ) { List dataDimensions = new ArrayList<>(); - + List indicators = new ArrayList<>(); List dataElements = new ArrayList<>(); List dataSets = new ArrayList<>(); List operandDataElements = new ArrayList<>(); - + options : for ( String uid : items ) { Indicator in = indicatorService.getIndicator( uid ); - + if ( in != null ) { indicators.add( in ); continue options; } - + DataElement de = dataElementService.getDataElement( uid ); - + if ( de != null ) - { + { dataElements.add( de ); continue options; } - + DataSet ds = dataSetService.getDataSet( uid ); - + if ( ds != null ) { dataSets.add( ds ); continue options; } - + DataElementOperand dc = operandService.getDataElementOperandByUid( uid ); - + if ( dc != null ) { operandDataElements.add( dc.getDataElement() ); continue options; } - - throw new IllegalQueryException( "Data dimension option identifier does not reference any option: " + uid ); + + throw new IllegalQueryException( "Data dimension option identifier does not reference any option: " + uid ); } - + if ( !indicators.isEmpty() ) { dataDimensions.add( new BaseDimensionalObject( INDICATOR_DIM_ID, DimensionType.INDICATOR, indicators ) ); } - + if ( !dataElements.isEmpty() ) { dataDimensions.add( new BaseDimensionalObject( DATAELEMENT_DIM_ID, DimensionType.DATAELEMENT, dataElements ) ); } - + if ( !dataSets.isEmpty() ) { dataDimensions.add( new BaseDimensionalObject( DATASET_DIM_ID, DimensionType.DATASET, dataSets ) ); } - + if ( !operandDataElements.isEmpty() ) { dataDimensions.add( new BaseDimensionalObject( DATAELEMENT_DIM_ID, DimensionType.DATAELEMENT, operandDataElements ) ); dataDimensions.add( new BaseDimensionalObject( CATEGORYOPTIONCOMBO_DIM_ID, DimensionType.CATEGORY_OPTION_COMBO, new ArrayList() ) ); } - + if ( indicators.isEmpty() && dataElements.isEmpty() && dataSets.isEmpty() && operandDataElements.isEmpty() ) { throw new IllegalQueryException( "Dimension dx is present in query without any valid dimension options" ); } - + return dataDimensions; } - + if ( CATEGORYOPTIONCOMBO_DIM_ID.equals( dimension ) ) { DimensionalObject object = new BaseDimensionalObject( dimension, DimensionType.CATEGORY_OPTION_COMBO, null, DISPLAY_NAME_CATEGORYOPTIONCOMBO, new ArrayList() ); - + return ListUtils.getList( object ); } if ( PERIOD_DIM_ID.equals( dimension ) ) { Set periods = new HashSet<>(); - + for ( String isoPeriod : items ) { if ( RelativePeriodEnum.contains( isoPeriod ) ) @@ -938,19 +959,19 @@ else { Period period = PeriodType.getPeriodFromIsoString( isoPeriod ); - + if ( period != null ) { periods.add( period ); } } } - + if ( periods.isEmpty() ) { throw new IllegalQueryException( "Dimension pe is present in query without any valid dimension options" ); } - + for ( Period period : periods ) { period.setName( format != null ? format.formatPeriod( period ) : null ); @@ -958,20 +979,20 @@ List periodList = new ArrayList<>( periods ); Collections.sort( periodList, AscendingPeriodEndDateComparator.INSTANCE ); - + DimensionalObject object = new BaseDimensionalObject( dimension, DimensionType.PERIOD, null, DISPLAY_NAME_PERIOD, asList( periodList ) ); - + return ListUtils.getList( object ); } - + if ( ORGUNIT_DIM_ID.equals( dimension ) ) { User user = currentUserService.getCurrentUser(); - + List ous = new UniqueArrayList<>(); List levels = new UniqueArrayList<>(); List groups = new UniqueArrayList<>(); - + for ( String ou : items ) { if ( KEY_USER_ORGUNIT.equals( ou ) && user != null && user.hasDataViewOrganisationUnitWithFallback() ) @@ -989,7 +1010,7 @@ else if ( ou != null && ou.startsWith( KEY_LEVEL ) ) { int level = DimensionalObjectUtils.getLevelFromLevelParam( ou ); - + if ( level > 0 ) { levels.add( level ); @@ -998,9 +1019,9 @@ else if ( ou != null && ou.startsWith( KEY_ORGUNIT_GROUP ) ) { String uid = DimensionalObjectUtils.getUidFromOrgUnitGroupParam( ou ); - + OrganisationUnitGroup group = organisationUnitGroupService.getOrganisationUnitGroup( uid ); - + if ( uid != null ) { groups.add( group ); @@ -1009,134 +1030,134 @@ else if ( CodeGenerator.isValidCode( ou ) ) { OrganisationUnit unit = organisationUnitService.getOrganisationUnit( ou ); - + if ( unit != null ) { ous.add( unit ); } } } - + List orgUnits = new UniqueArrayList<>(); List ousList = NameableObjectUtils.asTypedList( ous ); - + if ( !levels.isEmpty() ) { orgUnits.addAll( organisationUnitService.getOrganisationUnitsAtLevels( levels, ousList ) ); } - + if ( !groups.isEmpty() ) { orgUnits.addAll( organisationUnitService.getOrganisationUnits( groups, ousList ) ); } - + if ( levels.isEmpty() && groups.isEmpty() ) { orgUnits.addAll( ous ); - } - + } + if ( orgUnits.isEmpty() ) { throw new IllegalQueryException( "Dimension ou is present in query without any valid dimension options" ); } - + DimensionalObject object = new BaseDimensionalObject( dimension, DimensionType.ORGANISATIONUNIT, null, DISPLAY_NAME_ORGUNIT, orgUnits ); - + return ListUtils.getList( object ); } - + if ( LONGITUDE_DIM_ID.contains( dimension ) ) { DimensionalObject object = new BaseDimensionalObject( dimension, DimensionType.STATIC, null, DISPLAY_NAME_LONGITUDE, new ArrayList() ); - + return ListUtils.getList( object ); } if ( LATITUDE_DIM_ID.contains( dimension ) ) { DimensionalObject object = new BaseDimensionalObject( dimension, DimensionType.STATIC, null, DISPLAY_NAME_LATITUDE, new ArrayList() ); - + return ListUtils.getList( object ); } - + OrganisationUnitGroupSet ougs = organisationUnitGroupService.getOrganisationUnitGroupSet( dimension ); - + if ( ougs != null ) { List ous = asList( organisationUnitGroupService.getOrganisationUnitGroupsByUid( items ) ); - + DimensionalObject object = new BaseDimensionalObject( dimension, DimensionType.ORGANISATIONUNIT_GROUPSET, null, ougs.getDisplayName(), ous ); - + return ListUtils.getList( object ); } - + DataElementGroupSet degs = dataElementService.getDataElementGroupSet( dimension ); - + if ( degs != null ) { List des = asList( dataElementService.getDataElementGroupsByUid( items ) ); - + DimensionalObject object = new BaseDimensionalObject( dimension, DimensionType.DATAELEMENT_GROUPSET, null, degs.getDisplayName(), des ); - + return ListUtils.getList( object ); } - + CategoryOptionGroupSet cogs = categoryService.getCategoryOptionGroupSet( dimension ); - + if ( cogs != null ) { List cogz = asList( categoryService.getCategoryOptionGroupsByUid( items ) ); - + DimensionalObject object = new BaseDimensionalObject( dimension, DimensionType.CATEGORYOPTION_GROUPSET, null, cogs.getDisplayName(), cogz ); - + return ListUtils.getList( object ); } - + DataElementCategory dec = categoryService.getDataElementCategory( dimension ); - + if ( dec != null && dec.isDataDimension() ) { List decos = asList( categoryService.getDataElementCategoryOptionsByUid( items ) ); - + DimensionalObject object = new BaseDimensionalObject( dimension, DimensionType.CATEGORY, null, dec.getDisplayName(), decos ); - + return ListUtils.getList( object ); } - + if ( allowNull ) { return null; } - + throw new IllegalQueryException( "Dimension identifier does not reference any dimension: " + dimension ); } // ------------------------------------------------------------------------- // Supportive methods // ------------------------------------------------------------------------- - + /** * Replaces the indicator dimension including items with the data elements * part of the indicator expressions. - * + * * @param params the data query parameters. * @param indicatorIndex the index of the indicator dimension in the given query. */ private DataQueryParams replaceIndicatorsWithDataElements( DataQueryParams params, int indicatorIndex ) { - List indicators = asTypedList( params.getIndicators() ); + List indicators = asTypedList( params.getIndicators() ); List dataElements = asList( expressionService.getDataElementsInIndicators( indicators ) ); - + params.getDimensions().set( indicatorIndex, new BaseDimensionalObject( DATAELEMENT_DIM_ID, DimensionType.DATAELEMENT, dataElements ) ); params.enableCategoryOptionCombos(); - + return params; } - + /** - * Returns a mapping between the identifier and the name of all dimension and + * Returns a mapping between the identifier and the name of all dimension and * filter items for the given parameters. - * + * * @param params the data query. */ private Map getUidNameMap( DataQueryParams params ) @@ -1145,32 +1166,32 @@ map.putAll( getUidNameMap( params.getDimensions(), params.isHierarchyMeta() ) ); map.putAll( getUidNameMap( params.getFilters(), params.isHierarchyMeta() ) ); map.put( DATA_X_DIM_ID, DISPLAY_NAME_DATA_X ); - + return map; } /** * Returns a mapping between identifiers and names for the given dimensional * objects. - * + * * @param dimensions the dimensional objects. - * @param hierarchyMeta indicates whether to include meta data of the + * @param hierarchyMeta indicates whether to include meta data of the * organisation unit hierarchy. */ private Map getUidNameMap( List dimensions, boolean hierarchyMeta ) { Map map = new HashMap<>(); - + for ( DimensionalObject dimension : dimensions ) { List items = new ArrayList<>( dimension.getItems() ); boolean hierarchy = hierarchyMeta && DimensionType.ORGANISATIONUNIT.equals( dimension.getDimensionType() ); - + // ----------------------------------------------------------------- // If dimension is not fixed and has no options, insert all options // ----------------------------------------------------------------- - + if ( !FIXED_DIMS.contains( dimension.getDimension() ) && items.isEmpty() ) { if ( DimensionType.ORGANISATIONUNIT_GROUPSET.equals( dimension.getDimensionType() ) ) @@ -1194,52 +1215,63 @@ // ----------------------------------------------------------------- // Insert UID and name into map // ----------------------------------------------------------------- - + + Calendar calendar = PeriodType.getCalendar(); + for ( IdentifiableObject idObject : items ) { - map.put( idObject.getUid(), idObject.getDisplayName() ); - + if ( !calendar.isIso8601() && Period.class.isInstance( idObject ) ) + { + Period period = (Period) idObject; + DateTimeUnit dateTimeUnit = calendar.fromIso( DateTimeUnit.fromJdkDate( period.getStartDate() ) ); + map.put( period.getPeriodType().getIsoDate( dateTimeUnit ), idObject.getDisplayName() ); + } + else + { + map.put( idObject.getUid(), idObject.getDisplayName() ); + } + if ( hierarchy ) { OrganisationUnit unit = (OrganisationUnit) idObject; - + map.putAll( IdentifiableObjectUtils.getUidNameMap( unit.getAncestors() ) ); } } - + if ( dimension.getDisplayName() != null ) { map.put( dimension.getDimension(), dimension.getDisplayName() ); } } - + return map; } - + /** * Returns a mapping between the category option combo identifiers and names * in the given grid. Returns an empty map if the grid or cocIndex parameters * are null. - * + * * @param grid the grid. * @param cocIndex the category option combo index in the grid. */ private Map getCocNameMap( Grid grid, Integer cocIndex ) { Map metaData = new HashMap<>(); - + if ( grid != null && cocIndex != null ) { Set uids = new HashSet<>( ConversionUtils.cast( grid.getColumn( cocIndex ) ) ); - + Collection cocs = categoryService.getDataElementCategoryOptionCombosByUid( uids ); - + for ( DataElementCategoryOptionCombo coc : cocs ) { metaData.put( coc.getUid(), coc.getName() ); } } - + return metaData; } @@ -1251,7 +1283,7 @@ private int getProcessNo() { Integer cores = (Integer) systemSettingManager.getSystemSetting( SystemSettingManager.KEY_DATABASE_SERVER_CPUS ); - + return ( cores == null || cores == 0 ) ? SystemUtils.getCpuCores() : cores; } }