123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- /* ====================================================================
- 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;
-
- import java.lang.reflect.Constructor;
- import java.lang.reflect.Modifier;
- import java.util.HashMap;
- import java.util.Map;
-
- import org.apache.poi.ss.formula.ptg.AbstractFunctionPtg;
- import org.apache.poi.ss.formula.ptg.AddPtg;
- import org.apache.poi.ss.formula.ptg.ConcatPtg;
- import org.apache.poi.ss.formula.ptg.DividePtg;
- import org.apache.poi.ss.formula.ptg.EqualPtg;
- import org.apache.poi.ss.formula.ptg.GreaterEqualPtg;
- import org.apache.poi.ss.formula.ptg.GreaterThanPtg;
- import org.apache.poi.ss.formula.ptg.IntersectionPtg;
- import org.apache.poi.ss.formula.ptg.LessEqualPtg;
- import org.apache.poi.ss.formula.ptg.LessThanPtg;
- import org.apache.poi.ss.formula.ptg.MultiplyPtg;
- import org.apache.poi.ss.formula.ptg.NotEqualPtg;
- import org.apache.poi.ss.formula.ptg.OperationPtg;
- import org.apache.poi.ss.formula.ptg.PercentPtg;
- import org.apache.poi.ss.formula.ptg.PowerPtg;
- import org.apache.poi.ss.formula.ptg.RangePtg;
- import org.apache.poi.ss.formula.ptg.SubtractPtg;
- import org.apache.poi.ss.formula.ptg.UnaryMinusPtg;
- import org.apache.poi.ss.formula.ptg.UnaryPlusPtg;
- import org.apache.poi.ss.formula.eval.ConcatEval;
- import org.apache.poi.ss.formula.eval.FunctionEval;
- import org.apache.poi.ss.formula.eval.IntersectionEval;
- import org.apache.poi.ss.formula.eval.PercentEval;
- import org.apache.poi.ss.formula.eval.RangeEval;
- import org.apache.poi.ss.formula.eval.RelationalOperationEval;
- import org.apache.poi.ss.formula.eval.TwoOperandNumericOperation;
- import org.apache.poi.ss.formula.eval.UnaryMinusEval;
- import org.apache.poi.ss.formula.eval.UnaryPlusEval;
- import org.apache.poi.ss.formula.eval.ValueEval;
- import org.apache.poi.ss.formula.function.FunctionMetadataRegistry;
- import org.apache.poi.ss.formula.functions.ArrayFunction;
- import org.apache.poi.ss.formula.functions.Function;
- import org.apache.poi.ss.formula.functions.Indirect;
-
- /**
- * This class creates <tt>OperationEval</tt> instances to help evaluate <tt>OperationPtg</tt>
- * formula tokens.
- *
- * @author Josh Micich
- */
- final class OperationEvaluatorFactory {
-
- private static final Map<OperationPtg, Function> _instancesByPtgClass = initialiseInstancesMap();
-
- private OperationEvaluatorFactory() {
- // no instances of this class
- }
-
- private static Map<OperationPtg, Function> initialiseInstancesMap() {
- Map<OperationPtg, Function> m = new HashMap<OperationPtg, Function>(32);
-
- put(m, EqualPtg.instance, RelationalOperationEval.EqualEval);
- put(m, GreaterEqualPtg.instance, RelationalOperationEval.GreaterEqualEval);
- put(m, GreaterThanPtg.instance, RelationalOperationEval.GreaterThanEval);
- put(m, LessEqualPtg.instance, RelationalOperationEval.LessEqualEval);
- put(m, LessThanPtg.instance, RelationalOperationEval.LessThanEval);
- put(m, NotEqualPtg.instance, RelationalOperationEval.NotEqualEval);
-
- put(m, ConcatPtg.instance, ConcatEval.instance);
- put(m, AddPtg.instance, TwoOperandNumericOperation.AddEval);
- put(m, DividePtg.instance, TwoOperandNumericOperation.DivideEval);
- put(m, MultiplyPtg.instance, TwoOperandNumericOperation.MultiplyEval);
- put(m, PercentPtg.instance, PercentEval.instance);
- put(m, PowerPtg.instance, TwoOperandNumericOperation.PowerEval);
- put(m, SubtractPtg.instance, TwoOperandNumericOperation.SubtractEval);
- put(m, UnaryMinusPtg.instance, UnaryMinusEval.instance);
- put(m, UnaryPlusPtg.instance, UnaryPlusEval.instance);
- put(m, RangePtg.instance, RangeEval.instance);
- put(m, IntersectionPtg.instance, IntersectionEval.instance);
- return m;
- }
-
- private static void put(Map<OperationPtg, Function> m, OperationPtg ptgKey,
- Function instance) {
- // make sure ptg has single private constructor because map lookups assume singleton keys
- Constructor<?>[] cc = ptgKey.getClass().getDeclaredConstructors();
- if (cc.length > 1 || !Modifier.isPrivate(cc[0].getModifiers())) {
- throw new RuntimeException("Failed to verify instance ("
- + ptgKey.getClass().getName() + ") is a singleton.");
- }
- m.put(ptgKey, instance);
- }
-
- /**
- * returns the OperationEval concrete impl instance corresponding
- * to the supplied operationPtg
- */
- public static ValueEval evaluate(OperationPtg ptg, ValueEval[] args,
- OperationEvaluationContext ec) {
- if(ptg == null) {
- throw new IllegalArgumentException("ptg must not be null");
- }
- Function result = _instancesByPtgClass.get(ptg);
-
- if (result != null) {
- EvaluationSheet evalSheet = ec.getWorkbook().getSheet(ec.getSheetIndex());
- EvaluationCell evalCell = evalSheet.getCell(ec.getRowIndex(), ec.getColumnIndex());
-
- if (evalCell.isPartOfArrayFormulaGroup() && result instanceof ArrayFunction)
- return ((ArrayFunction) result).evaluateArray(args, ec.getRowIndex(), ec.getColumnIndex());
-
- return result.evaluate(args, ec.getRowIndex(), (short) ec.getColumnIndex());
- }
-
- if (ptg instanceof AbstractFunctionPtg) {
- AbstractFunctionPtg fptg = (AbstractFunctionPtg)ptg;
- int functionIndex = fptg.getFunctionIndex();
- switch (functionIndex) {
- case FunctionMetadataRegistry.FUNCTION_INDEX_INDIRECT:
- return Indirect.instance.evaluate(args, ec);
- case FunctionMetadataRegistry.FUNCTION_INDEX_EXTERNAL:
- return UserDefinedFunction.instance.evaluate(args, ec);
- }
-
- return FunctionEval.getBasicFunction(functionIndex).evaluate(args, ec.getRowIndex(), (short) ec.getColumnIndex());
- }
- throw new RuntimeException("Unexpected operation ptg class (" + ptg.getClass().getName() + ")");
- }
- }
|