com.github.sadikovi.netflowlib.predicate.Operators Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2016 sadikovi
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.sadikovi.netflowlib.predicate;
import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
import com.github.sadikovi.netflowlib.predicate.Columns.Column;
import com.github.sadikovi.netflowlib.predicate.Inspectors.Inspector;
import com.github.sadikovi.netflowlib.predicate.Inspectors.AndInspector;
import com.github.sadikovi.netflowlib.predicate.Inspectors.NotInspector;
import com.github.sadikovi.netflowlib.predicate.Inspectors.OrInspector;
import com.github.sadikovi.netflowlib.predicate.Inspectors.ValueInspector;
import com.github.sadikovi.netflowlib.statistics.Statistics;
public final class Operators {
private Operators() { }
/**
* Abstract [[FilterPredicate]] interface defines a common predicate instance that can be
* transformed into another predicate or converted into [[ValueInspector]]. This class represents
* original user-defined predicate tree.
*/
public static abstract interface FilterPredicate {
public FilterPredicate update(PredicateTransform transformer,
HashMap statistics);
public Inspector convert();
}
/**
* [[ColumnPredicate]] is a base class for column predicates, links to a column and filtering
* value.
* @param column predicate column
* @param value filtering value or list of values for predicates that support multiple values
*/
static abstract class ColumnPredicate implements FilterPredicate, Serializable {
ColumnPredicate(Column column, Object value) {
if (column == null) {
throw new IllegalArgumentException("Column is null for predicate " + getClass().getName());
}
this.column = column;
// Since value can be any object potentially, we store it as Serializable to make sure that
// any distributed systems can resolve predicate once, and ship it to any node.
this.value = (Serializable) value;
this.inspector = getValueInspector(column.getColumnType());
}
protected abstract ValueInspector getValueInspector(Class> clazz);
public Column getColumn() {
return column;
}
public Object getValue() {
return value;
}
public ValueInspector inspector() {
return inspector;
}
public final Inspector convert() {
return inspector();
}
@Override
public String toString() {
return getClass().getSimpleName() + "(" + column + ", " + value + ")";
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
ColumnPredicate that = (ColumnPredicate) obj;
if (!column.equals(that.column)) return false;
if (value != null ? !value.equals(that.value) : that.value != null) return false;
return true;
}
@Override
public int hashCode() {
int result = column.hashCode();
result = 31 * result + (value != null ? value.hashCode() : 0);
result = 31 * result + getClass().hashCode();
return result;
}
private final Column column;
private final Serializable value;
private final ValueInspector inspector;
}
//////////////////////////////////////////////////////////////
// Concrete implementation of column predicates (Eq, Gt, Le)
//////////////////////////////////////////////////////////////
/** Equality filter including null-safe filtering */
public static final class Eq extends ColumnPredicate {
Eq(Column column, Object value) {
super(column, value);
}
@Override
public FilterPredicate update(PredicateTransform transformer,
HashMap statistics) {
return transformer.transform(this, statistics);
}
@Override
protected ValueInspector getValueInspector(Class> clazz) {
if (clazz.equals(Byte.class)) {
return new ValueInspector() {
@Override
public void update(byte value) {
setResult(value == Byte.class.cast(getValue()));
}
};
} else if (clazz.equals(Short.class)) {
return new ValueInspector() {
@Override
public void update(short value) {
setResult(value == Short.class.cast(getValue()));
}
};
} else if (clazz.equals(Integer.class)) {
return new ValueInspector() {
@Override
public void update(int value) {
setResult(value == Integer.class.cast(getValue()));
}
};
} else if (clazz.equals(Long.class)) {
return new ValueInspector() {
@Override
public void update(long value) {
setResult(value == Long.class.cast(getValue()));
}
};
} else {
throw new UnsupportedOperationException("Unsupported type for predicate " + toString());
}
}
}
/** "Greater Than" filter */
public static final class Gt extends ColumnPredicate {
Gt(Column column, Object value) {
super(column, value);
}
@Override
public FilterPredicate update(
PredicateTransform transformer,
HashMap statistics) {
return transformer.transform(this, statistics);
}
@Override
protected ValueInspector getValueInspector(Class> clazz) {
if (clazz.equals(Byte.class)) {
return new ValueInspector() {
@Override
public void update(byte value) {
setResult(value > Byte.class.cast(getValue()));
}
};
} else if (clazz.equals(Short.class)) {
return new ValueInspector() {
@Override
public void update(short value) {
setResult(value > Short.class.cast(getValue()));
}
};
} else if (clazz.equals(Integer.class)) {
return new ValueInspector() {
@Override
public void update(int value) {
setResult(value > Integer.class.cast(getValue()));
}
};
} else if (clazz.equals(Long.class)) {
return new ValueInspector() {
@Override
public void update(long value) {
setResult(value > Long.class.cast(getValue()));
}
};
} else {
throw new UnsupportedOperationException("Unsupported type for predicate " + toString());
}
}
}
/** "Greater Than Or Equal" filter */
public static final class Ge extends ColumnPredicate {
Ge(Column column, Object value) {
super(column, value);
}
@Override
public FilterPredicate update(
PredicateTransform transformer,
HashMap statistics) {
return transformer.transform(this, statistics);
}
@Override
protected ValueInspector getValueInspector(Class> clazz) {
if (clazz.equals(Byte.class)) {
return new ValueInspector() {
@Override
public void update(byte value) {
setResult(value >= Byte.class.cast(getValue()));
}
};
} else if (clazz.equals(Short.class)) {
return new ValueInspector() {
@Override
public void update(short value) {
setResult(value >= Short.class.cast(getValue()));
}
};
} else if (clazz.equals(Integer.class)) {
return new ValueInspector() {
@Override
public void update(int value) {
setResult(value >= Integer.class.cast(getValue()));
}
};
} else if (clazz.equals(Long.class)) {
return new ValueInspector() {
@Override
public void update(long value) {
setResult(value >= Long.class.cast(getValue()));
}
};
} else {
throw new UnsupportedOperationException("Unsupported type for predicate " + toString());
}
}
}
/** "Less Than" filter */
public static final class Lt extends ColumnPredicate {
Lt(Column column, Object value) {
super(column, value);
}
@Override
public FilterPredicate update(
PredicateTransform transformer,
HashMap statistics) {
return transformer.transform(this, statistics);
}
@Override
protected ValueInspector getValueInspector(Class> clazz) {
if (clazz.equals(Byte.class)) {
return new ValueInspector() {
@Override
public void update(byte value) {
setResult(value < Byte.class.cast(getValue()));
}
};
} else if (clazz.equals(Short.class)) {
return new ValueInspector() {
@Override
public void update(short value) {
setResult(value < Short.class.cast(getValue()));
}
};
} else if (clazz.equals(Integer.class)) {
return new ValueInspector() {
@Override
public void update(int value) {
setResult(value < Integer.class.cast(getValue()));
}
};
} else if (clazz.equals(Long.class)) {
return new ValueInspector() {
@Override
public void update(long value) {
setResult(value < Long.class.cast(getValue()));
}
};
} else {
throw new UnsupportedOperationException("Unsupported type for predicate " + toString());
}
}
}
/** "Less Than Or Equal" filter */
public static final class Le extends ColumnPredicate {
Le(Column column, Object value) {
super(column, value);
}
@Override
public FilterPredicate update(
PredicateTransform transformer,
HashMap statistics) {
return transformer.transform(this, statistics);
}
@Override
protected ValueInspector getValueInspector(Class> clazz) {
if (clazz.equals(Byte.class)) {
return new ValueInspector() {
@Override
public void update(byte value) {
setResult(value <= Byte.class.cast(getValue()));
}
};
} else if (clazz.equals(Short.class)) {
return new ValueInspector() {
@Override
public void update(short value) {
setResult(value <= Short.class.cast(getValue()));
}
};
} else if (clazz.equals(Integer.class)) {
return new ValueInspector() {
@Override
public void update(int value) {
setResult(value <= Integer.class.cast(getValue()));
}
};
} else if (clazz.equals(Long.class)) {
return new ValueInspector() {
@Override
public void update(long value) {
setResult(value <= Long.class.cast(getValue()));
}
};
} else {
throw new UnsupportedOperationException("Unsupported type for predicate " + toString());
}
}
}
/**
* [[MultiValueColumnPredicate]] allows to compare across values in the set provided, e.g. "In"
* predicate. Currently does not check against null values. Note, that `getValue()` method in
* case of multi value predicate returns null, use `getValues()` instead.
* @param column base predicate column
* @param values set of values to compare
*/
static abstract class MultiValueColumnPredicate extends ColumnPredicate {
MultiValueColumnPredicate(Column column, HashSet> values) {
super(column, null);
for (Object obj: values) {
this.values.add(obj);
}
}
public HashSet