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
044 package 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 */
056 public 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 }