// Created by plusminus on 09:58:34 - 04.02.2009
package org.androad.sys.serverdowntime.adt;
import java.text.ParseException;
import junit.framework.Assert;
import org.androad.sys.serverdowntime.exc.DowntimeHasAlreadyPassedException;
import org.androad.util.TimeUtils;
import org.androad.util.constants.TimeConstants;
public class Downtime implements Comparable<Downtime>, TimeConstants {
// ===========================================================
// Constants
// ===========================================================
// ===========================================================
// Fields
// ===========================================================
private final Period mPeriod;
private final int mDurationSeconds;
private final long mStartTimestamp;
private final String mDescription;
// ===========================================================
// Constructors
// ===========================================================
public Downtime(final String pPeriodString, final String pDurationString, final String pStartTimeString, final String pDescription) throws ParseException {
this(Period.fromName(pPeriodString), TimeUtils.durationTimeString(pDurationString), TimeUtils.convertUTCStringToTimestamp(pStartTimeString), pDescription);
}
public Downtime(final Period pPeriod, final int pDurationSeconds, final long pStartTimestamp, final String pDescription) {
this.mPeriod = pPeriod;
this.mDurationSeconds = pDurationSeconds;
this.mStartTimestamp = pStartTimestamp;
this.mDescription = pDescription;
}
// ===========================================================
// Getter & Setter
// ===========================================================
public Period getPeriod() {
return this.mPeriod;
}
public int getDurationSeconds() {
return this.mDurationSeconds;
}
public long getStartTimestamp() {
return this.mStartTimestamp;
}
public String getDescription() {
return this.mDescription;
}
public long getNextOccurenceStartingFrom(final long pStartSearchFrom) throws DowntimeHasAlreadyPassedException {
/* Once occurring downtimes that have passed. */
if(this.mPeriod == Period.ONCE && pStartSearchFrom > this.mStartTimestamp + this.mDurationSeconds) {
throw new DowntimeHasAlreadyPassedException();
}
/* Future starting Downtimes. */
if(this.mStartTimestamp > pStartSearchFrom) {
return this.mStartTimestamp;
}
final long periodLengthMilliseconds;
/* Convert the Period from seconds to milliseconds. */
switch(this.mPeriod){
case ANUAL:
periodLengthMilliseconds = SECONDSPERYEAR * 1000;
break;
case MONTHLY:
periodLengthMilliseconds = SECONDSPERMONTH * 1000;
break;
case WEEKLY:
periodLengthMilliseconds = SECONDSPERWEEK * 1000;
break;
case DAILY:
periodLengthMilliseconds = SECONDSPERDAY * 1000;
break;
default:
throw new DowntimeHasAlreadyPassedException();
}
/* Calculate the startime of the period directly before pStartSearchFrom. */
final long diffMilliSeconds = pStartSearchFrom - this.mStartTimestamp;
final int periodsPassed = (int)(diffMilliSeconds / periodLengthMilliseconds);
final long startTimeOfPeriodBeforeSearchFrom = this.mStartTimestamp + periodLengthMilliseconds * periodsPassed;
Assert.assertTrue(pStartSearchFrom > startTimeOfPeriodBeforeSearchFrom);
/* Check if pStartSearchFrom is inside that period. */
if(pStartSearchFrom < startTimeOfPeriodBeforeSearchFrom + this.mDurationSeconds) {
return startTimeOfPeriodBeforeSearchFrom;
}
/* Otherwise return the next period start. */
return startTimeOfPeriodBeforeSearchFrom + periodLengthMilliseconds;
}
// ===========================================================
// Methods from SuperClass/Interfaces
// ===========================================================
@Override
public int compareTo(final Downtime another) {
return (int)(this.mStartTimestamp - another.mStartTimestamp);
}
@Override
public String toString() {
return new StringBuilder()
.append("Period: ")
.append(this.mPeriod.name())
.append(" Timestamp: ")
.append(TimeUtils.convertTimestampToUTCString(this.mStartTimestamp))
.append(" Duration: ")
.append(this.mDurationSeconds)
.append(" Description: ")
.append(this.mDescription).toString();
}
// ===========================================================
// Methods
// ===========================================================
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
}