package org.activityinfo.legacy.shared.adapter;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Lists;
import org.activityinfo.model.resource.ResourceId;
import org.activityinfo.core.shared.criteria.*;
import java.util.List;
/**
* Helper functions for evaluating criteria
*/
public class CriteriaEvaluation {
/**
* Partially evaluates a Criteria against a {@code FormClass} id
*
* @return a Predicate which returns true if {@code FormInstances} of this class
* <strong>might</strong> be included in the result.
*/
public static Predicate<ResourceId> evaluatePartiallyOnClassId(Criteria criteria) {
ClassIdEvaluator evaluator = new ClassIdEvaluator();
criteria.accept(evaluator);
return evaluator.getPredicate();
}
private static class ClassIdEvaluator extends CriteriaVisitor {
private List<Predicate<ResourceId>> classPredicates = Lists.newArrayList();
private boolean hasCriteriaIndependentOfClassId = false;
@Override
public void visitInstanceIdCriteria(IdCriteria criteria) {
hasCriteriaIndependentOfClassId = true;
}
@Override
public void visitFieldCriteria(FieldCriteria criteria) {
hasCriteriaIndependentOfClassId = true;
}
@Override
public void visitClassCriteria(ClassCriteria criteria) {
classPredicates.add(Predicates.equalTo(criteria.getClassId()));
}
@Override
public void visitIntersection(CriteriaIntersection intersection) {
ClassIdEvaluator visitor = evaluateSet(intersection);
if (visitor.hasCriteriaIndependentOfClassId) {
hasCriteriaIndependentOfClassId = true;
}
classPredicates.add(Predicates.and(visitor.classPredicates));
}
@Override
public void visitUnion(CriteriaUnion union) {
ClassIdEvaluator visitor = evaluateSet(union.getElements());
if (visitor.hasCriteriaIndependentOfClassId) {
hasCriteriaIndependentOfClassId = true;
} else {
classPredicates.add(Predicates.or(visitor.classPredicates));
}
}
private ClassIdEvaluator evaluateSet(Iterable<Criteria> set) {
ClassIdEvaluator visitor = new ClassIdEvaluator();
for (Criteria criteria : set) {
criteria.accept(visitor);
}
return visitor;
}
public Predicate<ResourceId> getPredicate() {
if (classPredicates.isEmpty()) {
return Predicates.alwaysTrue();
} else {
Preconditions.checkState(classPredicates.size() == 1);
return classPredicates.get(0);
}
}
}
}