package org.celllife.function; import java.util.Calendar; import java.util.Comparator; import java.util.Date; import org.celllife.idart.database.hibernate.APIException; import org.celllife.idart.misc.DateFieldComparator; import org.celllife.idart.misc.iDARTUtil; /** * <code>DateRangeRule</code> represents a rule that can be evaluated against a * given date to determine whether the given date falls within the defined * range. * * A <code>DateRangeRule</code> consists of a Date representing a boundry, a * boolean which denotes whether that boundry is inclusive or not and a * <code>RangeSelectionEnum</code> which denotes which side of the boudry is * valid. * * Example usage: * * <pre> * /// define range before boundry and exclude boundry as part of range. * DateRangeRule beforeExclusive = new DateRangeRule(false, boundry, * RangeSelectionEnum.BEFORE_BOUNDRY); * /// define range between upper and lower boundry of which both are inclusive * DateRangeRule lower = new DateRangeRule(inclusiveLower, lowerBoundry, * RangeSelectionEnum.AFTER_BOUNDRY); * DateRangeRule upper = new DateRangeRule(inclusiveUpper, upperBoundry, * RangeSelectionEnum.BEFORE_BOUNDRY); * IRule<Date> between = new AndRule<Date>(lower, upper); * </pre> * * @see DateRuleFactory * @see IRule */ public class DateRule extends AbstractRule<Date> { public enum RangeSelectionEnum { BEFORE_BOUNDRY, BEFORE_BOUNDRY_INCLUSIVE, AFTER_BOUNDRY, AFTER_BOUNDRY_INCLUSIVE, } private Date boundry; private RangeSelectionEnum rangeSelection; private Comparator<Date> comparator; public DateRule() { super(); } public DateRule(Date boundry, RangeSelectionEnum restriction) { super(); this.boundry = boundry; this.rangeSelection = restriction; } @Override public boolean evaluate(Date candidate) { boolean evaluation; Date boundryEvaluation; if (boundry == null) { boundryEvaluation = new Date(); } else { boundryEvaluation = boundry; } switch (rangeSelection) { case BEFORE_BOUNDRY: evaluation = compare(candidate, boundryEvaluation) < 0; break; case BEFORE_BOUNDRY_INCLUSIVE: evaluation = compare(candidate, boundryEvaluation) <= 0; break; case AFTER_BOUNDRY: evaluation = compare(candidate, boundryEvaluation) > 0; break; case AFTER_BOUNDRY_INCLUSIVE: evaluation = compare(candidate, boundryEvaluation) >= 0; break; default: throw new APIException("Unknown date restriction."); } return evaluation; } private int compare(Date candidate, Date boundryEvaluation) { if (comparator == null) return candidate.compareTo(boundryEvaluation); else return comparator.compare(candidate, boundryEvaluation); } public Date getBoundry() { return boundry == null ? new Date() : boundry; } /** * Generates a text message that describes this restriction or uses the * description if one has been set. * * @param fmt * @return description of the restriction. */ @Override public String getDescription() { String date = ""; if (description != null && description.length() > 0) return parseDescriptionAndInsertDate(iDARTUtil.format(boundry)); if (boundry == null || DateFieldComparator.compare(boundry, new Date(), Calendar.DAY_OF_MONTH) == 0) { date = "today"; } else { date = iDARTUtil.format(boundry); } String message = "The date must be "; switch (rangeSelection) { case AFTER_BOUNDRY: message += "after "; break; case AFTER_BOUNDRY_INCLUSIVE: message += "on or after "; break; case BEFORE_BOUNDRY: message += "before "; break; case BEFORE_BOUNDRY_INCLUSIVE: message += "on or before "; break; default: break; } return message + date; } private String parseDescriptionAndInsertDate(String date) { return description.replaceAll("<date>", date); } public RangeSelectionEnum getRangeSelection() { return rangeSelection; } public void setBoundry(Date boundry) { this.boundry = boundry; } public void setRangeSelection(RangeSelectionEnum rangeSelection) { this.rangeSelection = rangeSelection; } public void setDateComparator(Comparator<Date> comparator) { this.comparator = comparator; } }