/* CPSTextFilter.java - created: Jan 31, 2008 * Copyright (C) 2008 Clayton Carter * * This file is part of the project "Crop Planning Software". For more * information: * website: https://github.com/claytonrcarter/cropplanning * email: cropplanning@gmail.com * * 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 <http://www.gnu.org/licenses/>. * */ package CPS.Data; import ca.odell.glazedlists.matchers.AbstractMatcherEditor; import ca.odell.glazedlists.matchers.Matcher; import ca.odell.glazedlists.matchers.MatcherEditor; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; /** * A class to hold/represent information about a "view" or filter of a data * set, in this case, of crop plans. There are 7 aspects to a crop plan filter: * * Filtering on "planting status": Has the record been planted, transplanted or * harvested. Each of these "status" data can be stored as "show only yes", * "show only no" and "show all". (getDoneXXX for the first two, filterOnXXX * for the last.) * * Filtering on dates: Does the planting/transplanting/harvest date for a record * fall within a certain range. * * <b>Note</b>: this does not support or represent a free form text filter * */ public class CPSComplexPlantingFilter extends AbstractMatcherEditor<CPSPlanting> implements Matcher<CPSPlanting> { private boolean metaViewLimited; private boolean filterOnPlanting, donePlanting; private boolean filterOnTransplanting, doneTransplanting; private boolean filterOnHarvest, doneHarvesting; private boolean filterOnPlantingMeth, directSeeded; private boolean filterOnPlantingDate; private Date plantingRangeStart, plantingRageEnd; private boolean filterOnTPDate; private Date tpRangeStart, tpRangeEnd; private boolean filterOnHarvestDate; private Date harvestRangeStart, harvestRangeEnd; private boolean filterOnAnyDate; private Date anyDateRangeStart, anyDateRangeEnd; public CPSComplexPlantingFilter() { reset(); } public void reset() { setFilterOnPlantingMethod( false ); setFilterOnPlanting( false ); setFilterOnTransplanting( false ); setFilterOnHarvest( false ); setFilterOnPlantingDate( false ); setFilterOnTPDate( false ); setFilterOnHarvestDate( false ); setFilterOnAnyDate( false ); setViewLimited( false ); } public void changed() { fireChanged( this ); } public MatcherEditor<CPSPlanting> getMatcherEditor() { return this; } @Override // TODO ideally this would create a new, immutable matcher each time it's called public Matcher getMatcher() { return this; } public boolean matches( CPSPlanting item ) { if ( ! isViewLimited() ) return true; if ( item.getIgnore() ) return false; boolean m = true; if ( filterOnPlantingMethod() ) m &= filterMethodDirectSeed() == item.isDirectSeeded(); if ( filterOnPlanting() ) m &= isDonePlanting() == item.getDonePlanting(); if ( filterOnTransplanting() ) m &= isDoneTransplanting() == item.getDoneTP(); if ( filterOnHarvest()) m &= isDoneHarvesting() == item.getDoneHarvest(); if ( filterOnPlantingDate() ) // they only defined a start date for the range if ( getPlantingRangeEnd() == null ) m &= item.getDateToPlant().after( bumpDateByDay( getPlantingRangeStart(), -1 ) ); // they only defined an end date for the range else if ( getPlantingRangeStart() == null ) m &= item.getDateToPlant().before( bumpDateByDay( getPlantingRangeEnd(), 1 ) ); else m &= item.getDateToPlant().after( bumpDateByDay( getPlantingRangeStart(), -1 ) ) && item.getDateToPlant().before( bumpDateByDay( getPlantingRangeEnd(), 1 ) ); if ( filterOnTPDate() ) if ( getTpRangeEnd() == null ) m &= item.getDateToTP().after( bumpDateByDay( getTpRangeStart(), -1 ) ); else if ( getTpRangeStart() == null ) m &= item.getDateToTP().before( bumpDateByDay( getTpRangeEnd(), 1 ) ); else m &= item.getDateToTP().after( bumpDateByDay( getTpRangeStart(), -1 ) ) && item.getDateToTP().before( bumpDateByDay( getTpRangeEnd(), 1 ) ); if ( filterOnHarvestDate() ) if ( getHarvestRangeEnd() == null ) m &= item.getDateToHarvest().after( bumpDateByDay( getHarvestRangeStart(), -1 ) ); else if ( getHarvestRangeStart() == null ) m &= item.getDateToHarvest().before( bumpDateByDay( getHarvestRangeEnd(), 1 ) ); else m &= item.getDateToHarvest().after( bumpDateByDay( getHarvestRangeStart(), -1 ) ) && item.getDateToHarvest().before( bumpDateByDay( getHarvestRangeEnd(), 1 ) ); return m; // if ( filterOnAnyDate() ) { // if ( getAnyDateRangeEnd() == null ) // filterString += " ( date_plant >= " + escapeValue( getAnyDateRangeStart() ) + " OR " + // " date_tp >= " + escapeValue( getAnyDateRangeStart() ) + " OR " + // " date_harvest >= " + escapeValue( getAnyDateRangeStart() ) + " ) "; // else if ( getAnyDateRangeStart() == null ) // filterString += " ( date_plant <= " + escapeValue( getAnyDateRangeEnd() ) + " OR " + // " date_tp <= " + escapeValue( getAnyDateRangeEnd() ) + " OR " + // " date_harvest <= " + escapeValue( getAnyDateRangeEnd() ) + " ) "; // else { // both != null // filterString += " ( date_plant BETWEEN " + escapeValue( getAnyDateRangeStart() ) + " AND " + // escapeValue( getAnyDateRangeEnd() ) + " OR "; // filterString += " date_tp BETWEEN " + escapeValue( getAnyDateRangeStart() ) + " AND " + // escapeValue( getAnyDateRangeEnd() ) + " OR "; // filterString += " date_harvest BETWEEN " + escapeValue( getAnyDateRangeStart() ) + " AND " + // escapeValue( getAnyDateRangeEnd() ) + " ) "; // } // filterString += " AND "; // } } public boolean isViewLimited() { return metaViewLimited; } public void setViewLimited( boolean b ) { metaViewLimited = b; } /* ***************************************************************** */ /* PLANTING METHOD /* ***************************************************************** */ public boolean filterOnPlantingMethod() { return filterOnPlantingMeth; } public boolean setFilterOnPlantingMethod( boolean b ) { return filterOnPlantingMeth = b; } public boolean filterMethodDirectSeed() { return directSeeded; } public boolean setFilterMethodDirectSeed( boolean b ) { return directSeeded = b; } public boolean filterMethodTransplant() { return ! filterMethodDirectSeed(); } public boolean setFilterMethodTransplant( boolean b ) { return setFilterMethodDirectSeed( ! b ); } /* ***************************************************************** */ /* PLANTING/TP/HARVEST COMPLETED /* ***************************************************************** */ public boolean setFilterOnPlanting( boolean filterOnPlanting ) { return this.filterOnPlanting = filterOnPlanting; } public boolean setFilterOnTransplanting( boolean filterOnTransplanting ) { return this.filterOnTransplanting = filterOnTransplanting; } public boolean setFilterOnHarvest( boolean filterOnHarvest ) { return this.filterOnHarvest = filterOnHarvest; } public boolean filterOnPlanting() { return filterOnPlanting; } public boolean filterOnTransplanting() { return filterOnTransplanting; } public boolean filterOnHarvest() { return filterOnHarvest; } public void setDonePlanting( boolean donePlanting ) { this.donePlanting = donePlanting; } public void setDoneTransplanting( boolean doneTransplanting ) { this.doneTransplanting = doneTransplanting; } public void setDoneHarvesting( boolean doneHarvesting ) { this.doneHarvesting = doneHarvesting; } public boolean isDonePlanting() { return donePlanting; } public boolean isDoneTransplanting() { return doneTransplanting; } public boolean isDoneHarvesting() { return doneHarvesting; } /* ***************************************************************** */ /* DATES /* ***************************************************************** */ public boolean setFilterOnPlantingDate( boolean filterOnPlantingDate ) { return this.filterOnPlantingDate = filterOnPlantingDate; } public boolean setFilterOnTPDate( boolean filterOnTPDate ) { return this.filterOnTPDate = filterOnTPDate; } public boolean setFilterOnHarvestDate( boolean filterOnHarvestDate ) { return this.filterOnHarvestDate = filterOnHarvestDate; } public boolean setFilterOnAnyDate( boolean filterOnAnyDate ) { return this.filterOnAnyDate = filterOnAnyDate; } public void setPlantingRangeStart( Date plantingRangeStart ) { this.plantingRangeStart = plantingRangeStart; } public void setPlantingRangeEnd( Date plantingRangeEnd ) { this.plantingRageEnd = plantingRangeEnd; } public void setTpRangeStart( Date tpRangeStart ) { this.tpRangeStart = tpRangeStart; } public void setTpRangeEnd( Date tpRangeEnd ) { this.tpRangeEnd = tpRangeEnd; } public void setHarvestRangeStart( Date harvestDateStart ) { this.harvestRangeStart = harvestDateStart; } public void setHarvestRangeEnd( Date harvestDateEnd ) { this.harvestRangeEnd = harvestDateEnd; } public void setAnyDateRangeStart( Date anyDateRangeStart ) { this.anyDateRangeStart = anyDateRangeStart; } public void setAnyDateRangeEnd( Date anyDateRangeEnd ) { this.anyDateRangeEnd = anyDateRangeEnd; } public boolean filterOnPlantingDate() { return filterOnPlantingDate; } public boolean filterOnTPDate() { return filterOnTPDate; } public boolean filterOnHarvestDate() { return filterOnHarvestDate; } public boolean filterOnAnyDate() { return filterOnAnyDate; } public Date getPlantingRangeStart() { return plantingRangeStart; } public Date getPlantingRangeEnd() { return plantingRageEnd; } public Date getTpRangeStart() { return tpRangeStart; } public Date getTpRangeEnd() { return tpRangeEnd; } public Date getHarvestRangeStart() { return harvestRangeStart; } public Date getHarvestRangeEnd() { return harvestRangeEnd; } public Date getAnyDateRangeStart() { return anyDateRangeStart; } public Date getAnyDateRangeEnd() { return anyDateRangeEnd; } protected Date bumpDateByDay( Date d, int i ) { GregorianCalendar cal = new GregorianCalendar(); cal.setTime( d ); cal.add( GregorianCalendar.DAY_OF_YEAR, i ); return cal.getTime(); } /* ***************************************************************** */ /* methods to alter the filter in place /* ***************************************************************** */ public void setAsDirectSeededFilter() { reset(); setViewLimited(true); setFilterOnPlantingMethod(true); setFilterMethodDirectSeed(true); changed(); } public void setAsTransplatedFilter() { reset(); setViewLimited(true); setFilterOnPlantingMethod( true ); setFilterMethodTransplant(true); changed(); } public void setAsAllNotPlantedFilter() { reset(); setViewLimited(true); setFilterOnPlanting(true); setDonePlanting(false); changed(); } public void setAsDSNotPlantedFilter() { reset(); setAsAllNotPlantedFilter(); setFilterOnPlantingMethod(true); setFilterMethodDirectSeed(true); changed(); } public void setAsTPNotSeededFilter() { reset(); setAsAllNotPlantedFilter(); setFilterOnPlantingMethod(true); setFilterMethodTransplant(true); changed(); } public void setAsTPSeededNotPlantedFilter() { reset(); setAsTPNotSeededFilter(); setFilterOnPlanting(true); setDonePlanting(true); setFilterOnTransplanting(true); setDoneTransplanting(false); changed(); } public void setAsThisWeekFilter() { reset(); GregorianCalendar temp = new GregorianCalendar(); temp.setTime( new Date() ); setViewLimited(true); setFilterOnAnyDate(true); temp.set( Calendar.DAY_OF_WEEK, Calendar.SUNDAY ); setAnyDateRangeStart( temp.getTime() ); temp.set( Calendar.DAY_OF_WEEK, Calendar.SATURDAY ); setAnyDateRangeEnd( temp.getTime() ); changed(); } public void setAsNextWeekFilter() { reset(); setAsThisWeekFilter(); GregorianCalendar temp = new GregorianCalendar(); temp.setTime( new Date() ); // start day should be this Sunday ... temp.setTime( getAnyDateRangeStart() ); // ... so we add a week temp.add( GregorianCalendar.WEEK_OF_YEAR, 1 ); setAnyDateRangeStart( temp.getTime() ); temp.set( GregorianCalendar.DAY_OF_WEEK, GregorianCalendar.SATURDAY ); setAnyDateRangeEnd( temp.getTime() ); changed(); } public void setAsThisAndNextWeekFilter() { reset(); setAsThisWeekFilter(); GregorianCalendar temp = new GregorianCalendar(); // leave start date alone, since it should be OK already // end day should be this Saturday ... temp.setTime( getAnyDateRangeEnd() ); // ... so we add a week temp.add( GregorianCalendar.WEEK_OF_YEAR, 1 ); setAnyDateRangeEnd( temp.getTime() ); changed(); } /* ***************************************************************** */ /* STATIC factory methods for default "filters" /* ***************************************************************** */ /** * @return An instance of {@link CPSComplexPlantingFilter} set up to * match all direct seeded plantings ("done" or not) */ public static CPSComplexPlantingFilter directSeededFilter() { CPSComplexPlantingFilter ds = new CPSComplexPlantingFilter(); ds.setAsDirectSeededFilter(); return ds; } /** * @return An instance of {@link CPSComplexPlantingFilter} set up to * match all transplanted plantings ("done" or not) */ public static CPSComplexPlantingFilter transplantedFilter() { CPSComplexPlantingFilter tp = new CPSComplexPlantingFilter(); tp.setAsTransplatedFilter(); return tp; } public static CPSComplexPlantingFilter allNotPlantedFilter() { CPSComplexPlantingFilter f = new CPSComplexPlantingFilter(); f.setAsAllNotPlantedFilter(); return f; } public static CPSComplexPlantingFilter DSNotPlantedFilter() { CPSComplexPlantingFilter f = new CPSComplexPlantingFilter(); f.setAsDSNotPlantedFilter(); return f; } public static CPSComplexPlantingFilter TPNotSeededFilter() { CPSComplexPlantingFilter f = new CPSComplexPlantingFilter(); f.setAsTPNotSeededFilter(); return f; } public static CPSComplexPlantingFilter TPSeededNotPlantedFilter() { CPSComplexPlantingFilter f = new CPSComplexPlantingFilter(); f.setAsTPSeededNotPlantedFilter(); return f; } public static CPSComplexPlantingFilter thisWeekFilter() { CPSComplexPlantingFilter f = new CPSComplexPlantingFilter(); f.setAsThisWeekFilter(); return f; } public static CPSComplexPlantingFilter nextWeekFilter() { CPSComplexPlantingFilter f = new CPSComplexPlantingFilter(); f.setAsNextWeekFilter(); return f; } public static CPSComplexPlantingFilter thisAndNextWeekFilter() { CPSComplexPlantingFilter f = new CPSComplexPlantingFilter(); f.setAsThisAndNextWeekFilter(); return f; } public static CPSComplexPlantingFilter ghSeedingFilter( Date rangeStart, Date ranageEnd ) { CPSComplexPlantingFilter f = TPNotSeededFilter(); f.setFilterOnPlantingDate( true ); f.setPlantingRangeStart( rangeStart ); f.setPlantingRangeEnd( ranageEnd ); return f; } public static CPSComplexPlantingFilter fieldDSFilter( Date rangeStart, Date ranageEnd ) { CPSComplexPlantingFilter f = DSNotPlantedFilter(); f.setFilterOnPlantingDate( true ); f.setPlantingRangeStart( rangeStart ); f.setPlantingRangeEnd( ranageEnd ); return f; } public static CPSComplexPlantingFilter fieldTPFilter( Date rangeStart, Date ranageEnd ) { CPSComplexPlantingFilter f = TPSeededNotPlantedFilter(); f.setFilterOnTPDate( true ); f.setTpRangeStart( rangeStart ); f.setTpRangeEnd( ranageEnd ); return f; } }