package org.openanzo.glitter.expression.aggregate;
import java.util.Collection;
import java.util.List;
import org.openanzo.exceptions.LogUtils;
import org.openanzo.glitter.exception.ExpressionEvaluationException;
import org.openanzo.glitter.expression.AggregaterFunctionBase;
import org.openanzo.glitter.expression.builtin.PolymorphicLt;
import org.openanzo.glitter.query.PatternSolution;
import org.openanzo.glitter.query.SolutionSet;
import org.openanzo.glitter.util.Constants;
import org.openanzo.glitter.util.Glitter;
import org.openanzo.rdf.URI;
import org.openanzo.rdf.Value;
import org.openanzo.rdf.Variable;
import org.openanzo.rdf.Constants.NAMESPACES;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Implements the MIN() aggregate function.
*
* @author lee <lee@cambridgesemantics.com>
*
*/
public class Min extends AggregaterFunctionBase {
private static final Logger log = LoggerFactory.getLogger(Min.class);
public Value call(List<Variable> arguments, SolutionSet group) throws ExpressionEvaluationException {
// we find the minimum of all non-null values
// if any two values cannot be compared with '<', then the result is a type error.
Value min = null;
PolymorphicLt lt = new PolymorphicLt();
for (PatternSolution sol : group) {
Collection<Variable> vars = (arguments != null && !arguments.isEmpty()) ? arguments : sol.getBoundVariables();
for (Variable v : vars) {
Value val = sol.getBinding(v);
if (val != null) {
// skip malformed literals here
if (Glitter.isMalformedLiteral(val))
continue;
// swallow any exception comparing these values -- we arbitrarily go with the MIN
// of whatever type of value we see first
try {
if (min == null || lt.call(val, min).equals(Constants.TRUE))
min = val;
} catch (ExpressionEvaluationException e) {
log.trace(LogUtils.GLITTER_MARKER, "Skipping value that does not compare with canonical value in MIN(...)");
}
}
}
}
return min;
}
public URI getIdentifier() {
return Glitter.createURI(NAMESPACES.BUILTIN_AGGREGATE_NAMESPACE + "min");
}
@Override
public String toString() {
return "MIN";
}
}