001: /*
002: * @(#)Rule.java 1.6 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package sun.tools.javazic;
028:
029: import java.util.ArrayList;
030: import java.util.Arrays;
031: import java.util.Comparator;
032: import java.util.StringTokenizer;
033:
034: /**
035: * Rule manipulates Rule records.
036: *
037: * @since 1.4
038: */
039: class Rule {
040:
041: private ArrayList list;
042: private String name;
043:
044: /**
045: * Constructs a Rule which consists of a Rule record list. The
046: * specified name is given to this Rule.
047: * @param name the Rule name
048: */
049: Rule(String name) {
050: this .name = name;
051: list = new ArrayList();
052: }
053:
054: /**
055: * Added a RuleRec to the Rule record list.
056: */
057: void add(RuleRec rec) {
058: list.add(rec);
059: }
060:
061: /**
062: * @return the Rule name
063: */
064: String getName() {
065: return name;
066: }
067:
068: /**
069: * Gets all rule records that cover the given year.
070: * @param year the year number for which the rule is applicable.
071: * @return rules in ArrayList that are collated in time. If no rule is found, an empty
072: * ArrayList is returned.
073: */
074: ArrayList getRules(int year) {
075: ArrayList rules = new ArrayList(3);
076: for (int i = 0; i < list.size(); i++) {
077: RuleRec rec = (RuleRec) list.get(i);
078: if (year >= rec.getFromYear() && year <= rec.getToYear()) {
079: if ((rec.isOdd() && year % 2 == 0)
080: || (rec.isEven() && year % 2 == 1))
081: continue;
082: rules.add(rec);
083: }
084: }
085: int n = rules.size();
086: if (n <= 1) {
087: return rules;
088: }
089: if (n == 2) {
090: RuleRec rec1 = (RuleRec) rules.get(0);
091: RuleRec rec2 = (RuleRec) rules.get(1);
092: if (rec1.getMonthNum() > rec2.getMonthNum()) {
093: rules.set(0, rec2);
094: rules.set(1, rec1);
095: } else if (rec1.getMonthNum() == rec2.getMonthNum()) {
096: // TODO: it's not accurate to ignore time types (STD, WALL, UTC)
097: long t1 = Time.getLocalTime(year, rec1.getMonthNum(),
098: rec1.getDay(), rec1.getTime().getTime());
099: long t2 = Time.getLocalTime(year, rec2.getMonthNum(),
100: rec2.getDay(), rec2.getTime().getTime());
101: if (t1 > t2) {
102: rules.set(0, rec2);
103: rules.set(1, rec1);
104: }
105: }
106: return rules;
107: }
108:
109: final int y = year;
110: RuleRec[] recs = new RuleRec[rules.size()];
111: rules.toArray(recs);
112: Arrays.sort(recs, new Comparator() {
113: public int compare(Object o1, Object o2) {
114: RuleRec r1 = (RuleRec) o1;
115: RuleRec r2 = (RuleRec) o2;
116: int n = r1.getMonthNum() - r2.getMonthNum();
117: if (n != 0) {
118: return n;
119: }
120: // TODO: it's not accurate to ignore time types (STD, WALL, UTC)
121: long t1 = Time.getLocalTime(y, r1.getMonthNum(), r1
122: .getDay(), r1.getTime().getTime());
123: long t2 = Time.getLocalTime(y, r2.getMonthNum(), r2
124: .getDay(), r2.getTime().getTime());
125: return (int) (t1 - t2);
126: }
127:
128: public boolean equals(Object o1, Object o2) {
129: RuleRec r1 = (RuleRec) o1;
130: RuleRec r2 = (RuleRec) o2;
131: return r1.getMonthNum() == r2.getMonthNum();
132: }
133: });
134: rules.clear();
135: for (int i = 0; i < n; i++) {
136: rules.add(recs[i]);
137: }
138: return rules;
139: }
140:
141: /**
142: * Gets rule records that have either "max" or cover the endYear
143: * value in its DST schedule.
144: *
145: * @return rules that contain last DST schedule. An empty
146: * ArrayList is returned if no last rules are found.
147: */
148: ArrayList getLastRules() {
149: RuleRec start = null;
150: RuleRec end = null;
151:
152: for (int i = 0; i < list.size(); i++) {
153: RuleRec rec = (RuleRec) list.get(i);
154: if (rec.isLastRule()) {
155: if (rec.getSave() > 0) {
156: start = rec;
157: } else {
158: end = rec;
159: }
160: }
161: }
162: if (start == null || end == null) {
163: int endYear = Zoneinfo.getEndYear();
164: for (int i = 0; i < list.size(); i++) {
165: RuleRec rec = (RuleRec) list.get(i);
166: if (endYear >= rec.getFromYear()
167: && endYear <= rec.getToYear()) {
168: if (start == null && rec.getSave() > 0) {
169: start = rec;
170: } else {
171: if (end == null && rec.getSave() == 0) {
172: end = rec;
173: }
174: }
175: }
176: }
177: }
178:
179: ArrayList r = new ArrayList(2);
180: if (start == null || end == null) {
181: if (start != null || end != null) {
182: Main.warning("found last rules for " + name
183: + " inconsistent.");
184: }
185: return r;
186: }
187:
188: r.add(start);
189: r.add(end);
190: return r;
191: }
192: }
|