/**
* The contents of this file are subject to the Open Software License
* Version 3.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.opensource.org/licenses/osl-3.0.txt
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*/
package org.mulgara.query.filter.arithmetic;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.mulgara.query.QueryException;
import org.mulgara.query.Variable;
import org.mulgara.query.filter.value.NumericExpression;
/**
* Represents a numeric negation.
*
* @created Mar 17, 2008
* @author Paula Gearon
* @copyright © 2008 <a href="mailto:pgearon@users.sourceforge.net">Paula Gearon</a>
* @licence <a href="{@docRoot}/../../LICENCE.txt">Open Software License v3.0</a>
*/
public class UnaryMinus extends AbstractNumericOperation implements NumericExpression {
/** Generated Serialization ID for RMI */
private static final long serialVersionUID = 33264336439539952L;
/** The operand */
protected NumericExpression operand;
/**
* Creates a negation of the given term.
* @param operand The numeric term to negate.
*/
public UnaryMinus(NumericExpression operand) {
this.operand = operand;
operand.setContextOwner(this);
}
/** @see org.mulgara.query.filter.RDFTerm#getVariables() */
public Set<Variable> getVariables() {
return operand.getVariables();
}
/** {@inheritDoc} */
public boolean isGrounded() throws QueryException {
return operand.isGrounded();
}
// Not using generics in NumberOps as we can't know the types at this stage, but they are handy
// for defining the classes correctly
/**
* Calculate the result of this operation, returning it as a normal number.
* @throws QueryException The values of one of the operands could not be resolved.
* @see org.mulgara.query.filter.value.NumericExpression#getNumber()
*/
@SuppressWarnings("unchecked")
public Number getNumber() throws QueryException {
Number n = operand.getNumber();
InversionOp<Number> op = (InversionOp<Number>)opMap.get(n.getClass());
if (op == null) throw new AssertionError("Missing entry in negation operation map");
return op.invert(n);
}
/** Defines a unary negation function that returns a number of the same type as it receives */
interface InversionOp<T extends Number> {
public Class<T> getType();
public Number invert(T v);
}
/** A map of types to the functions that multiply them with correct type promotions */
protected static Map<Class<? extends Number>,InversionOp<? extends Number>> opMap = new HashMap<Class<? extends Number>,InversionOp<? extends Number>>();
/** A utility to add a number function to the promotion map */
private static void addType(InversionOp<? extends Number> op) { opMap.put(op.getType(), op); }
static {
addType(new InvertD());
addType(new InvertF());
addType(new InvertL());
addType(new InvertI());
addType(new InvertS());
addType(new InvertB());
}
private static class InvertD implements InversionOp<Double> {
public Class<Double> getType() { return Double.class; }
public Number invert(Double v) { return -v; }
}
private static class InvertF implements InversionOp<Float> {
public Class<Float> getType() { return Float.class; }
public Number invert(Float v) { return -v; }
}
private static class InvertL implements InversionOp<Long> {
public Class<Long> getType() { return Long.class; }
public Number invert(Long v) { return -v; }
}
private static class InvertI implements InversionOp<Integer> {
public Class<Integer> getType() { return Integer.class; }
public Number invert(Integer v) { return -v; }
}
private static class InvertS implements InversionOp<Short> {
public Class<Short> getType() { return Short.class; }
public Number invert(Short v) { return -v; }
}
private static class InvertB implements InversionOp<Byte> {
public Class<Byte> getType() { return Byte.class; }
public Number invert(Byte v) { return -v; }
}
}