All Downloads are FREE. Search and download functionalities are using the official Maven repository.

weka.classifiers.timeseries.core.CustomPeriodicTest Maven / Gradle / Ivy

Go to download

Provides a time series forecasting environment for Weka. Includes a wrapper for Weka regression schemes that automates the process of creating lagged variables and date-derived periodic variables and provides the ability to do closed-loop forecasting. New evaluation routines are provided by a special evaluation module and graphing of predictions/forecasts are provided via the JFreeChart library. Includes both command-line and GUI user interfaces. Sample time series data can be found in ${WEKA_HOME}/packages/timeseriesForecasting/sample-data.

The newest version!
/*
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see .
 */


/*
 *    CustomPeriodicTest.java
 *    Copyright (C) 2010-2016 University of Waikato, Hamilton, New Zealand
 */

package weka.classifiers.timeseries.core;

import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

/**
 * Class that evaluates a supplied date against user-specified
 * date constant fields. Fields that can be tested against include
 * year, month, week of year, week of month, day of year, day of month,
 * day of week, hour of day, minute of hour and second. Wildcard "*"
 * matches any value for a particular field. Each CustomPeriodicTest
 * is made up of one or two test parts. If the first test part's operator
 * is "=", then no second part is necessary. Otherwise the first test part
 * may use > or >= operators and the second test part < or <= operators.
 * Taken together, the two parts define an interval. An optional label
 * may be associated with the interval.
 * 
 * @author Mark Hall (mhall{[at]}pentaho{[dot]}com)
 * @version $Revision: 45163 $
 */
public class CustomPeriodicTest implements Serializable {
  
  /**
   * For serialization
   */
  private static final long serialVersionUID = -1470297629040276248L;  
  
  /**
   * Enum defining inequality operations
   */
  public static enum Operator {
    NONE("None") {
      boolean evaluate(int first, int second) {
        return false;
      }
    },
    EQUALS("=") {
      boolean evaluate(int first, int second) {
        return (first == second);
      }
    },
    GREATER_THAN_OR_EQUAL_TO(">=") {
      boolean evaluate(int first, int second) {
        return (first >= second);
      }
    },
    GREATER_THAN(">") {
      boolean evaluate(int first, int second) {
        return (first > second);
      }
    },
    LESS_THAN_OR_EQUAL_TO("<=") {
      boolean evaluate(int first, int second) {
        return (first <= second);
      }
    },
    LESS_THAN("<") {
      boolean evaluate(int first, int second) {
        return (first < second);
      }
    };
    
    private final String m_stringVal;
    
    abstract boolean evaluate(int first, int second);
    
    Operator(String name) {
      m_stringVal = name;
    }
    
    public String toString() {
      return m_stringVal;
    }
  }
  
  /**
   * Inner class defining one boundary of an interval
   */
  public class TestPart implements Serializable {
    /**
     * For serialization
     */
    private static final long serialVersionUID = -898852333853148631L;

    /** the operator for this bound */
    public Operator m_boundOperator = Operator.NONE;
    
    /** true if this is the upper bound */
    protected boolean m_isUpper = false;
    
    /** date fields */
    public int m_year = -100;
    protected int m_month = -100;
    public int m_week_of_yr = -100;
    public int m_week_of_month = -100;
    public int m_day_of_yr = -100;
    public int m_day_of_month = -100;
    protected int m_day_of_week = -100;
    public int m_hour_of_day = -100;
    public int m_min_of_hour = -100;
    public int m_second = -100;
    
    protected Calendar c = new GregorianCalendar();
    
    /**
     * Set whether this is the upper bound or not.
     * 
     * @param upper true if this is the upper bound.
     */
    public void setIsUpper(boolean upper) {
      m_isUpper = upper;
    }
    
    /**
     * Returns true if this is the upper bound.
     * 
     * @return true if this is the upper bound.
     */
    public boolean isUpper() {
      return m_isUpper;
    }
    
