Commits

timemachine  committed 158e637

Improved DateListSchedule and Schedules. Added EndOfMonthDateListProviderTest.

  • Participants
  • Parent commits ab3fbe4
  • Branches 1.1.x

Comments (0)

Files changed (5)

File timemachine-scheduler/src/main/java/timemachine/scheduler/Schedules.java

 	public static Date addSeconds(Date date, int num) {
 		return addDate(date, num, ScheduleUnit.SECOND);
 	}
-
 	public static Date addMinutes(Date date, int num) {
 		return addDate(date, num, ScheduleUnit.MINUTE);
 	}
-
 	public static Date addHours(Date date, int num) {
 		return addDate(date, num, ScheduleUnit.HOUR);
 	}
-
 	public static Date addDays(Date date, int num) {
 		return addDate(date, num, ScheduleUnit.DAY);
 	}
-
 	public static Date addWeeks(Date date, int num) {
 		return addDate(date, num, ScheduleUnit.WEEK);
 	}
-
 	public static Date addMonths(Date date, int num) {
 		return addDate(date, num, ScheduleUnit.MONTH);
 	}
-
 	public static Date addYears(Date date, int num) {
 		return addDate(date, num, ScheduleUnit.YEAR);
 	}
 
+	/** Same as setDate with explicit arguments, but this will take an array of 7 date parts from year to millis. */
+	public static Date setDateParts(int[] dateParts) {
+		Calendar cal = Calendar.getInstance();
+		cal.set(Calendar.MILLISECOND, dateParts[0]);
+		cal.set(Calendar.SECOND, dateParts[1]);
+		cal.set(Calendar.MINUTE, dateParts[2]);
+		cal.set(Calendar.HOUR, dateParts[3]);
+		cal.set(Calendar.DAY_OF_MONTH, dateParts[4]);
+		cal.set(Calendar.MONTH, dateParts[5] - 1);
+		cal.set(Calendar.YEAR, dateParts[6]);
+		return cal.getTime();
+	}
+	/** Return the date parts of given date: 
+	 *  int year, int month, int days, int hours, int minutes, int seconds, int millis. */
+	public static int[] getDateParts(Date date) {
+		int[] dateParts = new int[7];
+		Calendar cal = Calendar.getInstance();
+		cal.setTime(date);
+		dateParts[0] = cal.get(Calendar.MILLISECOND);
+		dateParts[1] = cal.get(Calendar.SECOND);
+		dateParts[2] = cal.get(Calendar.MINUTE);
+		dateParts[3] = cal.get(Calendar.HOUR);
+		dateParts[4] = cal.get(Calendar.DAY_OF_MONTH);
+		dateParts[5] = cal.get(Calendar.MONTH + 1);
+		dateParts[6] = cal.get(Calendar.YEAR);
+		return dateParts;
+	}
+	
+	
 	/** Factory method to create a Schedule that repeat secondly in every interval. */
 	public static RepeatSchedule secondly(int interval) {
 		RepeatSchedule schedule = new RepeatSchedule();
 	}
 	
 	/** Return the last day of the month for given date. */
