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
This commit is contained in:
Josh Micich 2008-12-31 19:32:44 +00:00
parent e85bd756c5
commit a991efc41e
15 changed files with 99 additions and 132 deletions

View File

@ -42,8 +42,4 @@ public abstract class OperationPtg extends Ptg {
public byte getDefaultOperandClass() { public byte getDefaultOperandClass() {
return Ptg.CLASS_VALUE; return Ptg.CLASS_VALUE;
} }
public final int getType() {
// TODO remove "int getType();" from Eval hierarchy
throw new RuntimeException("remove this method");
}
} }

View File

@ -60,8 +60,4 @@ public final class ConcatEval implements OperationEval {
public int getNumberOfOperands() { public int getNumberOfOperands() {
return delegate.getNumberOfOperands(); return delegate.getNumberOfOperands();
} }
public int getType() {
return delegate.getType();
}
} }

View File

@ -25,5 +25,5 @@ package org.apache.poi.hssf.record.formula.eval;
* *
*/ */
public interface Eval { public interface Eval {
// TODO - remove this interface
} }

View File

@ -44,10 +44,6 @@ public final class FuncVarEval extends FunctionEval {
return delegate.getNumberOfOperands(); return delegate.getNumberOfOperands();
} }
public int getType() {
return delegate.getType();
}
public short getFunctionIndex() { public short getFunctionIndex() {
return delegate.getFunctionIndex(); return delegate.getFunctionIndex();
} }

View File