    /**
     * Evaluate the supplied date against this bound. Handles
     * date fields that are cyclic (such as month, day of week etc.)
     * so that intervals such as oct < date < mar evaluate correctly.
     * 
     * @param d the date to test
     * @param other the other bound
     * @return true if the supplied date is within this bound
     */
    public boolean eval(Date d, TestPart other) {
      
      c.setTime(d);
      
      boolean result = true;
      
      if (m_year != -100) {
        result = (result && m_boundOperator.
            evaluate(c.get(Calendar.YEAR), m_year));
      }
      if (m_month != -100) {        
        int monthBound = m_month;
        int val = c.get(Calendar.MONTH);
        
        // are we the upper bound and part of a range?
        if (m_isUpper && other != null 
            && other.m_boundOperator != Operator.EQUALS &&
            other.m_month != -100) {
          
          // translate the upper bound by subtracting lower bound
          monthBound -= other.m_month;
          if (monthBound < 0) {
            monthBound += 12;
          }
          // translate the test value
          val -= other.m_month;
          if (val < 0) {
            val += 12;
          }           
        }
        
        // are we the lower bound and part of a range?
        if (!m_isUpper && m_boundOperator != Operator.EQUALS && other != null &&
            other.m_month != -100) {
          monthBound = 0; // lower bound becomes zero
          val -= m_month; // translate value
          if (val < 0) {
            val += 12;
          }
        }
        
        result = (result && m_boundOperator.
            evaluate(val, monthBound));
      }
      if (m_week_of_yr != -100) {
        int weekBound = m_week_of_yr;        
        int val = c.get(Calendar.WEEK_OF_YEAR);
        
        // are we the upper bound and part of a range?
        if (m_isUpper && other != null 
            && other.m_boundOperator != Operator.EQUALS &&
            other.m_week_of_yr != -100) {
          // translate by subtracting lower bound
          weekBound -= other.m_week_of_yr;
          if (weekBound < 0) {
            weekBound += 52;
          }
          // translate the test value
          val -= other.m_week_of_yr;
          if (val < 0) {
            val += 52;
          }
        }
        
        // are we the lower bound and part of a range?
        if (!m_isUpper && m_boundOperator != Operator.EQUALS && other != null &&
            other.m_week_of_yr != -100) {
          weekBound = 0;
          val -= m_week_of_yr;
          if (val < 0) {
            val += 52;
          }
        }
        
        result = (result && m_boundOperator.
            evaluate(val, weekBound));
      }
      if (m_week_of_month != -100) {
        int weekBound = m_week_of_month;
        int val = c.get(Calendar.WEEK_OF_MONTH);
        
        // are we the upper bound and part of a range?
        if (m_isUpper && other != null 
            && other.m_boundOperator != Operator.EQUALS &&
            other.m_week_of_month != -100) {
          // translate by subtracting lower bound
          weekBound -= other.m_week_of_month;
          if (weekBound < 0) {
            weekBound += 6;
          }
          // translate the test value
          val -= other.m_week_of_month;
          if (val < 0) {
            val += 6;
          }
        }
        
        // are we the lower bound and part of a range?
        if (!m_isUpper && m_boundOperator != Operator.EQUALS && other != null &&
            other.m_week_of_month != -100) {
          weekBound = 0;
          val -= m_week_of_month;
          if (val < 0) {
            val += 6;
          }
        }
        
        result = (result && m_boundOperator.evaluate(val, weekBound));
      }
      if (m_day_of_yr != -100) {
        int dayBound = m_day_of_yr;
        int val = c.get(Calendar.DAY_OF_YEAR);
        
        // are we the upper bound and part of a range?
        if (m_isUpper && other != null 
            && other.m_boundOperator != Operator.EQUALS &&
            other.m_day_of_yr != -100) {
          // translate by subtracting lower bound
          dayBound -= other.m_day_of_yr;
          if (dayBound < 0) {
            dayBound += 365;
          }
          // translate the test value
          val -= other.m_day_of_yr;
          if (val < 0) {
            val += 365;
          }
        }
        
        // are we the lower bound and part of a range?
        if (!m_isUpper && m_boundOperator != Operator.EQUALS && other != null &&
            other.m_day_of_yr != -100) {
          dayBound = 0;
          val -= m_day_of_yr;
          if (val < 0) {
            val += 365;
          }
        }
        
        result = (result && m_boundOperator.
            evaluate(val, dayBound));
      }
      if (m_day_of_month != -100) {
        int dayBound = m_day_of_month;
        int val = c.get(Calendar.DAY_OF_MONTH);
        
        // are we the upper bound and part of a range?
        if (m_isUpper && other != null 
            && other.m_boundOperator != Operator.EQUALS &&
            other.m_day_of_month != -100) {
          // translate by subtracting lower bound
          dayBound -= other.m_day_of_month;
          if (dayBound < 0) {
            dayBound += 31;
          }
          // translate the test value
          val -= other.m_day_of_month;
          if (val < 0) {
            val += 31;
          }
        }
        
        // are we the lower bound and part of a range?
        if (!m_isUpper && m_boundOperator != Operator.EQUALS && other != null &&
            other.m_day_of_month != -100) {
          dayBound = 0;
          val -= m_day_of_month;
          if (val < 0) {
            val += 31;
          }          
        }
        
        result = (result && m_boundOperator.
            evaluate(val, dayBound));
      }
      if (m_day_of_week != -100) {
        int dayBound = m_day_of_week;
        int val = c.get(Calendar.DAY_OF_WEEK);
        
        // are we the upper bound and part of a range?
        if (m_isUpper && other != null 
            && other.m_boundOperator != Operator.EQUALS &&
            other.m_day_of_week != -100) {
          // translate by subtracting lower bound
          dayBound -= other.m_day_of_week;
          if (dayBound < 0) {
            dayBound += 7;
          }
          // translate the test value
          val -= other.m_day_of_week;
          if (val < 0) {
            val += 7;
          }          
        }
        
        // are we the lower bound and part of a range?
        if (!m_isUpper && m_boundOperator != Operator.EQUALS && other != null &&
            other.m_day_of_week != -100) {
          dayBound = 0;
          val -= m_day_of_week;
          if (val < 0) {
            val += 7;
          }
        }
        
        result = (result && m_boundOperator.
            evaluate(val, dayBound));
      }
      if (m_hour_of_day != -100) {
        int hourBound = m_hour_of_day;
        int val = c.get(Calendar.HOUR_OF_DAY);
        
        // are we the upper bound and part of a range?
        if (m_isUpper && other != null 
            && other.m_boundOperator != Operator.EQUALS &&
            other.m_hour_of_day != -100) {
          // translate by subtracting lower bound
          hourBound -= other.m_hour_of_day;
          if (hourBound < 0) {
            hourBound += 24;
          }
          // translate test value
          val -= other.m_hour_of_day;
          if (val < 0) {
            val += 24;
          }
        }
        
        // are we the lower bound and part of a range?
        if (!m_isUpper && m_boundOperator != Operator.EQUALS && other != null &&
            other.m_hour_of_day != -100) {
          hourBound = 0;
          val -= m_hour_of_day;
          if (val < 0) {
            val += 24;
          }          
        }
        
        result = (result && m_boundOperator.
            evaluate(val, hourBound));
      }
      if (m_min_of_hour != -100) {
        int minBound = m_min_of_hour;
        int val = c.get(Calendar.MINUTE);
        
        // are we the upper bound and part of a range?
        if (m_isUpper && other != null 
            && other.m_boundOperator != Operator.EQUALS &&
            other.m_min_of_hour != -100) {
          // translate by subtracting lower bound
          minBound -= other.m_min_of_hour;
          if (minBound < 0) {
            minBound += 60;
          }
          // translate the test value
          val -= other.m_min_of_hour;
          if (val < 0) {
            val += 60;
          }          
        }
        
        // are we the lower bound and part of a range?
        if (!m_isUpper && m_boundOperator != Operator.EQUALS && other != null &&
            other.m_min_of_hour != -100) {
          minBound = 0;
          val -= m_min_of_hour;
          if (val < 0) {
            val += 60;
          }
        }
        
        result = (result && m_boundOperator.
            evaluate(val, minBound));
      }
      if (m_second != -100) {
        int secBound = m_second;
        int val = c.get(Calendar.SECOND);
        
        // are we the upper bound and part of a range?
        if (m_isUpper && other != null 
            && other.m_boundOperator != Operator.EQUALS &&
            other.m_second != -100) {
          // translate by subtracting lower bound
          secBound -= other.m_second;
          if (secBound < 0) {
            secBound += 60;
          }
          // translate the test value
          val -= other.m_second;
          if (val < 0) {
            val += 60;
          }          
        }
        
        // are we the lower bound and part of a range?
        if (!m_isUpper && m_boundOperator != Operator.EQUALS && other != null &&
            other.m_second != -100) {
          secBound = 0;
          val -= m_second;
          if (val < 0) {
            val += 60;
          }
        }
        
        result = (result && m_boundOperator.
            evaluate(val, secBound));
      }
            
      return result;
    }
    
