1 /* ============================================================
2  * JRobin : Pure java implementation of RRDTool's functionality
3  * ============================================================
4  *
5  * Project Info:  http://www.jrobin.org
6  * Project Lead:  Sasa Markovic (saxon@jrobin.org);
7  *
8  * (C) Copyright 2003-2005, by Sasa Markovic.
9  *
10  * Developers:    Sasa Markovic (saxon@jrobin.org)
11  *
12  *
13  * This library is free software; you can redistribute it and/or modify it under the terms
14  * of the GNU Lesser General Public License as published by the Free Software Foundation;
15  * either version 2.1 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
18  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19  * See the GNU Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public License along with this
22  * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
23  * Boston, MA 02111-1307, USA.
24  */

25 package org.jrobin.core.timespec;
26
27 class TimeScanner {
28     private String dateString;
29
30     private int pos, pos_save;
31     private TimeToken token, token_save;
32
33     static final TimeToken[] WORDS = {
34             new TimeToken("midnight", TimeToken.MIDNIGHT),    /* 00:00:00 of today or tomorrow */
35             new TimeToken("noon", TimeToken.NOON),        /* 12:00:00 of today or tomorrow */
36             new TimeToken("teatime", TimeToken.TEATIME),    /* 16:00:00 of today or tomorrow */
37             new TimeToken("am", TimeToken.AM),        /* morning times for 0-12 clock */
38             new TimeToken("pm", TimeToken.PM),        /* evening times for 0-12 clock */
39             new TimeToken("tomorrow", TimeToken.TOMORROW),
40             new TimeToken("yesterday", TimeToken.YESTERDAY),
41             new TimeToken("today", TimeToken.TODAY),
42             new TimeToken("now", TimeToken.NOW),
43             new TimeToken("n", TimeToken.NOW),
44             new TimeToken("start", TimeToken.START),
45             new TimeToken("s", TimeToken.START),
46             new TimeToken("end", TimeToken.END),
47             new TimeToken("e", TimeToken.END),
48             new TimeToken("jan", TimeToken.JAN),
49             new TimeToken("feb", TimeToken.FEB),
50             new TimeToken("mar", TimeToken.MAR),
51             new TimeToken("apr", TimeToken.APR),
52             new TimeToken("may", TimeToken.MAY),
53             new TimeToken("jun", TimeToken.JUN),
54             new TimeToken("jul", TimeToken.JUL),
55             new TimeToken("aug", TimeToken.AUG),
56             new TimeToken("sep", TimeToken.SEP),
57             new TimeToken("oct", TimeToken.OCT),
58             new TimeToken("nov", TimeToken.NOV),
59             new TimeToken("dec", TimeToken.DEC),
60             new TimeToken("january", TimeToken.JAN),
61             new TimeToken("february", TimeToken.FEB),
62             new TimeToken("march", TimeToken.MAR),
63             new TimeToken("april", TimeToken.APR),
64             new TimeToken("may", TimeToken.MAY),
65             new TimeToken("june", TimeToken.JUN),
66             new TimeToken("july", TimeToken.JUL),
67             new TimeToken("august", TimeToken.AUG),
68             new TimeToken("september", TimeToken.SEP),
69             new TimeToken("october", TimeToken.OCT),
70             new TimeToken("november", TimeToken.NOV),
71             new TimeToken("december", TimeToken.DEC),
72             new TimeToken("sunday", TimeToken.SUN),
73             new TimeToken("sun", TimeToken.SUN),
74             new TimeToken("monday", TimeToken.MON),
75             new TimeToken("mon", TimeToken.MON),
76             new TimeToken("tuesday", TimeToken.TUE),
77             new TimeToken("tue", TimeToken.TUE),
78             new TimeToken("wednesday", TimeToken.WED),
79             new TimeToken("wed", TimeToken.WED),
80             new TimeToken("thursday", TimeToken.THU),
81             new TimeToken("thu", TimeToken.THU),
82             new TimeToken("friday", TimeToken.FRI),
83             new TimeToken("fri", TimeToken.FRI),
84             new TimeToken("saturday", TimeToken.SAT),
85             new TimeToken("sat", TimeToken.SAT),
86             new TimeToken(null, 0)            /*** SENTINEL ***/
87     };
88
89     static TimeToken[] MULTIPLIERS = {
90             new TimeToken("second", TimeToken.SECONDS),    /* seconds multiplier */
91             new TimeToken("seconds", TimeToken.SECONDS),    /* (pluralized) */
92             new TimeToken("sec", TimeToken.SECONDS),        /* (generic) */
93             new TimeToken("s", TimeToken.SECONDS),        /* (short generic) */
94             new TimeToken("minute", TimeToken.MINUTES),    /* minutes multiplier */
95             new TimeToken("minutes", TimeToken.MINUTES),    /* (pluralized) */
96             new TimeToken("min", TimeToken.MINUTES),        /* (generic) */
97             new TimeToken("m", TimeToken.MONTHS_MINUTES),    /* (short generic) */
98             new TimeToken("hour", TimeToken.HOURS),        /* hours ... */
99             new TimeToken("hours", TimeToken.HOURS),        /* (pluralized) */
100             new TimeToken("hr", TimeToken.HOURS),        /* (generic) */
101             new TimeToken("h", TimeToken.HOURS),        /* (short generic) */
102             new TimeToken("day", TimeToken.DAYS),        /* days ... */
103             new TimeToken("days", TimeToken.DAYS),        /* (pluralized) */
104             new TimeToken("d", TimeToken.DAYS),        /* (short generic) */
105             new TimeToken("week", TimeToken.WEEKS),        /* week ... */
106             new TimeToken("weeks", TimeToken.WEEKS),        /* (pluralized) */
107             new TimeToken("wk", TimeToken.WEEKS),        /* (generic) */
108             new TimeToken("w", TimeToken.WEEKS),        /* (short generic) */
109             new TimeToken("month", TimeToken.MONTHS),    /* week ... */
110             new TimeToken("months", TimeToken.MONTHS),    /* (pluralized) */
111             new TimeToken("mon", TimeToken.MONTHS),        /* (generic) */
112             new TimeToken("year", TimeToken.YEARS),        /* year ... */
113             new TimeToken("years", TimeToken.YEARS),        /* (pluralized) */
114             new TimeToken("yr", TimeToken.YEARS),        /* (generic) */
115             new TimeToken("y", TimeToken.YEARS),        /* (short generic) */
116             new TimeToken(null, 0)            /*** SENTINEL ***/
117     };
118
119     TimeToken[] specials = WORDS;
120
121     public TimeScanner(String dateString) {
122         this.dateString = dateString;
123     }
124
125     void setContext(boolean parsingWords) {
126         specials = parsingWords ? WORDS : MULTIPLIERS;
127     }
128
129     TimeToken nextToken() {
130         StringBuffer buffer = new StringBuffer("");
131         while (pos < dateString.length()) {
132             char c = dateString.charAt(pos++);
133             if (Character.isWhitespace(c) || c == '_' || c == ',') {
134                 continue;
135             }
136             buffer.append(c);
137             if (Character.isDigit(c)) {
138                 // pick as many digits as possible
139                 while (pos < dateString.length()) {
140                     char next = dateString.charAt(pos);
141                     if (Character.isDigit(next)) {
142                         buffer.append(next);
143                         pos++;
144                     }
145                     else {
146                         break;
147                     }
148                 }
149                 String value = buffer.toString();
150                 return token = new TimeToken(value, TimeToken.NUMBER);
151             }
152             if (Character.isLetter(c)) {
153                 // pick as many letters as possible
154                 while (pos < dateString.length()) {
155                     char next = dateString.charAt(pos);
156                     if (Character.isLetter(next)) {
157                         buffer.append(next);
158                         pos++;
159                     }
160                     else {
161                         break;
162                     }
163                 }
164                 String value = buffer.toString();
165                 return token = new TimeToken(value, parseToken(value));
166             }
167             switch (c) {
168                 case ':':
169                     return token = new TimeToken(":", TimeToken.COLON);
170                 case '.':
171                     return token = new TimeToken(".", TimeToken.DOT);
172                 case '+':
173                     return token = new TimeToken("+", TimeToken.PLUS);
174                 case '-':
175                     return token = new TimeToken("-", TimeToken.MINUS);
176                 case '/':
177                     return token = new TimeToken("/", TimeToken.SLASH);
178                 default:
179                     pos--;
180                     return token = new TimeToken(null, TimeToken.EOF);
181             }
182         }
183         return token = new TimeToken(null, TimeToken.EOF);
184     }
185
186     TimeToken resolveMonthsMinutes(int newId) {
187         assert token.id == TimeToken.MONTHS_MINUTES;
188         assert newId == TimeToken.MONTHS || newId == TimeToken.MINUTES;
189         return token = new TimeToken(token.value, newId);
190     }
191
192     void saveState() {
193         token_save = token;
194         pos_save = pos;
195     }
196
197     TimeToken restoreState() {
198         pos = pos_save;
199         return token = token_save;
200     }
201
202     private int parseToken(String arg) {
203         for (int i = 0; specials[i].value != null; i++) {
204             if (specials[i].value.equalsIgnoreCase(arg)) {
205                 return specials[i].id;
206             }
207         }
208         return TimeToken.ID;
209     }
210 }