001/**
002 *  '$Author: welker $'
003 *  '$Date: 2010-05-06 05:21:26 +0000 (Thu, 06 May 2010) $'
004 *  '$Revision: 24234 $'
005 *
006 *  For Details:
007 *  http://www.kepler-project.org
008 *
009 *  Copyright (c) 2009-2010 The Regents of the
010 *  University of California. All rights reserved. Permission is hereby granted,
011 *  without written agreement and without license or royalty fees, to use, copy,
012 *  modify, and distribute this software and its documentation for any purpose,
013 *  provided that the above copyright notice and the following two paragraphs
014 *  appear in all copies of this software. IN NO EVENT SHALL THE UNIVERSITY OF
015 *  CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,
016 *  OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
017 *  DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
018 *  POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY
019 *  DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
020 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
021 *  SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
022 *  CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
023 *  ENHANCEMENTS, OR MODIFICATIONS.
024 */
025
026package org.kepler.workflowrunmanager;
027
028import java.util.regex.Matcher;
029import java.util.regex.Pattern;
030
031public class DurationQueryParse {
032
033        // TODO looks weird/ambiguous to allow e.g. 10:5:4
034        // TODO temporarily removing single-date-without-op searches since queries
035        // haven't been written yet.
036        private String singleDurationRegEx = "\\s*((\\d*):)??(([0-5]?[0-9]):)?([0-5]?[0-9])\\s*";
037        // String oneDurationRegEx = "\\s*"+singleDurationRegEx;
038        // Pattern oneDurationPattern = Pattern.compile(oneDurationRegEx);
039
040        private String oneDurationWithOpRegEx = "\\s*([><])\\s*"
041                        + singleDurationRegEx;
042        private Pattern oneDurationWithOpPattern = Pattern
043                        .compile(oneDurationWithOpRegEx);
044
045        private static final String RANGE_SEPARATOR = " - ";
046
047        // pattern for duration range. dur1 - dur2
048        private String durationRangeRegEx = singleDurationRegEx + "\\s*-\\s*"
049                        + singleDurationRegEx;
050        private Pattern durationRangePattern = Pattern.compile(durationRangeRegEx);
051
052        private boolean isValid = false;
053        private boolean isRange = false;
054        private String operator = null;
055        private int numDurations = 0;
056
057        private static final String SEPARATOR = ":";
058        private String completeText = "";
059
060        private static final String LESS_THAN = "<";
061        private static final String GREATER_THAN = ">";
062
063        // we could let users specify multiple ranges with a bit more work
064        // elsewhere...
065        private static int numAllowedDurations = 2;
066        private DurationParse[] parsedDurations = new DurationParse[numAllowedDurations];
067
068        public DurationQueryParse(String durationQuery) {
069
070                for (int i = 0; i < numAllowedDurations; i++) {
071                        parsedDurations[i] = new DurationParse();
072                }
073
074                // Matcher oneDurationMatcher =
075                // oneDurationPattern.matcher(durationQuery);
076                Matcher oneDurationWithOpMatcher = oneDurationWithOpPattern
077                                .matcher(durationQuery);
078                Matcher durationRangeMatcher = durationRangePattern
079                                .matcher(durationQuery);
080
081                if (durationRangeMatcher.matches()) {
082                        isRange = true;
083                        isValid = true;
084
085                        for (int i = 0, j = 2; i < numAllowedDurations; i++, j += 5) {
086                                if (durationRangeMatcher.group(j) == null
087                                                || durationRangeMatcher.group(j).equals("")) {
088                                        parsedDurations[i].setHours(0);
089                                } else {
090                                        parsedDurations[i].setHours(Integer
091                                                        .parseInt(durationRangeMatcher.group(j)));
092                                }
093                                if (durationRangeMatcher.group(j + 2) == null
094                                                || durationRangeMatcher.group(j + 2).equals("")) {
095                                        parsedDurations[i].setMins(0);
096                                } else {
097                                        parsedDurations[i].setMins(Integer
098                                                        .parseInt(durationRangeMatcher.group(j + 2)));
099                                }
100                                if (durationRangeMatcher.group(j + 3) == null
101                                                || durationRangeMatcher.group(j + 3).equals("")) {
102                                        parsedDurations[i].setSecs(0);
103                                } else {
104                                        parsedDurations[i].setSecs(Integer
105                                                        .parseInt(durationRangeMatcher.group(j + 3)));
106                                }
107                                numDurations = i + 1;
108
109                                if (i % 2 == 0) {
110                                        completeText += parsedDurations[i].getHours() + SEPARATOR
111                                                        + parsedDurations[i].getMins() + SEPARATOR
112                                                        + parsedDurations[i].getSecs() + RANGE_SEPARATOR;
113                                } else {
114                                        completeText += parsedDurations[i].getHours() + SEPARATOR
115                                                        + parsedDurations[i].getMins() + SEPARATOR
116                                                        + parsedDurations[i].getSecs();
117                                        // comma here if we allow >1 range
118                                }
119
120                        }
121
122                } else if (oneDurationWithOpMatcher.matches()) {
123                        isRange = false;
124                        operator = oneDurationWithOpMatcher.group(1);
125                        numDurations = 1;
126                        isValid = true;
127
128                        if (oneDurationWithOpMatcher.group(3) == null
129                                        || oneDurationWithOpMatcher.group(3).equals("")) {
130                                parsedDurations[0].setHours(0);
131                        } else {
132                                parsedDurations[0].setHours(Integer
133                                                .parseInt(oneDurationWithOpMatcher.group(3)));
134                        }
135                        if (oneDurationWithOpMatcher.group(5) == null
136                                        || oneDurationWithOpMatcher.group(5).equals("")) {
137                                parsedDurations[0].setMins(0);
138                        } else {
139                                parsedDurations[0].setMins(Integer
140                                                .parseInt(oneDurationWithOpMatcher.group(5)));
141                        }
142                        if (oneDurationWithOpMatcher.group(6) == null
143                                        || oneDurationWithOpMatcher.group(6).equals("")) {
144                                parsedDurations[0].setSecs(0);
145                        } else {
146                                parsedDurations[0].setSecs(Integer
147                                                .parseInt(oneDurationWithOpMatcher.group(6)));
148                        }
149
150                        completeText = getOperator() + " " + parsedDurations[0].getHours()
151                                        + SEPARATOR + parsedDurations[0].getMins() + SEPARATOR
152                                        + parsedDurations[0].getSecs();
153                }
154                /*
155                 * else if (oneDurationMatcher.matches()){ durationParse.put("isRange",
156                 * false); durationParse.put("numDurations", 1);
157                 * durationParse.put("valid", true);
158                 * 
159                 * parsedDurations[0] = new HashMap<String, Integer>(); if
160                 * (oneDurationMatcher.group(2) == null ||
161                 * oneDurationMatcher.group(2).equals("")){
162                 * parsedDurations[0].put("hours", 0); } else{
163                 * parsedDurations[0].put("hours",
164                 * Integer.parseInt(oneDurationMatcher.group(2))); } if
165                 * (oneDurationMatcher.group(4) == null ||
166                 * oneDurationMatcher.group(4).equals("")){
167                 * parsedDurations[0].put("minutes", 0); } else{
168                 * parsedDurations[0].put("minutes",
169                 * Integer.parseInt(oneDurationMatcher.group(4))); } if
170                 * (oneDurationMatcher.group(5) == null ||
171                 * oneDurationMatcher.group(5).equals("")){
172                 * parsedDurations[0].put("seconds", 0); } else{
173                 * parsedDurations[0].put("seconds",
174                 * Integer.parseInt(oneDurationMatcher.group(5))); } }
175                 */
176
177        }
178
179        public String getCompleteText() {
180                return completeText;
181        }
182
183        public int getTotalSecondsForDuration(int durationIndex) {
184                return parsedDurations[durationIndex].getTotalSeconds();
185        }
186
187        public boolean isValid() {
188                return isValid;
189        }
190
191        public boolean isRange() {
192                return isRange;
193        }
194
195        public String getOperator() {
196                return operator;
197        }
198
199        public int getNumItems() {
200                return numDurations;
201        }
202
203        public boolean passesFilter(int inputDuration) {
204                if (isValid()) {
205                        if (isRange()) {
206                                if ((getTotalSecondsForDuration(0) <= inputDuration)
207                                                && (getTotalSecondsForDuration(1) >= inputDuration)) {
208                                        return true;
209                                }
210                        } else {
211                                if (getOperator().equals(GREATER_THAN)) {
212                                        if (inputDuration > getTotalSecondsForDuration(0)) {
213                                                return true;
214                                        }
215                                } else if (getOperator().equals(LESS_THAN)) {
216                                        if (inputDuration < getTotalSecondsForDuration(0)) {
217                                                return true;
218                                        }
219                                }
220                        }
221                }
222
223                return false;
224        }
225
226        private static class DurationParse {
227
228                private static final int NUM_SECONDS_IN_HOUR = 3600;
229                private static final int NUM_SECONDS_IN_MINUTE = 60;
230
231                private Integer hours = 0;
232                private String hoursString = hours.toString();
233                private Integer minutes = 0;
234                private String minutesString = minutes.toString();
235                private Integer seconds = 0;
236                private String secondsString = seconds.toString();
237                private Integer totalSeconds = 0;
238
239                public DurationParse() {
240                }
241
242                public String getHours() {
243                        return hoursString;
244                }
245
246                public String getMins() {
247                        return minutesString;
248                }
249
250                public String getSecs() {
251                        return secondsString;
252                }
253
254                public void setHours(int h) {
255                        hours = h;
256                        hoursString = hours.toString();
257                        if (hours < 10) {
258                                hoursString = "0" + hours;
259                        }
260                        setTotalSeconds();
261                }
262
263                public void setMins(int mins) {
264                        minutes = mins;
265                        minutesString = minutes.toString();
266                        if (minutes < 10) {
267                                minutesString = "0" + minutes;
268                        }
269                        setTotalSeconds();
270                }
271
272                public void setSecs(int secs) {
273                        seconds = secs;
274                        secondsString = seconds.toString();
275                        if (seconds < 10) {
276                                secondsString = "0" + seconds;
277                        }
278                        setTotalSeconds();
279                }
280
281                public void setTotalSeconds() {
282                        totalSeconds = (hours * NUM_SECONDS_IN_HOUR)
283                                        + (minutes * NUM_SECONDS_IN_MINUTE) + seconds;
284                }
285
286                public int getTotalSeconds() {
287                        return totalSeconds;
288                }
289        }
290
291}