    /**
     * Provides a textual representation of this test bound
     * 
     * @return a textual description of this test bound
     */
    public String toString() {
      StringBuffer result = new StringBuffer();
      result.append(m_boundOperator.toString());
      
      if (m_year != -100) {
        result.append("" + m_year);
      } else {
        result.append("*");
      }
      result.append(":");
      if (m_month != -100) {
        result.append(getMonthString());
      } else {
        result.append("*");
      }
      result.append(":");
      if (m_week_of_yr != -100) {
        result.append("" + m_week_of_yr);
      } else {
        result.append("*");
      }
      result.append(":");
      if (m_week_of_month != -100) {
        result.append("" + m_week_of_month);
      } else {
        result.append("*");
      }
      result.append(":");
      if (m_day_of_yr != -100) {
        result.append("" + m_day_of_yr);
      } else {
        result.append("*");
      }
      result.append(":");
      if (m_day_of_month != -100) {
        result.append("" + m_day_of_month);
      } else {
        result.append("*");
      }
      result.append(":");
      if (m_day_of_week != -100) {
        result.append(getDayString());
      } else {
        result.append("*");
      }
      result.append(":");
      if (m_hour_of_day != -100) {
        result.append("" + m_hour_of_day);
      } else {
        result.append("*");
      }
      result.append(":");
      if (m_min_of_hour != -100) {
        result.append("" + m_min_of_hour);
      } else {
        result.append("*");
      }
      result.append(":");
      if (m_second != -100) {
        result.append("" + m_second);
      } else {
        result.append("*");
      }
      
      return result.toString();
    }
    
