package org.mulgara.query.filter.arithmetic; import java.util.HashSet; import java.util.Set; import org.jrdf.graph.Node; import org.mulgara.query.QueryException; import org.mulgara.query.filter.Context; import org.mulgara.query.filter.ContextOwner; import org.mulgara.query.filter.RDFTerm; import org.mulgara.query.filter.value.AbstractComparable; import org.mulgara.query.filter.value.IRI; import org.mulgara.query.filter.value.NumericExpression; import org.mulgara.query.filter.value.NumericLiteral; import org.mulgara.query.filter.value.SimpleLiteral; /** * Implements common functionality for arithmetic operations. * * @created Apr 10, 2008 * @author Paula Gearon * @copyright © 2008 <a href="http://www.topazproject.org/">The Topaz Project</a> * @licence <a href="{@docRoot}/../../LICENCE.txt">Open Software License v3.0</a> */ public abstract class AbstractNumericOperation extends AbstractComparable implements NumericExpression { /** Serialization ID */ private static final long serialVersionUID = -6795347129998821301L; /** The owner of the context for resolving here */ private ContextOwner owner = null; public AbstractNumericOperation() { super(); } /** @see org.mulgara.query.filter.value.ComparableExpression#getValue() */ public Number getValue() throws QueryException { return getNumber(); } /** @see org.mulgara.query.filter.RDFTerm#getJRDFValue() */ public Node getJRDFValue() throws QueryException { return new NumericLiteral(getNumber()).getJRDFValue(); } /** @see org.mulgara.query.filter.RDFTerm#equals(RDFTerm) */ public boolean equals(RDFTerm v) throws QueryException { return compare(getNumber(), v.getValue()) == 0; } /** @see org.mulgara.query.filter.RDFTerm#isBlank() */ public boolean isBlank() throws QueryException { return false; } /** @see org.mulgara.query.filter.RDFTerm#isIRI() */ public boolean isIRI() throws QueryException { return false; } /** @see org.mulgara.query.filter.RDFTerm#isLiteral() */ public boolean isLiteral() throws QueryException { return true; } /** @see org.mulgara.query.filter.RDFTerm#isURI() */ public boolean isURI() throws QueryException { return false; } /** @see org.mulgara.query.filter.RDFTerm#sameTerm(RDFTerm) */ public boolean sameTerm(RDFTerm v) throws QueryException { return getNumber().equals(v.getValue()); } /** @see org.mulgara.query.filter.Filter#test(Context) */ public boolean test(Context context) throws QueryException { setCurrentContext(context); return getNumber().doubleValue() != 0.0; } /** @see org.mulgara.query.filter.RDFTerm#setContextOwner(org.mulgara.query.filter.ContextOwner) */ public void setContextOwner(ContextOwner owner) { this.owner = owner; owner.addContextListener(this); } /** @see org.mulgara.query.filter.RDFTerm#getContextOwner() */ public ContextOwner getContextOwner() { return owner; } /** @see org.mulgara.query.filter.value.NumericExpression#getNumber() */ public abstract Number getNumber() throws QueryException; ////////////////////////////////////////////////////////////// // Implementation of AbstractComparable.compare(Object,Object) ////////////////////////////////////////////////////////////// /** The set of classes to be compared as floating point */ private static Set<Class<? extends Number>> floatUpcast = new HashSet<Class<? extends Number>>(); /* Initialize the set of classes to be compared as floating point */ static { floatUpcast.add(Double.class); floatUpcast.add(Float.class); } /** * @see org.mulgara.query.filter.value.AbstractComparable#compare(java.lang.Object, java.lang.Object) */ protected int compare(Object left, Object right) throws QueryException { return compare((Number)left, right); } /** * Compares 2 numbers of unknown type. If they are both floating point, then use Double compare, * otherwise use Long compare. * @param left The first number in the comparison. * @param right The second number. This cannot be assumed to be a number due to poorly formed queries. * @return -1 if left<right, +1 if left>right, 0 if left==right * @throws QueryException if right is a type other than {@link java.lang.Number}. */ protected int compare(Number left, Object right) throws QueryException { if (!(right instanceof Number)) throw new QueryException("Cannot compare a number to a: " + right.getClass().getSimpleName()); if (floatUpcast.contains(left.getClass()) || floatUpcast.contains(right.getClass())) { return Double.valueOf(left.doubleValue()).compareTo(((Number)right).doubleValue()); } return Long.valueOf(left.longValue()).compareTo(((Number)right).longValue()); } ///////////////////////////////// // Implementation of ValueLiteral ///////////////////////////////// /** @see org.mulgara.query.filter.value.ValueLiteral#getLexical() */ public String getLexical() throws QueryException { return getValue().toString(); } /** @see org.mulgara.query.filter.value.ValueLiteral#getLang() */ public SimpleLiteral getLang() { return SimpleLiteral.EMPTY; } /** @see org.mulgara.query.filter.value.ValueLiteral#getType() */ public IRI getType() throws QueryException { return NumericLiteral.getTypeFor(getValue()); } /** @see org.mulgara.query.filter.value.ValueLiteral#isSimple() */ public boolean isSimple() throws QueryException { return false; } }