Removed OperationEval and rearranged function/operator evaluation.
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@880593 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
5630df07a4
commit
518ae59f07
@ -17,17 +17,15 @@
|
||||
|
||||
package org.apache.poi.hssf.record.formula.eval;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.AbstractFunctionPtg;
|
||||
import org.apache.poi.hssf.record.formula.function.FunctionMetadata;
|
||||
import org.apache.poi.hssf.record.formula.function.FunctionMetadataRegistry;
|
||||
import org.apache.poi.hssf.record.formula.functions.*;
|
||||
import org.apache.poi.ss.formula.OperationEvaluationContext;
|
||||
import org.apache.poi.ss.formula.eval.NotImplementedException;
|
||||
|
||||
/**
|
||||
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
|
||||
*/
|
||||
public final class FunctionEval implements OperationEval {
|
||||
public final class FunctionEval {
|
||||
/**
|
||||
* Some function IDs that require special treatment
|
||||
*/
|
||||
@ -37,7 +35,7 @@ public final class FunctionEval implements OperationEval {
|
||||
/** 78 */
|
||||
public static final int OFFSET = 78;
|
||||
/** 148 */
|
||||
public static final int INDIRECT = 148;
|
||||
public static final int INDIRECT = FunctionMetadataRegistry.FUNCTION_INDEX_INDIRECT;
|
||||
/** 255 */
|
||||
public static final int EXTERNAL_FUNC = FunctionMetadataRegistry.FUNCTION_INDEX_EXTERNAL;
|
||||
}
|
||||
@ -222,33 +220,21 @@ public final class FunctionEval implements OperationEval {
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
private AbstractFunctionPtg _delegate;
|
||||
|
||||
public FunctionEval(AbstractFunctionPtg funcPtg) {
|
||||
_delegate = funcPtg;
|
||||
}
|
||||
|
||||
public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
|
||||
int fidx = _delegate.getFunctionIndex();
|
||||
/**
|
||||
* @return <code>null</code> if the specified functionIndex is for INDIRECT() or any external (add-in) function.
|
||||
*/
|
||||
public static Function getBasicFunction(int functionIndex) {
|
||||
// check for 'free ref' functions first
|
||||
switch (fidx) {
|
||||
switch (functionIndex) {
|
||||
case FunctionID.INDIRECT:
|
||||
return Indirect.instance.evaluate(args, ec);
|
||||
case FunctionID.EXTERNAL_FUNC:
|
||||
return UserDefinedFunction.instance.evaluate(args, ec);
|
||||
return null;
|
||||
}
|
||||
// else - must be plain function
|
||||
Function f = functions[fidx];
|
||||
if (f == null) {
|
||||
throw new NotImplementedException("FuncIx=" + fidx);
|
||||
Function result = functions[functionIndex];
|
||||
if (result == null) {
|
||||
throw new NotImplementedException("FuncIx=" + functionIndex);
|
||||
}
|
||||
int srcCellRow = ec.getRowIndex();
|
||||
int srcCellCol = ec.getColumnIndex();
|
||||
return f.evaluate(args, srcCellRow, (short) srcCellCol);
|
||||
}
|
||||
|
||||
public int getNumberOfOperands() {
|
||||
return _delegate.getNumberOfOperands();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -1,40 +0,0 @@
|
||||
/* ====================================================================
|
||||
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.hssf.record.formula.eval;
|
||||
|
||||
import org.apache.poi.ss.formula.OperationEvaluationContext;
|
||||
|
||||
/**
|
||||
* Common interface for implementations of Excel formula operations.
|
||||
*
|
||||
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
|
||||
*
|
||||
*/
|
||||
public interface OperationEval {
|
||||
|
||||
/**
|
||||
* @param args the evaluated operation arguments. Elements of this array typically implement
|
||||
* {@link ValueEval}. Empty values are represented with {@link BlankEval} or {@link
|
||||
* MissingArgEval}, never <code>null</code>.
|
||||
* @param ec used to identify the current cell under evaluation, and potentially to
|
||||
* dynamically create references
|
||||
* @return The evaluated result, possibly an {@link ErrorEval}, never <code>null</code>.
|
||||
*/
|
||||
ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec);
|
||||
int getNumberOfOperands();
|
||||
}
|
@ -31,6 +31,7 @@ public final class FunctionMetadataRegistry {
|
||||
public static final String FUNCTION_NAME_IF = "IF";
|
||||
|
||||
public static final short FUNCTION_INDEX_SUM = 4;
|
||||
public static final short FUNCTION_INDEX_INDIRECT = 148;
|
||||
public static final short FUNCTION_INDEX_EXTERNAL = 255;
|
||||
private static FunctionMetadataRegistry _instance;
|
||||
|
||||
|
@ -44,7 +44,6 @@ import org.apache.poi.hssf.record.formula.UnaryPlusPtg;
|
||||
import org.apache.poi.hssf.record.formula.eval.ConcatEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.FunctionEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.IntersectionEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.OperationEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.PercentEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.RangeEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.RelationalOperationEval;
|
||||
@ -52,7 +51,9 @@ import org.apache.poi.hssf.record.formula.eval.TwoOperandNumericOperation;
|
||||
import org.apache.poi.hssf.record.formula.eval.UnaryMinusEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.UnaryPlusEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
import org.apache.poi.hssf.record.formula.function.FunctionMetadataRegistry;
|
||||
import org.apache.poi.hssf.record.formula.functions.Function;
|
||||
import org.apache.poi.hssf.record.formula.functions.Indirect;
|
||||
|
||||
/**
|
||||
* This class creates <tt>OperationEval</tt> instances to help evaluate <tt>OperationPtg</tt>
|
||||
@ -62,85 +63,73 @@ import org.apache.poi.hssf.record.formula.functions.Function;
|
||||
*/
|
||||
final class OperationEvaluatorFactory {
|
||||
|
||||
private static final Map<OperationPtg, OperationEval> _instancesByPtgClass = initialiseInstancesMap2();
|
||||
private static final Map<OperationPtg, Function> _instancesByPtgClass = initialiseInstancesMap();
|
||||
|
||||
private OperationEvaluatorFactory() {
|
||||
// no instances of this class
|
||||
}
|
||||
|
||||
private static Map<OperationPtg, OperationEval> initialiseInstancesMap2() {
|
||||
Map<OperationPtg, OperationEval> m = new HashMap<OperationPtg, OperationEval>(32);
|
||||
private static Map<OperationPtg, Function> initialiseInstancesMap() {
|
||||
Map<OperationPtg, Function> m = new HashMap<OperationPtg, Function>(32);
|
||||
|
||||
put(m, 2, EqualPtg.instance, RelationalOperationEval.EqualEval);
|
||||
put(m, 2, GreaterEqualPtg.instance, RelationalOperationEval.GreaterEqualEval);
|
||||
put(m, 2, GreaterThanPtg.instance, RelationalOperationEval.GreaterThanEval);
|
||||
put(m, 2, LessEqualPtg.instance, RelationalOperationEval.LessEqualEval);
|
||||
put(m, 2, LessThanPtg.instance, RelationalOperationEval.LessThanEval);
|
||||
put(m, 2, NotEqualPtg.instance, RelationalOperationEval.NotEqualEval);
|
||||
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, 2, ConcatPtg.instance, ConcatEval.instance);
|
||||
put(m, 2, AddPtg.instance, TwoOperandNumericOperation.AddEval);
|
||||
put(m, 2, DividePtg.instance, TwoOperandNumericOperation.DivideEval);
|
||||
put(m, 2, MultiplyPtg.instance, TwoOperandNumericOperation.MultiplyEval);
|
||||
put(m, 1, PercentPtg.instance, PercentEval.instance);
|
||||
put(m, 2, PowerPtg.instance, TwoOperandNumericOperation.PowerEval);
|
||||
put(m, 2, SubtractPtg.instance, TwoOperandNumericOperation.SubtractEval);
|
||||
put(m, 1, UnaryMinusPtg.instance, UnaryMinusEval.instance);
|
||||
put(m, 1, UnaryPlusPtg.instance, UnaryPlusEval.instance);
|
||||
put(m, 2, RangePtg.instance, RangeEval.instance);
|
||||
put(m, 2, IntersectionPtg.instance, IntersectionEval.instance);
|
||||
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, OperationEval> m, int argCount,
|
||||
OperationPtg ptgKey, Function instance) {
|
||||
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, new OperationFunctionEval(instance, argCount));
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple adapter from {@link OperationEval} to {@link Function}
|
||||
*/
|
||||
private static final class OperationFunctionEval implements OperationEval {
|
||||
|
||||
private final Function _function;
|
||||
private final int _numberOfOperands;
|
||||
|
||||
public OperationFunctionEval(Function function, int argCount) {
|
||||
_function = function;
|
||||
_numberOfOperands = argCount;
|
||||
}
|
||||
|
||||
public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
|
||||
return _function.evaluate(args, ec.getRowIndex(), (short) ec.getColumnIndex());
|
||||
}
|
||||
|
||||
public int getNumberOfOperands() {
|
||||
return _numberOfOperands;
|
||||
}
|
||||
m.put(ptgKey, instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the OperationEval concrete impl instance corresponding
|
||||
* to the supplied operationPtg
|
||||
*/
|
||||
public static OperationEval create(OperationPtg ptg) {
|
||||
public static ValueEval evaluate(OperationPtg ptg, ValueEval[] args,
|
||||
OperationEvaluationContext ec) {
|
||||
if(ptg == null) {
|
||||
throw new IllegalArgumentException("ptg must not be null");
|
||||
}
|
||||
OperationEval result = _instancesByPtgClass.get(ptg);
|
||||
Function result = _instancesByPtgClass.get(ptg);
|
||||
|
||||
if (result != null) {
|
||||
return result;
|
||||
return result.evaluate(args, ec.getRowIndex(), (short) ec.getColumnIndex());
|
||||
}
|
||||
|
||||
if (ptg instanceof AbstractFunctionPtg) {
|
||||
return new FunctionEval((AbstractFunctionPtg)ptg);
|
||||
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() + ")");
|
||||
}
|
||||
|
@ -15,8 +15,11 @@
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record.formula.eval;
|
||||
package org.apache.poi.ss.formula;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.eval.NameEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.NameXEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
|
||||
import org.apache.poi.ss.formula.OperationEvaluationContext;
|
||||
import org.apache.poi.ss.formula.eval.NotImplementedException;
|
@ -57,7 +57,6 @@ import org.apache.poi.hssf.record.formula.eval.MissingArgEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.NameEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.NameXEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.NumberEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.OperationEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.RefEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.StringEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
@ -425,9 +424,8 @@ public final class WorkbookEvaluator {
|
||||
|
||||
if (optg instanceof UnionPtg) { continue; }
|
||||
|
||||
OperationEval operation = OperationEvaluatorFactory.create(optg);
|
||||
|
||||
int numops = operation.getNumberOfOperands();
|
||||
int numops = optg.getNumberOfOperands();
|
||||
ValueEval[] ops = new ValueEval[numops];
|
||||
|
||||
// storing the ops in reverse order since they are popping
|
||||
@ -436,7 +434,7 @@ public final class WorkbookEvaluator {
|
||||
ops[j] = p;
|
||||
}
|
||||
// logDebug("invoke " + operation + " (nAgs=" + numops + ")");
|
||||
opResult = operation.evaluate(ops, ec);
|
||||
opResult = OperationEvaluatorFactory.evaluate(optg, ops, ec);
|
||||
if (opResult == MissingArgEval.instance) {
|
||||
opResult = BlankEval.INSTANCE;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user