    /**
     * Set the operator for this bound
     * 
     * @param operator as a String
     */
    public void setOperator(String operator) {
      for (Operator t : Operator.values()) {
        if (operator.equals(t.toString())) {
          m_boundOperator = t;
          break;
        }
      }
    }
    
    /**
     * Set the year for this bound.
     * 
     * @param year the year or "*" to match any value.
     */
    public void setYear(String year) {
      if (year.equals("*")) {
        m_year = -100;
      } else {
        m_year = Integer.parseInt(year);
      }
    }
    
    /**
     * Set the week of the year for this bound.
     * 
     * @param week the week of the year or "*" to match any value.
     */
    public void setWeekOfYear(String week) {
      if (week.equals("*")) {
        m_week_of_yr = -100;
      } else {
        m_week_of_yr = Integer.parseInt(week);
      }
    }
    
    /**
     * Set the week of the month for this bound.
     * 
     * @param week the week of the month or "*" to match any value.
     */
    public void setWeekOfMonth(String week) {
      if (week.equals("*")) {
        m_week_of_yr = -100;
      } else {
        m_week_of_month = Integer.parseInt(week);
      }
    }
    
    /**
     * Set the day of the year for this bound.
     * 
     * @param dayOfYear the day of the year or "*" to match any value.
     */
    public void setDayOfYear(String dayOfYear) {
      if (dayOfYear.equals("*")) {
        m_day_of_yr = -100;
      } else {
        m_day_of_yr = Integer.parseInt(dayOfYear);
      }
    }
    
    /**
     * Set the day of the month for this bound.
     * 
     * @param dayOfMonth the day of the month or "*" to match any value.
     */
    public void setDayOfMonth(String dayOfMonth) {
      if (dayOfMonth.equals("*")) {
        m_day_of_month = -100;
      } else {
        m_day_of_month = Integer.parseInt(dayOfMonth);
      }
    }
    
    /**
     * Set the month for this bound.
     * 
     * @param month the month or "*" to match any value.
     */
    public void setMonth(String month) {
      m_month = parseMonth(month);
    }
    
    /**
     * Set the day of the week for this bound.
     * 
     * @param dayOfWeek the day of the week or "*" to match any value.
     */
    public void setDayOfWeek(String dayOfWeek) {
      m_day_of_week = parseDay(dayOfWeek);
    }
    
    /**
     * Set the hour of the day for this bound.
     * 
     * @param hourOfDay the hour of the day or "*" to match any value.
     */
    public void setHourOfDay(String hourOfDay) {
      if (hourOfDay.equals("*")) {
        m_hour_of_day = -100;
      } else {
        m_hour_of_day = Integer.parseInt(hourOfDay);
      }
    }
    
