content: /*
   * Copyright (c) 2009 Andrejs Jermakovics.
   * 
   * 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:
   *     Andrejs Jermakovics - initial implementation
   */
  package it.unibz.instasearch.indexing.querying;
  
  import it.unibz.instasearch.indexing.Field;
  
  import java.util.ArrayList;
  import java.util.Calendar;
  import java.util.List;
  import java.util.Locale;
  import java.util.concurrent.TimeUnit;
  
  import org.apache.commons.lang.math.NumberUtils;
  import org.apache.lucene.index.Term;
  import org.apache.lucene.search.Query;
  import org.apache.lucene.search.TermQuery;
  import org.apache.lucene.search.TermRangeQuery;
  
  /**
   * Replaces named modified field values with millisecond range queries
   */
  public class ModifiedTimeConverter extends QueryVisitor {
  
  	private static ArrayList<String> intervalNames = new ArrayList<String>();
  	private static Calendar cal = Calendar.getInstance();
  	
  	static {
  		for(Interval interval: Interval.values())
  			intervalNames.add(interval.toString().toLowerCase(Locale.ENGLISH));
  		
  		intervalNames.add("3 days"); // as an example, any number can be specified
  	}
  	
  	private enum Interval
  	{
  		TODAY,
  		YESTERDAY,
  		HOUR(TimeUnit.HOURS.toMillis(1)),
  		DAY(TimeUnit.DAYS.toMillis(1)),
  		WEEK(TimeUnit.DAYS.toMillis(7)),
  		MONTH(TimeUnit.DAYS.toMillis(30))
  		;
  		
  		private long millis;
  		
  		Interval() {  };
  		
  		Interval(long millis) 
  		{
  			this.millis = millis;
  		}
  	}
  	
  	public static List<String> getDurationNames()
  	{
  		return intervalNames;
  	}
  	
  	/**
  	 * 
  	 */
  	public ModifiedTimeConverter() {
  	}
  	
  	@Override
  	public Query visit(TermQuery termQuery, Field termField) {
  		
  		if( termField != Field.MODIFIED )
  			return super.visit(termQuery, termField);
  		
  		Term t = termQuery.getTerm();
  		String intervalName = t.text();
  		int multiplier = 1;
  		
  		if( intervalName.matches("^[0-9]+.*$") ) // e.g. "3 days"
  		{
  			String multiplierString = intervalName.replaceAll("[^0-9]+", ""); // remove non-digits
  			multiplier = NumberUtils.toInt(multiplierString.trim(), 1);
  			
  			intervalName = intervalName.replaceAll("[0-9 ]+", "").trim(); // remove digits
  		}
  		
  		if( intervalName.endsWith("s") )
  			intervalName = intervalName.substring(0, intervalName.length() - 1 );
  		
  		Interval interval = getIntervalByName(intervalName);
  
  		if( interval == null )
  			return super.visit(termQuery, termField);
  
  		long start = 0, end = System.currentTimeMillis();
  		cal.setTimeInMillis(end);
  		
  		switch(interval)
  		{
  		case TODAY:
  			cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
  			start = cal.getTimeInMillis();
  			break;
  		case YESTERDAY:
  			cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DATE), 0, 0, 0);
  			end = cal.getTimeInMillis();
  			cal.add(Calendar.DATE, -1);
  			start = cal.getTimeInMillis();
  			break;
  		default: 
  			start = end - multiplier * interval.millis;
  		}
  		
  		String field = Field.MODIFIED.name().toLowerCase(Locale.ENGLISH);
  		//NumericRangeQuery rangeQuery = NumericRangeQuery.newLongRange(field, start, end, true, true);
  		
  		return new TermRangeQuery(field, "" + start, "" + end, true, true);
  	}
  	
  	private static Interval getIntervalByName(String intervalName)
  	{
  		try {
  			return Interval.valueOf(intervalName.toUpperCase());
  		} 
  		catch(Throwable ignored)
  		{
  			return null;
  		}
  	}
  }
  