/* * © Copyright FOCONIS AG, 2014 * * 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 org.openntf.formula.function; import org.openntf.formula.DateTime; import org.openntf.formula.FormulaContext; import org.openntf.formula.ValueHolder; import org.openntf.formula.ValueHolder.DataType; import org.openntf.formula.impl.AtFunction; /** * This class implements the default arithmetic, boolean and compare operators. * * As Operations are used at most, this is implemented to be (or to try to be) as fast as possible * * @author Roland Praml, Foconis AG * */ public abstract class OperatorsAbstract extends AtFunction { protected boolean isPermutative; /** * The constructor. Operators shoud be constructed via Operator.Factory * */ public OperatorsAbstract(final String image) { super(image); // Autodetect if the operation is permutative this.isPermutative = (image.charAt(0) == '*' && image.length() > 1); } /** * Evaluates the operator */ public ValueHolder evaluate(final FormulaContext ctx, final ValueHolder[] params) { ValueHolder v1 = params[0]; // Fetch first element to determine operation ValueHolder v2 = params[1]; // Fetch first element to determine operation if (v1.dataType == DataType.ERROR) { return v1; } if (v2.dataType == DataType.ERROR) { return v2; } boolean multi = v1.size > 1 ? true : false; if (v2.size > 1) multi = true; switch (v1.dataType) { case DATETIME: if (v2.dataType == DataType.DATETIME) { if (multi) return evaluateDateTime(ctx, params); return evaluateDateTime(ctx, v1.getDateTime(0), v2.getDateTime(0)); } break; case INTEGER: if (v2.dataType == DataType.INTEGER) { if (multi) return evaluateInt(ctx, params); return evaluateInt(ctx, v1.getInt(0), v2.getInt(0)); } //do not break - fall through. It may be integer & double case DOUBLE: if (v2.dataType.numeric) { if (multi) return evaluateNumber(ctx, params); return evaluateNumber(ctx, v1.getDouble(0), v2.getDouble(0)); } break; case STRING: if (v2.dataType == DataType.STRING) { if (multi) return evaluateString(ctx, params); return evaluateString(ctx, v1.getString(0), v2.getString(0)); } break; case BOOLEAN: if (v2.dataType == DataType.BOOLEAN) { if (multi) return evaluateBoolean(ctx, params); return evaluateBoolean(ctx, v1.getBoolean(0), v2.getBoolean(0)); } break; case _UNSET: break; case ERROR: break; default: break; } throw new IllegalArgumentException("Operation '" + v1.dataType + " " + getImage() + " " + v2.dataType + "' is not supported."); } protected abstract ValueHolder evaluateString(final FormulaContext ctx, final ValueHolder[] params); protected abstract ValueHolder evaluateString(final FormulaContext ctx, final String s1, final String s2); protected abstract ValueHolder evaluateNumber(final FormulaContext ctx, final ValueHolder[] params); protected abstract ValueHolder evaluateNumber(final FormulaContext ctx, final double d1, final double d2); protected abstract ValueHolder evaluateInt(final FormulaContext ctx, final ValueHolder[] params); protected abstract ValueHolder evaluateInt(final FormulaContext ctx, final int i1, final int i2); protected abstract ValueHolder evaluateDateTime(final FormulaContext ctx, final ValueHolder[] params); protected abstract ValueHolder evaluateDateTime(final FormulaContext ctx, final DateTime dt1, final DateTime dt2); protected abstract ValueHolder evaluateBoolean(final FormulaContext ctx, final ValueHolder[] params); protected abstract ValueHolder evaluateBoolean(final FormulaContext ctx, final boolean b1, final boolean b2); /* -------------------------------------------------- */ public boolean checkParamCount(final int i) { // ensured by parser return true; } }