    /**
     * Set the minute of the hour for this bound.
     * 
     * @param min the minute of the hour or "*" to match any value.
     */
    public void setMinuteOfHour(String min) {
      if (min.equals("*")) {
        m_min_of_hour = -100;
      } else {
        m_min_of_hour = Integer.parseInt(min);
      }
    }
    
    /**
     * Set the second for this bound.
     * 
     * @param second the second or "*" to match any value.
     */
    public void setSecond(String second) {
      if (second.equals("*")) {
        m_second = -100;
      } else {
        m_second = Integer.parseInt(second);
      }
    }
    
    /**
     * Get the day of the week as a string.
     * 
     * @return the day of the week.
     */
    public String getDayString() {
      
      if (m_day_of_week == Calendar.SUNDAY) {
        return "sun";
      }
      if (m_day_of_week == Calendar.MONDAY) {
        return "mon";
      }
      if (m_day_of_week == Calendar.TUESDAY) {
        return "tue";
      }
      if (m_day_of_week == Calendar.WEDNESDAY) {
        return "wed";
      }
      if (m_day_of_week == Calendar.THURSDAY) {
        return "thu";
      }
      if (m_day_of_week == Calendar.FRIDAY) {
        return "fri";
      }
      if (m_day_of_week == Calendar.SATURDAY) {
        return "sat";
      }
      
      return "*";
    }
    
    /**
     * Get the month as a String.
     * 
     * @return the month.
     */
    public String getMonthString() {
      if (m_month == Calendar.JANUARY) {
        return "jan";
      }
      if (m_month == Calendar.FEBRUARY) {
        return "feb";
      }
      if (m_month == Calendar.MARCH) {
        return "mar";
      }
      if (m_month == Calendar.APRIL) {
        return "apr";
      }
      if (m_month == Calendar.MAY) {
        return "may";
      }
      if (m_month == Calendar.JUNE) {
        return "jun";
      }
      if (m_month == Calendar.JULY) {
        return "jul";
      }
      if (m_month == Calendar.AUGUST) {
        return "aug";
      }
      if (m_month == Calendar.SEPTEMBER) {
        return "sep";
      }
      if (m_month == Calendar.OCTOBER) {
        return "oct";
      }
      if (m_month == Calendar.NOVEMBER) {
        return "nov";
      }
      if (m_month == Calendar.DECEMBER) {
        return "dec";
      }
      
      return "*";
    }
  }
  
  /** the upper bound */
  protected TestPart m_upperTest;
  
  /** the lower bound */
  protected TestPart m_lowerTest;
  
  /** the (optional) label for this interval */
  protected String m_label;
  
  /**
   * Constructor.
   * 
   * @param theTest the test definition as a String
   * @throws IllegalArgumentException if the test can't be parsed or is 
   * ill defined.
   */
  public CustomPeriodicTest(String theTest) throws IllegalArgumentException {
    setTest(theTest);
  }
  
  /**
   * Get the lower bound test
   * 
   * @return the lower bound test
   */
  public TestPart getLowerTest() {
    return m_lowerTest;
  }
  
  /**
   * Get the upper bound test
   * 
   * @return the upper bound test.
   */
  public TestPart getUpperTest() {
    return m_upperTest;
  }
  
  /**
   * Set the test as a String
   * 
   * @param theTest the test
   * @throws IllegalArgumentException if the test can't be parsed or is
   * ill defined.
   */
  public void setTest(String theTest) throws IllegalArgumentException {
    /*// check for brackets first
    if (theTest.indexOf('(') < 0 || theTest.indexOf(')') < 0) {
      throw new IllegalArgumentException("Custom periodic test needs enclosing " +
      		"parenthesis!");
    } */
      
/*    // split off brackets
    theTest = theTest.substring(1, theTest.indexOf(')') - 1); */
    theTest = theTest.trim();
    
    if (theTest.indexOf(' ') > 0) {
      String[] parts = theTest.split(" ");
      
      m_lowerTest = parseTest(parts[0]);
      m_upperTest = parseTest(parts[1]);
      m_upperTest.setIsUpper(true);
      
      if (m_upperTest.m_boundOperator == m_lowerTest.m_boundOperator) {
        throw new IllegalArgumentException("Doesn't make sense to define " +
        		"an upper and lower test that uses the same operator");
      }      
    } else {
      m_lowerTest = parseTest(theTest);
    }
  }
  
