package edu.brown.workload.filters;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import org.voltdb.catalog.CatalogType;
import edu.brown.logging.LoggerUtil;
import edu.brown.logging.LoggerUtil.LoggerBoolean;
import edu.brown.utils.ClassUtil;
import edu.brown.workload.AbstractTraceElement;
/**
* WorkloadIterator Filter
*/
public abstract class Filter {
public static final Logger LOG = Logger.getLogger(Filter.class);
private static final LoggerBoolean debug = new LoggerBoolean();
private static final LoggerBoolean trace = new LoggerBoolean();
static {
LoggerUtil.attachObserver(LOG, debug, trace);
}
private Filter next;
public enum FilterResult {
ALLOW,
SKIP,
HALT,
};
public Filter(Filter next) {
this.next = next;
}
public Filter() {
this(null);
}
/**
* Returns an ordered list of the filters within the chain that are the same type as the
* given search class (inclusive).
* @param <T>
* @param search
* @return
*/
public final <T extends Filter> List<T> getFilters(Class<? extends T> search) {
return (this.getFilters(search, new ArrayList<T>()));
}
public final List<Filter> getFilters() {
return (this.getFilters(Filter.class, new ArrayList<Filter>()));
}
@SuppressWarnings("unchecked")
private final <T extends Filter> List<T> getFilters(Class<? extends T> search, List<T> found) {
if (ClassUtil.getSuperClasses(this.getClass()).contains(search)) {
found.add((T)this);
}
if (this.next != null) this.next.getFilters(search, found);
return (found);
}
/**
* Chain a Filter to be executed after this Filter
* @param next
* @return This Filter
*/
public final Filter attach(Filter next) {
if (this.next != null) this.next.attach(next);
else this.next = next;
assert(this.next != null);
return (this);
}
public Filter.FilterResult apply(AbstractTraceElement<? extends CatalogType> element) {
Filter.FilterResult result = this.applyImpl(element);
if (debug.val)
LOG.debug("Filter: " + element + " => " + result);
return (result);
}
private final Filter.FilterResult applyImpl(AbstractTraceElement<? extends CatalogType> element) {
assert(element != null);
Filter.FilterResult result = this.filter(element);
if (trace.val && result != FilterResult.ALLOW)
LOG.trace(String.format("%s Filter: %s => %s",
this.getClass().getSimpleName(), element, result));
if (result == FilterResult.ALLOW && this.next != null) {
result = this.next.applyImpl(element);
}
return (result);
}
public void reset() {
this.resetImpl();
if (this.next != null) this.next.reset();
return;
}
protected abstract Filter.FilterResult filter(AbstractTraceElement<? extends CatalogType> element);
protected abstract void resetImpl();
public abstract String debugImpl();
public final String toString() {
return (this.debugImpl() + (this.next != null ? "\n" + this.next.toString() : ""));
}
}