io.katharsis.queryspec.InMemoryEvaluator Maven / Gradle / Ivy
package io.katharsis.queryspec;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import io.katharsis.utils.PropertyUtils;
/**
* Applies the given QuerySpec to the provided list in memory. Result available
* with getResult(). Use QuerySpec.apply to make use of this class.
*/
public class InMemoryEvaluator {
public List eval(List resources, QuerySpec querySpec) {
List results = new ArrayList();
results.addAll(resources);
// filter
if (!querySpec.getFilters().isEmpty()) {
FilterSpec filterSpec = FilterSpec.and(querySpec.getFilters());
applyFilter(results, filterSpec);
}
// sort
applySorting(results, querySpec.getSort());
// offset/limit
results = applyPaging(results, querySpec);
return results;
}
private void applySorting(List results, List sortSpec) {
if (!sortSpec.isEmpty()) {
Collections.sort(results, new SortSpecComparator(sortSpec));
}
}
private List applyPaging(List results, QuerySpec querySpec) {
int offset = (int) Math.min(querySpec.getOffset(), Integer.MAX_VALUE);
int limit = (int) Math.min(Integer.MAX_VALUE,
querySpec.getLimit() != null ? querySpec.getLimit() : Integer.MAX_VALUE);
limit = Math.min(results.size() - offset, limit);
if (offset > 0 || limit < results.size()) {
return results.subList(offset, offset + limit);
}
return results;
}
private void applyFilter(List results, FilterSpec filterSpec) {
if (filterSpec != null) {
Iterator iterator = results.iterator();
while (iterator.hasNext()) {
if (!matches(iterator.next(), filterSpec)) {
iterator.remove();
}
}
}
}
public static boolean matches(Object object, FilterSpec filterSpec) {
List expressions = filterSpec.getExpression();
if (expressions == null) {
Object value = PropertyUtils.getProperty(object, filterSpec.getAttributePath());
return filterSpec.getOperator().matches(value, filterSpec.getValue());
} else if (filterSpec.getOperator() == FilterOperator.OR) {
return matchesOr(object, expressions);
} else if (filterSpec.getOperator() == FilterOperator.AND) {
return matchesAnd(object, expressions);
} else if (filterSpec.getOperator() == FilterOperator.NOT) {
return !matches(object, FilterSpec.and(expressions));
}
throw new UnsupportedOperationException("not implemented " + filterSpec);
}
private static boolean matchesOr(Object object, List expressions) {
for (FilterSpec expr : expressions) {
if (matches(object, expr)) {
return true;
}
}
return false;
}
private static boolean matchesAnd(Object object, List expressions) {
for (FilterSpec expr : expressions) {
if (!matches(object, expr)) {
return false;
}
}
return true;
}
static class SortSpecComparator implements Comparator {
private List sortSpecs;
public SortSpecComparator(List sortSpecs) {
this.sortSpecs = sortSpecs;
}
@Override
@SuppressWarnings("unchecked")
public int compare(T o1, T o2) {
for (SortSpec orderSpec : sortSpecs) {
Comparable
© 2015 - 2024 Weber Informatics LLC | Privacy Policy