  /**
   * Get the optional label for this interval.
   * 
   * @return the label for this interval
   */
  public String getLabel() {
    return m_label;
  }
  
  /**
   * Set the label for this interval
   * 
   * @param label the label for this interval
   */
  public void setLabel(String label) {
    m_label = label;
  }
  
  /**
   * Evaluate the supplied date with respect to this custom periodic
   * test interval
   * 
   * @param d the date to test
   * @return true if the date lies within the interval.
   */
  public boolean evaluate(Date d) {
    boolean result = m_lowerTest.eval(d, m_upperTest);
    
    // only evaluate the upper test if there is one and the lower operator
    // is not equals
    if (m_upperTest != null && m_lowerTest.m_boundOperator != Operator.EQUALS) {      
      result = (result && m_upperTest.eval(d, m_lowerTest));
    }
    
    return result;
  }
  
  /**
   * Parses the day of the week as either a number or
   * a string
   * 
   * @param day the day of the week
   * @return the integer index of the day of the week
   * @throws IllegalArgumentException if the supplied day can't be parsed
   */
  private int parseDay(String day) throws IllegalArgumentException {
    // try parsing as a number
    try {
      int result = Integer.parseInt(day);
      return result;
    } catch (NumberFormatException e) {}
    
    // try parsing as a word
    day = day.toLowerCase();
    if (day.equals("sunday") || day.equals("sun")) {
      return Calendar.SUNDAY;
    }
    if (day.equals("monday") || day.equals("mon")) {
      return Calendar.MONDAY;
    }
    if (day.equals("tuesday") || day.equals("tue")) {
      return Calendar.TUESDAY;
    }
    if (day.equals("wednesday") || day.equals("wed")) {
      return Calendar.WEDNESDAY;
    }
    if (day.equals("thursday") || day.equals("thu")) {
      return Calendar.THURSDAY;
    }
    if (day.equals("friday") || day.equals("fri")) {
      return Calendar.FRIDAY;
    }
    if (day.equals("saturday") || day.equals("sat")) {
      return Calendar.SATURDAY;
    }
    if (day.equals("*")) {
      return -100;
    }
    throw new IllegalArgumentException("Can't parse month!");
  }
  
  /**
   * Parses the month as either a number or
   * a string
   * 
   * @param month the month of the year
   * @return the integer index of the month
   * @throws IllegalArgumentException if the supplied month can't be parsed
   */
  private int parseMonth(String month) throws IllegalArgumentException {
    // try parsing as a number
    try {
      int result = Integer.parseInt(month);
      return result;
    } catch (NumberFormatException e) {}
    
    // try parsing as a word
    month = month.toLowerCase();
    if (month.equals("january") || month.equals("jan")) {
      return Calendar.JANUARY;
    }
    if (month.equals("february") || month.equals("feb")) {
      return Calendar.FEBRUARY;
    }
    if (month.equals("march") || month.equals("mar")) {
      return Calendar.MARCH;
    }
    if (month.equals("april") || month.equals("apr")) {
      return Calendar.APRIL;
    }
    if (month.equals("may")) {
      return Calendar.MAY;
    }
    if (month.equals("june") || month.equals("jun")) {
      return Calendar.JUNE;
    }
    if (month.equals("july") || month.equals("jul")) {
      return Calendar.JULY;
    }
    if (month.equals("august") || month.equals("aug")) {
      return Calendar.AUGUST;
    }
    if (month.equals("september") || month.equals("sep")) {
      return Calendar.SEPTEMBER;
    }
    if (month.equals("october") || month.equals("oct")) {
      return Calendar.OCTOBER;
    }
    if (month.equals("november") || month.equals("nov")) {
      return Calendar.NOVEMBER;
    }
    if (month.equals("december") || month.equals("dec")) {
      return Calendar.DECEMBER;
    }
    if (month.equals("*")) {
      return -100;
    }
    
    throw new IllegalArgumentException("Can't parse month!");
  }
  