-	public static Date lastOfMonth(Date date) {
+	public static Date endOfMonth(Date date) {
 		Calendar cal = Calendar.getInstance();
 		cal.setTime(date);
 		cal.add(Calendar.MONTH, 1);

File timemachine-scheduler/src/main/java/timemachine/scheduler/schedule/DateListSchedule.java

 	public Date getNextRun(Date after) {
 		if ((nextRunIndex + 1) < dates.size())
 			return dates.get(nextRunIndex + 1);
-		
-		if (dateListProviderClassName == null)
-			return null;
-		
-		// Our nextRunIndex has passed our dates size, and we have a provider, so let's generate a new list
-		dates.clear(); // clean up the dates list and reset the nextRunIndex
-		nextRunIndex = 0;
-		updateDateListAfterEnded();
-		
-		if (dates.size() > 0) {
-			return dates.get(nextRunIndex);
+
+		// We have used all of dates in the list, so we will call updateDateListAfterEnded() to regenerate
+		// new one if possible, else we will return null.
+		Date result = null;
+		if (dateListProviderClassName != null) {
+			updateDateListAfterEnded();
+			if (nextRunIndex < dates.size()) {
+				result = dates.get(nextRunIndex);
+			}
 		}
-
-		// If after we call provider, and we still get a empty date list, then we are done.
-		return null;
+		return result;
+	}
+	
+	/** Clear the dates list and reset the nextRunIndex. */
+	public void resetDateList() {
+		dates.clear();
+		nextRunIndex = 0;		
 	}
 
 	@Override
 	 * This gets called when the date list in this schedule got run out. If {@link #dateListProviderClassName} is
 	 * set, then it will instantiate the provider and get new date list to run.
 	 */
-	private void updateDateListAfterEnded() {
-		dates.addAll(generateNextDateList(this));
+	private void updateDateListAfterEnded() {		
+		List<Date> newDateList = generateNextDateList(this);
+		
+		// We will reset date list and populate new one only if provider return something.
+		if (newDateList.size() > 0) {
+			resetDateList();
+			dates.addAll(newDateList);
+		}
 	}
 	
 	private List<Date> generateNextDateList(DateListSchedule schedule) {
 	public List<Date> getNextRuns(Date after, int maxCount) {
 		List<Date> result = new ArrayList<Date>();		
 		try {
+			DateListSchedule clonedSchedule = (DateListSchedule)clone();
 			Date previewNextRun = null;
-			DateListSchedule clone = (DateListSchedule)clone();
-			
-			while ((previewNextRun = clone.getNextRun(after)) != null) {
+			// Try more if we are still need more.			
+			while ((result.size() < maxCount) && 
+					(previewNextRun = clonedSchedule.getNextRun()) != null) {
 				result.add(previewNextRun);
-				clone.updateNextRun();
-				
-				if (result.size() >= maxCount)
-					break;
+				clonedSchedule.updateNextRun();
 			}
 		} catch (CloneNotSupportedException e) {
 			throw new SchedulerException("Failed to clone DateListSchedule to generate preview next runs.", e);
 		this.dateListProviderClassName = dateListProviderClassName;
 		return this;
 	}
+
+	public DateListSchedule setDateListProviderClassName(Class<? extends DateListProvider> providerClass) {
+		return setDateListProviderClassName(providerClass.getName());
+	}
 }

File timemachine-scheduler/src/main/java/timemachine/scheduler/schedule/EndOfMonthDateListProvider.java

+/*
+ * Copyright 2012 Zemian Deng
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package timemachine.scheduler.schedule;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import timemachine.scheduler.Schedules;
+import timemachine.scheduler.schedule.DateListSchedule;
+import timemachine.scheduler.schedule.DateListSchedule.DateListProvider;
+
+/**
+ * A provider that always returns the end of month date from prevRunDate. If prevRunDate is null, then end of 
+ * current month.
+ * @author Zemian Deng
+ */
+public class EndOfMonthDateListProvider implements DateListProvider {
+
+	@Override
+	public List<Date> getDateList(DateListSchedule schedule) {
+		List<Date> result = new ArrayList<Date>();
+		
+		Date prevDate = schedule.getPrevRun();
+		if (prevDate == null) {
+			Date now = Schedules.time("00:00:00");
+			result.add(Schedules.endOfMonth(now));
+		} else {
+			result.add(Schedules.endOfMonth(Schedules.addMonths(prevDate, 1)));
+		}
+		return result;
+	}
+}

File timemachine-scheduler/src/main/java/timemachine/scheduler/schedule/LastMonthDateListProvider.java

-/*
- * Copyright 2012 Zemian Deng
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *    http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package timemachine.scheduler.schedule;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
-import timemachine.scheduler.Schedules;
-import timemachine.scheduler.schedule.DateListSchedule;
-import timemachine.scheduler.schedule.DateListSchedule.DateListProvider;
-
-/**
- * A provider that always returns the end of month date from prevRunDate. If prevRunDate is null, then end of 
- * current month.
- * @author Zemian Deng
- */
-public class LastMonthDateListProvider implements DateListProvider {
-
-	@Override
-	public List<Date> getDateList(DateListSchedule schedule) {
-		List<Date> result = new ArrayList<Date>();
-		
-		Date prevDate = schedule.getPrevRun();
-		if (prevDate == null)
-			result.add(Schedules.lastOfMonth(new Date()));
-		else
-			result.add(Schedules.lastOfMonth(Schedules.addMonths(prevDate, 1)));
-		
-		return result;
-	}
-}

File timemachine-scheduler/src/test/java/unit/timemachine/scheduler/schedule/EndOfMonthDateListProviderTest.java

+/*
+ * Copyright 2012 Zemian Deng
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package unit.timemachine.scheduler.schedule;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
+import java.util.Date;
+import java.util.List;
+
+import org.junit.Test;
+
+import timemachine.scheduler.Schedules;
+import timemachine.scheduler.schedule.DateListSchedule;
+import timemachine.scheduler.schedule.EndOfMonthDateListProvider;
+
+public class EndOfMonthDateListProviderTest {	
+	@Test
+	public void testClone() throws Exception {
+		DateListSchedule s = new DateListSchedule().setDateListProviderClassName(EndOfMonthDateListProvider.class);
+		s.initOnce();
+		
+		assertThat(s.getNextRun() != null, is(true));
+		assertThat(s.getNextRun(), is(Schedules.endOfMonth(Schedules.time("00:00:00"))));
+		
+		Date start = Schedules.time("00:00:00");
+		List<Date> dates = s.getNextRuns(null, 10);
+		assertThat(dates.size(), is(10));
+		assertThat(dates.get(0), is(Schedules.endOfMonth(start)));
+		assertThat(dates.get(1), is(Schedules.endOfMonth(Schedules.addMonths(start, 1))));
+		assertThat(dates.get(2), is(Schedules.endOfMonth(Schedules.addMonths(start, 2))));
+		assertThat(dates.get(3), is(Schedules.endOfMonth(Schedules.addMonths(start, 3))));
+		assertThat(dates.get(4), is(Schedules.endOfMonth(Schedules.addMonths(start, 4))));
+		assertThat(dates.get(5), is(Schedules.endOfMonth(Schedules.addMonths(start, 5))));
+		assertThat(dates.get(6), is(Schedules.endOfMonth(Schedules.addMonths(start, 6))));
+		assertThat(dates.get(7), is(Schedules.endOfMonth(Schedules.addMonths(start, 7))));
+		assertThat(dates.get(8), is(Schedules.endOfMonth(Schedules.addMonths(start, 8))));
+		assertThat(dates.get(9), is(Schedules.endOfMonth(Schedules.addMonths(start, 9))));
+	}
+}