/* Copyright 2013 The jeo project. All rights reserved.
*
* Licensed 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 io.jeo.filter;
import java.util.Locale;
import java.util.Objects;
/**
*
* @author Ian Schneider <ischneider@boundlessgeo.com>
*/
public class Math implements Expression {
public static final char ADD = '+';
public static final char SUBTRACT = '-';
public static final char MULTIPLY = '*';
public static final char DIVIDE = '/';
final char operator;
final Expression left;
final Expression right;
public Math(char operator, Expression left, Expression right) {
Objects.requireNonNull(left, "operands must not be null");
Objects.requireNonNull(right, "operands must not be null");
if ("+-*/".indexOf(operator) < 0) {
throw new IllegalArgumentException(String.format(Locale.ROOT,"illegal operator: %s, must be one of: %s, %s, %s, %s",
Character.toString(operator), operator, ADD, SUBTRACT, MULTIPLY, DIVIDE));
}
this.operator = operator;
this.left = left;
this.right = right;
}
public char operator() {
return operator;
}
public Expression left() {
return left;
}
public Expression right() {
return right;
}
double getValue(Expression e, Object obj) {
Object val = e.evaluate(obj);
// mask missing values as NaN
return val == null ? Double.NaN : ((Number) val).doubleValue();
}
@Override
public Object evaluate(Object obj) {
double n1 = getValue(left, obj);
double n2 = getValue(right, obj);
Double res;
switch (operator) {
case ADD: res = n1 + n2; break;
case SUBTRACT: res = n1 - n2; break;
case MULTIPLY: res = n1 * n2; break;
case DIVIDE: res = n1 / n2; break;
default:
throw new RuntimeException();
}
return res;
}
@Override
public <R> R accept(FilterVisitor<R> visitor, Object obj) {
return visitor.visit(this, obj);
}
@Override
public int hashCode() {
int hash = 7;
hash = 13 * hash + this.operator;
hash = 13 * hash + (this.left != null ? this.left.hashCode() : 0);
hash = 13 * hash + (this.right != null ? this.right.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Math other = (Math) obj;
if (this.operator != other.operator) {
return false;
}
if (this.left != other.left && (this.left == null || !this.left.equals(other.left))) {
return false;
}
if (this.right != other.right && (this.right == null || !this.right.equals(other.right))) {
return false;
}
return true;
}
@Override
public String toString() {
return "(" + left + " " + operator + " " + right + ")";
}
}