  /**
   * Parses the textual definition of one bound
   * 
   * @param aTest the bound to parse
   * @return a TestPart object encapsulating the bound
   * @throws IllegalArgumentException if the test can't be parsed or
   * is ill defined
   */
  protected TestPart parseTest(String aTest) throws IllegalArgumentException {
    // check for a label
    if (aTest.indexOf('/') > 0) {
      String[] parts = aTest.split("/");
      aTest = parts[0].trim();
      m_label = parts[1].trim();
    }     
    
    aTest = aTest.trim();
    TestPart newTest = new TestPart();
    
    if (aTest.charAt(0) == '=') {
      newTest.m_boundOperator = Operator.EQUALS;
      aTest = aTest.substring(1, aTest.length());
    } else {
      if (aTest.charAt(0) == '>') {
        newTest.m_boundOperator = Operator.GREATER_THAN;
        aTest = aTest.substring(1, aTest.length());
        if (aTest.charAt(0) == '=') {
          newTest.m_boundOperator = Operator.GREATER_THAN_OR_EQUAL_TO;
          aTest = aTest.substring(1, aTest.length());
        }
      } else if (aTest.charAt(0) == '<') {
        newTest.m_boundOperator = Operator.LESS_THAN;
        aTest = aTest.substring(1, aTest.length());
        if (aTest.charAt(0) == '=') {
          newTest.m_boundOperator = Operator.LESS_THAN_OR_EQUAL_TO;
          aTest = aTest.substring(1, aTest.length());
        }
      }
    }
    
    String[] parts = aTest.split(":");
    // do we have the right number of parts?
    if (parts.length != 10) {
/*      System.err.println(aTest);
      System.err.println("-- Num parts " + parts.length);
      for (int z = 0; z < parts.length; z++) {
        System.err.println(parts[z]);
      }*/
      throw new IllegalArgumentException("Test does not contain 10 parts!");
    }
    if (parts[0].trim().length() > 0 && parts[0].charAt(0) != '*') {
      newTest.m_year = Integer.parseInt(parts[0].trim());
    }
    if (parts[1].trim().length() > 0 && parts[1].charAt(0) != '*') {
      newTest.m_month = parseMonth(parts[1].trim());
    }
    if (parts[2].trim().length() > 0 && parts[2].charAt(0) != '*') {
      newTest.m_week_of_yr = Integer.parseInt(parts[2].trim());
    }
    if (parts[3].trim().length() > 0 && parts[3].charAt(0) != '*') {
      newTest.m_week_of_month = Integer.parseInt(parts[3].trim());
    }
    if (parts[4].trim().length() > 0 && parts[4].charAt(0) != '*') {
      newTest.m_day_of_yr = Integer.parseInt(parts[4].trim());
    }
    if (parts[5].trim().length() > 0 && parts[5].charAt(0) != '*') {
      newTest.m_day_of_month = Integer.parseInt(parts[5].trim());
    }
    if (parts[6].trim().length() > 0 && parts[6].charAt(0) != '*') {
      newTest.m_day_of_week = parseDay(parts[6].trim());
    }
    if (parts[7].trim().length() > 0 && parts[7].charAt(0) != '*') {
      newTest.m_hour_of_day = Integer.parseInt(parts[7].trim());
    }
    if (parts[8].trim().length() > 0 && parts[8].charAt(0) != '*') {
      newTest.m_min_of_hour = Integer.parseInt(parts[8].trim());
    }
    if (parts[9].trim().length() > 0 && parts[9].charAt(0) != '*') {
      newTest.m_second = Integer.parseInt(parts[9].trim());
    }
    
    return newTest;
  }
  
  /**
   * Returns a textual description of this test
   * 
   * @return a textual description of this test
   */
  public String toString() {
    String result = m_lowerTest.toString();
    if (m_upperTest != null && m_lowerTest.m_boundOperator != Operator.EQUALS) {
      result += (" " + m_upperTest.toString());
    }
    if (m_label != null && m_label.length()> 0) {
      result += "/" + m_label;
    }
    return result;
  }
  
  /**
   * Main method for testing this class
   * 
   * @param args command line arguments - first element should
   * contain a textual definition of a test
   */
  public static void main(String[] args) {
    try {
      if (args.length != 1) {
        System.err.println("Usage: CustomPeriodicTest \"TestPart TestPart\"");
        System.exit(1);
      }
      CustomPeriodicTest test = new CustomPeriodicTest(args[0]);
      System.out.println("CustomPeriodicTest: \n\n" + test.toString());
    } catch (Exception ex) {
      ex.printStackTrace();      
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy