1 /*
   2  * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package build.tools.javazic;
  27 
  28 import java.util.ArrayList;
  29 import java.util.HashMap;
  30 import java.util.List;
  31 import java.util.Map;
  32 
  33 /**
  34  * RuleDay class represents the value of the "ON" field.  The day of
  35  * week values start from 1 following the {@link java.util.Calendar}
  36  * convention.
  37  *
  38  * @since 1.4
  39  */
  40 class RuleDay {
  41     private static final Map<String,DayOfWeek> abbreviations = new HashMap<String,DayOfWeek>(7);
  42     static {
  43         for (DayOfWeek day : DayOfWeek.values()) {
  44             abbreviations.put(day.getAbbr(), day);
  45         }
  46     }
  47 
  48     private String dayName = null;
  49     private DayOfWeek dow;
  50     private boolean lastOne = false;
  51     private int soonerOrLater = 0;
  52     private int thanDayOfMonth; // day of month (e.g., 8 for "Sun>=8")
  53 
  54     RuleDay() {
  55     }
  56 
  57     RuleDay(int day) {
  58         thanDayOfMonth = day;
  59     }
  60 
  61     int getDay() {
  62         return thanDayOfMonth;
  63     }
  64 
  65     /**
  66      * @return the day of week value (1-based)
  67      */
  68     int getDayOfWeekNum() {
  69         return dow.value();
  70     }
  71 
  72     /**
  73      * @return true if this rule day represents the last day of
  74      * week. (e.g., lastSun).
  75      */
  76     boolean isLast() {
  77         return lastOne;
  78     }
  79 
  80     /**
  81      * @return true if this rule day represents the day of week on or
  82      * later than (after) the {@link #getDay}. (e.g., Sun>=1)
  83      */
  84     boolean isLater() {
  85         return soonerOrLater > 0;
  86     }
  87 
  88     /**
  89      * @return true if this rule day represents the day of week on or
  90      * earlier than (before) the {@link #getDay}. (e.g., Sun<=15)
  91      */
  92     boolean isEarlier() {
  93         return soonerOrLater < 0;
  94     }
  95 
  96     /**
  97      * @return true if this rule day represents an exact day.
  98      */
  99     boolean isExact() {
 100         return soonerOrLater == 0;
 101     }
 102 
 103     /**
 104      * Parses the "ON" field and constructs a RuleDay.
 105      * @param day an "ON" field string (e.g., "Sun>=1")
 106      * @return a RuleDay representing the given "ON" field
 107      */
 108     static RuleDay parse(String day) {
 109         RuleDay d = new RuleDay();
 110         if (day.startsWith("last")) {
 111             d.lastOne = true;
 112             d.dayName = day.substring(4);
 113             d.dow = getDOW(d.dayName);
 114         } else {
 115             int index;
 116             if ((index = day.indexOf(">=")) != -1) {
 117                 d.dayName = day.substring(0, index);
 118                 d.dow = getDOW(d.dayName);
 119                 d.soonerOrLater = 1; // greater or equal
 120                 d.thanDayOfMonth = Integer.parseInt(day.substring(index+2));
 121             } else if ((index = day.indexOf("<=")) != -1) {
 122                 d.dayName = day.substring(0, index);
 123                 d.dow = getDOW(d.dayName);
 124                 d.soonerOrLater = -1; // less or equal
 125                 d.thanDayOfMonth = Integer.parseInt(day.substring(index+2));
 126             } else {
 127                 // it should be an integer value.
 128                 d.thanDayOfMonth = Integer.parseInt(day);
 129             }
 130         }
 131         return d;
 132     }
 133 
 134     /**
 135      * Converts this RuleDay to the SimpleTimeZone day rule.
 136      * @return the converted SimpleTimeZone day rule
 137      */
 138     int getDayForSimpleTimeZone() {
 139         if (isLast()) {
 140             return -1;
 141         }
 142         return isEarlier() ? -getDay() : getDay();
 143     }
 144 
 145     /**
 146      * Converts this RuleDay to the SimpleTimeZone day-of-week rule.
 147      * @return the SimpleTimeZone day-of-week rule value
 148      */
 149     int getDayOfWeekForSimpleTimeZoneInt() {
 150         if (isEarlier() || isLater()) {
 151             return -getDayOfWeekNum();
 152         }
 153         return isLast() ? getDayOfWeekNum() : 0;
 154     }
 155 
 156     /**
 157      * @return the string representation of the {@link
 158      * #getDayOfWeekForSimpleTimeZoneInt} value
 159      */
 160     String getDayOfWeekForSimpleTimeZone() {
 161         int d = getDayOfWeekForSimpleTimeZoneInt();
 162         if (d == 0) {
 163             return "0";
 164         }
 165         String sign = "";
 166         if (d < 0) {
 167             sign = "-";
 168             d = -d;
 169         }
 170         return sign + toString(d);
 171     }
 172 
 173     private static DayOfWeek getDOW(String abbr) {
 174         return abbreviations.get(abbr);
 175     }
 176 
 177     /**
 178      * Converts the specified day of week value to the day-of-week
 179      * name defined in {@link java.util.Calenda}.
 180      * @param dow 1-based day of week value
 181      * @return the Calendar day of week name with "Calendar." prefix.
 182      * @throws IllegalArgumentException if the specified dow value is out of range.
 183      */
 184     static String toString(int dow) {
 185         if (dow >= DayOfWeek.SUNDAY.value() && dow <= DayOfWeek.SATURDAY.value()) {
 186             return "Calendar." + DayOfWeek.values()[dow - 1];
 187         }
 188         throw new IllegalArgumentException("wrong Day_of_Week number: " + dow);
 189     }
 190 }