/**
* 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.concurrent.atomic.AtomicInteger;
import org.eobjects.analyzer.beans.api.Categorized;
import org.eobjects.analyzer.beans.api.Configured;
import org.eobjects.analyzer.beans.api.Description;
import org.eobjects.analyzer.beans.api.Distributed;
import org.eobjects.analyzer.beans.api.FilterBean;
import org.eobjects.analyzer.beans.api.NumberProperty;
import org.eobjects.analyzer.beans.api.QueryOptimizedFilter;
import org.eobjects.analyzer.beans.api.Validate;
import org.eobjects.analyzer.beans.categories.FilterCategory;
import org.eobjects.analyzer.data.InputColumn;
import org.eobjects.analyzer.data.InputRow;
import org.eobjects.analyzer.util.HasLabelAdvice;
import org.apache.metamodel.query.Query;
import org.apache.metamodel.schema.Column;
@FilterBean("Max rows")
@Description("Sets a maximum number of rows to process.")
@Categorized(FilterCategory.class)
@Distributed(false)
public class MaxRowsFilter implements QueryOptimizedFilter<MaxRowsFilter.Category>, HasLabelAdvice {
public static enum Category {
VALID, INVALID
}
@Configured
@NumberProperty(negative = false, zero = false)
@Description("The maximum number of rows to process.")
int maxRows = 1000;
@Configured
@NumberProperty(negative = false, zero = false)
@Description("The first row (aka 'offset') to process.")
int firstRow = 1;
@Configured(required = false)
@Description("Optional column to use for specifying dataset ordering. Use if consistent pagination is needed.")
InputColumn<?> orderColumn;
private final AtomicInteger counter = new AtomicInteger();
public MaxRowsFilter() {
}
public MaxRowsFilter(int firstRow, int maxRows) {
this();
this.firstRow = firstRow;
this.maxRows = maxRows;
}
@Override
public String getSuggestedLabel() {
return "Max " + getMaxRows() + " rows";
}
public void setMaxRows(int maxRows) {
this.maxRows = maxRows;
}
public int getMaxRows() {
return maxRows;
}
public int getFirstRow() {
return firstRow;
}
public void setFirstRow(int firstRow) {
this.firstRow = firstRow;
}
public InputColumn<?> getOrderColumn() {
return orderColumn;
}
public void setOrderColumn(InputColumn<?> orderColumn) {
this.orderColumn = orderColumn;
}
@Validate
public void validate() {
if (maxRows <= 0) {
throw new IllegalStateException("Max rows value must be a positive integer");
}
if (firstRow <= 0) {
throw new IllegalStateException("First row value must be a positive integer");
}
}
@Override
public Category categorize(InputRow inputRow) {
int count = counter.incrementAndGet();
if (count < firstRow || count >= maxRows + firstRow) {
return Category.INVALID;
}
return Category.VALID;
}
@Override
public boolean isOptimizable(Category category) {
// can only optimize the valid records
return category == Category.VALID;
}
@Override
public Query optimizeQuery(Query q, Category category) {
if (category == Category.VALID) {
q.setMaxRows(maxRows);
if (firstRow > 1) {
q.setFirstRow(firstRow);
}
if (orderColumn != null) {
Column physicalColumn = orderColumn.getPhysicalColumn();
q.orderBy(physicalColumn);
}
} else {
throw new IllegalStateException("Can only optimize the VALID max rows category");
}
return q;
}
}