From 43db5ea180b5b02b8091c30b7b8c9d8228165521 Mon Sep 17 00:00:00 2001 From: Josh Micich Date: Mon, 1 Sep 2008 01:48:45 +0000 Subject: [PATCH] Converted AreEval and RefEval to be lazy (part of fix for bug 45358) git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@690835 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/poi/hssf/record/formula/AreaI.java | 73 +++-- .../poi/hssf/record/formula/RefPtgBase.java | 8 - .../hssf/record/formula/eval/Area2DEval.java | 32 -- .../hssf/record/formula/eval/Area3DEval.java | 39 --- .../hssf/record/formula/eval/AreaEval.java | 6 + .../record/formula/eval/AreaEvalBase.java | 33 +- .../record/formula/eval/FunctionEval.java | 3 +- .../record/formula/eval/LazyAreaEval.java | 65 ++++ .../hssf/record/formula/eval/LazyRefEval.java | 52 +++ .../hssf/record/formula/eval/Ref2DEval.java | 3 + .../hssf/record/formula/eval/Ref3DEval.java | 53 ---- .../poi/hssf/record/formula/eval/RefEval.java | 50 +-- .../hssf/record/formula/eval/RefEvalBase.java | 18 ++ .../record/formula/functions/CountUtils.java | 9 +- .../poi/hssf/record/formula/functions/If.java | 74 +++-- .../record/formula/functions/LookupUtils.java | 10 +- .../hssf/record/formula/functions/MathX.java | 79 ----- .../hssf/record/formula/functions/Offset.java | 100 ++---- .../hssf/usermodel/HSSFFormulaEvaluator.java | 298 ++++-------------- .../record/formula/eval/TestAreaEval.java | 9 +- .../formula/eval/TestUnaryPlusEval.java | 26 +- .../record/formula/functions/EvalFactory.java | 64 +++- .../formula/functions/TestCountFuncs.java | 15 +- .../record/formula/functions/TestIndex.java | 5 +- .../record/formula/functions/TestMatch.java | 167 +++++----- .../record/formula/functions/TestMathX.java | 70 ++-- .../record/formula/functions/TestMid.java | 38 +-- .../formula/functions/TestSumproduct.java | 8 +- .../record/formula/functions/TestTFunc.java | 8 +- .../functions/TestXYNumericFunction.java | 4 +- 30 files changed, 595 insertions(+), 824 deletions(-) delete mode 100644 src/java/org/apache/poi/hssf/record/formula/eval/Area2DEval.java delete mode 100644 src/java/org/apache/poi/hssf/record/formula/eval/Area3DEval.java create mode 100644 src/java/org/apache/poi/hssf/record/formula/eval/LazyAreaEval.java create mode 100644 src/java/org/apache/poi/hssf/record/formula/eval/LazyRefEval.java delete mode 100644 src/java/org/apache/poi/hssf/record/formula/eval/Ref3DEval.java create mode 100644 src/java/org/apache/poi/hssf/record/formula/eval/RefEvalBase.java diff --git a/src/java/org/apache/poi/hssf/record/formula/AreaI.java b/src/java/org/apache/poi/hssf/record/formula/AreaI.java index 6e2103b3d..477d32f67 100644 --- a/src/java/org/apache/poi/hssf/record/formula/AreaI.java +++ b/src/java/org/apache/poi/hssf/record/formula/AreaI.java @@ -14,30 +14,63 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ + package org.apache.poi.hssf.record.formula; /** - * Common interface for AreaPtg and Area3DPtg, and their - * child classes. + * Common interface for AreaPtg and Area3DPtg, and their child classes. */ public interface AreaI { - /** - * @return the first row in the area - */ - public int getFirstRow(); + /** + * @return the first row in the area + */ + public int getFirstRow(); + + /** + * @return last row in the range (x2 in x1,y1-x2,y2) + */ + public int getLastRow(); + + /** + * @return the first column number in the area. + */ + public int getFirstColumn(); + + /** + * @return lastcolumn in the area + */ + public int getLastColumn(); + + class OffsetArea implements AreaI { + + private final int _firstColumn; + private final int _firstRow; + private final int _lastColumn; + private final int _lastRow; + + public OffsetArea(int baseRow, int baseColumn, int relFirstRowIx, int relLastRowIx, + int relFirstColIx, int relLastColIx) { + _firstRow = baseRow + relFirstRowIx; + _lastRow = baseRow + relLastRowIx; + _firstColumn = baseColumn + relFirstColIx; + _lastColumn = baseColumn + relLastColIx; + } + + public int getFirstColumn() { + return _firstColumn; + } + + public int getFirstRow() { + return _firstRow; + } + + public int getLastColumn() { + return _lastColumn; + } + + public int getLastRow() { + return _lastRow; + } + } - /** - * @return last row in the range (x2 in x1,y1-x2,y2) - */ - public int getLastRow(); - - /** - * @return the first column number in the area. - */ - public int getFirstColumn(); - - /** - * @return lastcolumn in the area - */ - public int getLastColumn(); } \ No newline at end of file diff --git a/src/java/org/apache/poi/hssf/record/formula/RefPtgBase.java b/src/java/org/apache/poi/hssf/record/formula/RefPtgBase.java index a105522df..74c4d7d74 100644 --- a/src/java/org/apache/poi/hssf/record/formula/RefPtgBase.java +++ b/src/java/org/apache/poi/hssf/record/formula/RefPtgBase.java @@ -131,14 +131,6 @@ public abstract class RefPtgBase extends OperandPtg { field_2_col=colRelative.setBoolean(field_2_col,rel); } - public final void setColumnRawX(int col) { // TODO - field_2_col = col; - } - - public int getColumnRawX() { // TODO - return field_2_col; - } - public final void setColumn(int col) { if(col < 0 || col >= 0x100) { throw new IllegalArgumentException("Specified colIx (" + col + ") is out of range"); diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/Area2DEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/Area2DEval.java deleted file mode 100644 index 5ae98b39f..000000000 --- a/src/java/org/apache/poi/hssf/record/formula/eval/Area2DEval.java +++ /dev/null @@ -1,32 +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.hssf.record.formula.AreaPtg; -import org.apache.poi.hssf.record.formula.Ptg; - -/** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - * - */ -public final class Area2DEval extends AreaEvalBase { - - public Area2DEval(Ptg ptg, ValueEval[] values) { - super((AreaPtg) ptg, values); - } -} \ No newline at end of file diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/Area3DEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/Area3DEval.java deleted file mode 100644 index 89209e21b..000000000 --- a/src/java/org/apache/poi/hssf/record/formula/eval/Area3DEval.java +++ /dev/null @@ -1,39 +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.hssf.record.formula.Area3DPtg; -import org.apache.poi.hssf.record.formula.Ptg; - -/** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - * - */ -public final class Area3DEval extends AreaEvalBase { - - private final int _externSheetIndex; - - public Area3DEval(Ptg ptg, ValueEval[] values) { - super((Area3DPtg) ptg, values); - _externSheetIndex = ((Area3DPtg) ptg).getExternSheetIndex(); - } - - public int getExternSheetIndex() { - return _externSheetIndex; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/AreaEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/AreaEval.java index eaecf267a..b528eb784 100644 --- a/src/java/org/apache/poi/hssf/record/formula/eval/AreaEval.java +++ b/src/java/org/apache/poi/hssf/record/formula/eval/AreaEval.java @@ -97,4 +97,10 @@ public interface AreaEval extends ValueEval { * specified indexes should relative to the top left corner of this area. */ ValueEval getRelativeValue(int relativeRowIndex, int relativeColumnIndex); + + /** + * Creates an {@link AreaEval} offset by a relative amount from from the upper left cell + * of this area + */ + AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx, int relLastColIx); } diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/AreaEvalBase.java b/src/java/org/apache/poi/hssf/record/formula/eval/AreaEvalBase.java index 0a812102d..94f6c9fe4 100644 --- a/src/java/org/apache/poi/hssf/record/formula/eval/AreaEvalBase.java +++ b/src/java/org/apache/poi/hssf/record/formula/eval/AreaEvalBase.java @@ -22,20 +22,16 @@ import org.apache.poi.hssf.record.formula.AreaI; /** * @author Josh Micich */ -abstract class AreaEvalBase implements AreaEval { +public abstract class AreaEvalBase implements AreaEval { private final int _firstColumn; private final int _firstRow; private final int _lastColumn; private final int _lastRow; - private final ValueEval[] _values; private final int _nColumns; private final int _nRows; - protected AreaEvalBase(AreaI ptg, ValueEval[] values) { - if (values == null) { - throw new IllegalArgumentException("values must not be null"); - } + protected AreaEvalBase(AreaI ptg) { _firstRow = ptg.getFirstRow(); _firstColumn = ptg.getFirstColumn(); _lastRow = ptg.getLastRow(); @@ -43,22 +39,6 @@ abstract class AreaEvalBase implements AreaEval { _nColumns = _lastColumn - _firstColumn + 1; _nRows = _lastRow - _firstRow + 1; - - int expectedItemCount = _nRows * _nColumns; - if ((values.length != expectedItemCount)) { - // Note - this math may need alteration when POI starts to support full column or full row refs - throw new IllegalArgumentException("Array size should be (" + expectedItemCount - + ") but was (" + values.length + ")"); - } - - - - for (int i = values.length - 1; i >= 0; i--) { - if (values[i] == null) { - throw new IllegalArgumentException("value array elements must not be null"); - } - } - _values = values; } public final int getFirstColumn() { @@ -116,14 +96,7 @@ abstract class AreaEvalBase implements AreaEval { return _lastRow-_firstRow+1; } - public ValueEval getRelativeValue(int relativeRowIndex, int relativeColumnIndex) { - int index = relativeRowIndex * _nColumns + relativeColumnIndex; - ValueEval result = _values[index]; - if (result == null) { - return BlankEval.INSTANCE; - } - return result; - } + public abstract ValueEval getRelativeValue(int relativeRowIndex, int relativeColumnIndex); public int getWidth() { return _lastColumn-_firstColumn+1; diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/FunctionEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/FunctionEval.java index 533c604a0..fe58c69c0 100644 --- a/src/java/org/apache/poi/hssf/record/formula/eval/FunctionEval.java +++ b/src/java/org/apache/poi/hssf/record/formula/eval/FunctionEval.java @@ -50,7 +50,6 @@ public abstract class FunctionEval implements OperationEval { static { Map m = new HashMap(); - addMapping(m, ID.OFFSET, new Offset()); addMapping(m, ID.INDIRECT, new Indirect()); addMapping(m, ID.EXTERNAL_FUNC, new ExternalFunction()); freeRefFunctionsByIdMap = m; @@ -155,7 +154,7 @@ public abstract class FunctionEval implements OperationEval { retval[75] = new Areas(); // AREAS retval[76] = new Rows(); // ROWS retval[77] = new Columns(); // COLUMNS - retval[ID.OFFSET] = null; // Offset.evaluate has a different signature + retval[ID.OFFSET] = new Offset(); // OFFSET retval[79] = new Absref(); // ABSREF retval[80] = new Relref(); // RELREF retval[81] = new Argument(); // ARGUMENT diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/LazyAreaEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/LazyAreaEval.java new file mode 100644 index 000000000..828f054b1 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/eval/LazyAreaEval.java @@ -0,0 +1,65 @@ +/* +* 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.hssf.record.formula.AreaI; +import org.apache.poi.hssf.record.formula.AreaI.OffsetArea; +import org.apache.poi.hssf.usermodel.HSSFCell; +import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator; +import org.apache.poi.hssf.usermodel.HSSFRow; +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; + +/** + * @author Amol S. Deshmukh < amolweb at ya hoo dot com > + * + */ +public final class LazyAreaEval extends AreaEvalBase { + + private final HSSFSheet _sheet; + private HSSFWorkbook _workbook; + + public LazyAreaEval(AreaI ptg, HSSFSheet sheet, HSSFWorkbook workbook) { + super(ptg); + _sheet = sheet; + _workbook = workbook; + } + + public ValueEval getRelativeValue(int relativeRowIndex, int relativeColumnIndex) { + + int rowIx = (relativeRowIndex + getFirstRow() ) & 0xFFFF; + int colIx = (relativeColumnIndex + getFirstColumn() ) & 0x00FF; + + HSSFRow row = _sheet.getRow(rowIx); + if (row == null) { + return BlankEval.INSTANCE; + } + HSSFCell cell = row.getCell(colIx); + if (cell == null) { + return BlankEval.INSTANCE; + } + return HSSFFormulaEvaluator.getEvalForCell(cell, _sheet, _workbook); + } + + public AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx, int relLastColIx) { + AreaI area = new OffsetArea(getFirstRow(), getFirstColumn(), + relFirstRowIx, relLastRowIx, relFirstColIx, relLastColIx); + + return new LazyAreaEval(area, _sheet, _workbook); + } +} diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/LazyRefEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/LazyRefEval.java new file mode 100644 index 000000000..62da3c499 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/eval/LazyRefEval.java @@ -0,0 +1,52 @@ +package org.apache.poi.hssf.record.formula.eval; + +import org.apache.poi.hssf.record.formula.AreaI; +import org.apache.poi.hssf.record.formula.AreaI.OffsetArea; +import org.apache.poi.hssf.record.formula.Ref3DPtg; +import org.apache.poi.hssf.record.formula.RefPtg; +import org.apache.poi.hssf.usermodel.HSSFCell; +import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator; +import org.apache.poi.hssf.usermodel.HSSFRow; +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; + +public final class LazyRefEval extends RefEvalBase { + + private final HSSFSheet _sheet; + private final HSSFWorkbook _workbook; + + + public LazyRefEval(RefPtg ptg, HSSFSheet sheet, HSSFWorkbook workbook) { + super(ptg.getRow(), ptg.getColumn()); + _sheet = sheet; + _workbook = workbook; + } + public LazyRefEval(Ref3DPtg ptg, HSSFSheet sheet, HSSFWorkbook workbook) { + super(ptg.getRow(), ptg.getColumn()); + _sheet = sheet; + _workbook = workbook; + } + + public ValueEval getInnerValueEval() { + int rowIx = getRow(); + int colIx = getColumn(); + + HSSFRow row = _sheet.getRow(rowIx); + if (row == null) { + return BlankEval.INSTANCE; + } + HSSFCell cell = row.getCell(colIx); + if (cell == null) { + return BlankEval.INSTANCE; + } + return HSSFFormulaEvaluator.getEvalForCell(cell, _sheet, _workbook); + } + + public AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx, int relLastColIx) { + + AreaI area = new OffsetArea(getRow(), getColumn(), + relFirstRowIx, relLastRowIx, relFirstColIx, relLastColIx); + + return new LazyAreaEval(area, _sheet, _workbook); + } +} diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/Ref2DEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/Ref2DEval.java index 033ecc1f8..e4bb47a43 100644 --- a/src/java/org/apache/poi/hssf/record/formula/eval/Ref2DEval.java +++ b/src/java/org/apache/poi/hssf/record/formula/eval/Ref2DEval.java @@ -47,4 +47,7 @@ public final class Ref2DEval implements RefEval { public int getColumn() { return delegate.getColumn(); } + public AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx, int relLastColIx) { + throw new RuntimeException("should not be called"); // TODO - delete this whole class + } } diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/Ref3DEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/Ref3DEval.java deleted file mode 100644 index 622d68632..000000000 --- a/src/java/org/apache/poi/hssf/record/formula/eval/Ref3DEval.java +++ /dev/null @@ -1,53 +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.hssf.record.formula.Ref3DPtg; - -/** - * @author Amol S. Deshmukh - * - */ -public final class Ref3DEval implements RefEval { - - private final ValueEval value; - private final Ref3DPtg delegate; - - public Ref3DEval(Ref3DPtg ptg, ValueEval ve) { - if(ve == null) { - throw new IllegalArgumentException("ve must not be null"); - } - if(ptg == null) { - throw new IllegalArgumentException("ptg must not be null"); - } - value = ve; - delegate = ptg; - } - public ValueEval getInnerValueEval() { - return value; - } - public int getRow() { - return delegate.getRow(); - } - public int getColumn() { - return delegate.getColumn(); - } - public int getExternSheetIndex() { - return delegate.getExternSheetIndex(); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/RefEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/RefEval.java index e462586d7..397d1f1c9 100644 --- a/src/java/org/apache/poi/hssf/record/formula/eval/RefEval.java +++ b/src/java/org/apache/poi/hssf/record/formula/eval/RefEval.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; @@ -30,22 +30,22 @@ package org.apache.poi.hssf.record.formula.eval; public interface RefEval extends ValueEval { /** - * The (possibly evaluated) ValueEval contained - * in this RefEval. eg. if cell A1 contains "test" - * then in a formula referring to cell A1 - * the RefEval representing - * A1 will return as the getInnerValueEval() the - * object of concrete type StringEval + * @return the evaluated value of the cell referred to by this RefEval. */ - public ValueEval getInnerValueEval(); + ValueEval getInnerValueEval(); /** * returns the zero based column index. */ - public int getColumn(); + int getColumn(); /** * returns the zero based row index. */ - public int getRow(); + int getRow(); + + /** + * Creates an {@link AreaEval} offset by a relative amount from this RefEval + */ + AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx, int relLastColIx); } diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/RefEvalBase.java b/src/java/org/apache/poi/hssf/record/formula/eval/RefEvalBase.java new file mode 100644 index 000000000..37d20f808 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/eval/RefEvalBase.java @@ -0,0 +1,18 @@ +package org.apache.poi.hssf.record.formula.eval; + +public abstract class RefEvalBase implements RefEval { + + private final int _rowIndex; + private final int _columnIndex; + + protected RefEvalBase(int rowIndex, int columnIndex) { + _rowIndex = rowIndex; + _columnIndex = columnIndex; + } + public final int getRow() { + return _rowIndex; + } + public final int getColumn() { + return _columnIndex; + } +} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/CountUtils.java b/src/java/org/apache/poi/hssf/record/formula/functions/CountUtils.java index f8d888382..27dfcc1b6 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/CountUtils.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/CountUtils.java @@ -50,9 +50,9 @@ final class CountUtils { for (int rrIx=0; rrIx - * It is the responsibility of the caller - * to ensure that the two subarrays are of equal length. If the - * subarrays are not of equal length, the return value can be - * unpredictable. - * @param xarr - * @param yarr - */ - public static double sumx2my2(double[] xarr, double[] yarr) { - double d = 0; - - try { - for (int i=0, iSize=xarr.length; i - * It is the responsibility of the caller - * to ensure that the two subarrays are of equal length. If the - * subarrays are not of equal length, the return value can be - * unpredictable. - * @param xarr - * @param yarr - */ - public static double sumx2py2(double[] xarr, double[] yarr) { - double d = 0; - - try { - for (int i=0, iSize=xarr.length; i - * It is the responsibility of the caller - * to ensure that the two subarrays are of equal length. If the - * subarrays are not of equal length, the return value can be - * unpredictable. - * @param xarr - * @param yarr - */ - public static double sumxmy2(double[] xarr, double[] yarr) { - double d = 0; - - try { - for (int i=0, iSize=xarr.length; i * @@ -51,7 +43,7 @@ import org.apache.poi.hssf.usermodel.HSSFWorkbook; * * @author Josh Micich */ -public final class Offset implements FreeRefFunction { +public final class Offset implements Function { // These values are specific to BIFF8 private static final int LAST_VALID_ROW_INDEX = 0xFFFF; private static final int LAST_VALID_COLUMN_INDEX = 0xFF; @@ -125,37 +117,29 @@ public final class Offset implements FreeRefFunction { * Encapsulates either an area or cell reference which may be 2d or 3d. */ private static final class BaseRef { - private static final int INVALID_SHEET_INDEX = -1; private final int _firstRowIndex; private final int _firstColumnIndex; private final int _width; private final int _height; - private final int _externalSheetIndex; + private final RefEval _refEval; + private final AreaEval _areaEval; public BaseRef(RefEval re) { + _refEval = re; + _areaEval = null; _firstRowIndex = re.getRow(); _firstColumnIndex = re.getColumn(); _height = 1; _width = 1; - if (re instanceof Ref3DEval) { - Ref3DEval r3e = (Ref3DEval) re; - _externalSheetIndex = r3e.getExternSheetIndex(); - } else { - _externalSheetIndex = INVALID_SHEET_INDEX; - } } public BaseRef(AreaEval ae) { + _refEval = null; + _areaEval = ae; _firstRowIndex = ae.getFirstRow(); _firstColumnIndex = ae.getFirstColumn(); _height = ae.getLastRow() - ae.getFirstRow() + 1; _width = ae.getLastColumn() - ae.getFirstColumn() + 1; - if (ae instanceof Area3DEval) { - Area3DEval a3e = (Area3DEval) ae; - _externalSheetIndex = a3e.getExternSheetIndex(); - } else { - _externalSheetIndex = INVALID_SHEET_INDEX; - } } public int getWidth() { @@ -170,19 +154,17 @@ public final class Offset implements FreeRefFunction { public int getFirstColumnIndex() { return _firstColumnIndex; } - public boolean isIs3d() { - return _externalSheetIndex > 0; - } - public short getExternalSheetIndex() { - if(_externalSheetIndex < 0) { - throw new IllegalStateException("external sheet index only available for 3d refs"); + public AreaEval offset(int relFirstRowIx, int relLastRowIx, + int relFirstColIx, int relLastColIx) { + if (_refEval == null) { + return _areaEval.offset(relFirstRowIx, relLastRowIx, relFirstColIx, relLastColIx); } - return (short) _externalSheetIndex; + return _refEval.offset(relFirstRowIx, relLastRowIx, relFirstColIx, relLastColIx); } } - public ValueEval evaluate(Eval[] args, int srcCellRow, short srcCellCol, HSSFWorkbook workbook, HSSFSheet sheet) { + public Eval evaluate(Eval[] args, int srcCellRow, short srcCellCol) { if(args.length < 3 || args.length > 5) { return ErrorEval.VALUE_INVALID; @@ -206,37 +188,25 @@ public final class Offset implements FreeRefFunction { } LinearOffsetRange rowOffsetRange = new LinearOffsetRange(rowOffset, height); LinearOffsetRange colOffsetRange = new LinearOffsetRange(columnOffset, width); - return createOffset(baseRef, rowOffsetRange, colOffsetRange, workbook, sheet); + return createOffset(baseRef, rowOffsetRange, colOffsetRange); } catch (EvaluationException e) { return e.getErrorEval(); } } private static AreaEval createOffset(BaseRef baseRef, - LinearOffsetRange rowOffsetRange, LinearOffsetRange colOffsetRange, - HSSFWorkbook workbook, HSSFSheet sheet) throws EvaluationException { + LinearOffsetRange orRow, LinearOffsetRange orCol) throws EvaluationException { - LinearOffsetRange rows = rowOffsetRange.normaliseAndTranslate(baseRef.getFirstRowIndex()); - LinearOffsetRange cols = colOffsetRange.normaliseAndTranslate(baseRef.getFirstColumnIndex()); + LinearOffsetRange absRows = orRow.normaliseAndTranslate(baseRef.getFirstRowIndex()); + LinearOffsetRange absCols = orCol.normaliseAndTranslate(baseRef.getFirstColumnIndex()); - if(rows.isOutOfBounds(0, LAST_VALID_ROW_INDEX)) { + if(absRows.isOutOfBounds(0, LAST_VALID_ROW_INDEX)) { throw new EvaluationException(ErrorEval.REF_INVALID); } - if(cols.isOutOfBounds(0, LAST_VALID_COLUMN_INDEX)) { + if(absCols.isOutOfBounds(0, LAST_VALID_COLUMN_INDEX)) { throw new EvaluationException(ErrorEval.REF_INVALID); } - if(baseRef.isIs3d()) { - Area3DPtg a3dp = new Area3DPtg(rows.getFirstIndex(), rows.getLastIndex(), - cols.getFirstIndex(), cols.getLastIndex(), - false, false, false, false, - baseRef.getExternalSheetIndex()); - return HSSFFormulaEvaluator.evaluateArea3dPtg(workbook, a3dp); - } - - AreaPtg ap = new AreaPtg(rows.getFirstIndex(), rows.getLastIndex(), - cols.getFirstIndex(), cols.getLastIndex(), - false, false, false, false); - return HSSFFormulaEvaluator.evaluateAreaPtg(sheet, workbook, ap); + return baseRef.offset(orRow.getFirstIndex(), orRow.getLastIndex(), orCol.getFirstIndex(), orCol.getLastIndex()); } private static BaseRef evaluateBaseRef(Eval eval) throws EvaluationException { diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java b/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java index 769c6ef3f..f7874d0ca 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java @@ -17,10 +17,7 @@ package org.apache.poi.hssf.usermodel; -import java.lang.reflect.Constructor; -import java.util.HashMap; import java.util.Iterator; -import java.util.Map; import java.util.Stack; import org.apache.poi.hssf.model.FormulaParser; @@ -29,6 +26,7 @@ import org.apache.poi.hssf.record.formula.Area3DPtg; import org.apache.poi.hssf.record.formula.AreaPtg; import org.apache.poi.hssf.record.formula.BoolPtg; import org.apache.poi.hssf.record.formula.ControlPtg; +import org.apache.poi.hssf.record.formula.ErrPtg; import org.apache.poi.hssf.record.formula.IntPtg; import org.apache.poi.hssf.record.formula.MemErrPtg; import org.apache.poi.hssf.record.formula.MissingArgPtg; @@ -42,20 +40,18 @@ import org.apache.poi.hssf.record.formula.RefPtg; import org.apache.poi.hssf.record.formula.StringPtg; import org.apache.poi.hssf.record.formula.UnionPtg; import org.apache.poi.hssf.record.formula.UnknownPtg; -import org.apache.poi.hssf.record.formula.eval.Area2DEval; -import org.apache.poi.hssf.record.formula.eval.Area3DEval; import org.apache.poi.hssf.record.formula.eval.AreaEval; import org.apache.poi.hssf.record.formula.eval.BlankEval; import org.apache.poi.hssf.record.formula.eval.BoolEval; 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.FunctionEval; +import org.apache.poi.hssf.record.formula.eval.LazyAreaEval; +import org.apache.poi.hssf.record.formula.eval.LazyRefEval; 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.Ref2DEval; -import org.apache.poi.hssf.record.formula.eval.Ref3DEval; 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; @@ -66,32 +62,6 @@ import org.apache.poi.hssf.record.formula.eval.ValueEval; */ public class HSSFFormulaEvaluator { - // params to lookup the right constructor using reflection - private static final Class[] VALUE_CONTRUCTOR_CLASS_ARRAY = new Class[] { Ptg.class }; - - private static final Class[] AREA3D_CONSTRUCTOR_CLASS_ARRAY = new Class[] { Ptg.class, ValueEval[].class }; - - private static final Class[] REFERENCE_CONSTRUCTOR_CLASS_ARRAY = new Class[] { Ptg.class, ValueEval.class }; - - private static final Class[] REF3D_CONSTRUCTOR_CLASS_ARRAY = new Class[] { Ptg.class, ValueEval.class }; - - // Maps for mapping *Eval to *Ptg - private static final Map VALUE_EVALS_MAP = new HashMap(); - - /* - * Following is the mapping between the Ptg tokens returned - * by the FormulaParser and the *Eval classes that are used - * by the FormulaEvaluator - */ - static { - VALUE_EVALS_MAP.put(BoolPtg.class, BoolEval.class); - VALUE_EVALS_MAP.put(IntPtg.class, NumberEval.class); - VALUE_EVALS_MAP.put(NumberPtg.class, NumberEval.class); - VALUE_EVALS_MAP.put(StringPtg.class, StringEval.class); - - } - - protected HSSFSheet _sheet; protected HSSFWorkbook _workbook; @@ -265,29 +235,29 @@ public class HSSFFormulaEvaluator { * This is a helpful wrapper around looping over all * cells, and calling evaluateFormulaCell on each one. */ - public static void evaluateAllFormulaCells(HSSFWorkbook wb) { - for(int i=0; iNumberEval, StringEval, BoolEval, - * BlankEval or ErrorEval. Never null. + * @return a NumberEval, StringEval, BoolEval, + * BlankEval or ErrorEval. Never null. */ private static ValueEval dereferenceValue(ValueEval evaluationResult, int srcRowNum, short srcColNum) { if (evaluationResult instanceof RefEval) { @@ -475,105 +415,49 @@ public class HSSFFormulaEvaluator { return operation.evaluate(ops, srcRowNum, srcColNum); } - public static AreaEval evaluateAreaPtg(HSSFSheet sheet, HSSFWorkbook workbook, AreaPtg ap) { - int row0 = ap.getFirstRow(); - int col0 = ap.getFirstColumn(); - int row1 = ap.getLastRow(); - int col1 = ap.getLastColumn(); - - // If the last row is -1, then the - // reference is for the rest of the column - // (eg C:C) - // TODO: Handle whole column ranges properly - if(row1 == -1 && row0 >= 0) { - row1 = (short)sheet.getLastRowNum(); - } - ValueEval[] values = evalArea(workbook, sheet, row0, col0, row1, col1); - return new Area2DEval(ap, values); - } - - public static AreaEval evaluateArea3dPtg(HSSFWorkbook workbook, Area3DPtg a3dp) { - int row0 = a3dp.getFirstRow(); - int col0 = a3dp.getFirstColumn(); - int row1 = a3dp.getLastRow(); - int col1 = a3dp.getLastColumn(); - Workbook wb = workbook.getWorkbook(); - HSSFSheet xsheet = workbook.getSheetAt(wb.getSheetIndexFromExternSheetIndex(a3dp.getExternSheetIndex())); - - // If the last row is -1, then the - // reference is for the rest of the column - // (eg C:C) - // TODO: Handle whole column ranges properly - if(row1 == -1 && row0 >= 0) { - row1 = (short)xsheet.getLastRowNum(); - } - - ValueEval[] values = evalArea(workbook, xsheet, row0, col0, row1, col1); - return new Area3DEval(a3dp, values); - } - - private static ValueEval[] evalArea(HSSFWorkbook workbook, HSSFSheet sheet, - int row0, int col0, int row1, int col1) { - ValueEval[] values = new ValueEval[(row1 - row0 + 1) * (col1 - col0 + 1)]; - for (int x = row0; sheet != null && x < row1 + 1; x++) { - HSSFRow row = sheet.getRow(x); - for (int y = col0; y < col1 + 1; y++) { - ValueEval cellEval; - if(row == null) { - cellEval = BlankEval.INSTANCE; - } else { - cellEval = getEvalForCell(row.getCell(y), row, sheet, workbook); - } - values[(x - row0) * (col1 - col0 + 1) + (y - col0)] = cellEval; - } - } - return values; - } - /** * returns an appropriate Eval impl instance for the Ptg. The Ptg must be * one of: Area3DPtg, AreaPtg, ReferencePtg, Ref3DPtg, IntPtg, NumberPtg, * StringPtg, BoolPtg
special Note: OperationPtg subtypes cannot be * passed here! - * - * @param ptg */ - protected static Eval getEvalForPtg(Ptg ptg) { - Eval retval = null; - - Class clazz = (Class) VALUE_EVALS_MAP.get(ptg.getClass()); - try { - if (ptg instanceof Area3DPtg) { - Constructor constructor = clazz.getConstructor(AREA3D_CONSTRUCTOR_CLASS_ARRAY); - retval = (OperationEval) constructor.newInstance(new Ptg[] { ptg }); - } - else if (ptg instanceof AreaPtg) { - Constructor constructor = clazz.getConstructor(AREA3D_CONSTRUCTOR_CLASS_ARRAY); - retval = (OperationEval) constructor.newInstance(new Ptg[] { ptg }); - } - else if (ptg instanceof RefPtg) { - Constructor constructor = clazz.getConstructor(REFERENCE_CONSTRUCTOR_CLASS_ARRAY); - retval = (OperationEval) constructor.newInstance(new Ptg[] { ptg }); - } - else if (ptg instanceof Ref3DPtg) { - Constructor constructor = clazz.getConstructor(REF3D_CONSTRUCTOR_CLASS_ARRAY); - retval = (OperationEval) constructor.newInstance(new Ptg[] { ptg }); - } - else { - if (ptg instanceof IntPtg || ptg instanceof NumberPtg || ptg instanceof StringPtg - || ptg instanceof BoolPtg) { - Constructor constructor = clazz.getConstructor(VALUE_CONTRUCTOR_CLASS_ARRAY); - retval = (ValueEval) constructor.newInstance(new Ptg[] { ptg }); - } - } + private static Eval getEvalForPtg(Ptg ptg, HSSFSheet sheet, HSSFWorkbook workbook) { + if (ptg instanceof RefPtg) { + return new LazyRefEval(((RefPtg) ptg), sheet, workbook); } - catch (Exception e) { - throw new RuntimeException("Fatal Error: ", e); + if (ptg instanceof Ref3DPtg) { + Ref3DPtg refPtg = (Ref3DPtg) ptg; + Workbook wb = workbook.getWorkbook(); + HSSFSheet xsheet = workbook.getSheetAt(wb.getSheetIndexFromExternSheetIndex(refPtg.getExternSheetIndex())); + return new LazyRefEval(refPtg, xsheet, workbook); + } + if (ptg instanceof AreaPtg) { + return new LazyAreaEval(((AreaPtg) ptg), sheet, workbook); + } + if (ptg instanceof Area3DPtg) { + Area3DPtg a3dp = (Area3DPtg) ptg; + Workbook wb = workbook.getWorkbook(); + HSSFSheet xsheet = workbook.getSheetAt(wb.getSheetIndexFromExternSheetIndex(a3dp.getExternSheetIndex())); + return new LazyAreaEval(a3dp, xsheet, workbook); } - return retval; + if (ptg instanceof IntPtg) { + return new NumberEval(((IntPtg)ptg).getValue()); + } + if (ptg instanceof NumberPtg) { + return new NumberEval(((NumberPtg)ptg).getValue()); + } + if (ptg instanceof StringPtg) { + return new StringEval(((StringPtg) ptg).getValue()); + } + if (ptg instanceof BoolPtg) { + return BoolEval.valueOf(((BoolPtg) ptg).getValue()); + } + if (ptg instanceof ErrPtg) { + return ErrorEval.valueOf(((ErrPtg) ptg).getErrorCode()); + } + throw new RuntimeException("Unexpected ptg class (" + ptg.getClass().getName() + ")"); } - /** * Given a cell, find its type and from that create an appropriate ValueEval * impl instance and return that. Since the cell could be an external @@ -583,7 +467,7 @@ public class HSSFFormulaEvaluator { * @param sheet * @param workbook */ - protected static ValueEval getEvalForCell(HSSFCell cell, HSSFRow row, HSSFSheet sheet, HSSFWorkbook workbook) { + public static ValueEval getEvalForCell(HSSFCell cell, HSSFSheet sheet, HSSFWorkbook workbook) { if (cell == null) { return BlankEval.INSTANCE; @@ -605,58 +489,6 @@ public class HSSFFormulaEvaluator { throw new RuntimeException("Unexpected cell type (" + cell.getCellType() + ")"); } - /** - * Creates a Ref2DEval for ReferencePtg. - * Non existent cells are treated as RefEvals containing BlankEval. - */ - private static Ref2DEval createRef2DEval(RefPtg ptg, HSSFCell cell, - HSSFSheet sheet, HSSFWorkbook workbook) { - if (cell == null) { - return new Ref2DEval(ptg, BlankEval.INSTANCE); - } - - switch (cell.getCellType()) { - case HSSFCell.CELL_TYPE_NUMERIC: - return new Ref2DEval(ptg, new NumberEval(cell.getNumericCellValue())); - case HSSFCell.CELL_TYPE_STRING: - return new Ref2DEval(ptg, new StringEval(cell.getRichStringCellValue().getString())); - case HSSFCell.CELL_TYPE_FORMULA: - return new Ref2DEval(ptg, internalEvaluate(cell, sheet, workbook)); - case HSSFCell.CELL_TYPE_BOOLEAN: - return new Ref2DEval(ptg, BoolEval.valueOf(cell.getBooleanCellValue())); - case HSSFCell.CELL_TYPE_BLANK: - return new Ref2DEval(ptg, BlankEval.INSTANCE); - case HSSFCell.CELL_TYPE_ERROR: - return new Ref2DEval(ptg, ErrorEval.valueOf(cell.getErrorCellValue())); - } - throw new RuntimeException("Unexpected cell type (" + cell.getCellType() + ")"); - } - - /** - * create a Ref3DEval for Ref3DPtg. - */ - private static Ref3DEval createRef3DEval(Ref3DPtg ptg, HSSFCell cell, - HSSFSheet sheet, HSSFWorkbook workbook) { - if (cell == null) { - return new Ref3DEval(ptg, BlankEval.INSTANCE); - } - switch (cell.getCellType()) { - case HSSFCell.CELL_TYPE_NUMERIC: - return new Ref3DEval(ptg, new NumberEval(cell.getNumericCellValue())); - case HSSFCell.CELL_TYPE_STRING: - return new Ref3DEval(ptg, new StringEval(cell.getRichStringCellValue().getString())); - case HSSFCell.CELL_TYPE_FORMULA: - return new Ref3DEval(ptg, internalEvaluate(cell, sheet, workbook)); - case HSSFCell.CELL_TYPE_BOOLEAN: - return new Ref3DEval(ptg, BoolEval.valueOf(cell.getBooleanCellValue())); - case HSSFCell.CELL_TYPE_BLANK: - return new Ref3DEval(ptg, BlankEval.INSTANCE); - case HSSFCell.CELL_TYPE_ERROR: - return new Ref3DEval(ptg, ErrorEval.valueOf(cell.getErrorCellValue())); - } - throw new RuntimeException("Unexpected cell type (" + cell.getCellType() + ")"); - } - /** * Mimics the 'data view' of a cell. This allows formula evaluator * to return a CellValue instead of precasting the value to String @@ -752,15 +584,9 @@ public class HSSFFormulaEvaluator { /** * debug method - * - * @param formula - * @param sheet - * @param workbook */ void inspectPtgs(String formula) { - FormulaParser fp = new FormulaParser(formula, _workbook); - fp.parse(); - Ptg[] ptgs = fp.getRPNPtg(); + Ptg[] ptgs = FormulaParser.parse(formula, _workbook); System.out.println(""); for (int i = 0, iSize = ptgs.length; i < iSize; i++) { System.out.println(""); diff --git a/src/testcases/org/apache/poi/hssf/record/formula/eval/TestAreaEval.java b/src/testcases/org/apache/poi/hssf/record/formula/eval/TestAreaEval.java index 6c855707b..71d15745e 100644 --- a/src/testcases/org/apache/poi/hssf/record/formula/eval/TestAreaEval.java +++ b/src/testcases/org/apache/poi/hssf/record/formula/eval/TestAreaEval.java @@ -20,7 +20,8 @@ package org.apache.poi.hssf.record.formula.eval; import junit.framework.AssertionFailedError; import junit.framework.TestCase; -import org.apache.poi.hssf.record.formula.Area3DPtg; +import org.apache.poi.hssf.record.formula.AreaPtg; +import org.apache.poi.hssf.record.formula.functions.EvalFactory; /** * Tests for AreaEval @@ -30,8 +31,8 @@ import org.apache.poi.hssf.record.formula.Area3DPtg; public final class TestAreaEval extends TestCase { public void testGetValue_bug44950() { - - Area3DPtg ptg = new Area3DPtg("B2:D3", (short)0); + // TODO - this test probably isn't testing much anymore + AreaPtg ptg = new AreaPtg("B2:D3"); NumberEval one = new NumberEval(1); ValueEval[] values = { one, @@ -41,7 +42,7 @@ public final class TestAreaEval extends TestCase { new NumberEval(5), new NumberEval(6), }; - AreaEval ae = new Area3DEval(ptg, values); + AreaEval ae = EvalFactory.createAreaEval(ptg, values); if (one == ae.getValueAt(1, 2)) { throw new AssertionFailedError("Identified bug 44950 a"); } diff --git a/src/testcases/org/apache/poi/hssf/record/formula/eval/TestUnaryPlusEval.java b/src/testcases/org/apache/poi/hssf/record/formula/eval/TestUnaryPlusEval.java index dc20c0d8e..33c38a6c1 100755 --- a/src/testcases/org/apache/poi/hssf/record/formula/eval/TestUnaryPlusEval.java +++ b/src/testcases/org/apache/poi/hssf/record/formula/eval/TestUnaryPlusEval.java @@ -18,22 +18,23 @@ package org.apache.poi.hssf.record.formula.eval; +import junit.framework.TestCase; + import org.apache.poi.hssf.record.formula.AreaPtg; import org.apache.poi.hssf.record.formula.UnaryPlusPtg; +import org.apache.poi.hssf.record.formula.functions.EvalFactory; import org.apache.poi.hssf.record.formula.functions.NumericFunctionInvoker; -import junit.framework.TestCase; - /** * Test for unary plus operator evaluator. - * + * * @author Josh Micich */ public final class TestUnaryPlusEval extends TestCase { - + /** * Test for bug observable at svn revision 618865 (5-Feb-2008)
- * The code for handling column operands had been copy-pasted from the row handling code. + * The code for handling column operands had been copy-pasted from the row handling code. */ public void testColumnOperand() { @@ -42,15 +43,14 @@ public final class TestUnaryPlusEval extends TestCase { short colNum = (short)5; AreaPtg areaPtg = new AreaPtg(firstRow, lastRow, colNum, colNum, false, false, false, false); ValueEval[] values = { - new NumberEval(27), - new NumberEval(29), - new NumberEval(35), // value in row 10 - new NumberEval(37), - new NumberEval(38), + new NumberEval(27), + new NumberEval(29), + new NumberEval(35), // value in row 10 + new NumberEval(37), + new NumberEval(38), }; - Eval areaEval = new Area2DEval(areaPtg, values); - Eval[] args = { - areaEval, + Eval[] args = { + EvalFactory.createAreaEval(areaPtg, values), }; double result = NumericFunctionInvoker.invoke(new UnaryPlusEval(UnaryPlusPtg.instance), args, 10, (short)20); diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/EvalFactory.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/EvalFactory.java index 51435d314..1c8d74f44 100755 --- a/src/testcases/org/apache/poi/hssf/record/formula/functions/EvalFactory.java +++ b/src/testcases/org/apache/poi/hssf/record/formula/functions/EvalFactory.java @@ -14,17 +14,17 @@ 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.AreaPtg; +import org.apache.poi.hssf.record.formula.Ref3DPtg; import org.apache.poi.hssf.record.formula.RefPtg; -import org.apache.poi.hssf.record.formula.eval.Area2DEval; import org.apache.poi.hssf.record.formula.eval.AreaEval; +import org.apache.poi.hssf.record.formula.eval.AreaEvalBase; import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.Ref2DEval; import org.apache.poi.hssf.record.formula.eval.RefEval; +import org.apache.poi.hssf.record.formula.eval.RefEvalBase; import org.apache.poi.hssf.record.formula.eval.ValueEval; /** @@ -32,7 +32,7 @@ import org.apache.poi.hssf.record.formula.eval.ValueEval; * * @author Josh Micich */ -final class EvalFactory { +public final class EvalFactory { private EvalFactory() { // no instances of this class @@ -44,6 +44,14 @@ final class EvalFactory { */ public static AreaEval createAreaEval(String areaRefStr, ValueEval[] values) { AreaPtg areaPtg = new AreaPtg(areaRefStr); + return createAreaEval(areaPtg, values); + } + + /** + * Creates a dummy AreaEval + * @param values empty (null) entries in this array will be converted to NumberEval.ZERO + */ + public static AreaEval createAreaEval(AreaPtg areaPtg, ValueEval[] values) { int nCols = areaPtg.getLastColumn() - areaPtg.getFirstColumn() + 1; int nRows = areaPtg.getLastRow() - areaPtg.getFirstRow() + 1; int nExpected = nRows * nCols; @@ -55,13 +63,57 @@ final class EvalFactory { values[i] = NumberEval.ZERO; } } - return new Area2DEval(areaPtg, values); + return new MockAreaEval(areaPtg, values); } /** * Creates a single RefEval (with value zero) */ public static RefEval createRefEval(String refStr) { - return new Ref2DEval(new RefPtg(refStr), NumberEval.ZERO); + return createRefEval(refStr, NumberEval.ZERO); } + public static RefEval createRefEval(String refStr, ValueEval value) { + return new MockRefEval(new RefPtg(refStr), value); + } + + private static final class MockAreaEval extends AreaEvalBase { + private final ValueEval[] _values; + public MockAreaEval(AreaPtg areaPtg, ValueEval[] values) { + super(areaPtg); + _values = values; + } + public ValueEval getRelativeValue(int relativeRowIndex, int relativeColumnIndex) { + if (relativeRowIndex < 0 || relativeRowIndex >=getHeight()) { + throw new IllegalArgumentException("row index out of range"); + } + int width = getWidth(); + if (relativeColumnIndex < 0 || relativeColumnIndex >=width) { + throw new IllegalArgumentException("column index out of range"); + } + int oneDimensionalIndex = relativeRowIndex * width + relativeColumnIndex; + return _values[oneDimensionalIndex]; + } + public AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx, int relLastColIx) { + throw new RuntimeException("Operation not implemented on this mock object"); + } + } + + private static final class MockRefEval extends RefEvalBase { + private final ValueEval _value; + public MockRefEval(RefPtg ptg, ValueEval value) { + super(ptg.getRow(), ptg.getColumn()); + _value = value; + } + public MockRefEval(Ref3DPtg ptg, ValueEval value) { + super(ptg.getRow(), ptg.getColumn()); + _value = value; + } + public ValueEval getInnerValueEval() { + return _value; + } + public AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx, int relLastColIx) { + throw new RuntimeException("Operation not implemented on this mock object"); + } + } + } diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestCountFuncs.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestCountFuncs.java index c594f18c6..c31877c8c 100755 --- a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestCountFuncs.java +++ b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestCountFuncs.java @@ -21,9 +21,7 @@ import junit.framework.AssertionFailedError; import junit.framework.TestCase; import org.apache.poi.hssf.HSSFTestDataSamples; -import org.apache.poi.hssf.record.formula.AreaPtg; import org.apache.poi.hssf.record.formula.RefPtg; -import org.apache.poi.hssf.record.formula.eval.Area2DEval; import org.apache.poi.hssf.record.formula.eval.AreaEval; import org.apache.poi.hssf.record.formula.eval.BlankEval; import org.apache.poi.hssf.record.formula.eval.BoolEval; @@ -91,7 +89,7 @@ public final class TestCountFuncs extends TestCase { BoolEval.TRUE, BlankEval.INSTANCE, }; - range = createAreaEval("A1:B3", values); + range = EvalFactory.createAreaEval("A1:B3", values); confirmCountIf(2, range, BoolEval.TRUE); // when criteria is numeric @@ -103,7 +101,7 @@ public final class TestCountFuncs extends TestCase { new NumberEval(2), BoolEval.TRUE, }; - range = createAreaEval("A1:B3", values); + range = EvalFactory.createAreaEval("A1:B3", values); confirmCountIf(3, range, new NumberEval(2)); // note - same results when criteria is a string that parses as the number with the same value confirmCountIf(3, range, new StringEval("2.00")); @@ -126,20 +124,15 @@ public final class TestCountFuncs extends TestCase { new NumberEval(25), new NumberEval(25), }; - Area2DEval arg0 = new Area2DEval(new AreaPtg("C1:C6"), values); + AreaEval arg0 = EvalFactory.createAreaEval("C1:C6", values); - Ref2DEval criteriaArg = new Ref2DEval(new RefPtg("A1"), new NumberEval(25)); + ValueEval criteriaArg = EvalFactory.createRefEval("A1", new NumberEval(25)); Eval[] args= { arg0, criteriaArg, }; double actual = NumericFunctionInvoker.invoke(new Countif(), args); assertEquals(4, actual, 0D); } - - private static AreaEval createAreaEval(String areaRefStr, ValueEval[] values) { - return new Area2DEval(new AreaPtg(areaRefStr), values); - } - private static void confirmCountA(int expected, Eval[] args) { double result = NumericFunctionInvoker.invoke(new Counta(), args); assertEquals(expected, result, 0); diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestIndex.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestIndex.java index 492d68e98..80c154596 100755 --- a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestIndex.java +++ b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestIndex.java @@ -19,8 +19,7 @@ package org.apache.poi.hssf.record.formula.functions; import junit.framework.TestCase; -import org.apache.poi.hssf.record.formula.AreaPtg; -import org.apache.poi.hssf.record.formula.eval.Area2DEval; +import org.apache.poi.hssf.record.formula.eval.AreaEval; import org.apache.poi.hssf.record.formula.eval.Eval; import org.apache.poi.hssf.record.formula.eval.NumberEval; import org.apache.poi.hssf.record.formula.eval.ValueEval; @@ -68,7 +67,7 @@ public final class TestIndex extends TestCase { for (int i = 0; i < values.length; i++) { values[i] = new NumberEval(dValues[i]); } - Area2DEval arg0 = new Area2DEval(new AreaPtg(areaRefString), values); + AreaEval arg0 = EvalFactory.createAreaEval(areaRefString, values); Eval[] args; if (colNum > 0) { diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestMatch.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestMatch.java index d275e5f33..48104c22e 100755 --- a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestMatch.java +++ b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestMatch.java @@ -19,8 +19,6 @@ package org.apache.poi.hssf.record.formula.functions; import junit.framework.TestCase; -import org.apache.poi.hssf.record.formula.AreaPtg; -import org.apache.poi.hssf.record.formula.eval.Area2DEval; import org.apache.poi.hssf.record.formula.eval.AreaEval; import org.apache.poi.hssf.record.formula.eval.BoolEval; import org.apache.poi.hssf.record.formula.eval.ErrorEval; @@ -32,7 +30,7 @@ import org.apache.poi.hssf.record.formula.eval.ValueEval; /** * Test cases for MATCH() - * + * * @author Josh Micich */ public final class TestMatch extends TestCase { @@ -41,8 +39,8 @@ public final class TestMatch extends TestCase { private static final NumberEval MATCH_EXACT = new NumberEval(0); /** greater than or equal to */ private static final NumberEval MATCH_SMALLEST_GTE = new NumberEval(-1); - - + + private static Eval invokeMatch(Eval lookup_value, Eval lookup_array, Eval match_type) { Eval[] args = { lookup_value, lookup_array, match_type, }; return new Match().evaluate(args, -1, (short)-1); @@ -54,26 +52,19 @@ public final class TestMatch extends TestCase { NumericValueEval nve = (NumericValueEval)actualEval; assertEquals(expected, nve.getNumberValue(), 0); } - /** - * Convenience method - * @return new Area2DEval(new AreaPtg(ref), values) - */ - private static AreaEval createAreaEval(String ref, ValueEval[] values) { - return new Area2DEval(new AreaPtg(ref), values); - } - + public void testSimpleNumber() { - + ValueEval[] values = { - new NumberEval(4), - new NumberEval(5), - new NumberEval(10), - new NumberEval(10), - new NumberEval(25), + new NumberEval(4), + new NumberEval(5), + new NumberEval(10), + new NumberEval(10), + new NumberEval(25), }; - - AreaEval ae = createAreaEval("A1:A5", values); - + + AreaEval ae = EvalFactory.createAreaEval("A1:A5", values); + confirmInt(2, invokeMatch(new NumberEval(5), ae, MATCH_LARGEST_LTE)); confirmInt(2, invokeMatch(new NumberEval(5), ae, MATCH_EXACT)); confirmInt(4, invokeMatch(new NumberEval(10), ae, MATCH_LARGEST_LTE)); @@ -81,19 +72,19 @@ public final class TestMatch extends TestCase { confirmInt(4, invokeMatch(new NumberEval(20), ae, MATCH_LARGEST_LTE)); assertEquals(ErrorEval.NA, invokeMatch(new NumberEval(20), ae, MATCH_EXACT)); } - + public void testReversedNumber() { - + ValueEval[] values = { - new NumberEval(25), - new NumberEval(10), - new NumberEval(10), - new NumberEval(10), - new NumberEval(4), + new NumberEval(25), + new NumberEval(10), + new NumberEval(10), + new NumberEval(10), + new NumberEval(4), }; - - AreaEval ae = createAreaEval("A1:A5", values); - + + AreaEval ae = EvalFactory.createAreaEval("A1:A5", values); + confirmInt(2, invokeMatch(new NumberEval(10), ae, MATCH_SMALLEST_GTE)); confirmInt(2, invokeMatch(new NumberEval(10), ae, MATCH_EXACT)); confirmInt(4, invokeMatch(new NumberEval(9), ae, MATCH_SMALLEST_GTE)); @@ -101,19 +92,19 @@ public final class TestMatch extends TestCase { assertEquals(ErrorEval.NA, invokeMatch(new NumberEval(20), ae, MATCH_EXACT)); assertEquals(ErrorEval.NA, invokeMatch(new NumberEval(26), ae, MATCH_SMALLEST_GTE)); } - + public void testSimpleString() { - + ValueEval[] values = { - new StringEval("Albert"), - new StringEval("Charles"), - new StringEval("Ed"), - new StringEval("Greg"), - new StringEval("Ian"), + new StringEval("Albert"), + new StringEval("Charles"), + new StringEval("Ed"), + new StringEval("Greg"), + new StringEval("Ian"), }; - - AreaEval ae = createAreaEval("A1:A5", values); - + + AreaEval ae = EvalFactory.createAreaEval("A1:A5", values); + // Note String comparisons are case insensitive confirmInt(3, invokeMatch(new StringEval("Ed"), ae, MATCH_LARGEST_LTE)); confirmInt(3, invokeMatch(new StringEval("eD"), ae, MATCH_LARGEST_LTE)); @@ -122,90 +113,90 @@ public final class TestMatch extends TestCase { confirmInt(4, invokeMatch(new StringEval("Hugh"), ae, MATCH_LARGEST_LTE)); assertEquals(ErrorEval.NA, invokeMatch(new StringEval("Hugh"), ae, MATCH_EXACT)); } - + public void testSimpleBoolean() { - + ValueEval[] values = { - BoolEval.FALSE, - BoolEval.FALSE, - BoolEval.TRUE, - BoolEval.TRUE, + BoolEval.FALSE, + BoolEval.FALSE, + BoolEval.TRUE, + BoolEval.TRUE, }; - - AreaEval ae = createAreaEval("A1:A4", values); - + + AreaEval ae = EvalFactory.createAreaEval("A1:A4", values); + // Note String comparisons are case insensitive confirmInt(2, invokeMatch(BoolEval.FALSE, ae, MATCH_LARGEST_LTE)); confirmInt(1, invokeMatch(BoolEval.FALSE, ae, MATCH_EXACT)); confirmInt(4, invokeMatch(BoolEval.TRUE, ae, MATCH_LARGEST_LTE)); confirmInt(3, invokeMatch(BoolEval.TRUE, ae, MATCH_EXACT)); } - + public void testHeterogeneous() { - + ValueEval[] values = { - new NumberEval(4), - BoolEval.FALSE, + new NumberEval(4), + BoolEval.FALSE, new NumberEval(5), - new StringEval("Albert"), - BoolEval.FALSE, - BoolEval.TRUE, - new NumberEval(10), - new StringEval("Charles"), - new StringEval("Ed"), - new NumberEval(10), - new NumberEval(25), - BoolEval.TRUE, - new StringEval("Ed"), + new StringEval("Albert"), + BoolEval.FALSE, + BoolEval.TRUE, + new NumberEval(10), + new StringEval("Charles"), + new StringEval("Ed"), + new NumberEval(10), + new NumberEval(25), + BoolEval.TRUE, + new StringEval("Ed"), }; - - AreaEval ae = createAreaEval("A1:A13", values); - + + AreaEval ae = EvalFactory.createAreaEval("A1:A13", values); + assertEquals(ErrorEval.NA, invokeMatch(new StringEval("Aaron"), ae, MATCH_LARGEST_LTE)); - + confirmInt(5, invokeMatch(BoolEval.FALSE, ae, MATCH_LARGEST_LTE)); confirmInt(2, invokeMatch(BoolEval.FALSE, ae, MATCH_EXACT)); confirmInt(3, invokeMatch(new NumberEval(5), ae, MATCH_LARGEST_LTE)); confirmInt(3, invokeMatch(new NumberEval(5), ae, MATCH_EXACT)); - + confirmInt(8, invokeMatch(new StringEval("CHARLES"), ae, MATCH_EXACT)); - + confirmInt(4, invokeMatch(new StringEval("Ben"), ae, MATCH_LARGEST_LTE)); - + confirmInt(13, invokeMatch(new StringEval("ED"), ae, MATCH_LARGEST_LTE)); confirmInt(9, invokeMatch(new StringEval("ED"), ae, MATCH_EXACT)); - + confirmInt(13, invokeMatch(new StringEval("Hugh"), ae, MATCH_LARGEST_LTE)); assertEquals(ErrorEval.NA, invokeMatch(new StringEval("Hugh"), ae, MATCH_EXACT)); - + confirmInt(11, invokeMatch(new NumberEval(30), ae, MATCH_LARGEST_LTE)); confirmInt(12, invokeMatch(BoolEval.TRUE, ae, MATCH_LARGEST_LTE)); } - + /** * Ensures that the match_type argument can be an AreaEval.
* Bugzilla 44421 */ public void testMatchArgTypeArea() { - - ValueEval[] values = { - new NumberEval(4), - new NumberEval(5), - new NumberEval(10), - new NumberEval(10), - new NumberEval(25), - }; - - AreaEval ae = createAreaEval("A1:A5", values); - AreaEval matchAE = createAreaEval("C1:C1", new ValueEval[] { MATCH_LARGEST_LTE, }); - + ValueEval[] values = { + new NumberEval(4), + new NumberEval(5), + new NumberEval(10), + new NumberEval(10), + new NumberEval(25), + }; + + AreaEval ae = EvalFactory.createAreaEval("A1:A5", values); + + AreaEval matchAE = EvalFactory.createAreaEval("C1:C1", new ValueEval[] { MATCH_LARGEST_LTE, }); + try { confirmInt(4, invokeMatch(new NumberEval(10), ae, matchAE)); } catch (RuntimeException e) { if(e.getMessage().startsWith("Unexpected match_type type")) { - // identified bug 44421 + // identified bug 44421 fail(e.getMessage()); } // some other error ?? diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestMathX.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestMathX.java index eb576506a..d95718524 100644 --- a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestMathX.java +++ b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestMathX.java @@ -20,6 +20,8 @@ */ package org.apache.poi.hssf.record.formula.functions; +import org.apache.poi.hssf.record.formula.functions.XYNumericFunction.Accumulator; + /** * @author Amol S. Deshmukh < amolweb at ya hoo dot com > @@ -566,99 +568,99 @@ public class TestMathX extends AbstractNumericTestCase { } public void testSumx2my2() { - double d = 0; double[] xarr = null; double[] yarr = null; xarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; yarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - d = MathX.sumx2my2(xarr, yarr); - assertEquals("sumx2my2 ", 100, d); + confirmSumx2my2(xarr, yarr, 100); xarr = new double[]{-1, -2, -3, -4, -5, -6, -7, -8, -9, -10}; yarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - d = MathX.sumx2my2(xarr, yarr); - assertEquals("sumx2my2 ", 100, d); + confirmSumx2my2(xarr, yarr, 100); xarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; yarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - d = MathX.sumx2my2(xarr, yarr); - assertEquals("sumx2my2 ", -100, d); + confirmSumx2my2(xarr, yarr, -100); xarr = new double[]{10}; yarr = new double[]{9}; - d = MathX.sumx2my2(xarr, yarr); - assertEquals("sumx2my2 ", 19, d); + confirmSumx2my2(xarr, yarr, 19); xarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; yarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - d = MathX.sumx2my2(xarr, yarr); - assertEquals("sumx2my2 ", 0, d); - + confirmSumx2my2(xarr, yarr, 0); } public void testSumx2py2() { - double d = 0; double[] xarr = null; double[] yarr = null; xarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; yarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - d = MathX.sumx2py2(xarr, yarr); - assertEquals("sumx2py2 ", 670, d); + confirmSumx2py2(xarr, yarr, 670); xarr = new double[]{-1, -2, -3, -4, -5, -6, -7, -8, -9, -10}; yarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - d = MathX.sumx2py2(xarr, yarr); - assertEquals("sumx2py2 ", 670, d); + confirmSumx2py2(xarr, yarr, 670); xarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; yarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - d = MathX.sumx2py2(xarr, yarr); - assertEquals("sumx2py2 ", 670, d); + confirmSumx2py2(xarr, yarr, 670); xarr = new double[]{10}; yarr = new double[]{9}; - d = MathX.sumx2py2(xarr, yarr); - assertEquals("sumx2py2 ", 181, d); + confirmSumx2py2(xarr, yarr, 181); xarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; yarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - d = MathX.sumx2py2(xarr, yarr); - assertEquals("sumx2py2 ", 770, d); + confirmSumx2py2(xarr, yarr, 770); } public void testSumxmy2() { - double d = 0; double[] xarr = null; double[] yarr = null; xarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; yarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - d = MathX.sumxmy2(xarr, yarr); - assertEquals("sumxmy2 ", 10, d); + confirmSumxmy2(xarr, yarr, 10); xarr = new double[]{-1, -2, -3, -4, -5, -6, -7, -8, -9, -10}; yarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - d = MathX.sumxmy2(xarr, yarr); - assertEquals("sumxmy2 ", 1330, d); + confirmSumxmy2(xarr, yarr, 1330); xarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; yarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - d = MathX.sumxmy2(xarr, yarr); - assertEquals("sumxmy2 ", 10, d); + confirmSumxmy2(xarr, yarr, 10); xarr = new double[]{10}; yarr = new double[]{9}; - d = MathX.sumxmy2(xarr, yarr); - assertEquals("sumxmy2 ", 1, d); + confirmSumxmy2(xarr, yarr, 1); xarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; yarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - d = MathX.sumxmy2(xarr, yarr); - assertEquals("sumxmy2 ", 0, d); + confirmSumxmy2(xarr, yarr, 0); } + private static void confirmSumx2my2(double[] xarr, double[] yarr, double expectedResult) { + confirmXY(new Sumx2my2().createAccumulator(), xarr, yarr, expectedResult); + } + private static void confirmSumx2py2(double[] xarr, double[] yarr, double expectedResult) { + confirmXY(new Sumx2py2().createAccumulator(), xarr, yarr, expectedResult); + } + private static void confirmSumxmy2(double[] xarr, double[] yarr, double expectedResult) { + confirmXY(new Sumxmy2().createAccumulator(), xarr, yarr, expectedResult); + } + + private static void confirmXY(Accumulator acc, double[] xarr, double[] yarr, + double expectedResult) { + double result = 0.0; + for (int i = 0; i < xarr.length; i++) { + result += acc.accumulate(xarr[i], yarr[i]); + } + assertEquals(expectedResult, result, 0.0); + } + public void testRound() { double d = 0; int p = 0; diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestMid.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestMid.java index 87dd470c6..76cd1056e 100755 --- a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestMid.java +++ b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestMid.java @@ -17,29 +17,25 @@ package org.apache.poi.hssf.record.formula.functions; -import org.apache.poi.hssf.record.formula.AreaPtg; -import org.apache.poi.hssf.record.formula.RefPtg; -import org.apache.poi.hssf.record.formula.eval.Area2DEval; +import junit.framework.TestCase; + import org.apache.poi.hssf.record.formula.eval.AreaEval; import org.apache.poi.hssf.record.formula.eval.BlankEval; import org.apache.poi.hssf.record.formula.eval.BoolEval; 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.NumberEval; -import org.apache.poi.hssf.record.formula.eval.Ref2DEval; 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; - -import junit.framework.TestCase; /** * Tests for Excel function MID() - * + * * @author Josh Micich */ public final class TestMid extends TestCase { - + private static Eval invokeMid(Eval text, Eval startPos, Eval numChars) { Eval[] args = new Eval[] { text, startPos, numChars, }; return new Mid().evaluate(args, -1, (short)-1); @@ -56,28 +52,28 @@ public final class TestMid extends TestCase { assertEquals(ErrorEval.class, result.getClass()); assertEquals(expectedError.getErrorCode(), ((ErrorEval)result).getErrorCode()); } - + public void testBasic() { - + confirmMid(new StringEval("galactic"), new NumberEval(3), new NumberEval(4), "lact"); } - + /** * Valid cases where args are not precisely (string, int, int) but can be resolved OK. */ public void testUnusualArgs() { // startPos with fractional digits confirmMid(new StringEval("galactic"), new NumberEval(3.1), new NumberEval(4), "lact"); - + // string startPos confirmMid(new StringEval("galactic"), new StringEval("3"), new NumberEval(4), "lact"); - - // text (first) arg type is number, other args are strings with fractional digits + + // text (first) arg type is number, other args are strings with fractional digits confirmMid(new NumberEval(123456), new StringEval("3.1"), new StringEval("2.9"), "34"); - + // startPos is 1x1 area ref, numChars is cell ref - AreaEval aeStart = new Area2DEval(new AreaPtg("A1:A1"), new ValueEval[] { new NumberEval(2), } ); - RefEval reNumChars = new Ref2DEval(new RefPtg("B1"), new NumberEval(3)); + AreaEval aeStart = EvalFactory.createAreaEval("A1:A1", new ValueEval[] { new NumberEval(2), } ); + RefEval reNumChars = EvalFactory.createRefEval("B1", new NumberEval(3)); confirmMid(new StringEval("galactic"), aeStart, reNumChars, "ala"); confirmMid(new StringEval("galactic"), new NumberEval(3.1), BlankEval.INSTANCE, ""); @@ -85,7 +81,7 @@ public final class TestMid extends TestCase { confirmMid(new StringEval("galactic"), new NumberEval(3), BoolEval.FALSE, ""); confirmMid(new StringEval("galactic"), new NumberEval(3), BoolEval.TRUE, "l"); confirmMid(BlankEval.INSTANCE, new NumberEval(3), BoolEval.TRUE, ""); - + } /** @@ -93,7 +89,7 @@ public final class TestMid extends TestCase { */ public void testExtremes() { confirmMid(new StringEval("galactic"), new NumberEval(4), new NumberEval(400), "actic"); - + confirmMid(new StringEval("galactic"), new NumberEval(30), new NumberEval(4), ""); confirmMid(new StringEval("galactic"), new NumberEval(3), new NumberEval(0), ""); } @@ -106,9 +102,9 @@ public final class TestMid extends TestCase { confirmMid(new StringEval("galactic"), ErrorEval.NAME_INVALID, new NumberEval(4), ErrorEval.NAME_INVALID); confirmMid(new StringEval("galactic"), new NumberEval(3), ErrorEval.NAME_INVALID, ErrorEval.NAME_INVALID); confirmMid(new StringEval("galactic"), ErrorEval.DIV_ZERO, ErrorEval.NAME_INVALID, ErrorEval.DIV_ZERO); - + confirmMid(new StringEval("galactic"), BlankEval.INSTANCE, new NumberEval(3.1), ErrorEval.VALUE_INVALID); - + confirmMid(new StringEval("galactic"), new NumberEval(0), new NumberEval(4), ErrorEval.VALUE_INVALID); confirmMid(new StringEval("galactic"), new NumberEval(1), new NumberEval(-1), ErrorEval.VALUE_INVALID); } diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestSumproduct.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestSumproduct.java index 884b9b4a3..47ee0afbb 100755 --- a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestSumproduct.java +++ b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestSumproduct.java @@ -17,18 +17,16 @@ package org.apache.poi.hssf.record.formula.functions; -import org.apache.poi.hssf.record.formula.RefPtg; +import junit.framework.TestCase; + import org.apache.poi.hssf.record.formula.eval.AreaEval; 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.NumberEval; import org.apache.poi.hssf.record.formula.eval.NumericValueEval; -import org.apache.poi.hssf.record.formula.eval.Ref2DEval; import org.apache.poi.hssf.record.formula.eval.RefEval; import org.apache.poi.hssf.record.formula.eval.ValueEval; -import junit.framework.TestCase; - /** * Test cases for SUMPRODUCT() * @@ -50,7 +48,7 @@ public final class TestSumproduct extends TestCase { public void testScalarSimple() { - RefEval refEval = new Ref2DEval(new RefPtg("A1"), new NumberEval(3)); + RefEval refEval = EvalFactory.createRefEval("A1", new NumberEval(3)); Eval[] args = { refEval, new NumberEval(2), diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestTFunc.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestTFunc.java index c57640eab..ac7152d0e 100755 --- a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestTFunc.java +++ b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestTFunc.java @@ -17,18 +17,16 @@ package org.apache.poi.hssf.record.formula.functions; -import org.apache.poi.hssf.record.formula.RefPtg; +import junit.framework.TestCase; + import org.apache.poi.hssf.record.formula.eval.BlankEval; import org.apache.poi.hssf.record.formula.eval.BoolEval; 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.NumberEval; -import org.apache.poi.hssf.record.formula.eval.Ref2DEval; import org.apache.poi.hssf.record.formula.eval.StringEval; import org.apache.poi.hssf.record.formula.eval.ValueEval; -import junit.framework.TestCase; - /** * Test cases for Excel function T() * @@ -50,7 +48,7 @@ public final class TestTFunc extends TestCase { * where cell A1 has the specified innerValue */ private Eval invokeTWithReference(ValueEval innerValue) { - Eval arg = new Ref2DEval(new RefPtg((short)1, (short)1, false, false), innerValue); + Eval arg = EvalFactory.createRefEval("$B$2", innerValue); return invokeT(arg); } diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestXYNumericFunction.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestXYNumericFunction.java index c9f043bd3..0d62b1fb0 100755 --- a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestXYNumericFunction.java +++ b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestXYNumericFunction.java @@ -19,8 +19,6 @@ package org.apache.poi.hssf.record.formula.functions; import junit.framework.TestCase; -import org.apache.poi.hssf.record.formula.AreaPtg; -import org.apache.poi.hssf.record.formula.eval.Area2DEval; 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.NumberEval; @@ -100,7 +98,7 @@ public final class TestXYNumericFunction extends TestCase { private static ValueEval createAreaEval(ValueEval[] values) { String refStr = "A1:A" + values.length; - return new Area2DEval(new AreaPtg(refStr), values); + return EvalFactory.createAreaEval(refStr, values); } public void testErrors() {