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() {
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() {
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 {
// TODO - remove this interface
}

View File

@ -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();
}

View File

@ -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;

View File

@ -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;

View File

@ -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 <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>.
*/
Eval evaluate(Eval[] args, int srcRowIndex, short srcColumnIndex);
public abstract int getNumberOfOperands();
public abstract int getType();
int getNumberOfOperands();
}

View File

@ -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");
}
}

View File

@ -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");
}
}

View File

@ -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");
}
}

View File

@ -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);

View File

@ -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");
}
}

View File

@ -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");
}
}

View File

@ -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 &lt; amolweb at ya hoo dot com &gt;
* 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 <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
/* 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++) {
// 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 <br/>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");
}