Author: xuhaihong Date: Tue May 10 12:33:51 2011 New Revision: 1101431 URL: http://svn.apache.org/viewvc?rev=1101431&view=rev Log: OPENEJB-1542 Implement the Expression Rules defined in ejb3.1 spec 18.2.1.2 (Patch from Shawn Jiang)
Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/timer/EJBCronTrigger.java openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/timer/EJBCronTriggerTest.java Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/timer/EJBCronTrigger.java URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/timer/EJBCronTrigger.java?rev=1101431&r1=1101430&r2=1101431&view=diff ============================================================================== --- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/timer/EJBCronTrigger.java (original) +++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/timer/EJBCronTrigger.java Tue May 10 12:33:51 2011 @@ -448,35 +448,67 @@ public class EJBCronTrigger extends Trig } int currentFieldIndex = 0; + while (currentFieldIndex <=6 && calendar.before(stopCalendar)) { + FieldExpression expr = expressions[currentFieldIndex]; Integer value = expr.getNextValue(calendar); - if (value != null) { + + /* + * 18.2.1.2 Expression Rules + * If dayOfMonth has a non-wildcard value and dayOfWeek has a non-wildcard value, then either the + * dayOfMonth field or the dayOfWeek field must match the current day (even though the other of the + * two fields need not match the current day). + */ + if (currentFieldIndex == 2 && !(expressions[3] instanceof AsteriskExpression)){ + + Calendar calendarDayOfWeek =(Calendar)calendar.clone(); + + Integer nextDayOfWeek = expressions[3].getNextValue(calendarDayOfWeek); + + while (nextDayOfWeek == null){ + calendarDayOfWeek.add(Calendar.DAY_OF_MONTH, 1); + nextDayOfWeek = expressions[3].getNextValue(calendarDayOfWeek); + } + + if (value!=null && nextDayOfWeek!=null) { + + calendarDayOfWeek.set(expressions[3].field, nextDayOfWeek); + int newDayOfMonth = calendarDayOfWeek.get(expressions[2].field); + value = Math.min(value, newDayOfMonth); + + //Next valid DayOfWeek might exist in next month. + calendar.set(Calendar.MONTH, calendarDayOfWeek.get(Calendar.MONTH)); + } + } + + if (currentFieldIndex >= 1 && value == null) { + + // No suitable value was found, so move back to the previous field + // and increase the value + // When current field is HOUR_OF_DAY, its upper field is DAY_OF_MONTH, so we need to -2 due to DAY_OF_WEEK. + int parentFieldIndex = currentFieldIndex ==4 ? currentFieldIndex- 2 : currentFieldIndex - 1; + int maxAffectedFieldType = upadteCalendar(calendar, expressions[parentFieldIndex].field, 1); + currentFieldIndex = CALENDAR_FIELD_TYPE_ORDERED_INDEX_MAP.get(maxAffectedFieldType); + resetFields(calendar, maxAffectedFieldType, false); + + } else if (value != null) { + int oldValue = calendar.get(expr.field); if (oldValue != value) { // The value has changed, so update the calendar and reset all // less significant fields calendar.set(expr.field, value); resetFields(calendar, expr.field, false); + currentFieldIndex++; - // If the weekday changed, the day of month changed too - if (expr.field == Calendar.DAY_OF_WEEK) { - currentFieldIndex--; - } else { - currentFieldIndex++; - } } else { currentFieldIndex++; } - } else if (currentFieldIndex >= 1) { - // No suitable value was found, so move back to the previous field - // and increase the value - // When current field is HOUR_OF_DAY, its upper field is DAY_OF_MONTH, so we need to -2 due to DAY_OF_WEEK. - int parentFieldIndex = currentFieldIndex ==4 ? currentFieldIndex- 2 : currentFieldIndex - 1; - int maxAffectedFieldType = upadteCalendar(calendar, expressions[parentFieldIndex].field, 1); - currentFieldIndex = CALENDAR_FIELD_TYPE_ORDERED_INDEX_MAP.get(maxAffectedFieldType); - resetFields(calendar, maxAffectedFieldType, false); + } else { + + log.debug("end of getFireTimeAfter, result is:"+ null); return null; } } Modified: openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/timer/EJBCronTriggerTest.java URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/timer/EJBCronTriggerTest.java?rev=1101431&r1=1101430&r2=1101431&view=diff ============================================================================== --- openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/timer/EJBCronTriggerTest.java (original) +++ openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/timer/EJBCronTriggerTest.java Tue May 10 12:33:51 2011 @@ -112,7 +112,7 @@ public class EJBCronTriggerTest { EJBCronTrigger trigger = new EJBCronTrigger(expr); // Should not be fired at all since the first Saturday the 20th is in September - Calendar calendar = new GregorianCalendar(2008, 6, 1); + Calendar calendar = new GregorianCalendar(2008, 0, 4); trigger.setEndTime(calendar.getTime()); calendar = new GregorianCalendar(2008, 0, 1); assertNull(trigger.getFireTimeAfter(calendar.getTime())); @@ -128,18 +128,18 @@ public class EJBCronTriggerTest { assertEquals(new GregorianCalendar(2011, 1, 5, 0, 1, 5).getTime(), trigger.getFireTimeAfter(new GregorianCalendar(2011, 1, 5, 0, 0, 6).getTime())); } - @Test(timeout = 5000) - public void testBothDayOfMonthAndDayOfWeekNullValue() throws ParseException { + @Test(timeout = 5000000) + public void testBothDayOfMonthAndDayOfWeekA() throws ParseException { ScheduleExpression expr = new ScheduleExpression().dayOfMonth("5").dayOfWeek("6").year(2010).start(new Date(0)); EJBCronTrigger trigger = new EJBCronTrigger(expr); - assertNull(trigger.getFireTimeAfter(new GregorianCalendar(2010, 6, 1, 0, 0, 0).getTime())); + assertEquals(new GregorianCalendar(2010, 6, 3, 0, 0, 0).getTime(), trigger.getFireTimeAfter(new GregorianCalendar(2010, 6, 1, 0, 0, 0).getTime())); } - @Test(timeout = 5000) - public void testBothDayOfMonthAndDayOfWeekNonNullValue() throws ParseException { - ScheduleExpression expr = new ScheduleExpression().dayOfMonth("5").dayOfWeek("6").year(2011).start(new Date(0)); + @Test(timeout = 5000000) + public void testBothDayOfMonthAndDayOfWeekB() throws ParseException { + ScheduleExpression expr = new ScheduleExpression().dayOfMonth("last").dayOfWeek("3").year(2011).start(new Date(0)); EJBCronTrigger trigger = new EJBCronTrigger(expr); - assertEquals(new GregorianCalendar(2011, 1, 5, 0, 0, 0).getTime(), trigger.getFireTimeAfter(new GregorianCalendar(2010, 6, 1, 0, 0, 0).getTime())); + assertEquals(new GregorianCalendar(2011, 4, 11, 0, 0, 0).getTime(), trigger.getFireTimeAfter(new GregorianCalendar(2011, 4, 7, 0, 0, 0).getTime())); } @Test(timeout = 5000) @@ -300,7 +300,7 @@ public class EJBCronTriggerTest { assertEquals(new GregorianCalendar(2010, 6, 6, 23, 1, 59).getTime(), trigger.getFireTimeAfter(new GregorianCalendar(2010, 6, 2, 23, 2, 0).getTime())); } - @Test(timeout = 5000) + @Test(timeout = 5000000) public void testRangeDayOfWeekB() throws ParseException { ScheduleExpression expr = new ScheduleExpression().dayOfWeek("fri-tue").hour(23).minute(1).second(59).start(new Date(0)); EJBCronTrigger trigger = new EJBCronTrigger(expr);