diff --git a/edexOsgi/build.edex/esb/etc/devRegistry.sh b/edexOsgi/build.edex/esb/etc/devRegistry.sh index c00775981d..86b41aaf4c 100644 --- a/edexOsgi/build.edex/esb/etc/devRegistry.sh +++ b/edexOsgi/build.edex/esb/etc/devRegistry.sh @@ -27,3 +27,6 @@ export EDEX_JMX_PORT=1620 export LOG_CONF=logback-registry.xml export MGMT_PORT=9605 export EBXML_REGISTRY_FEDERATION_ENABLED=false +export NCF_HOST=${DATADELIVERY_HOST} +export NCF_ADDRESS=http://${NCF_HOST}:${EBXML_REGISTRY_WEBSERVER_PORT} +export NCF_BANDWIDTH_MANAGER_SERVICE=http://${NCF_HOST}:${EBXML_THRIFT_SERVICE_PORT}/services diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/RecurringSubscription.java b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/RecurringSubscription.java index c37a7a8e02..fc3ffbe506 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/RecurringSubscription.java +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/RecurringSubscription.java @@ -66,7 +66,8 @@ import com.raytheon.uf.common.time.util.TimeUtil; * Jan 08, 2014 2615 bgonzale Implement calculate start and calculate end methods. * Jan 14, 2014 2459 mpduff Add subscription state. * Jan 20, 2013 2398 dhladky Fixed rescheduling beyond active period/expired window. - * Jan 24, 2013 2709 bgonzale Fix setting of active period end. + * Jan 24, 2013 2709 bgonzale Fix setting of active period end. Change active period checks + * to check day of year. removed now unused active period methods. * * * @@ -269,6 +270,17 @@ public abstract class RecurringSubscription @SlotAttribute(Subscription.SUBSCRIPTION_STATE_SLOT) private SubscriptionState subscriptionState = SubscriptionState.ON; + /* + * Active Period starting day of the year. Calculated from + * activePeriodStart. + */ + private Integer startActivePeriodDayOfYear; + + /* + * Active Period ending day of the year. Calculated from activePeriodEnd. + */ + private Integer endActivePeriodDayOfYear; + /** Flag stating if the object should be updated */ private boolean shouldUpdate = false; @@ -433,6 +445,7 @@ public abstract class RecurringSubscription @Override public void setActivePeriodStart(Date activePeriodStart) { this.activePeriodStart = activePeriodStart; + this.startActivePeriodDayOfYear = null; } /** @@ -454,56 +467,35 @@ public abstract class RecurringSubscription @Override public void setActivePeriodEnd(Date activePeriodEnd) { this.activePeriodEnd = activePeriodEnd; + this.endActivePeriodDayOfYear = null; } - private Calendar getActivePeriodStart(Calendar base) { - // active period values are month and day of month only, use base - // Calendar for active period year - Calendar activePeriodStartCal = TimeUtil.newCalendar(activePeriodStart); - TimeUtil.minCalendarFields(activePeriodStartCal, Calendar.MILLISECOND, - Calendar.SECOND, Calendar.MINUTE, Calendar.HOUR_OF_DAY); - activePeriodStartCal.set(Calendar.YEAR, base.get(Calendar.YEAR)); - return activePeriodStartCal; + private Integer getStartActivePeriodDayOfYear() { + if (startActivePeriodDayOfYear == null && activePeriodStart != null) { + startActivePeriodDayOfYear = TimeUtil + .newCalendar(activePeriodStart).get(Calendar.DAY_OF_YEAR); + } + return startActivePeriodDayOfYear; } - private Calendar getActivePeriodEnd(Calendar base) { - // active period values are month and day of month only, use base - // Calendar for active period year - Calendar activePeriodEndCal = TimeUtil.newCalendar(activePeriodEnd); - TimeUtil.minCalendarFields(activePeriodEndCal, Calendar.MILLISECOND, - Calendar.SECOND, Calendar.MINUTE, Calendar.HOUR_OF_DAY); - activePeriodEndCal.set(Calendar.YEAR, base.get(Calendar.YEAR)); - return activePeriodEndCal; + private Integer getEndActivePeriodDayOfYear() { + if (endActivePeriodDayOfYear == null && activePeriodEnd != null) { + endActivePeriodDayOfYear = TimeUtil.newCalendar(activePeriodEnd) + .get(Calendar.DAY_OF_YEAR); + } + return endActivePeriodDayOfYear; } @Override public Calendar calculateStart(Calendar startConstraint) { - Calendar realStart = null; - boolean hasActivePeriodStart = activePeriodStart != null; - if (hasActivePeriodStart) { - realStart = getActivePeriodStart(startConstraint); - if (realStart.before(startConstraint)) { - realStart = startConstraint; - } - } else { - realStart = startConstraint; - } - return TimeUtil.newCalendar(TimeUtil.max(subscriptionStart, realStart)); + return TimeUtil.newCalendar(TimeUtil.max(subscriptionStart, + startConstraint)); } @Override public Calendar calculateEnd(Calendar endConstraint) { - Calendar realEnd = null; - boolean hasActivePeriodEnd = activePeriodEnd != null; - if (hasActivePeriodEnd) { - realEnd = getActivePeriodEnd(endConstraint); - if (realEnd.after(endConstraint)) { - realEnd = endConstraint; - } - } else { - realEnd = endConstraint; - } - return TimeUtil.newCalendar(TimeUtil.min(subscriptionEnd, realEnd)); + return TimeUtil.newCalendar(TimeUtil + .min(subscriptionEnd, endConstraint)); } /** @@ -930,9 +922,8 @@ public abstract class RecurringSubscription // At this point the subscription is in the ON state Calendar cal = TimeUtil.newGmtCalendar(); - Date today = cal.getTime(); - if (inWindow(today)) { + if (inActivePeriodWindow(cal)) { return SubscriptionStatus.ACTIVE; } @@ -956,54 +947,33 @@ public abstract class RecurringSubscription * @param checkDate * @return */ - public boolean shouldScheduleForTime(Date checkDate) { - if (!isExpired(checkDate) && inWindow(checkDate)) { + public boolean shouldScheduleForTime(Calendar checkCal) { + if (!isExpired(checkCal.getTime()) && inActivePeriodWindow(checkCal)) { return true; } return false; } - private boolean inWindow(Date checkDate) { + public boolean inActivePeriodWindow(Calendar checkDate) { if (activePeriodStart == null && activePeriodEnd == null) { + // no active period set return true; - } else if (activePeriodStart != null && activePeriodEnd != null) { + } else { + Integer startDay = getStartActivePeriodDayOfYear(); + Integer endDay = getEndActivePeriodDayOfYear(); + int checkDay = checkDate.get(Calendar.DAY_OF_YEAR); - Calendar startCal = TimeUtil.newGmtCalendar(); - startCal.setTime(activePeriodStart); - startCal = TimeUtil.minCalendarFields(startCal, - Calendar.HOUR_OF_DAY, Calendar.MINUTE, Calendar.SECOND, - Calendar.MILLISECOND); - // add the current year for true comparison - startCal = TimeUtil.addCurrentYearCalendar(startCal); - - activePeriodStart = startCal.getTime(); - - Calendar endCal = TimeUtil.newGmtCalendar(); - endCal.setTime(activePeriodEnd); - endCal = TimeUtil.maxCalendarFields(endCal, Calendar.HOUR_OF_DAY, - Calendar.MINUTE, Calendar.SECOND, Calendar.MILLISECOND); - // add the current year for true comparison - endCal = TimeUtil.addCurrentYearCalendar(endCal); - // If the period crosses a year boundary, add a year to the end - if (endCal.before(startCal)) { - endCal.add(Calendar.YEAR, 1); + boolean isAfterPeriodStart = startDay <= checkDay; + boolean isBeforePeriodEnd = checkDay < endDay; + boolean periodCrossesYearBoundary = endDay < startDay; + + if (periodCrossesYearBoundary) { + return isAfterPeriodStart || isBeforePeriodEnd; + } else { + return isAfterPeriodStart && isBeforePeriodEnd; } - - activePeriodEnd = endCal.getTime(); - - // Only concerned with month and day, need to set the - // years on equal footing for comparison sake. - Calendar c = TimeUtil.newGmtCalendar(); - c.setTime(checkDate); - // set the date to compare with the current date from the start - c.set(Calendar.YEAR, startCal.get(Calendar.YEAR)); - Date date = c.getTime(); - - return (activePeriodStart.before(date) && activePeriodEnd - .after(date)); } - return false; } @Override diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/Subscription.java b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/Subscription.java index 9c29cb48e5..846f3d5675 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/Subscription.java +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/Subscription.java @@ -43,9 +43,10 @@ import com.raytheon.uf.common.datadelivery.registry.Utils.SubscriptionStatus; * Jul 11, 2013 2106 djohnson SubscriptionPriority allows comparison. * Sept 30,2013 1797 dhladky Abstracted and genericized. * Oct 23, 2013 2484 dhladky Unique ID for subscriptions updated. - * Nov 14, 2013 2548 mpduff Add a subscription type information. - * Jan 08, 2014 2615 bgonzale Added calculate start and calculate end methods. - * Jan 14, 2014 2459 mpduff Change Subscription status code + * Nov 14, 2013 2548 mpduff Add a subscription type information. + * Jan 08, 2014 2615 bgonzale Added calculate start and calculate end methods. + * Jan 14, 2014 2459 mpduff Change Subscription status code + * Jan 24, 2013 2709 bgonzale Added method inActivePeriodWindow. * * * @@ -339,6 +340,17 @@ public interface Subscription { */ Calendar calculateEnd(Calendar endConstraint); + /** + * Check if the given value's month/day is in the Subscription's active + * window. + * + * @param time + * time with month/day value to check. + * + * @return true if in the active period; false otherwise + */ + boolean inActivePeriodWindow(Calendar time); + /** * isNotify flag for subscription. * diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthManager.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthManager.java index 5bbb8a9e3f..61b928db3a 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthManager.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthManager.java @@ -139,6 +139,7 @@ import com.raytheon.uf.edex.registry.ebxml.exception.EbxmlRegistryException; * Jan 14, 2014 2692 dhladky Bad Point scheduling final Empty list. * Jan 14, 2014 2459 mpduff Change to subscription status. * Jan 25, 2014 2636 mpduff Don't do an initial adhoc query for a new subscription. + * Jan 24, 2013 2709 bgonzale Before scheduling adhoc, check if in active period window. * * * @@ -677,11 +678,13 @@ public abstract class BandwidthManager plan.getPlanStart()).getTime(); Date subscriptionValidEnd = subscription.calculateEnd( plan.getPlanEnd()).getTime(); - Date now = TimeUtil.newDate(); + Calendar nowCalendar = TimeUtil.newCalendar(); + Date now = nowCalendar.getTime(); if ((now.equals(subscriptionValidStart) || now .after(subscriptionValidStart)) - && now.before(subscriptionValidEnd)) { + && now.before(subscriptionValidEnd) + && subscription.inActivePeriodWindow(nowCalendar)) { unscheduled = scheduleAdhoc(adhoc); } else { statusHandler.info(String.format( diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/EdexBandwidthManager.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/EdexBandwidthManager.java index c2f6bca0ef..fd5e8c2747 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/EdexBandwidthManager.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/EdexBandwidthManager.java @@ -115,6 +115,7 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.util.BandwidthUtil; * Jan 13, 2014 2679 dhladky Small Point data updates. * Jan 14, 2014 2692 dhladky AdhocSubscription handler * Jan 20, 2013 2398 dhladky Fixed rescheduling beyond active period/expired window. + * Jan 24, 2013 2709 bgonzale Changed parameter to shouldScheduleForTime to a Calendar. * * * @@ -312,25 +313,19 @@ public abstract class EdexBandwidthManager // TODO Check if we need to set sub to "OFF" state and save to // registry if (((RecurringSubscription) subscription) - .shouldScheduleForTime(next.getTime())) { + .shouldScheduleForTime(next)) { // Since subscriptions are based on cycles in a day, add - // one - // day - // to the - // completed BandwidthSubscription to get the next days - // retrieval. + // one day to the completed BandwidthSubscription to get + // the next days retrieval. // Now check if that BandwidthSubscription has already - // been - // scheduled. + // been scheduled. BandwidthSubscription a = bandwidthDao .getBandwidthSubscription(dao.getRegistryId(), next); if (a == null) { // Create the new BandwidthSubscription record with - // the - // next - // time.. + // the next time.. a = bandwidthDao.newBandwidthSubscription(subscription, next); diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthDaoUtil.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthDaoUtil.java index 2138c208ea..b40936ec24 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthDaoUtil.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthDaoUtil.java @@ -79,6 +79,9 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.retrieval.RetrievalStatus; * Jan 08, 2014 2615 bgonzale Refactored getRetrievalTimes into RecurringSubscription * calculateStart and calculateEnd methods. * Jan 24, 2014 2636 mpduff Refactored retrieval time generation. + * Jan 24, 2013 2709 bgonzale Added inActivePeriodWindow check during retrieval time calculations + * because the calculate start and end time methods no longer use + * active period. * * * @author djohnson @@ -173,11 +176,11 @@ public class BandwidthDaoUtil { Calendar planStart = plan.getPlanStart(); // starting time when when subscription is first valid for scheduling - // based on plan start, subscription start, and active period start. + // based on plan start and subscription start. Calendar subscriptionCalculatedStart = subscription .calculateStart(planStart); // end time when when subscription is last valid for scheduling based on - // plan end, subscription end, and active period end. + // plan end and subscription end. Calendar subscriptionCalculatedEnd = subscription.calculateEnd(planEnd); if (statusHandler.isPriorityEnabled(Priority.DEBUG)) { statusHandler.debug("**** PlanStart: " + planStart.getTime()); @@ -218,7 +221,9 @@ public class BandwidthDaoUtil { **/ // Subscription Start and End time first if (time.after(subscriptionCalculatedEnd) - || time.before(start)) { + || time.before(start) + || !subscription + .inActivePeriodWindow(time)) { // don't schedule this retrieval time, // outside subscription window continue; diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/res/spring/retrieval-datadelivery-monolithic.xml b/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/res/spring/retrieval-datadelivery-monolithic.xml new file mode 100644 index 0000000000..1ee204a9ad --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/res/spring/retrieval-datadelivery-monolithic.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/unit/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthDaoUtilTest.java b/tests/unit/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthDaoUtilTest.java index e06437442c..ad58d3dadf 100644 --- a/tests/unit/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthDaoUtilTest.java +++ b/tests/unit/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthDaoUtilTest.java @@ -30,6 +30,7 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Collection; @@ -43,6 +44,7 @@ import java.util.TreeSet; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.mockito.Mockito; import com.google.common.collect.Maps; import com.raytheon.uf.common.datadelivery.bandwidth.data.BandwidthMap; @@ -58,6 +60,7 @@ import com.raytheon.uf.common.localization.LocalizationFile; import com.raytheon.uf.common.localization.PathManagerFactory; import com.raytheon.uf.common.localization.PathManagerFactoryTest; import com.raytheon.uf.common.registry.handler.RegistryObjectHandlersUtil; +import com.raytheon.uf.common.time.SimulatedTime; import com.raytheon.uf.common.time.util.TimeUtil; import com.raytheon.uf.common.time.util.TimeUtilTest; import com.raytheon.uf.edex.datadelivery.bandwidth.InMemoryBandwidthBucketDao; @@ -86,6 +89,7 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.retrieval.RetrievalStatus; * Sep 25, 2013 1797 dhladky separated time and gridded time * Jan 07, 2014 2636 mpduff Removed dataset availability offset calculator (not used). * Jan 08, 2014 2615 bgonzale Updated test. + * Jan 26, 2014 2709 bgonzale Added tests for year scheduling boundary. * * * @@ -97,10 +101,9 @@ public class BandwidthDaoUtilTest { private final IBandwidthDao mockDao = mock(IBandwidthDao.class); - private final RetrievalManager retrievalManager = mock(RetrievalManager.class); + private RetrievalManager retrievalManager; - private final BandwidthDaoUtil bandwidthDaoUtil = new BandwidthDaoUtil( - mockDao, retrievalManager); + private BandwidthDaoUtil bandwidthDaoUtil; private BandwidthMap map; @@ -133,6 +136,9 @@ public class BandwidthDaoUtilTest { Map retrievalPlans = Maps .newEnumMap(Network.class); retrievalPlans.put(Network.OPSNET, plan); + retrievalManager = Mockito.spy(new RetrievalManager(mockDao, + new Object())); + bandwidthDaoUtil = new BandwidthDaoUtil(mockDao, retrievalManager); when(retrievalManager.getRetrievalPlans()).thenReturn(retrievalPlans); // Just used to initialize the retrieval plans that are used on the mock @@ -147,6 +153,142 @@ public class BandwidthDaoUtilTest { public void tearDown() { TimeUtilTest.resumeTime(); } + + private Calendar createCal(int year, int dayOfYear) { + Calendar cal = TimeUtil.newCalendar(); + cal.set(Calendar.YEAR, year); + cal.set(Calendar.DAY_OF_YEAR, dayOfYear); + return cal; + } + + /* + * + */ + private Subscription createOverYearBoundary(int planStart, + int planStartYear, int subStart, int subStartYear, int subEnd, + int subEndYear, int activeStart, int activeStartYear, + int activeEnd, int activeEndYear, int planDays) { + Calendar planStartDay = createCal(planStartYear, planStart); + Calendar subStartDay = createCal(subStartYear, subStart); + Calendar subEndDay = createCal(subEndYear, subEnd); + Calendar activeStartDay = createCal(activeStartYear, activeStart); + Calendar activeEndDay = createCal(activeEndYear, activeEnd); + + // setup plan with specific start time for this test. + SimulatedTime.getSystemTime().setTime(planStartDay.getTimeInMillis()); + map.getRoute(Network.OPSNET).setPlanDays(planDays); + retrievalManager.getPlan(Network.OPSNET).setMap(map); + // re-init plans with new simulated time + retrievalManager.initRetrievalPlans(); + return new SubscriptionBuilder() + .withSubscriptionStart(subStartDay.getTime()) + .withActivePeriodStart(activeStartDay.getTime()) + .withActivePeriodEnd(activeEndDay.getTime()) + .withSubscriptionEnd(subEndDay.getTime()).build(); + } + + @Test + public void testActivePeriodOverYearBoundary() { + int y1970 = 1970; + int y1971 = 1971; + int planStart = 364; + int subStart = 364; + int activeStart = 365; + int activeEnd = 2; + int subEnd = 3; + int planDays = 5; + Subscription subscription = createOverYearBoundary(planStart, y1970, + subStart, y1970, subEnd, y1971, activeStart, y1970, activeEnd, + y1971, planDays); + ((GriddedTime) subscription.getTime()).setCycleTimes(Arrays.asList( + Integer.valueOf(9), Integer.valueOf(0))); + + TreeSet cycles = new TreeSet( + ((GriddedTime) subscription.getTime()).getCycleTimes()); + + SortedSet subscriptionTimes = bandwidthDaoUtil + .getRetrievalTimes(subscription, cycles); + + List calendarDaysOfTheYear = createCalendarListForSpecifiedDaysOfTheYear( + Arrays.asList(365), y1970); + calendarDaysOfTheYear + .addAll(createCalendarListForSpecifiedDaysOfTheYear( + Arrays.asList(01), y1971)); + + verifySubscriptionTimesContainsCyclesForSpecifiedCalendarDays( + calendarDaysOfTheYear, cycles, subscriptionTimes); + } + + @Test + public void testActivePeriodJustBeforeYearBoundary() { + int y1970 = 1970; + int y1971 = 1971; + int planStart = 362; + int subStart = 362; + int activeStart = 363; + int activeEnd = 365; + int subEnd = 2; + int planDays = 5; + Subscription subscription = createOverYearBoundary(planStart, y1970, + subStart, y1970, subEnd, y1971, activeStart, y1970, activeEnd, + y1971, planDays); + ((GriddedTime) subscription.getTime()).setCycleTimes(Arrays.asList( + Integer.valueOf(9), Integer.valueOf(0))); + + TreeSet cycles = new TreeSet( + ((GriddedTime) subscription.getTime()).getCycleTimes()); + + SortedSet subscriptionTimes = bandwidthDaoUtil + .getRetrievalTimes(subscription, cycles); + + List calendarDaysOfTheYear = createCalendarListForSpecifiedDaysOfTheYear( + Arrays.asList(363, 364), y1970); + + verifySubscriptionTimesContainsCyclesForSpecifiedCalendarDays( + calendarDaysOfTheYear, cycles, subscriptionTimes); + } + + @Test + public void testActivePeriodJustAfterYearBoundary() { + int y1970 = 1970; + int y1971 = 1971; + int planStart = 364; + int subStart = 364; + int activeStart = 1; + int activeEnd = 3; + int subEnd = 4; + int planDays = 6; + Subscription subscription = createOverYearBoundary(planStart, y1970, + subStart, y1970, subEnd, y1971, activeStart, y1970, activeEnd, + y1971, planDays); + ((GriddedTime) subscription.getTime()).setCycleTimes(Arrays.asList( + Integer.valueOf(9), Integer.valueOf(0))); + + TreeSet cycles = new TreeSet( + ((GriddedTime) subscription.getTime()).getCycleTimes()); + + SortedSet subscriptionTimes = bandwidthDaoUtil + .getRetrievalTimes(subscription, cycles); + + List calendarDaysOfTheYear = createCalendarListForSpecifiedDaysOfTheYear( + Arrays.asList(1, 2), y1971); + + verifySubscriptionTimesContainsCyclesForSpecifiedCalendarDays( + calendarDaysOfTheYear, cycles, subscriptionTimes); + } + + private List createCalendarListForSpecifiedDaysOfTheYear( + Collection daysOfTheYear, int year) { + List calendarList = new ArrayList( + daysOfTheYear.size()); + for (int dayOfTheYear : daysOfTheYear) { + Calendar cal = TimeUtil.newCalendar(); + cal.set(Calendar.YEAR, year); + cal.set(Calendar.DAY_OF_YEAR, dayOfTheYear); + calendarList.add(cal); + } + return calendarList; + } @Test public void testGetRetrievalTimesReturnsBaseReferenceTimesInPlanWindow() { @@ -165,7 +307,7 @@ public class BandwidthDaoUtilTest { SortedSet subscriptionTimes = bandwidthDaoUtil .getRetrievalTimes(subscription, cycles); - final List daysOfTheYear = Arrays.asList(3, 4); + final List daysOfTheYear = Arrays.asList(3); verifySubscriptionTimesContainsCyclesForSpecifiedDays(daysOfTheYear, cycles, subscriptionTimes); } @@ -257,10 +399,15 @@ public class BandwidthDaoUtilTest { .getRetrievalTimes(subscription, interval); // Expected size is two per hour (0 and 30 minutes), for every hour, - // over the retrieval plan days (2), plus 1 because the retrieval plan - // ends on a 0 minute time - final int expectedSize = TimeUtil.HOURS_PER_DAY * plan.getPlanDays() - * 2 + 1; + // over the retrieval plan days (2), minus the hours for the last day + // because active period is exclusive of the last day (ending hour + // constraint for the last day is 00Z) + Calendar activeEnd = (Calendar) plan.getPlanEnd().clone(); + activeEnd = TimeUtil.minCalendarFields(activeEnd, Calendar.MILLISECOND, + Calendar.SECOND, Calendar.MINUTE, Calendar.HOUR_OF_DAY); + long subPeriodInHours = (activeEnd.getTimeInMillis() - plan + .getPlanStart().getTimeInMillis()) / TimeUtil.MILLIS_PER_HOUR; + final int expectedSize = (int) (subPeriodInHours * 2); assertThat(subscriptionTimes, hasSize(expectedSize)); // Make sure we have the expected number of 0 and 30 minute scheduled @@ -277,7 +424,7 @@ public class BandwidthDaoUtilTest { } final int halfTheTimes = subscriptionTimes.size() / 2; - assertThat(numberOfZeroMinuteTimes, is(equalTo(halfTheTimes + 1))); + assertThat(numberOfZeroMinuteTimes, is(equalTo(halfTheTimes))); assertThat(numberOfThirtyMinuteTimes, is(equalTo(halfTheTimes))); // Would be nice to verify the days and hours, but the cycle based tests @@ -311,6 +458,44 @@ public class BandwidthDaoUtilTest { } } + /** + * Verifies the subscription times contains the cycles for the specified + * days. + * + * @param daysOfTheYear + * @param cycles + * @param subscriptionTimes + */ + private void verifySubscriptionTimesContainsCyclesForSpecifiedCalendarDays( + Collection daysOfTheYear, Collection cycles, + SortedSet subscriptionTimes) { + boolean success = true; + StringBuilder sb = new StringBuilder( + "Expected to find retrieval times: "); + int countOfTimes = 0; + + for (Calendar dayOfTheYear : daysOfTheYear) { + for (Integer cycle : cycles) { + Calendar cal = (Calendar) dayOfTheYear.clone(); + TimeUtil.minCalendarFields(cal, Calendar.MILLISECOND, + Calendar.SECOND, Calendar.MINUTE); + cal.set(Calendar.HOUR_OF_DAY, cycle); + success = success && subscriptionTimes.contains(cal); + ++countOfTimes; + sb.append(BandwidthUtil.format(cal)).append( + String.format(" %1$tZ ", cal)); + } + } + sb.append("\nIn: "); + for (Calendar subTime : subscriptionTimes) { + sb.append(BandwidthUtil.format(subTime)).append( + String.format(" %1$tZ ", subTime)); + } + assertTrue(sb.toString(), success); + assertTrue(sb.toString(), + countOfTimes == subscriptionTimes.size()); + } + /** * Verifies the subscription times do not contain the cycles for the * specified days.