001/* ======================================================================== 002 * JCommon : a free general purpose class library for the Java(tm) platform 003 * ======================================================================== 004 * 005 * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors. 006 * 007 * Project Info: http://www.jfree.org/jcommon/index.html 008 * 009 * This library is free software; you can redistribute it and/or modify it 010 * under the terms of the GNU Lesser General Public License as published by 011 * the Free Software Foundation; either version 2.1 of the License, or 012 * (at your option) any later version. 013 * 014 * This library is distributed in the hope that it will be useful, but 015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 017 * License for more details. 018 * 019 * You should have received a copy of the GNU Lesser General Public 020 * License along with this library; if not, write to the Free Software 021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 022 * USA. 023 * 024 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 025 * in the United States and other countries.] 026 * 027 * -------------------------- 028 * RelativeDayOfWeekRule.java 029 * -------------------------- 030 * (C) Copyright 2000-2003, by Object Refinery Limited and Contributors. 031 * 032 * Original Author: David Gilbert (for Object Refinery Limited); 033 * Contributor(s): -; 034 * 035 * $Id: RelativeDayOfWeekRule.java,v 1.6 2005/11/16 15:58:40 taqua Exp $ 036 * 037 * Changes (from 26-Oct-2001) 038 * -------------------------- 039 * 26-Oct-2001 : Changed package to com.jrefinery.date.*; 040 * 03-Oct-2002 : Fixed errors reported by Checkstyle (DG); 041 * 042 */ 043 044package org.jfree.date; 045 046/** 047 * An annual date rule that returns a date for each year based on (a) a 048 * reference rule; (b) a day of the week; and (c) a selection parameter 049 * (SerialDate.PRECEDING, SerialDate.NEAREST, SerialDate.FOLLOWING). 050 * <P> 051 * For example, Good Friday can be specified as 'the Friday PRECEDING Easter 052 * Sunday'. 053 * 054 * @author David Gilbert 055 */ 056public class RelativeDayOfWeekRule extends AnnualDateRule { 057 058 /** A reference to the annual date rule on which this rule is based. */ 059 private AnnualDateRule subrule; 060 061 /** 062 * The day of the week (SerialDate.MONDAY, SerialDate.TUESDAY, and so on). 063 */ 064 private int dayOfWeek; 065 066 /** Specifies which day of the week (PRECEDING, NEAREST or FOLLOWING). */ 067 private int relative; 068 069 /** 070 * Default constructor - builds a rule for the Monday following 1 January. 071 */ 072 public RelativeDayOfWeekRule() { 073 this(new DayAndMonthRule(), SerialDate.MONDAY, SerialDate.FOLLOWING); 074 } 075 076 /** 077 * Standard constructor - builds rule based on the supplied sub-rule. 078 * 079 * @param subrule the rule that determines the reference date. 080 * @param dayOfWeek the day-of-the-week relative to the reference date. 081 * @param relative indicates *which* day-of-the-week (preceding, nearest 082 * or following). 083 */ 084 public RelativeDayOfWeekRule(final AnnualDateRule subrule, 085 final int dayOfWeek, final int relative) { 086 this.subrule = subrule; 087 this.dayOfWeek = dayOfWeek; 088 this.relative = relative; 089 } 090 091 /** 092 * Returns the sub-rule (also called the reference rule). 093 * 094 * @return The annual date rule that determines the reference date for this 095 * rule. 096 */ 097 public AnnualDateRule getSubrule() { 098 return this.subrule; 099 } 100 101 /** 102 * Sets the sub-rule. 103 * 104 * @param subrule the annual date rule that determines the reference date 105 * for this rule. 106 */ 107 public void setSubrule(final AnnualDateRule subrule) { 108 this.subrule = subrule; 109 } 110 111 /** 112 * Returns the day-of-the-week for this rule. 113 * 114 * @return the day-of-the-week for this rule. 115 */ 116 public int getDayOfWeek() { 117 return this.dayOfWeek; 118 } 119 120 /** 121 * Sets the day-of-the-week for this rule. 122 * 123 * @param dayOfWeek the day-of-the-week (SerialDate.MONDAY, 124 * SerialDate.TUESDAY, and so on). 125 */ 126 public void setDayOfWeek(final int dayOfWeek) { 127 this.dayOfWeek = dayOfWeek; 128 } 129 130 /** 131 * Returns the 'relative' attribute, that determines *which* 132 * day-of-the-week we are interested in (SerialDate.PRECEDING, 133 * SerialDate.NEAREST or SerialDate.FOLLOWING). 134 * 135 * @return The 'relative' attribute. 136 */ 137 public int getRelative() { 138 return this.relative; 139 } 140 141 /** 142 * Sets the 'relative' attribute (SerialDate.PRECEDING, SerialDate.NEAREST, 143 * SerialDate.FOLLOWING). 144 * 145 * @param relative determines *which* day-of-the-week is selected by this 146 * rule. 147 */ 148 public void setRelative(final int relative) { 149 this.relative = relative; 150 } 151 152 /** 153 * Creates a clone of this rule. 154 * 155 * @return a clone of this rule. 156 * 157 * @throws CloneNotSupportedException this should never happen. 158 */ 159 public Object clone() throws CloneNotSupportedException { 160 final RelativeDayOfWeekRule duplicate 161 = (RelativeDayOfWeekRule) super.clone(); 162 duplicate.subrule = (AnnualDateRule) duplicate.getSubrule().clone(); 163 return duplicate; 164 } 165 166 /** 167 * Returns the date generated by this rule, for the specified year. 168 * 169 * @param year the year (1900 <= year <= 9999). 170 * 171 * @return The date generated by the rule for the given year (possibly 172 * <code>null</code>). 173 */ 174 public SerialDate getDate(final int year) { 175 176 // check argument... 177 if ((year < SerialDate.MINIMUM_YEAR_SUPPORTED) 178 || (year > SerialDate.MAXIMUM_YEAR_SUPPORTED)) { 179 throw new IllegalArgumentException( 180 "RelativeDayOfWeekRule.getDate(): year outside valid range."); 181 } 182 183 // calculate the date... 184 SerialDate result = null; 185 final SerialDate base = this.subrule.getDate(year); 186 187 if (base != null) { 188 switch (this.relative) { 189 case(SerialDate.PRECEDING): 190 result = SerialDate.getPreviousDayOfWeek(this.dayOfWeek, 191 base); 192 break; 193 case(SerialDate.NEAREST): 194 result = SerialDate.getNearestDayOfWeek(this.dayOfWeek, 195 base); 196 break; 197 case(SerialDate.FOLLOWING): 198 result = SerialDate.getFollowingDayOfWeek(this.dayOfWeek, 199 base); 200 break; 201 default: 202 break; 203 } 204 } 205 return result; 206 207 } 208 209}