blob: 163c5dcb555b2022130533cc5c15259f031f2368 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package org.apache.geode.cache.query.internal;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.query.AmbiguousNameException;
import org.apache.geode.cache.query.FunctionDomainException;
import org.apache.geode.cache.query.NameResolutionException;
import org.apache.geode.cache.query.QueryInvocationTargetException;
import org.apache.geode.cache.query.TypeMismatchException;
import org.apache.geode.cache.query.internal.parse.OQLLexerTokenTypes;
import org.apache.geode.pdx.PdxInstance;
/**
* Comparison value: <, >, <=, >=, <>, =
*
*/
public abstract class CompiledArithmetic extends AbstractCompiledValue
implements OQLLexerTokenTypes {
// persistent inst vars
public final CompiledValue _left;
public final CompiledValue _right;
private int _operator;
CompiledArithmetic(CompiledValue left, CompiledValue right, int op) {
// invariant:
_left = left;
_right = right;
_operator = op;
}
/* ******** CompiledValue Methods **************** */
@Override
public List getChildren() {
List list = new ArrayList();
list.add(_left);
list.add(_right);
return list;
}
@Override
public abstract int getType();
@Override
public Object evaluate(ExecutionContext context) throws FunctionDomainException,
TypeMismatchException, NameResolutionException, QueryInvocationTargetException {
Object left = _left.evaluate(context);
Object right = _right.evaluate(context);
if (context.isCqQueryContext() && left instanceof Region.Entry) {
left = ((Region.Entry) left).getValue();
}
if (context.isCqQueryContext() && right instanceof Region.Entry) {
right = ((Region.Entry) right).getValue();
}
if (left == null || right == null) {
throw new TypeMismatchException("Cannot evaluate arithmetic operations on null values");
}
// if read-serialized is not set, deserialize the pdx instance for comparison
// only if it is of the same class as that of the other object
if (!context.getCache().getPdxReadSerialized()) {
if (left instanceof PdxInstance && !(right instanceof PdxInstance)
&& ((PdxInstance) left).getClassName().equals(right.getClass().getName())) {
left = ((PdxInstance) left).getObject();
} else if (right instanceof PdxInstance && !(left instanceof PdxInstance)
&& ((PdxInstance) right).getClassName().equals(left.getClass().getName())) {
right = ((PdxInstance) right).getObject();
}
}
if (!(left instanceof Number && right instanceof Number)) {
throw new TypeMismatchException("Arithmetic Operations can only be applied to numbers");
}
Number num1 = (Number) left;
Number num2 = (Number) right;
try {
if (num1 instanceof Double)
if (num2 instanceof Double)
return evaluateArithmeticOperation((Double) num1, ((Double) num2));
else
return evaluateArithmeticOperation((Double) num1, Double.valueOf(num2.doubleValue()));
else if (num2 instanceof Double)
return evaluateArithmeticOperation(Double.valueOf(num1.doubleValue()), (Double) num2);
if (num1 instanceof Float)
if (num2 instanceof Float)
return evaluateArithmeticOperation((Float) num1, (Float) num2);
else
return evaluateArithmeticOperation((Float) num1, new Float(num2.doubleValue()));
else if (num2 instanceof Float)
return evaluateArithmeticOperation(new Float(num1.doubleValue()), (Float) num2);
if (num1 instanceof Long)
if (num2 instanceof Long)
return evaluateArithmeticOperation((Long) num1, ((Long) num2));
else {
long l1 = num1.longValue();
long l2 = num2.longValue();
return evaluateArithmeticOperation(l1, l2);
}
else if (num2 instanceof Long) {
long l1 = num1.longValue();
long l2 = num2.longValue();
return evaluateArithmeticOperation(l1, l2);
}
if (num1 instanceof Integer)
if (num2 instanceof Integer)
return evaluateArithmeticOperation((Integer) num1, (Integer) num2);
else {
int i1 = num1.intValue();
int i2 = num2.intValue();
return evaluateArithmeticOperation(i1, i2);
}
else if (num2 instanceof Integer) {
int i1 = num1.intValue();
int i2 = num2.intValue();
return evaluateArithmeticOperation(i1, i2);
}
if (num1 instanceof Short)
if (num2 instanceof Short)
return evaluateArithmeticOperation((Short) num1, ((Short) num2));
else {
short s1 = num1.shortValue();
short s2 = num2.shortValue();
return evaluateArithmeticOperation(s1, s2);
}
else if (num2 instanceof Short) {
short s1 = num1.shortValue();
short s2 = num2.shortValue();
return evaluateArithmeticOperation(s1, s2);
}
} catch (ArithmeticException e) {
throw new QueryInvocationTargetException(e);
}
throw new TypeMismatchException("Unable to apply arithmetic operation on non number");
}
@Override
public Set computeDependencies(ExecutionContext context)
throws TypeMismatchException, AmbiguousNameException, NameResolutionException {
context.addDependencies(this, _left.computeDependencies(context));
return context.addDependencies(this, _right.computeDependencies(context));
}
public abstract Double evaluateArithmeticOperation(Double n1, Double n2);
public abstract Float evaluateArithmeticOperation(Float n1, Float n2);
public abstract Long evaluateArithmeticOperation(Long n1, Long n2);
public abstract Integer evaluateArithmeticOperation(Integer n1, Integer n2);
public abstract Integer evaluateArithmeticOperation(Short n1, Short n2);
}