123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- /* ====================================================================
- 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.poi.ss.formula.eval;
-
- import org.apache.poi.ss.formula.functions.ArrayFunction;
- import org.apache.poi.ss.formula.functions.Fixed2ArgFunction;
- import org.apache.poi.ss.formula.functions.Function;
- import org.apache.poi.ss.util.NumberComparer;
-
- /**
- * Base class for all comparison operator evaluators
- */
- public abstract class RelationalOperationEval extends Fixed2ArgFunction implements ArrayFunction {
-
- /**
- * Converts a standard compare result (-1, 0, 1) to <code>true</code> or <code>false</code>
- * according to subclass' comparison type.
- */
- protected abstract boolean convertComparisonResult(int cmpResult);
-
- /**
- * This is a description of how the relational operators apply in MS Excel.
- * Use this as a guideline when testing/implementing the evaluate methods
- * for the relational operators Evals.
- *
- * <pre>
- * Bool.TRUE > any number.
- * Bool > any string. ALWAYS
- * Bool.TRUE > Bool.FALSE
- * Bool.FALSE == Blank
- *
- * Strings are never converted to numbers or booleans
- * String > any number. ALWAYS
- * Non-empty String > Blank
- * Empty String == Blank
- * String are sorted dictionary wise
- *
- * Blank > Negative numbers
- * Blank == 0
- * Blank < Positive numbers
- * </pre>
- */
-
- public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
-
- ValueEval vA;
- ValueEval vB;
- try {
- vA = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex);
- vB = OperandResolver.getSingleValue(arg1, srcRowIndex, srcColumnIndex);
- } catch (EvaluationException e) {
- return e.getErrorEval();
- }
- int cmpResult = doCompare(vA, vB);
- boolean result = convertComparisonResult(cmpResult);
- return BoolEval.valueOf(result);
- }
-
- @Override
- public ValueEval evaluateArray(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
- ValueEval arg0 = args[0];
- ValueEval arg1 = args[1];
- return evaluateTwoArrayArgs(arg0, arg1, srcRowIndex, srcColumnIndex, (vA, vB) -> {
- int cmpResult = doCompare(vA, vB);
- boolean result = convertComparisonResult(cmpResult);
- return BoolEval.valueOf(result);
- });
-
- }
-
- private static int doCompare(ValueEval va, ValueEval vb) {
- // special cases when one operand is blank or missing
- if (va == BlankEval.instance || va instanceof MissingArgEval) {
- return compareBlank(vb);
- }
- if (vb == BlankEval.instance || vb instanceof MissingArgEval) {
- return -compareBlank(va);
- }
-
- if (va instanceof BoolEval) {
- if (vb instanceof BoolEval) {
- BoolEval bA = (BoolEval) va;
- BoolEval bB = (BoolEval) vb;
- if (bA.getBooleanValue() == bB.getBooleanValue()) {
- return 0;
- }
- return bA.getBooleanValue() ? 1 : -1;
- }
- return 1;
- }
- if (vb instanceof BoolEval) {
- return -1;
- }
- if (va instanceof StringEval) {
- if (vb instanceof StringEval) {
- StringEval sA = (StringEval) va;
- StringEval sB = (StringEval) vb;
- return sA.getStringValue().compareToIgnoreCase(sB.getStringValue());
- }
- return 1;
- }
- if (vb instanceof StringEval) {
- return -1;
- }
- if (va instanceof NumberEval) {
- if (vb instanceof NumberEval) {
- NumberEval nA = (NumberEval) va;
- NumberEval nB = (NumberEval) vb;
- return NumberComparer.compare(nA.getNumberValue(), nB.getNumberValue());
- }
- }
- throw new IllegalArgumentException("Bad operand types (" + va.getClass().getName() + "), ("
- + vb.getClass().getName() + ")");
- }
-
- private static int compareBlank(ValueEval v) {
- if (v == BlankEval.instance || v instanceof MissingArgEval) {
- return 0;
- }
- if (v instanceof BoolEval) {
- BoolEval boolEval = (BoolEval) v;
- return boolEval.getBooleanValue() ? -1 : 0;
- }
- if (v instanceof NumberEval) {
- NumberEval ne = (NumberEval) v;
- return NumberComparer.compare(0.0, ne.getNumberValue());
- }
- if (v instanceof StringEval) {
- StringEval se = (StringEval) v;
- return se.getStringValue().length() < 1 ? 0 : -1;
- }
- throw new IllegalArgumentException("bad value class (" + v.getClass().getName() + ")");
- }
-
- public static final Function EqualEval = new RelationalOperationEval() {
- protected boolean convertComparisonResult(int cmpResult) {
- return cmpResult == 0;
- }
- };
- public static final Function GreaterEqualEval = new RelationalOperationEval() {
- protected boolean convertComparisonResult(int cmpResult) {
- return cmpResult >= 0;
- }
- };
- public static final Function GreaterThanEval = new RelationalOperationEval() {
- protected boolean convertComparisonResult(int cmpResult) {
- return cmpResult > 0;
- }
- };
- public static final Function LessEqualEval = new RelationalOperationEval() {
- protected boolean convertComparisonResult(int cmpResult) {
- return cmpResult <= 0;
- }
- };
- public static final Function LessThanEval = new RelationalOperationEval() {
- protected boolean convertComparisonResult(int cmpResult) {
- return cmpResult < 0;
- }
- };
- public static final Function NotEqualEval = new RelationalOperationEval() {
- protected boolean convertComparisonResult(int cmpResult) {
- return cmpResult != 0;
- }
- };
- }
|