From a991efc41e58482343db15a1717669b01c84a75f Mon Sep 17 00:00:00 2001 From: Josh Micich Date: Wed, 31 Dec 2008 19:32:44 +0000 Subject: [PATCH] Simplifying ValueEval hierarchy, added comments to Function and OperationEval. git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@730450 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/hssf/record/formula/OperationPtg.java | 4 - .../hssf/record/formula/eval/ConcatEval.java | 4 - .../poi/hssf/record/formula/eval/Eval.java | 2 +- .../hssf/record/formula/eval/FuncVarEval.java | 4 - .../hssf/record/formula/eval/NameEval.java | 2 +- .../hssf/record/formula/eval/NameXEval.java | 2 +- .../record/formula/eval/OperationEval.java | 74 ++++++++----------- .../hssf/record/formula/eval/PercentEval.java | 5 +- .../hssf/record/formula/eval/RangeEval.java | 5 +- .../formula/eval/RelationalOperationEval.java | 5 -- .../eval/TwoOperandNumericOperation.java | 4 - .../record/formula/eval/UnaryMinusEval.java | 5 +- .../record/formula/eval/UnaryPlusEval.java | 37 +++++----- .../record/formula/functions/Function.java | 59 +++++++++------ .../poi/ss/formula/WorkbookEvaluator.java | 19 ++--- 15 files changed, 99 insertions(+), 132 deletions(-) diff --git a/src/java/org/apache/poi/hssf/record/formula/OperationPtg.java b/src/java/org/apache/poi/hssf/record/formula/OperationPtg.java index f8acc81df3..ac0dcb45ff 100644 --- a/src/java/org/apache/poi/hssf/record/formula/OperationPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/OperationPtg.java @@ -42,8 +42,4 @@ public abstract class OperationPtg extends Ptg { public byte getDefaultOperandClass() { return Ptg.CLASS_VALUE; } - public final int getType() { - // TODO remove "int getType();" from Eval hierarchy - throw new RuntimeException("remove this method"); - } } diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/ConcatEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/ConcatEval.java index e08d8112fa..3833f94b9e 100644 --- a/src/java/org/apache/poi/hssf/record/formula/eval/ConcatEval.java +++ b/src/java/org/apache/poi/hssf/record/formula/eval/ConcatEval.java @@ -60,8 +60,4 @@ public final class ConcatEval implements OperationEval { public int getNumberOfOperands() { return delegate.getNumberOfOperands(); } - - public int getType() { - return delegate.getType(); - } } diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/Eval.java b/src/java/org/apache/poi/hssf/record/formula/eval/Eval.java index 086b765a30..1cf9047f7e 100644 --- a/src/java/org/apache/poi/hssf/record/formula/eval/Eval.java +++ b/src/java/org/apache/poi/hssf/record/formula/eval/Eval.java @@ -25,5 +25,5 @@ package org.apache.poi.hssf.record.formula.eval; * */ public interface Eval { - + // TODO - remove this interface } diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/FuncVarEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/FuncVarEval.java index feeb456bd1..d30c353599 100644 --- a/src/java/org/apache/poi/hssf/record/formula/eval/FuncVarEval.java +++ b/src/java/org/apache/poi/hssf/record/formula/eval/FuncVarEval.java @@ -44,10 +44,6 @@ public final class FuncVarEval extends FunctionEval { return delegate.getNumberOfOperands(); } - public int getType() { - return delegate.getType(); - } - public short getFunctionIndex() { return delegate.getFunctionIndex(); } diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/NameEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/NameEval.java index 1f77deec2a..9b5e21b184 100755 --- a/src/java/org/apache/poi/hssf/record/formula/eval/NameEval.java +++ b/src/java/org/apache/poi/hssf/record/formula/eval/NameEval.java @@ -20,7 +20,7 @@ package org.apache.poi.hssf.record.formula.eval; /** * @author Josh Micich */ -public final class NameEval implements Eval { +public final class NameEval implements ValueEval { private final String _functionName; diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/NameXEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/NameXEval.java index b67f4eb3d3..d1b8ffef76 100644 --- a/src/java/org/apache/poi/hssf/record/formula/eval/NameXEval.java +++ b/src/java/org/apache/poi/hssf/record/formula/eval/NameXEval.java @@ -22,7 +22,7 @@ import org.apache.poi.hssf.record.formula.NameXPtg; /** * @author Josh Micich */ -public final class NameXEval implements Eval { +public final class NameXEval implements ValueEval { private final NameXPtg _ptg; diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/OperationEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/OperationEval.java index aefd5aefad..22f7d364ae 100644 --- a/src/java/org/apache/poi/hssf/record/formula/eval/OperationEval.java +++ b/src/java/org/apache/poi/hssf/record/formula/eval/OperationEval.java @@ -1,53 +1,39 @@ -/* -* 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. -*/ -/* - * Created on May 8, 2005 - * - */ +/* ==================================================================== + 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; /** + * Common interface for implementations of Excel formula operations. + * * @author Amol S. Deshmukh < amolweb at ya hoo dot com > * */ -public interface OperationEval extends Eval { +public interface OperationEval { - /* - * Read this, this will make your work easier when coding - * an "evaluate()" - * - * Things to note when implementing evaluate(): - * 1. Check the length of operands - * (use "switch(operands[x])" if possible) - * - * 2. The possible Evals that you can get as args to evaluate are one of: - * NumericValueEval, StringValueEval, RefEval, AreaEval - * 3. If it is RefEval, the innerValueEval could be one of: - * NumericValueEval, StringValueEval, BlankEval - * 4. If it is AreaEval, each of the values could be one of: - * NumericValueEval, StringValueEval, BlankEval, RefEval - * - * 5. For numeric functions/operations, keep the result in double - * till the end and before returning a new NumberEval, check to see - * if the double is a NaN - if NaN, return ErrorEval.ERROR_503 - */ - public abstract Eval evaluate(Eval[] evals, int srcCellRow, short srcCellCol); + /** + * @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 null. + * @param srcRowIndex row index of the cell containing the formula under evaluation + * @param srcColumnIndex column index of the cell containing the formula under evaluation + * @return The evaluated result, possibly an {@link ErrorEval}, never null. + */ + Eval evaluate(Eval[] args, int srcRowIndex, short srcColumnIndex); - public abstract int getNumberOfOperands(); - - public abstract int getType(); + int getNumberOfOperands(); } diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/PercentEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/PercentEval.java index d8a579c42d..a7c0cbad4b 100755 --- a/src/java/org/apache/poi/hssf/record/formula/eval/PercentEval.java +++ b/src/java/org/apache/poi/hssf/record/formula/eval/PercentEval.java @@ -27,6 +27,7 @@ public final class PercentEval implements OperationEval { public static final OperationEval instance = new PercentEval(); private PercentEval() { + // enforce singleton } public Eval evaluate(Eval[] args, int srcRow, short srcCol) { @@ -46,8 +47,4 @@ public final class PercentEval implements OperationEval { public int getNumberOfOperands() { return 1; } - public final int getType() { - // TODO - remove - throw new RuntimeException("obsolete code should not be called"); - } } diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/RangeEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/RangeEval.java index 9398108fdc..938241c281 100644 --- a/src/java/org/apache/poi/hssf/record/formula/eval/RangeEval.java +++ b/src/java/org/apache/poi/hssf/record/formula/eval/RangeEval.java @@ -27,6 +27,7 @@ public final class RangeEval implements OperationEval { public static final OperationEval instance = new RangeEval(); private RangeEval() { + // enforces singleton } public Eval evaluate(Eval[] args, int srcCellRow, short srcCellCol) { @@ -64,8 +65,4 @@ public final class RangeEval implements OperationEval { public int getNumberOfOperands() { return 2; } - - public int getType() { - throw new RuntimeException("obsolete code should not be called"); - } } diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/RelationalOperationEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/RelationalOperationEval.java index 058b00e1ad..a1397f07f4 100644 --- a/src/java/org/apache/poi/hssf/record/formula/eval/RelationalOperationEval.java +++ b/src/java/org/apache/poi/hssf/record/formula/eval/RelationalOperationEval.java @@ -137,9 +137,4 @@ public abstract class RelationalOperationEval implements OperationEval { public final int getNumberOfOperands() { return 2; } - - public final int getType() { - // TODO - get rid of this method - throw new RuntimeException("Obsolete code - should not be called"); - } } diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/TwoOperandNumericOperation.java b/src/java/org/apache/poi/hssf/record/formula/eval/TwoOperandNumericOperation.java index 0f2933faea..5e0a91cc6f 100644 --- a/src/java/org/apache/poi/hssf/record/formula/eval/TwoOperandNumericOperation.java +++ b/src/java/org/apache/poi/hssf/record/formula/eval/TwoOperandNumericOperation.java @@ -22,10 +22,6 @@ package org.apache.poi.hssf.record.formula.eval; */ abstract class TwoOperandNumericOperation implements OperationEval { - public final int getType() { - // TODO - remove - throw new RuntimeException("obsolete code should not be called"); - } protected final double singleOperandEvaluate(Eval arg, int srcCellRow, short srcCellCol) throws EvaluationException { ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol); return OperandResolver.coerceValueToDouble(ve); diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/UnaryMinusEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/UnaryMinusEval.java index 780334ae8d..1354a78a36 100644 --- a/src/java/org/apache/poi/hssf/record/formula/eval/UnaryMinusEval.java +++ b/src/java/org/apache/poi/hssf/record/formula/eval/UnaryMinusEval.java @@ -27,6 +27,7 @@ public final class UnaryMinusEval implements OperationEval { public static final OperationEval instance = new UnaryMinusEval(); private UnaryMinusEval() { + // enforce singleton } public Eval evaluate(Eval[] args, int srcRow, short srcCol) { @@ -46,8 +47,4 @@ public final class UnaryMinusEval implements OperationEval { public int getNumberOfOperands() { return 1; } - public final int getType() { - // TODO - remove - throw new RuntimeException("obsolete code should not be called"); - } } diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/UnaryPlusEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/UnaryPlusEval.java index 831d342866..508fb0d060 100644 --- a/src/java/org/apache/poi/hssf/record/formula/eval/UnaryPlusEval.java +++ b/src/java/org/apache/poi/hssf/record/formula/eval/UnaryPlusEval.java @@ -1,19 +1,19 @@ -/* -* 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. -*/ +/* ==================================================================== + 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; @@ -27,6 +27,7 @@ public final class UnaryPlusEval implements OperationEval { public static final OperationEval instance = new UnaryPlusEval(); private UnaryPlusEval() { + // enforce singleton } public Eval evaluate(Eval[] args, int srcCellRow, short srcCellCol) { @@ -52,8 +53,4 @@ public final class UnaryPlusEval implements OperationEval { public int getNumberOfOperands() { return 1; } - - public int getType() { - throw new RuntimeException("obsolete code should not be called"); - } } diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Function.java b/src/java/org/apache/poi/hssf/record/formula/functions/Function.java index e33514a463..3bce8ffa83 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Function.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Function.java @@ -1,33 +1,46 @@ -/* -* 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. -*/ -/* - * Created on May 9, 2005 - * - */ +/* ==================================================================== + 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.functions; +import org.apache.poi.hssf.record.formula.eval.BlankEval; +import org.apache.poi.hssf.record.formula.eval.ErrorEval; import org.apache.poi.hssf.record.formula.eval.Eval; +import org.apache.poi.hssf.record.formula.eval.MissingArgEval; +import org.apache.poi.hssf.record.formula.eval.ValueEval; /** + * Common interface for all implementations of Excel built-in functions. + * * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - * Function serves as a marker interface. */ public interface Function { - public Eval evaluate(Eval[] evals, int srcCellRow, short srcCellCol); - + /** + * @param args the evaluated function arguments. Elements of this array typically implement + * {@link ValueEval}. Empty values are represented with {@link BlankEval} or {@link + * MissingArgEval}, never null. + * @param srcRowIndex row index of the cell containing the formula under evaluation + * @param srcColumnIndex column index of the cell containing the formula under evaluation + * @return The evaluated result, possibly an {@link ErrorEval}, never null. + * Note - Excel uses the error code #NUM! instead of IEEE NaN, so when + * numeric functions evaluate to {@link Double#NaN} be sure to translate the result to {@link + * ErrorEval#NUM_ERROR}. + * + */ + Eval evaluate(Eval[] args, int srcRowIndex, short srcColumnIndex); } diff --git a/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java b/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java index fac5715b1d..f913f924e2 100644 --- a/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java +++ b/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java @@ -263,7 +263,7 @@ public final class WorkbookEvaluator { // visibility raised for testing /* package */ ValueEval evaluateFormula(int sheetIndex, int srcRowNum, int srcColNum, Ptg[] ptgs, EvaluationTracker tracker) { - Stack stack = new Stack(); + Stack stack = new Stack(); for (int i = 0, iSize = ptgs.length; i < iSize; i++) { // since we don't know how to handle these yet :( @@ -287,7 +287,7 @@ public final class WorkbookEvaluator { } if (ptg instanceof MemErrPtg) { continue; } - Eval opResult; + ValueEval opResult; if (ptg instanceof OperationPtg) { OperationPtg optg = (OperationPtg) ptg; @@ -296,11 +296,11 @@ public final class WorkbookEvaluator { OperationEval operation = OperationEvaluatorFactory.create(optg); int numops = operation.getNumberOfOperands(); - Eval[] ops = new Eval[numops]; + ValueEval[] ops = new ValueEval[numops]; // storing the ops in reverse order since they are popping for (int j = numops - 1; j >= 0; j--) { - Eval p = stack.pop(); + ValueEval p = stack.pop(); ops[j] = p; } // logDebug("invoke " + operation + " (nAgs=" + numops + ")"); @@ -318,7 +318,7 @@ public final class WorkbookEvaluator { stack.push(opResult); } - ValueEval value = (ValueEval) stack.pop(); + ValueEval value = stack.pop(); if (!stack.isEmpty()) { throw new IllegalStateException("evaluation stack not empty"); } @@ -359,7 +359,7 @@ public final class WorkbookEvaluator { return evaluationResult; } - private static Eval invokeOperation(OperationEval operation, Eval[] ops, + private static ValueEval invokeOperation(OperationEval operation, Eval[] ops, EvaluationWorkbook workbook, int sheetIndex, int srcRowNum, int srcColNum) { if(operation instanceof FunctionEval) { @@ -368,7 +368,8 @@ public final class WorkbookEvaluator { return fe.getFreeRefFunction().evaluate(ops, workbook, sheetIndex, srcRowNum, srcColNum); } } - return operation.evaluate(ops, srcRowNum, (short)srcColNum); + // TODO - fix return type of this evaluate method: + return (ValueEval) operation.evaluate(ops, srcRowNum, (short)srcColNum); } private SheetRefEvaluator createExternSheetRefEvaluator(EvaluationTracker tracker, ExternSheetReferenceToken ptg) { @@ -391,7 +392,7 @@ public final class WorkbookEvaluator { * StringPtg, BoolPtg
special Note: OperationPtg subtypes cannot be * passed here! */ - private Eval getEvalForPtg(Ptg ptg, int sheetIndex, EvaluationTracker tracker) { + private ValueEval getEvalForPtg(Ptg ptg, int sheetIndex, EvaluationTracker tracker) { // consider converting all these (ptg instanceof XxxPtg) expressions to (ptg.getClass() == XxxPtg.class) if (ptg instanceof NamePtg) { @@ -465,7 +466,7 @@ public final class WorkbookEvaluator { throw new RuntimeException("Unexpected ptg class (" + ptg.getClass().getName() + ")"); } - private Eval evaluateNameFormula(Ptg[] ptgs, int sheetIndex, EvaluationTracker tracker) { + private ValueEval evaluateNameFormula(Ptg[] ptgs, int sheetIndex, EvaluationTracker tracker) { if (ptgs.length > 1) { throw new RuntimeException("Complex name formulas not supported yet"); }