/**
* Licensed to Jasig under one or more contributor license
* agreements. See the NOTICE file distributed with this work
* for additional information regarding copyright ownership.
* Jasig licenses this file to you 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 org.jasig.schedassist.model;
import java.io.Serializable;
import java.util.Date;
import org.apache.commons.lang.time.DateUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Java bean to encapsulate the derived fields from a request to view
* an {@link IScheduleOwner}'s visible schedule.
*
* @author Nicholas Blair, nblair@doit.wisc.edu
* @version $Id: VisibleScheduleDisplayRequestDetails.java $
*/
public class VisibleScheduleRequestConstraints implements Serializable {
/**
*
*/
private static final long serialVersionUID = -2213895500433357816L;
public static final int WEEKS_PER_PAGE = 4;
private static Log LOG = LogFactory.getLog(VisibleScheduleRequestConstraints.class);
private final Date targetStartDate;
private final Date targetEndDate;
private final Integer nextWeekIndex;
private final Integer prevWeekIndex;
private final int constrainedWeekStart;
/**
*
* @param targetStartDate
* @param targetEndDate
* @param nextWeekIndex
* @param prevWeekIndex
* @param constrainedWeekStart
*/
private VisibleScheduleRequestConstraints(Date targetStartDate,
Date targetEndDate, Integer nextWeekIndex, Integer prevWeekIndex,
int constrainedWeekStart) {
this.targetStartDate = targetStartDate;
this.targetEndDate = targetEndDate;
this.nextWeekIndex = nextWeekIndex;
this.prevWeekIndex = prevWeekIndex;
this.constrainedWeekStart = constrainedWeekStart;
}
/**
* @return the targetStartDate
*/
public Date getTargetStartDate() {
return targetStartDate;
}
/**
* @return the targetEndDate
*/
public Date getTargetEndDate() {
return targetEndDate;
}
/**
* @return the nextWeekIndex
*/
public Integer getNextWeekIndex() {
return nextWeekIndex;
}
/**
* @return the prevWeekIndex
*/
public Integer getPrevWeekIndex() {
return prevWeekIndex;
}
/**
* @return the constrainedWeekStart
*/
public int getConstrainedWeekStart() {
return constrainedWeekStart;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("VisibleScheduleDisplayRequestDetails [targetStartDate=");
builder.append(targetStartDate);
builder.append(", targetEndDate=");
builder.append(targetEndDate);
builder.append(", nextWeekIndex=");
builder.append(nextWeekIndex);
builder.append(", prevWeekIndex=");
builder.append(prevWeekIndex);
builder.append(", constrainedWeekStart=");
builder.append(constrainedWeekStart);
builder.append("]");
return builder.toString();
}
/**
* Use this method to construct a {@link VisibleScheduleRequestConstraints}, which
* enforces all the appropriate constraints.
*
* @param owner the target {@link IScheduleOwner} for the request
* @param weekStart an integer representing the number of weeks forward to start the request, 0 meaning "now"
* @return an appropriate VisibleScheduleRequestConstraints for the owner.
*/
public static VisibleScheduleRequestConstraints newInstance(IScheduleOwner owner, int weekStart) {
VisibleWindow window = owner.getPreferredVisibleWindow();
int constrainedWeekStart = constrainWeekStartToWindow(window, weekStart);
Integer nextWeekIndex = calculateNextWeekIndex(window, constrainedWeekStart);
Integer prevWeekIndex = calculatePrevWeekIndex(window, constrainedWeekStart);
Date targetStartDate = resolveStartDate(new Date(), constrainedWeekStart);
Date targetEndDate = resolveEndDate(window, targetStartDate);
VisibleScheduleRequestConstraints result = new VisibleScheduleRequestConstraints(
targetStartDate,
targetEndDate,
nextWeekIndex,
prevWeekIndex,
constrainedWeekStart);
return result;
}
/**
*
* @param window
* @param weekStart
* @return return a weekStart value that falls within the VisibleWindow argument
*/
protected static int constrainWeekStartToWindow(VisibleWindow window, int weekStart) {
if(weekStart < 1) {
//forcibly set weekStart to 1 for 0 and negative values
return 0;
} else if(weekStart > window.getWindowWeeksEnd()) {
return window.getWindowWeeksEnd();
} else {
return weekStart;
}
}
/**
*
* @param window
* @param weekStart
* @return increment weekStart if possible; return null if incrementing would put weekStart outside visible window
*/
protected static Integer calculateNextWeekIndex(VisibleWindow window, int weekStart) {
if(weekStart < 1) {
//forcibly set weekStart to 1 for 0 and negative values
weekStart = 0;
}
final int maxPreferredWeekStart = window.getWindowWeeksEnd();
Integer result = null;
if(window.getWindowWeeksEnd() > WEEKS_PER_PAGE && weekStart < maxPreferredWeekStart) {
result = weekStart + WEEKS_PER_PAGE;
if(result > maxPreferredWeekStart) {
result = null;
}
}
if(LOG.isDebugEnabled()) {
LOG.debug("calculateNextWeekStart for " + window + ", weekStart=" + weekStart + " returns " + result);
}
return result;
}
/**
*
* @param window
* @param weekStart
* @return decrement weekStart if possible; return null if decrementing would put weekStart outside visible window
*/
protected static Integer calculatePrevWeekIndex(VisibleWindow window, int weekStart) {
Integer result = null;
// ignore weekStart less than 1 and greater than to owner preferred visble window end
if(weekStart > 0 && window.getWindowWeeksEnd() > WEEKS_PER_PAGE && weekStart < window.getWindowWeeksEnd()) {
result = weekStart - WEEKS_PER_PAGE < 1 ? 0 : weekStart - WEEKS_PER_PAGE;
} else if (weekStart == window.getWindowWeeksEnd()) {
if(window.getWindowWeeksEnd() > WEEKS_PER_PAGE) {
result = weekStart - WEEKS_PER_PAGE;
}
}
if(LOG.isDebugEnabled()) {
LOG.debug("calculatePrevWeekStart for " + window + ", weekStart=" + weekStart + " returns " + result);
}
return result;
}
/**
*
* @param referencePoint
* @param weekStart
* @return add an appropriate number of days and weeks to the referencepoint based on the weekStart argument
*/
protected static Date resolveStartDate(Date referencePoint, int weekStart) {
Date start = referencePoint;
// weekStart <= 0 means "now"
if(weekStart > 0) {
// first roll start to sunday
start = DateUtils.addDays(start, CommonDateOperations.numberOfDaysUntilSunday(start));
// subtract 1 from weekStart
start = DateUtils.addWeeks(start, weekStart - 1);
}
return start;
}
/**
*
* @param window
* @param start
* @return an appropriate end date that falls within the visible window
*/
protected static Date resolveEndDate(VisibleWindow window, Date start) {
Date preferredEnd = DateUtils.addWeeks(start, window.getWindowWeeksEnd());
Date end = DateUtils.addWeeks(start, WEEKS_PER_PAGE);
if(end.after(preferredEnd)) {
return preferredEnd;
} else {
return end;
}
}
}