@ -20,7 +20,7 @@ package org.apache.poi.hssf.record.formula.eval;
/** /**
* @author Josh Micich * @author Josh Micich
*/ */
public final class NameEval implements Eval { public final class NameEval implements ValueEval {
private final String _functionName; private final String _functionName;

View File

@ -22,7 +22,7 @@ import org.apache.poi.hssf.record.formula.NameXPtg;
/** /**
* @author Josh Micich * @author Josh Micich
*/ */
public final class NameXEval implements Eval { public final class NameXEval implements ValueEval {
private final NameXPtg _ptg; private final NameXPtg _ptg;

View File

@ -1,53 +1,39 @@
/* /* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 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 not use this file except in compliance with
* the License. You may obtain a copy of the License at the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and See the License for the specific language governing permissions and
* limitations under the License. limitations under the License.
*/ ==================================================================== */
/*
* Created on May 8, 2005
*
*/
package org.apache.poi.hssf.record.formula.eval; 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 > * @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 * @param args the evaluated operation arguments. Elements of this array typically implement
* an "evaluate()" * {@link ValueEval}. Empty values are represented with {@link BlankEval} or {@link
* * MissingArgEval}, never <code>null</code>.
* Things to note when implementing evaluate(): * @param srcRowIndex row index of the cell containing the formula under evaluation
* 1. Check the length of operands * @param srcColumnIndex column index of the cell containing the formula under evaluation
* (use "switch(operands[x])" if possible) * @return The evaluated result, possibly an {@link ErrorEval}, never <code>null</code>.
* */
* 2. The possible Evals that you can get as args to evaluate are one of: Eval evaluate(Eval[] args, int srcRowIndex, short srcColumnIndex);
* 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);
public abstract int getNumberOfOperands(); int getNumberOfOperands();
public abstract int getType();
} }

View File

@ -27,6 +27,7 @@ public final class PercentEval implements OperationEval {
public static final OperationEval instance = new PercentEval(); public static final OperationEval instance = new PercentEval();
private PercentEval() { private PercentEval() {
// enforce singleton
} }
public Eval evaluate(Eval[] args, int srcRow, short srcCol) { public Eval evaluate(Eval[] args, int srcRow, short srcCol) {
@ -46,8 +47,4 @@ public final class PercentEval implements OperationEval {
public int getNumberOfOperands() { public int getNumberOfOperands() {
return 1; return 1;
} }
public final int getType() {
// TODO - remove
throw new RuntimeException("obsolete code should not be called");
}
} }

View File

@ -27,6 +27,7 @@ public final class RangeEval implements OperationEval {
public static final OperationEval instance = new RangeEval(); public static final OperationEval instance = new RangeEval();
private RangeEval() { private RangeEval() {
// enforces singleton
} }
public Eval evaluate(Eval[] args, int srcCellRow, short srcCellCol) { public Eval evaluate(Eval[] args, int srcCellRow, short srcCellCol) {
@ -64,8 +65,4 @@ public final class RangeEval implements OperationEval {
public int getNumberOfOperands() { public int getNumberOfOperands() {
return 2; return 2;
} }
public int getType() {
throw new RuntimeException("obsolete code should not be called");
}
} }

View File

@ -137,9 +137,4 @@ public abstract class RelationalOperationEval implements OperationEval {
public final int getNumberOfOperands() { public final int getNumberOfOperands() {
return 2; return 2;
} }
public final int getType() {
// TODO - get rid of this method
throw new RuntimeException("Obsolete code - should not be called");
}
} }

View File

@ -22,10 +22,6 @@ package org.apache.poi.hssf.record.formula.eval;
*/ */
abstract class TwoOperandNumericOperation implements OperationEval { 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 { protected final double singleOperandEvaluate(Eval arg, int srcCellRow, short srcCellCol) throws EvaluationException {
ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol); ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol);
return OperandResolver.coerceValueToDouble(ve); return OperandResolver.coerceValueToDouble(ve);

View File

@ -27,6 +27,7 @@ public final class UnaryMinusEval implements OperationEval {
public static final OperationEval instance = new UnaryMinusEval(); public static final OperationEval instance = new UnaryMinusEval();
private UnaryMinusEval() { private UnaryMinusEval() {
// enforce singleton
} }
public Eval evaluate(Eval[] args, int srcRow, short srcCol) { public Eval evaluate(Eval[] args, int srcRow, short srcCol) {
@ -46,8 +47,4 @@ public final class UnaryMinusEval implements OperationEval {
public int getNumberOfOperands() { public int getNumberOfOperands() {
return 1; return 1;
} }
public final int getType() {
// TODO - remove
throw new RuntimeException("obsolete code should not be called");
}
} }

View File

@ -1,19 +1,19 @@
/* /* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 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 not use this file except in compliance with
* the License. You may obtain a copy of the License at the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and See the License for the specific language governing permissions and
* limitations under the License. limitations under the License.
*/ ==================================================================== */
package org.apache.poi.hssf.record.formula.eval; 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(); public static final OperationEval instance = new UnaryPlusEval();
private UnaryPlusEval() { private UnaryPlusEval() {
// enforce singleton
} }
public Eval evaluate(Eval[] args, int srcCellRow, short srcCellCol) { public Eval evaluate(Eval[] args, int srcCellRow, short srcCellCol) {
@ -52,8 +53,4 @@ public final class UnaryPlusEval implements OperationEval {
public int getNumberOfOperands() { public int getNumberOfOperands() {
return 1; return 1;
} }
public int getType() {
throw new RuntimeException("obsolete code should not be called");
}
} }

View File

@ -1,33 +1,46 @@
/* /* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 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 not use this file except in compliance with
* the License. You may obtain a copy of the License at the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and See the License for the specific language governing permissions and
* limitations under the License. limitations under the License.
*/ ==================================================================== */
/*
* Created on May 9, 2005
*
*/
package org.apache.poi.hssf.record.formula.functions; 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.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 &lt; amolweb at ya hoo dot com &gt; * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* Function serves as a marker interface.
*/ */
public interface Function { 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 <code>null</code>.
* @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 <code>null</code>.
* <b>Note</b> - Excel uses the error code <i>#NUM!</i> instead of IEEE <i>NaN</i>, 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);
} }

View File

@ -263,7 +263,7 @@ public final class WorkbookEvaluator {
// visibility raised for testing // visibility raised for testing
/* package */ ValueEval evaluateFormula(int sheetIndex, int srcRowNum, int srcColNum, Ptg[] ptgs, EvaluationTracker tracker) { /* package */ ValueEval evaluateFormula(int sheetIndex, int srcRowNum, int srcColNum, Ptg[] ptgs, EvaluationTracker tracker) {
Stack<Eval> stack = new Stack<Eval>(); Stack<ValueEval> stack = new Stack<ValueEval>();
for (int i = 0, iSize = ptgs.length; i < iSize; i++) { for (int i = 0, iSize = ptgs.length; i < iSize; i++) {
// since we don't know how to handle these yet :( // since we don't know how to handle these yet :(
@ -287,7 +287,7 @@ public final class WorkbookEvaluator {
} }
if (ptg instanceof MemErrPtg) { continue; } if (ptg instanceof MemErrPtg) { continue; }
Eval opResult; ValueEval opResult;
if (ptg instanceof OperationPtg) { if (ptg instanceof OperationPtg) {
OperationPtg optg = (OperationPtg) ptg; OperationPtg optg = (OperationPtg) ptg;
@ -296,11 +296,11 @@ public final class WorkbookEvaluator {
OperationEval operation = OperationEvaluatorFactory.create(optg); OperationEval operation = OperationEvaluatorFactory.create(optg);
int numops = operation.getNumberOfOperands(); int numops = operation.getNumberOfOperands();
Eval[] ops = new Eval[numops]; ValueEval[] ops = new ValueEval[numops];
// storing the ops in reverse order since they are popping // storing the ops in reverse order since they are popping
for (int j = numops - 1; j >= 0; j--) { for (int j = numops - 1; j >= 0; j--) {
Eval p = stack.pop(); ValueEval p = stack.pop();
ops[j] = p; ops[j] = p;
} }
// logDebug("invoke " + operation + " (nAgs=" + numops + ")"); // logDebug("invoke " + operation + " (nAgs=" + numops + ")");
@ -318,7 +318,7 @@ public final class WorkbookEvaluator {
stack.push(opResult); stack.push(opResult);
} }
ValueEval value = (ValueEval) stack.pop(); ValueEval value = stack.pop();
if (!stack.isEmpty()) { if (!stack.isEmpty()) {
throw new IllegalStateException("evaluation stack not empty"); throw new IllegalStateException("evaluation stack not empty");
} }
@ -359,7 +359,7 @@ public final class WorkbookEvaluator {
return evaluationResult; 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) { EvaluationWorkbook workbook, int sheetIndex, int srcRowNum, int srcColNum) {
if(operation instanceof FunctionEval) { if(operation instanceof FunctionEval) {
@ -368,7 +368,8 @@ public final class WorkbookEvaluator {
return fe.getFreeRefFunction().evaluate(ops, workbook, sheetIndex, srcRowNum, srcColNum); 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, private SheetRefEvaluator createExternSheetRefEvaluator(EvaluationTracker tracker,
ExternSheetReferenceToken ptg) { ExternSheetReferenceToken ptg) {
@ -391,7 +392,7 @@ public final class WorkbookEvaluator {
* StringPtg, BoolPtg <br/>special Note: OperationPtg subtypes cannot be * StringPtg, BoolPtg <br/>special Note: OperationPtg subtypes cannot be
* passed here! * 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) // consider converting all these (ptg instanceof XxxPtg) expressions to (ptg.getClass() == XxxPtg.class)
if (ptg instanceof NamePtg) { if (ptg instanceof NamePtg) {
@ -465,7 +466,7 @@ public final class WorkbookEvaluator {
throw new RuntimeException("Unexpected ptg class (" + ptg.getClass().getName() + ")"); 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) { if (ptgs.length > 1) {
throw new RuntimeException("Complex name formulas not supported yet"); throw new RuntimeException("Complex name formulas not supported yet");
} }