/**
* AnalyzerBeans
* Copyright (C) 2014 Neopost - Customer Information Management
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.eobjects.analyzer.beans.filter;
import java.util.Comparator;
import org.eobjects.analyzer.beans.api.Distributed;
import org.eobjects.analyzer.beans.api.QueryOptimizedFilter;
import org.eobjects.analyzer.beans.api.Validate;
import org.eobjects.analyzer.data.InputColumn;
import org.eobjects.analyzer.data.InputRow;
import org.eobjects.analyzer.util.HasLabelAdvice;
import org.apache.metamodel.query.FilterItem;
import org.apache.metamodel.query.OperatorType;
import org.apache.metamodel.query.Query;
import org.apache.metamodel.query.SelectItem;
import org.apache.metamodel.schema.Column;
/**
* Abstract {@link QueryOptimizedFilter} which implementation for range filters
* which demarcate valid value bounds.
*/
@Distributed(true)
abstract class AbstractQueryOptimizedRangeFilter<E> implements QueryOptimizedFilter<RangeFilterCategory>,
Comparator<E>, HasLabelAdvice {
@Validate
public void validate() {
if (compare(getLowestValue(), getHighestValue()) > 0) {
throw new IllegalStateException("Lowest value is greater than the highest value");
}
}
public abstract InputColumn<? extends E> getColumn();
public abstract E getHighestValue();
public abstract E getLowestValue();
@Override
public RangeFilterCategory categorize(InputRow inputRow) {
E value = inputRow.getValue(getColumn());
return categorize(value);
}
protected RangeFilterCategory categorize(E value) {
if (value == null) {
return RangeFilterCategory.LOWER;
}
if (compare(value, getLowestValue()) < 0) {
return RangeFilterCategory.LOWER;
}
if (compare(value, getHighestValue()) > 0) {
return RangeFilterCategory.HIGHER;
}
return RangeFilterCategory.VALID;
}
@Override
public boolean isOptimizable(RangeFilterCategory category) {
return true;
}
@Override
public String getSuggestedLabel() {
final E highestValue = getHighestValue();
final E lowestValue = getLowestValue();
if (highestValue == null || lowestValue == null) {
return null;
}
final InputColumn<? extends E> column = getColumn();
if (column == null) {
return null;
}
return lowestValue + " =< " + column.getName() + " =< " + highestValue;
}
@Override
public Query optimizeQuery(Query q, RangeFilterCategory category) {
final Column col = getColumn().getPhysicalColumn();
final SelectItem selectItem = new SelectItem(col);
switch (category) {
case LOWER:
// special case, null is also considered "lower"
final FilterItem isNullFilter = new FilterItem(selectItem, OperatorType.EQUALS_TO, null);
final FilterItem isLowerThanFilter = new FilterItem(selectItem, OperatorType.LESS_THAN, getLowestValue());
q.where(new FilterItem(isNullFilter, isLowerThanFilter));
return q;
case HIGHER:
q.where(selectItem, OperatorType.GREATER_THAN, getHighestValue());
return q;
case VALID:
final E lowestValue = getLowestValue();
final E highestValue = getHighestValue();
if (compare(lowestValue, highestValue) == 0) {
// special case where highest and lowest value are equal
q.where(col, OperatorType.EQUALS_TO, lowestValue);
return q;
}
final FilterItem orFilter1;
{
final FilterItem f1 = new FilterItem(selectItem, OperatorType.GREATER_THAN, lowestValue);
final FilterItem f2 = new FilterItem(selectItem, OperatorType.EQUALS_TO, lowestValue);
orFilter1 = new FilterItem(f1, f2);
}
final FilterItem orFilter2;
{
final FilterItem f3 = new FilterItem(selectItem, OperatorType.LESS_THAN, highestValue);
final FilterItem f4 = new FilterItem(selectItem, OperatorType.EQUALS_TO, highestValue);
orFilter2 = new FilterItem(f3, f4);
}
q.where(orFilter1);
q.where(orFilter2);
return q;
default:
throw new UnsupportedOperationException();
}
}
}