/*******************************************************************************
* Copyright (c) 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* IBM Research
*******************************************************************************/
package com.ibm.research.tagging.core.ui.expressions;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import com.ibm.research.tagging.core.IWaypoint;
/**
* handles date expressions in FilteredTable. examples:
*
* date=June (show all waypoints with dates set in June, regardless of day and year)
* date>7/05 (show all waypoints with dates after July 2005)
* date<3/1/06 (show all waypoints with dates before March 1st, 2006)
* date!2005 (show all waypoints with dates not during 2005)
*
* note: cannot handle queries with spaces in them
*
* @tag tagsea expressions : instance of an ExpressionMatcher
* @tag date tagsea : example of doing simple date logic and formatting
*
* @author Li-Te Cheng
* CUE, IBM Research 2006
*/
public class DateMatcher extends ExpressionMatcher {
public static final String TYPE = "date";
private static final int IGNORE_DATE_FIELD = -2,
LT_DATE_FIELD = -1,
EQ_DATE_FIELD = 0,
GT_DATE_FIELD = 1;
// simple internal class to parse dates and do date field comparisons
static class DateFieldComparator
{
private SimpleDateFormat parser;
private boolean compareMonth;
private boolean compareDay;
private boolean compareYear;
public DateFieldComparator(SimpleDateFormat parser, boolean compareMonth, boolean compareDay, boolean compareYear)
{
this.parser = parser;
this.compareMonth = compareMonth;
this.compareDay = compareDay;
this.compareYear = compareYear;
}
public Date parse(String date)
{
Date parsed = null;
try {
parsed = parser.parse(date);
} catch (ParseException e) {
return null;
}
return parsed;
}
private int compareField(int f1, int f2)
{
if ( f1<f2 )
return LT_DATE_FIELD;
else if ( f1>f2 )
return GT_DATE_FIELD;
return EQ_DATE_FIELD;
}
public int compare(Date date1, Date date2)
{
if (date1==null || date2==null)
return IGNORE_DATE_FIELD;
Calendar cal1 = new GregorianCalendar(),
cal2 = new GregorianCalendar();
cal1.setTime(date1);
cal2.setTime(date2);
int month=IGNORE_DATE_FIELD,
day=IGNORE_DATE_FIELD,
year=IGNORE_DATE_FIELD;
if ( compareMonth )
month = compareField(cal1.get(Calendar.MONTH),cal2.get(Calendar.MONTH));
if ( compareDay )
day = compareField(cal1.get(Calendar.DAY_OF_MONTH),cal2.get(Calendar.DAY_OF_MONTH));
if ( compareYear )
year = compareField(cal1.get(Calendar.YEAR),cal2.get(Calendar.YEAR));
if ( compareYear )
{
if (year!=EQ_DATE_FIELD)
return year;
if ( compareMonth )
{
if (month!=EQ_DATE_FIELD)
return month;
if ( compareDay )
return day;
return EQ_DATE_FIELD; // months are equal, no days to compare against
}
return EQ_DATE_FIELD; // years are equal, no months to compare against
}
else if ( compareMonth )
{
if ( month!=EQ_DATE_FIELD )
return month;
if ( compareDay )
return day;
return EQ_DATE_FIELD; // months are equal, no days to compare against
}
else if ( compareDay )
return day;
return IGNORE_DATE_FIELD;
}
};
// set of date patterns recognized by this matcher
private static final DateFieldComparator[] COMPARATORS = {
new DateFieldComparator(new SimpleDateFormat("MM/dd/yy"),true,true,true),
new DateFieldComparator(new SimpleDateFormat("MM/dd/yyyy"),true,true,true),
new DateFieldComparator(new SimpleDateFormat("MM/yy"),true,false,true),
new DateFieldComparator(new SimpleDateFormat("MM/yyyy"),true,false,true),
new DateFieldComparator(new SimpleDateFormat("MMM/yy"),true,false,false),
new DateFieldComparator(new SimpleDateFormat("MMM/yyyy"),true,false,false),
new DateFieldComparator(new SimpleDateFormat("MMM"),true,false,false),
new DateFieldComparator(new SimpleDateFormat("yy"),false,false,true),
new DateFieldComparator(new SimpleDateFormat("yyyy"),false,false,true)
};
// recognized matcher and date to use in matching
private DateFieldComparator comparator;
private Date rightDate;
/**
* throws IllegalArgumentException if cannot parse supplied date
* @param matcher
* @param right - date string to match against
*/
public void init(char matcher, String right)
{
super.init(matcher,right);
for (DateFieldComparator c : COMPARATORS)
{
rightDate = c.parse(right);
if ( rightDate!=null )
{
comparator = c;
break;
}
}
if ( rightDate==null || comparator==null)
{
throw new IllegalArgumentException("unable to parse date=" + right);
}
// @tag datematcher debug tagsea expressions : debug statement
// System.out.println("using rightDate=" + rightDate + " comparator=" + comparator);
}
public boolean matches(Object object) {
if ( object instanceof IWaypoint )
{
IWaypoint wp = (IWaypoint) object;
if ( rightDate!=null && comparator!=null )
{
int result = comparator.compare(wp.getDate(), rightDate);
switch ( getMatcher() )
{
case '<':
return result==LT_DATE_FIELD;
case '>':
return result==GT_DATE_FIELD;
case '=':
return result==EQ_DATE_FIELD;
case '!':
return !(result==EQ_DATE_FIELD);
}
}
}
return false;
}
}