001/* 002 * #%L 003 * Netarchivesuite - harvester 004 * %% 005 * Copyright (C) 2005 - 2018 The Royal Danish Library, 006 * the National Library of France and the Austrian National Library. 007 * %% 008 * This program is free software: you can redistribute it and/or modify 009 * it under the terms of the GNU Lesser General Public License as 010 * published by the Free Software Foundation, either version 2.1 of the 011 * License, or (at your option) any later version. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Lesser Public License for more details. 017 * 018 * You should have received a copy of the GNU General Lesser Public 019 * License along with this program. If not, see 020 * <http://www.gnu.org/licenses/lgpl-2.1.html>. 021 * #L% 022 */ 023 024package dk.netarkivet.harvester.datamodel; 025 026import java.util.Calendar; 027import java.util.Date; 028import java.util.GregorianCalendar; 029 030import dk.netarkivet.common.exceptions.ArgumentNotValid; 031 032/** 033 * This class implements a frequency of a number of weeks. 034 */ 035 036public class WeeklyFrequency extends Frequency { 037 038 /** The minute of the hour the event should happen at. */ 039 private int minute; 040 /** The hour of the day the event should happen at. */ 041 private int hour; 042 /** The day of the week the event should happen at. */ 043 private int dayOfWeek; 044 045 /** 046 * Create a new weekly frequency that happens every numUnits weeks, anytime. 047 * 048 * @param numUnits Number of weeks from event to event. 049 * @throws ArgumentNotValid if numUnits if 0 or negative 050 */ 051 public WeeklyFrequency(int numUnits) { 052 super(numUnits, true); 053 } 054 055 /** 056 * Create a new weekly frequency that happens every numUnits days, on the given day of week, hour, and minute. 057 * 058 * @param numUnits Number of days from event to event. 059 * @param dayOfWeek Which day of the week this event should happen. Sunday is day 1 of the week. 060 * @param hour The hour on which the event should happen. 061 * @param minute The minute of hour on which the event should happen. 062 * @throws ArgumentNotValid if numUnits if 0 or negative or dayOfWeek <1=SUNDAY >7=SATURDAY or hour is <0 or >23 or 063 * minutes is <0 or >59 064 */ 065 public WeeklyFrequency(int numUnits, int dayOfWeek, int hour, int minute) { 066 super(numUnits, false); 067 Calendar cal = GregorianCalendar.getInstance(); 068 if (dayOfWeek < cal.getMinimum(Calendar.DAY_OF_WEEK) || dayOfWeek > cal.getMaximum(Calendar.DAY_OF_WEEK)) { 069 throw new ArgumentNotValid("Day in week must be in legal range '" + cal.getMinimum(Calendar.DAY_OF_WEEK) 070 + "' to '" + cal.getMaximum(Calendar.DAY_OF_WEEK) + "'"); 071 } 072 if (hour < cal.getMinimum(Calendar.HOUR_OF_DAY) || hour > cal.getMaximum(Calendar.HOUR_OF_DAY)) { 073 throw new ArgumentNotValid("Hour of day must be in legal range '" + cal.getMinimum(Calendar.HOUR_OF_DAY) 074 + "' to '" + cal.getMaximum(Calendar.HOUR_OF_DAY) + "'"); 075 } 076 if (minute < cal.getMinimum(Calendar.MINUTE) || minute > cal.getMaximum(Calendar.MINUTE)) { 077 throw new ArgumentNotValid("Minute must be in legal range '" + cal.getMinimum(Calendar.MINUTE) + "' to '" 078 + cal.getMaximum(Calendar.MINUTE) + "'"); 079 } 080 081 this.dayOfWeek = dayOfWeek; 082 this.hour = hour; 083 this.minute = minute; 084 } 085 086 /** 087 * Given when the last event happened, tell us when the next event should happen (even if the new event is in the 088 * past). 089 * <p> 090 * The time of the next event is guaranteed to be later that lastEvent. For certain frequencies (e.g. once a day, 091 * any time of day), the time of the next event is derived from lastEvent, for others (e.g. once a day at 13:00) the 092 * time of the next event is the first matching time after lastEvent. 093 * 094 * @param lastEvent A time from which the next event should be calculated. 095 * @return At what point the event should happen next. 096 */ 097 public Date getNextEvent(Date lastEvent) { 098 ArgumentNotValid.checkNotNull(lastEvent, "lastEvent"); 099 100 Calendar last = new GregorianCalendar(); 101 last.setTime(getFirstEvent(lastEvent)); 102 last.add(Calendar.WEEK_OF_YEAR, getNumUnits()); 103 return getFirstEvent(last.getTime()); 104 } 105 106 /** 107 * Given a starting time, tell us when the first event should happen. 108 * 109 * @param startTime The earliest time the event can happen. 110 * @return At what point the event should happen the first time. 111 */ 112 public Date getFirstEvent(Date startTime) { 113 ArgumentNotValid.checkNotNull(startTime, "startTime"); 114 115 if (isAnytime()) { 116 return startTime; 117 } 118 Calendar start = new GregorianCalendar(); 119 start.setTime(startTime); 120 start.set(Calendar.MINUTE, minute); 121 start.set(Calendar.HOUR_OF_DAY, hour); 122 start.set(Calendar.DAY_OF_WEEK, dayOfWeek); 123 if (start.getTime().before(startTime)) { 124 start.add(Calendar.WEEK_OF_YEAR, 1); 125 } 126 return start.getTime(); 127 128 } 129 130 /** 131 * If not anytime, the minute at which events should start. 132 * 133 * @return the minute 134 */ 135 public int getMinute() { 136 return minute; 137 } 138 139 /** 140 * If not anytime, the hour at which events should start. 141 * 142 * @return the hour 143 */ 144 public int getHour() { 145 return hour; 146 } 147 148 /** 149 * If not anytime, the day in the week at which events should start. 150 * 151 * @return the day. Sunday=1 152 */ 153 public int getDayOfWeek() { 154 return dayOfWeek; 155 } 156 157 /** 158 * Autogenerated equals. 159 * 160 * @param o The object to compare with 161 * @return Whether objects are equal 162 */ 163 public boolean equals(Object o) { 164 if (this == o) { 165 return true; 166 } 167 if (!(o instanceof WeeklyFrequency)) { 168 return false; 169 } 170 if (!super.equals(o)) { 171 return false; 172 } 173 174 final WeeklyFrequency weeklyFrequency = (WeeklyFrequency) o; 175 176 if (isAnytime()) { 177 return true; 178 } 179 180 if (dayOfWeek != weeklyFrequency.dayOfWeek) { 181 return false; 182 } 183 if (hour != weeklyFrequency.hour) { 184 return false; 185 } 186 if (minute != weeklyFrequency.minute) { 187 return false; 188 } 189 190 return true; 191 } 192 193 /** 194 * Autogenerated hashcode method. 195 * 196 * @return the hashcode 197 */ 198 public int hashCode() { 199 int result = super.hashCode(); 200 result = 29 * result + minute; 201 result = 29 * result + hour; 202 result = 29 * result + dayOfWeek; 203 return result; 204 } 205 206 /** 207 * Return the exact minute this event should happen on, or null if this is an anyTime event or doesn't define what 208 * minute it should happen on. 209 * 210 * @return the exact minute this event should happen on 211 */ 212 public Integer getOnMinute() { 213 if (!isAnytime()) { 214 return minute; 215 } 216 return null; 217 } 218 219 /** 220 * Return the exact hour event should happen on, or null if this is an anyTime event or doesn't define what hour it 221 * should happen on. 222 * 223 * @return the exact hour event should happen on 224 */ 225 public Integer getOnHour() { 226 if (!isAnytime()) { 227 return hour; 228 } 229 return null; 230 } 231 232 /** 233 * Return the exact day of week event should happen on, or null if this is an anyTime event or doesn't define what 234 * day of week it should happen on. 235 * 236 * @return the exact day of week event should happen on 237 */ 238 public Integer getOnDayOfWeek() { 239 if (!isAnytime()) { 240 return dayOfWeek; 241 } 242 return null; 243 } 244 245 /** 246 * Return the exact day of month event should happen on, or null if this is an anyTime event or doesn't define what 247 * day of month it should happen on. 248 * 249 * @return null (always) 250 */ 251 public Integer getOnDayOfMonth() { 252 return null; 253 } 254 255 /** 256 * Return an integer that can be used to identify the kind of frequency. No two subclasses should use the same 257 * integer 258 * 259 * @return an integer that can be used to identify the kind of frequency 260 */ 261 public int ordinal() { 262 return TimeUnit.WEEKLY.ordinal(); 263 } 264 265 /** 266 * Human readable representation of this object. 267 * 268 * @return Human readable representation 269 */ 270 public String toString() { 271 if (isAnytime()) { 272 return "every " + getNumUnits() + " weeks"; 273 } 274 return "every " + getNumUnits() + " weeks, on weekday " + dayOfWeek + " at " + hour + ":" + minute; 275 } 276 277}