mirror of https://github.com/apache/poi.git
Made BlankEval instance consistent with other Eval singletons.
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@885061 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
b8b1ec057e
commit
410dc0236b
|
@ -23,7 +23,11 @@ package org.apache.poi.hssf.record.formula.eval;
|
||||||
*/
|
*/
|
||||||
public final class BlankEval implements ValueEval {
|
public final class BlankEval implements ValueEval {
|
||||||
|
|
||||||
public static BlankEval INSTANCE = new BlankEval();
|
public static final BlankEval instance = new BlankEval();
|
||||||
|
/**
|
||||||
|
* @deprecated (Nov 2009) use {@link #instance}
|
||||||
|
*/
|
||||||
|
public static final BlankEval INSTANCE = instance;
|
||||||
|
|
||||||
private BlankEval() {
|
private BlankEval() {
|
||||||
// enforce singleton
|
// enforce singleton
|
||||||
|
|
|
@ -51,7 +51,7 @@ public final class ConcatEval extends Fixed2ArgFunction {
|
||||||
StringValueEval sve = (StringValueEval) ve;
|
StringValueEval sve = (StringValueEval) ve;
|
||||||
return sve.getStringValue();
|
return sve.getStringValue();
|
||||||
}
|
}
|
||||||
if (ve == BlankEval.INSTANCE) {
|
if (ve == BlankEval.instance) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
throw new IllegalAccessError("Unexpected value type ("
|
throw new IllegalAccessError("Unexpected value type ("
|
||||||
|
|
|
@ -106,7 +106,7 @@ public final class OperandResolver {
|
||||||
if(result == null) {
|
if(result == null) {
|
||||||
// This seems to be required because AreaEval.values() array may contain nulls.
|
// This seems to be required because AreaEval.values() array may contain nulls.
|
||||||
// perhaps that should not be allowed.
|
// perhaps that should not be allowed.
|
||||||
result = BlankEval.INSTANCE;
|
result = BlankEval.instance;
|
||||||
}
|
}
|
||||||
if (result instanceof ErrorEval) {
|
if (result instanceof ErrorEval) {
|
||||||
throw new EvaluationException((ErrorEval) result);
|
throw new EvaluationException((ErrorEval) result);
|
||||||
|
@ -179,7 +179,7 @@ public final class OperandResolver {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public static int coerceValueToInt(ValueEval ev) throws EvaluationException {
|
public static int coerceValueToInt(ValueEval ev) throws EvaluationException {
|
||||||
if (ev == BlankEval.INSTANCE) {
|
if (ev == BlankEval.instance) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
double d = coerceValueToDouble(ev);
|
double d = coerceValueToDouble(ev);
|
||||||
|
@ -201,7 +201,7 @@ public final class OperandResolver {
|
||||||
*/
|
*/
|
||||||
public static double coerceValueToDouble(ValueEval ev) throws EvaluationException {
|
public static double coerceValueToDouble(ValueEval ev) throws EvaluationException {
|
||||||
|
|
||||||
if (ev == BlankEval.INSTANCE) {
|
if (ev == BlankEval.instance) {
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
if (ev instanceof NumericValueEval) {
|
if (ev instanceof NumericValueEval) {
|
||||||
|
@ -268,7 +268,7 @@ public final class OperandResolver {
|
||||||
StringValueEval sve = (StringValueEval) ve;
|
StringValueEval sve = (StringValueEval) ve;
|
||||||
return sve.getStringValue();
|
return sve.getStringValue();
|
||||||
}
|
}
|
||||||
if (ve == BlankEval.INSTANCE) {
|
if (ve == BlankEval.instance) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
throw new IllegalArgumentException("Unexpected eval class (" + ve.getClass().getName() + ")");
|
throw new IllegalArgumentException("Unexpected eval class (" + ve.getClass().getName() + ")");
|
||||||
|
@ -280,7 +280,7 @@ public final class OperandResolver {
|
||||||
*/
|
*/
|
||||||
public static Boolean coerceValueToBoolean(ValueEval ve, boolean stringsAreBlanks) throws EvaluationException {
|
public static Boolean coerceValueToBoolean(ValueEval ve, boolean stringsAreBlanks) throws EvaluationException {
|
||||||
|
|
||||||
if (ve == null || ve == BlankEval.INSTANCE) {
|
if (ve == null || ve == BlankEval.instance) {
|
||||||
// TODO - remove 've == null' condition once AreaEval is fixed
|
// TODO - remove 've == null' condition once AreaEval is fixed
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -288,7 +288,7 @@ public final class OperandResolver {
|
||||||
return Boolean.valueOf(((BoolEval) ve).getBooleanValue());
|
return Boolean.valueOf(((BoolEval) ve).getBooleanValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ve == BlankEval.INSTANCE) {
|
if (ve == BlankEval.instance) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,10 +73,10 @@ public abstract class RelationalOperationEval extends Fixed2ArgFunction {
|
||||||
|
|
||||||
private static int doCompare(ValueEval va, ValueEval vb) {
|
private static int doCompare(ValueEval va, ValueEval vb) {
|
||||||
// special cases when one operand is blank
|
// special cases when one operand is blank
|
||||||
if (va == BlankEval.INSTANCE) {
|
if (va == BlankEval.instance) {
|
||||||
return compareBlank(vb);
|
return compareBlank(vb);
|
||||||
}
|
}
|
||||||
if (vb == BlankEval.INSTANCE) {
|
if (vb == BlankEval.instance) {
|
||||||
return -compareBlank(va);
|
return -compareBlank(va);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ public abstract class RelationalOperationEval extends Fixed2ArgFunction {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int compareBlank(ValueEval v) {
|
private static int compareBlank(ValueEval v) {
|
||||||
if (v == BlankEval.INSTANCE) {
|
if (v == BlankEval.instance) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (v instanceof BoolEval) {
|
if (v instanceof BoolEval) {
|
||||||
|
|
|
@ -41,7 +41,7 @@ public final class Choose implements Function {
|
||||||
}
|
}
|
||||||
ValueEval result = OperandResolver.getSingleValue(args[ix], srcRowIndex, srcColumnIndex);
|
ValueEval result = OperandResolver.getSingleValue(args[ix], srcRowIndex, srcColumnIndex);
|
||||||
if (result == MissingArgEval.instance) {
|
if (result == MissingArgEval.instance) {
|
||||||
return BlankEval.INSTANCE;
|
return BlankEval.instance;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
} catch (EvaluationException e) {
|
} catch (EvaluationException e) {
|
||||||
|
|
|
@ -62,7 +62,7 @@ public final class Counta implements Function {
|
||||||
// Error values like #VALUE!, #REF!, #DIV/0!, #NAME? etc don't cause this COUNTA to return an error
|
// Error values like #VALUE!, #REF!, #DIV/0!, #NAME? etc don't cause this COUNTA to return an error
|
||||||
// in fact, they seem to get counted
|
// in fact, they seem to get counted
|
||||||
|
|
||||||
if(valueEval == BlankEval.INSTANCE) {
|
if(valueEval == BlankEval.instance) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Note - everything but BlankEval counts
|
// Note - everything but BlankEval counts
|
||||||
|
|
|
@ -54,7 +54,7 @@ public final class Countblank extends Fixed1ArgFunction {
|
||||||
|
|
||||||
public boolean matches(ValueEval valueEval) {
|
public boolean matches(ValueEval valueEval) {
|
||||||
// Note - only BlankEval counts
|
// Note - only BlankEval counts
|
||||||
return valueEval == BlankEval.INSTANCE;
|
return valueEval == BlankEval.instance;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -445,7 +445,7 @@ public final class Countif extends Fixed2ArgFunction {
|
||||||
if(evaluatedCriteriaArg instanceof ErrorEval) {
|
if(evaluatedCriteriaArg instanceof ErrorEval) {
|
||||||
return new ErrorMatcher(((ErrorEval)evaluatedCriteriaArg).getErrorCode(), CmpOp.OP_NONE);
|
return new ErrorMatcher(((ErrorEval)evaluatedCriteriaArg).getErrorCode(), CmpOp.OP_NONE);
|
||||||
}
|
}
|
||||||
if(evaluatedCriteriaArg == BlankEval.INSTANCE) {
|
if(evaluatedCriteriaArg == BlankEval.instance) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
throw new RuntimeException("Unexpected type for criteria ("
|
throw new RuntimeException("Unexpected type for criteria ("
|
||||||
|
|
|
@ -38,7 +38,7 @@ public final class If extends Var2or3ArgFunction {
|
||||||
}
|
}
|
||||||
if (b) {
|
if (b) {
|
||||||
if (arg1 == MissingArgEval.instance) {
|
if (arg1 == MissingArgEval.instance) {
|
||||||
return BlankEval.INSTANCE;
|
return BlankEval.instance;
|
||||||
}
|
}
|
||||||
return arg1;
|
return arg1;
|
||||||
}
|
}
|
||||||
|
@ -55,12 +55,12 @@ public final class If extends Var2or3ArgFunction {
|
||||||
}
|
}
|
||||||
if (b) {
|
if (b) {
|
||||||
if (arg1 == MissingArgEval.instance) {
|
if (arg1 == MissingArgEval.instance) {
|
||||||
return BlankEval.INSTANCE;
|
return BlankEval.instance;
|
||||||
}
|
}
|
||||||
return arg1;
|
return arg1;
|
||||||
}
|
}
|
||||||
if (arg2 == MissingArgEval.instance) {
|
if (arg2 == MissingArgEval.instance) {
|
||||||
return BlankEval.INSTANCE;
|
return BlankEval.instance;
|
||||||
}
|
}
|
||||||
return arg2;
|
return arg2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -200,7 +200,7 @@ public final class Index implements Function2Arg, Function3Arg, Function4Arg {
|
||||||
if (ev == MissingArgEval.instance) {
|
if (ev == MissingArgEval.instance) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (ev == BlankEval.INSTANCE) {
|
if (ev == BlankEval.instance) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int result = OperandResolver.coerceValueToInt(ev);
|
int result = OperandResolver.coerceValueToInt(ev);
|
||||||
|
|
|
@ -80,7 +80,7 @@ public final class Indirect implements FreeRefFunction {
|
||||||
throws EvaluationException {
|
throws EvaluationException {
|
||||||
ValueEval ve = OperandResolver.getSingleValue(arg, ec.getRowIndex(), ec.getColumnIndex());
|
ValueEval ve = OperandResolver.getSingleValue(arg, ec.getRowIndex(), ec.getColumnIndex());
|
||||||
|
|
||||||
if (ve == BlankEval.INSTANCE || ve == MissingArgEval.instance) {
|
if (ve == BlankEval.instance || ve == MissingArgEval.instance) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// numeric quantities follow standard boolean conversion rules
|
// numeric quantities follow standard boolean conversion rules
|
||||||
|
|
|
@ -585,7 +585,7 @@ final class LookupUtils {
|
||||||
|
|
||||||
public static LookupValueComparer createLookupComparer(ValueEval lookupValue) {
|
public static LookupValueComparer createLookupComparer(ValueEval lookupValue) {
|
||||||
|
|
||||||
if (lookupValue == BlankEval.INSTANCE) {
|
if (lookupValue == BlankEval.instance) {
|
||||||
// blank eval translates to zero
|
// blank eval translates to zero
|
||||||
// Note - a blank eval in the lookup column/row never matches anything
|
// Note - a blank eval in the lookup column/row never matches anything
|
||||||
// empty string in the lookup column/row can only be matched by explicit empty string
|
// empty string in the lookup column/row can only be matched by explicit empty string
|
||||||
|
|
|
@ -118,7 +118,7 @@ public final class Mode implements Function {
|
||||||
if (arg instanceof ErrorEval) {
|
if (arg instanceof ErrorEval) {
|
||||||
throw new EvaluationException((ErrorEval) arg);
|
throw new EvaluationException((ErrorEval) arg);
|
||||||
}
|
}
|
||||||
if (arg == BlankEval.INSTANCE || arg instanceof BoolEval || arg instanceof StringEval) {
|
if (arg == BlankEval.instance || arg instanceof BoolEval || arg instanceof StringEval) {
|
||||||
if (mustBeNumber) {
|
if (mustBeNumber) {
|
||||||
throw EvaluationException.invalidValue();
|
throw EvaluationException.invalidValue();
|
||||||
}
|
}
|
||||||
|
|
|
@ -185,7 +185,7 @@ public abstract class MultiOperandNumericFunction implements Function {
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (ve == BlankEval.INSTANCE) {
|
if (ve == BlankEval.instance) {
|
||||||
if (_isBlankCounted) {
|
if (_isBlankCounted) {
|
||||||
temp.add(0.0);
|
temp.add(0.0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,10 +30,10 @@ import org.apache.poi.ss.formula.IEvaluationListener.ICacheEntry;
|
||||||
*/
|
*/
|
||||||
abstract class CellCacheEntry implements ICacheEntry {
|
abstract class CellCacheEntry implements ICacheEntry {
|
||||||
public static final CellCacheEntry[] EMPTY_ARRAY = { };
|
public static final CellCacheEntry[] EMPTY_ARRAY = { };
|
||||||
|
|
||||||
private final FormulaCellCacheEntrySet _consumingCells;
|
private final FormulaCellCacheEntrySet _consumingCells;
|
||||||
private ValueEval _value;
|
private ValueEval _value;
|
||||||
|
|
||||||
|
|
||||||
protected CellCacheEntry() {
|
protected CellCacheEntry() {
|
||||||
_consumingCells = new FormulaCellCacheEntrySet();
|
_consumingCells = new FormulaCellCacheEntrySet();
|
||||||
|
@ -53,7 +53,7 @@ abstract class CellCacheEntry implements ICacheEntry {
|
||||||
public final ValueEval getValue() {
|
public final ValueEval getValue() {
|
||||||
return _value;
|
return _value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean areValuesEqual(ValueEval a, ValueEval b) {
|
private static boolean areValuesEqual(ValueEval a, ValueEval b) {
|
||||||
if (a == null) {
|
if (a == null) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -63,7 +63,7 @@ abstract class CellCacheEntry implements ICacheEntry {
|
||||||
// value type is changing
|
// value type is changing
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (a == BlankEval.INSTANCE) {
|
if (a == BlankEval.instance) {
|
||||||
return b == a;
|
return b == a;
|
||||||
}
|
}
|
||||||
if (cls == NumberEval.class) {
|
if (cls == NumberEval.class) {
|
||||||
|
@ -83,7 +83,7 @@ abstract class CellCacheEntry implements ICacheEntry {
|
||||||
|
|
||||||
public final void addConsumingCell(FormulaCellCacheEntry cellLoc) {
|
public final void addConsumingCell(FormulaCellCacheEntry cellLoc) {
|
||||||
_consumingCells.add(cellLoc);
|
_consumingCells.add(cellLoc);
|
||||||
|
|
||||||
}
|
}
|
||||||
public final FormulaCellCacheEntry[] getConsumingCells() {
|
public final FormulaCellCacheEntry[] getConsumingCells() {
|
||||||
return _consumingCells.toArray();
|
return _consumingCells.toArray();
|
||||||
|
@ -102,23 +102,23 @@ abstract class CellCacheEntry implements ICacheEntry {
|
||||||
recurseClearCachedFormulaResults(listener, 1);
|
recurseClearCachedFormulaResults(listener, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls formulaCell.setFormulaResult(null, null) recursively all the way up the tree of
|
* Calls formulaCell.setFormulaResult(null, null) recursively all the way up the tree of
|
||||||
* dependencies. Calls usedCell.clearConsumingCell(fc) for each child of a cell that is
|
* dependencies. Calls usedCell.clearConsumingCell(fc) for each child of a cell that is
|
||||||
* cleared along the way.
|
* cleared along the way.
|
||||||
* @param formulaCells
|
* @param formulaCells
|
||||||
*/
|
*/
|
||||||
protected final void recurseClearCachedFormulaResults() {
|
protected final void recurseClearCachedFormulaResults() {
|
||||||
FormulaCellCacheEntry[] formulaCells = getConsumingCells();
|
FormulaCellCacheEntry[] formulaCells = getConsumingCells();
|
||||||
|
|
||||||
for (int i = 0; i < formulaCells.length; i++) {
|
for (int i = 0; i < formulaCells.length; i++) {
|
||||||
FormulaCellCacheEntry fc = formulaCells[i];
|
FormulaCellCacheEntry fc = formulaCells[i];
|
||||||
fc.clearFormulaEntry();
|
fc.clearFormulaEntry();
|
||||||
fc.recurseClearCachedFormulaResults();
|
fc.recurseClearCachedFormulaResults();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Identical to {@link #recurseClearCachedFormulaResults()} except for the listener call-backs
|
* Identical to {@link #recurseClearCachedFormulaResults()} except for the listener call-backs
|
||||||
*/
|
*/
|
||||||
|
@ -133,5 +133,4 @@ abstract class CellCacheEntry implements ICacheEntry {
|
||||||
fc.recurseClearCachedFormulaResults(listener, depth+1);
|
fc.recurseClearCachedFormulaResults(listener, depth+1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -31,10 +31,9 @@ import org.apache.poi.ss.formula.PlainCellCache.Loc;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performance optimisation for {@link HSSFFormulaEvaluator}. This class stores previously
|
* Performance optimisation for {@link HSSFFormulaEvaluator}. This class stores previously
|
||||||
* calculated values of already visited cells, to avoid unnecessary re-calculation when the
|
* calculated values of already visited cells, to avoid unnecessary re-calculation when the
|
||||||
* same cells are referenced multiple times
|
* same cells are referenced multiple times
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* @author Josh Micich
|
* @author Josh Micich
|
||||||
*/
|
*/
|
||||||
final class EvaluationCache {
|
final class EvaluationCache {
|
||||||
|
@ -84,7 +83,7 @@ final class EvaluationCache {
|
||||||
} else {
|
} else {
|
||||||
ValueEval value = WorkbookEvaluator.getValueFromNonFormulaCell(cell);
|
ValueEval value = WorkbookEvaluator.getValueFromNonFormulaCell(cell);
|
||||||
if (pcce == null) {
|
if (pcce == null) {
|
||||||
if (value != BlankEval.INSTANCE) {
|
if (value != BlankEval.instance) {
|
||||||
// only cache non-blank values in the plain cell cache
|
// only cache non-blank values in the plain cell cache
|
||||||
// (dependencies on blank cells are managed by
|
// (dependencies on blank cells are managed by
|
||||||
// FormulaCellCacheEntry._usedBlankCellGroup)
|
// FormulaCellCacheEntry._usedBlankCellGroup)
|
||||||
|
@ -102,7 +101,7 @@ final class EvaluationCache {
|
||||||
if (pcce.updateValue(value)) {
|
if (pcce.updateValue(value)) {
|
||||||
pcce.recurseClearCachedFormulaResults(_evaluationListener);
|
pcce.recurseClearCachedFormulaResults(_evaluationListener);
|
||||||
}
|
}
|
||||||
if (value == BlankEval.INSTANCE) {
|
if (value == BlankEval.instance) {
|
||||||
_plainCellCache.remove(loc);
|
_plainCellCache.remove(loc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,7 +116,7 @@ final class EvaluationCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateAnyBlankReferencingFormulas(int bookIndex, int sheetIndex,
|
private void updateAnyBlankReferencingFormulas(int bookIndex, int sheetIndex,
|
||||||
final int rowIndex, final int columnIndex) {
|
final int rowIndex, final int columnIndex) {
|
||||||
final BookSheetKey bsk = new BookSheetKey(bookIndex, sheetIndex);
|
final BookSheetKey bsk = new BookSheetKey(bookIndex, sheetIndex);
|
||||||
_formulaCellCache.applyOperation(new IEntryOperation() {
|
_formulaCellCache.applyOperation(new IEntryOperation() {
|
||||||
|
@ -130,7 +129,7 @@ final class EvaluationCache {
|
||||||
|
|
||||||
public PlainValueCellCacheEntry getPlainValueEntry(int bookIndex, int sheetIndex,
|
public PlainValueCellCacheEntry getPlainValueEntry(int bookIndex, int sheetIndex,
|
||||||
int rowIndex, int columnIndex, ValueEval value) {
|
int rowIndex, int columnIndex, ValueEval value) {
|
||||||
|
|
||||||
Loc loc = new Loc(bookIndex, sheetIndex, rowIndex, columnIndex);
|
Loc loc = new Loc(bookIndex, sheetIndex, rowIndex, columnIndex);
|
||||||
PlainValueCellCacheEntry result = _plainCellCache.get(loc);
|
PlainValueCellCacheEntry result = _plainCellCache.get(loc);
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
|
@ -140,7 +139,7 @@ final class EvaluationCache {
|
||||||
_evaluationListener.onReadPlainValue(sheetIndex, rowIndex, columnIndex, result);
|
_evaluationListener.onReadPlainValue(sheetIndex, rowIndex, columnIndex, result);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// TODO - if we are confident that this sanity check is not required, we can remove 'value' from plain value cache entry
|
// TODO - if we are confident that this sanity check is not required, we can remove 'value' from plain value cache entry
|
||||||
if (!areValuesEqual(result.getValue(), value)) {
|
if (!areValuesEqual(result.getValue(), value)) {
|
||||||
throw new IllegalStateException("value changed");
|
throw new IllegalStateException("value changed");
|
||||||
}
|
}
|
||||||
|
@ -159,7 +158,7 @@ final class EvaluationCache {
|
||||||
// value type is changing
|
// value type is changing
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (a == BlankEval.INSTANCE) {
|
if (a == BlankEval.instance) {
|
||||||
return b == a;
|
return b == a;
|
||||||
}
|
}
|
||||||
if (cls == NumberEval.class) {
|
if (cls == NumberEval.class) {
|
||||||
|
@ -176,11 +175,11 @@ final class EvaluationCache {
|
||||||
}
|
}
|
||||||
throw new IllegalStateException("Unexpected value class (" + cls.getName() + ")");
|
throw new IllegalStateException("Unexpected value class (" + cls.getName() + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
public FormulaCellCacheEntry getOrCreateFormulaCellEntry(EvaluationCell cell) {
|
public FormulaCellCacheEntry getOrCreateFormulaCellEntry(EvaluationCell cell) {
|
||||||
FormulaCellCacheEntry result = _formulaCellCache.get(cell);
|
FormulaCellCacheEntry result = _formulaCellCache.get(cell);
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
|
|
||||||
result = new FormulaCellCacheEntry();
|
result = new FormulaCellCacheEntry();
|
||||||
_formulaCellCache.put(cell, result);
|
_formulaCellCache.put(cell, result);
|
||||||
}
|
}
|
||||||
|
@ -198,11 +197,11 @@ final class EvaluationCache {
|
||||||
_formulaCellCache.clear();
|
_formulaCellCache.clear();
|
||||||
}
|
}
|
||||||
public void notifyDeleteCell(int bookIndex, int sheetIndex, EvaluationCell cell) {
|
public void notifyDeleteCell(int bookIndex, int sheetIndex, EvaluationCell cell) {
|
||||||
|
|
||||||
if (cell.getCellType() == HSSFCell.CELL_TYPE_FORMULA) {
|
if (cell.getCellType() == HSSFCell.CELL_TYPE_FORMULA) {
|
||||||
FormulaCellCacheEntry fcce = _formulaCellCache.remove(cell);
|
FormulaCellCacheEntry fcce = _formulaCellCache.remove(cell);
|
||||||
if (fcce == null) {
|
if (fcce == null) {
|
||||||
// formula cell has not been evaluated yet
|
// formula cell has not been evaluated yet
|
||||||
} else {
|
} else {
|
||||||
fcce.setSensitiveInputCells(null);
|
fcce.setSensitiveInputCells(null);
|
||||||
fcce.recurseClearCachedFormulaResults(_evaluationListener);
|
fcce.recurseClearCachedFormulaResults(_evaluationListener);
|
||||||
|
@ -210,7 +209,7 @@ final class EvaluationCache {
|
||||||
} else {
|
} else {
|
||||||
Loc loc = new Loc(bookIndex, sheetIndex, cell.getRowIndex(), cell.getColumnIndex());
|
Loc loc = new Loc(bookIndex, sheetIndex, cell.getRowIndex(), cell.getColumnIndex());
|
||||||
PlainValueCellCacheEntry pcce = _plainCellCache.get(loc);
|
PlainValueCellCacheEntry pcce = _plainCellCache.get(loc);
|
||||||
|
|
||||||
if (pcce == null) {
|
if (pcce == null) {
|
||||||
// cache entry doesn't exist. nothing to do
|
// cache entry doesn't exist. nothing to do
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -84,7 +84,7 @@ final class EvaluationTracker {
|
||||||
if (result == ErrorEval.CIRCULAR_REF_ERROR && nFrames > 1) {
|
if (result == ErrorEval.CIRCULAR_REF_ERROR && nFrames > 1) {
|
||||||
// Don't cache a circular ref error result if this cell is not the top evaluated cell.
|
// Don't cache a circular ref error result if this cell is not the top evaluated cell.
|
||||||
// A true circular ref error will propagate all the way around the loop. However, it's
|
// A true circular ref error will propagate all the way around the loop. However, it's
|
||||||
// possible to have parts of the formula tree (/ parts of the loop) to evaluate to
|
// possible to have parts of the formula tree (/ parts of the loop) to evaluate to
|
||||||
// CIRCULAR_REF_ERROR, and that value not get used in the final cell result (see the
|
// CIRCULAR_REF_ERROR, and that value not get used in the final cell result (see the
|
||||||
// unit tests for a simple example). Thus, the only CIRCULAR_REF_ERROR result that can
|
// unit tests for a simple example). Thus, the only CIRCULAR_REF_ERROR result that can
|
||||||
// safely be cached is that of the top evaluated cell.
|
// safely be cached is that of the top evaluated cell.
|
||||||
|
@ -140,7 +140,7 @@ final class EvaluationTracker {
|
||||||
// Top level frame, there is no 'cell' above this frame that is using the current cell
|
// Top level frame, there is no 'cell' above this frame that is using the current cell
|
||||||
} else {
|
} else {
|
||||||
CellEvaluationFrame consumingFrame = _evaluationFrames.get(prevFrameIndex);
|
CellEvaluationFrame consumingFrame = _evaluationFrames.get(prevFrameIndex);
|
||||||
if (value == BlankEval.INSTANCE) {
|
if (value == BlankEval.instance) {
|
||||||
consumingFrame.addUsedBlankCell(bookIndex, sheetIndex, rowIndex, columnIndex);
|
consumingFrame.addUsedBlankCell(bookIndex, sheetIndex, rowIndex, columnIndex);
|
||||||
} else {
|
} else {
|
||||||
PlainValueCellCacheEntry cce = _cache.getPlainValueEntry(bookIndex, sheetIndex,
|
PlainValueCellCacheEntry cce = _cache.getPlainValueEntry(bookIndex, sheetIndex,
|
||||||
|
|
|
@ -313,7 +313,7 @@ public final class WorkbookEvaluator {
|
||||||
*/
|
*/
|
||||||
/* package */ static ValueEval getValueFromNonFormulaCell(EvaluationCell cell) {
|
/* package */ static ValueEval getValueFromNonFormulaCell(EvaluationCell cell) {
|
||||||
if (cell == null) {
|
if (cell == null) {
|
||||||
return BlankEval.INSTANCE;
|
return BlankEval.instance;
|
||||||
}
|
}
|
||||||
int cellType = cell.getCellType();
|
int cellType = cell.getCellType();
|
||||||
switch (cellType) {
|
switch (cellType) {
|
||||||
|
@ -324,7 +324,7 @@ public final class WorkbookEvaluator {
|
||||||
case Cell.CELL_TYPE_BOOLEAN:
|
case Cell.CELL_TYPE_BOOLEAN:
|
||||||
return BoolEval.valueOf(cell.getBooleanCellValue());
|
return BoolEval.valueOf(cell.getBooleanCellValue());
|
||||||
case Cell.CELL_TYPE_BLANK:
|
case Cell.CELL_TYPE_BLANK:
|
||||||
return BlankEval.INSTANCE;
|
return BlankEval.instance;
|
||||||
case Cell.CELL_TYPE_ERROR:
|
case Cell.CELL_TYPE_ERROR:
|
||||||
return ErrorEval.valueOf(cell.getErrorCellValue());
|
return ErrorEval.valueOf(cell.getErrorCellValue());
|
||||||
}
|
}
|
||||||
|
@ -401,7 +401,7 @@ public final class WorkbookEvaluator {
|
||||||
i+= countTokensToBeSkipped(ptgs, i, dist);
|
i+= countTokensToBeSkipped(ptgs, i, dist);
|
||||||
if (stack.peek() == MissingArgEval.instance) {
|
if (stack.peek() == MissingArgEval.instance) {
|
||||||
stack.pop();
|
stack.pop();
|
||||||
stack.push(BlankEval.INSTANCE);
|
stack.push(BlankEval.instance);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -450,7 +450,7 @@ public final class WorkbookEvaluator {
|
||||||
throw new IllegalStateException("evaluation stack not empty");
|
throw new IllegalStateException("evaluation stack not empty");
|
||||||
}
|
}
|
||||||
value = dereferenceValue(value, ec.getRowIndex(), ec.getColumnIndex());
|
value = dereferenceValue(value, ec.getRowIndex(), ec.getColumnIndex());
|
||||||
if (value == BlankEval.INSTANCE) {
|
if (value == BlankEval.instance) {
|
||||||
// Note Excel behaviour here. A blank final final value is converted to zero.
|
// Note Excel behaviour here. A blank final final value is converted to zero.
|
||||||
return NumberEval.ZERO;
|
return NumberEval.ZERO;
|
||||||
// Formulas _never_ evaluate to blank. If a formula appears to have evaluated to
|
// Formulas _never_ evaluate to blank. If a formula appears to have evaluated to
|
||||||
|
|
|
@ -49,7 +49,7 @@ final class ForkedEvaluationCell implements EvaluationCell {
|
||||||
_sheet = sheet;
|
_sheet = sheet;
|
||||||
_masterCell = masterCell;
|
_masterCell = masterCell;
|
||||||
// start with value blank, but expect construction to be immediately
|
// start with value blank, but expect construction to be immediately
|
||||||
setValue(BlankEval.INSTANCE); // followed by a proper call to setValue()
|
setValue(BlankEval.instance); // followed by a proper call to setValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getIdentityKey() {
|
public Object getIdentityKey() {
|
||||||
|
|
|
@ -59,7 +59,7 @@ public final class TestEqualEval extends TestCase {
|
||||||
|
|
||||||
ValueEval[] args = {
|
ValueEval[] args = {
|
||||||
new StringEval(""),
|
new StringEval(""),
|
||||||
BlankEval.INSTANCE,
|
BlankEval.instance,
|
||||||
};
|
};
|
||||||
ValueEval result = evaluate(EI.Equal, args, 10, 10);
|
ValueEval result = evaluate(EI.Equal, args, 10, 10);
|
||||||
assertEquals(BoolEval.class, result.getClass());
|
assertEquals(BoolEval.class, result.getClass());
|
||||||
|
|
|
@ -61,11 +61,11 @@ public final class TestAverage extends TestCase {
|
||||||
values = new ValueEval[] {
|
values = new ValueEval[] {
|
||||||
new NumberEval(1),
|
new NumberEval(1),
|
||||||
new NumberEval(2),
|
new NumberEval(2),
|
||||||
BlankEval.INSTANCE,
|
BlankEval.instance,
|
||||||
new NumberEval(3),
|
new NumberEval(3),
|
||||||
BlankEval.INSTANCE,
|
BlankEval.instance,
|
||||||
new NumberEval(4),
|
new NumberEval(4),
|
||||||
BlankEval.INSTANCE,
|
BlankEval.instance,
|
||||||
};
|
};
|
||||||
|
|
||||||
confirmAverage(values, 2.5);
|
confirmAverage(values, 2.5);
|
||||||
|
|
|
@ -57,7 +57,7 @@ public final class TestCountFuncs extends TestCase {
|
||||||
BoolEval.TRUE,
|
BoolEval.TRUE,
|
||||||
BoolEval.FALSE,
|
BoolEval.FALSE,
|
||||||
ErrorEval.DIV_ZERO,
|
ErrorEval.DIV_ZERO,
|
||||||
BlankEval.INSTANCE,
|
BlankEval.instance,
|
||||||
};
|
};
|
||||||
range = EvalFactory.createAreaEval("A1:B3", values);
|
range = EvalFactory.createAreaEval("A1:B3", values);
|
||||||
confirmCountBlank(1, range);
|
confirmCountBlank(1, range);
|
||||||
|
@ -65,10 +65,10 @@ public final class TestCountFuncs extends TestCase {
|
||||||
values = new ValueEval[] {
|
values = new ValueEval[] {
|
||||||
new NumberEval(0),
|
new NumberEval(0),
|
||||||
new StringEval(""), // note - does not match blank
|
new StringEval(""), // note - does not match blank
|
||||||
BlankEval.INSTANCE,
|
BlankEval.instance,
|
||||||
BoolEval.FALSE,
|
BoolEval.FALSE,
|
||||||
BoolEval.TRUE,
|
BoolEval.TRUE,
|
||||||
BlankEval.INSTANCE,
|
BlankEval.instance,
|
||||||
};
|
};
|
||||||
range = EvalFactory.createAreaEval("A1:B3", values);
|
range = EvalFactory.createAreaEval("A1:B3", values);
|
||||||
confirmCountBlank(2, range);
|
confirmCountBlank(2, range);
|
||||||
|
@ -116,7 +116,7 @@ public final class TestCountFuncs extends TestCase {
|
||||||
BoolEval.TRUE,
|
BoolEval.TRUE,
|
||||||
BoolEval.FALSE,
|
BoolEval.FALSE,
|
||||||
BoolEval.TRUE,
|
BoolEval.TRUE,
|
||||||
BlankEval.INSTANCE,
|
BlankEval.instance,
|
||||||
};
|
};
|
||||||
range = EvalFactory.createAreaEval("A1:B3", values);
|
range = EvalFactory.createAreaEval("A1:B3", values);
|
||||||
confirmCountIf(2, range, BoolEval.TRUE);
|
confirmCountIf(2, range, BoolEval.TRUE);
|
||||||
|
@ -414,7 +414,7 @@ public final class TestCountFuncs extends TestCase {
|
||||||
assertEquals(expectedResult, matchPredicate.matches(new NumberEval(value)));
|
assertEquals(expectedResult, matchPredicate.matches(new NumberEval(value)));
|
||||||
}
|
}
|
||||||
private static void confirmPredicate(boolean expectedResult, I_MatchPredicate matchPredicate, String value) {
|
private static void confirmPredicate(boolean expectedResult, I_MatchPredicate matchPredicate, String value) {
|
||||||
ValueEval ev = value == null ? BlankEval.INSTANCE : new StringEval(value);
|
ValueEval ev = value == null ? BlankEval.instance : new StringEval(value);
|
||||||
assertEquals(expectedResult, matchPredicate.matches(ev));
|
assertEquals(expectedResult, matchPredicate.matches(ev));
|
||||||
}
|
}
|
||||||
private static void confirmPredicate(boolean expectedResult, I_MatchPredicate matchPredicate, ErrorEval value) {
|
private static void confirmPredicate(boolean expectedResult, I_MatchPredicate matchPredicate, ErrorEval value) {
|
||||||
|
|
|
@ -63,7 +63,7 @@ public final class TestLen extends TestCase {
|
||||||
confirmLen(new NumberEval(123456), 6);
|
confirmLen(new NumberEval(123456), 6);
|
||||||
confirmLen(BoolEval.FALSE, 5);
|
confirmLen(BoolEval.FALSE, 5);
|
||||||
confirmLen(BoolEval.TRUE, 4);
|
confirmLen(BoolEval.TRUE, 4);
|
||||||
confirmLen(BlankEval.INSTANCE, 0);
|
confirmLen(BlankEval.instance, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testErrors() {
|
public void testErrors() {
|
||||||
|
|
|
@ -75,11 +75,11 @@ public final class TestMid extends TestCase {
|
||||||
RefEval reNumChars = EvalFactory.createRefEval("B1", new NumberEval(3));
|
RefEval reNumChars = EvalFactory.createRefEval("B1", new NumberEval(3));
|
||||||
confirmMid(new StringEval("galactic"), aeStart, reNumChars, "ala");
|
confirmMid(new StringEval("galactic"), aeStart, reNumChars, "ala");
|
||||||
|
|
||||||
confirmMid(new StringEval("galactic"), new NumberEval(3.1), BlankEval.INSTANCE, "");
|
confirmMid(new StringEval("galactic"), new NumberEval(3.1), BlankEval.instance, "");
|
||||||
|
|
||||||
confirmMid(new StringEval("galactic"), new NumberEval(3), BoolEval.FALSE, "");
|
confirmMid(new StringEval("galactic"), new NumberEval(3), BoolEval.FALSE, "");
|
||||||
confirmMid(new StringEval("galactic"), new NumberEval(3), BoolEval.TRUE, "l");
|
confirmMid(new StringEval("galactic"), new NumberEval(3), BoolEval.TRUE, "l");
|
||||||
confirmMid(BlankEval.INSTANCE, new NumberEval(3), BoolEval.TRUE, "");
|
confirmMid(BlankEval.instance, new NumberEval(3), BoolEval.TRUE, "");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ public final class TestMid extends TestCase {
|
||||||
confirmMid(new StringEval("galactic"), new NumberEval(3), ErrorEval.NAME_INVALID, 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"), 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"), 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(0), new NumberEval(4), ErrorEval.VALUE_INVALID);
|
||||||
confirmMid(new StringEval("galactic"), new NumberEval(1), new NumberEval(-1), ErrorEval.VALUE_INVALID);
|
confirmMid(new StringEval("galactic"), new NumberEval(1), new NumberEval(-1), ErrorEval.VALUE_INVALID);
|
||||||
|
|
|
@ -94,7 +94,7 @@ public final class TestTFunc extends TestCase {
|
||||||
public void testOtherValues() {
|
public void testOtherValues() {
|
||||||
confirmOther(new NumberEval(2));
|
confirmOther(new NumberEval(2));
|
||||||
confirmOther(BoolEval.FALSE);
|
confirmOther(BoolEval.FALSE);
|
||||||
confirmOther(BlankEval.INSTANCE); // can this particular case be verified?
|
confirmOther(BlankEval.instance); // can this particular case be verified?
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRefValues() {
|
public void testRefValues() {
|
||||||
|
|
|
@ -69,7 +69,7 @@ public final class TestTrim extends TestCase {
|
||||||
confirmTrim(new NumberEval(123456), "123456");
|
confirmTrim(new NumberEval(123456), "123456");
|
||||||
confirmTrim(BoolEval.FALSE, "FALSE");
|
confirmTrim(BoolEval.FALSE, "FALSE");
|
||||||
confirmTrim(BoolEval.TRUE, "TRUE");
|
confirmTrim(BoolEval.TRUE, "TRUE");
|
||||||
confirmTrim(BlankEval.INSTANCE, "");
|
confirmTrim(BlankEval.instance, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testErrors() {
|
public void testErrors() {
|
||||||
|
|
|
@ -178,7 +178,7 @@ public class TestEvaluationCache extends TestCase {
|
||||||
BoolEval be = (BoolEval) value;
|
BoolEval be = (BoolEval) value;
|
||||||
return be.getStringValue();
|
return be.getStringValue();
|
||||||
}
|
}
|
||||||
if (value == BlankEval.INSTANCE) {
|
if (value == BlankEval.instance) {
|
||||||
return "#BLANK#";
|
return "#BLANK#";
|
||||||
}
|
}
|
||||||
if (value instanceof ErrorEval) {
|
if (value instanceof ErrorEval) {
|
||||||
|
|
Loading…
Reference in New Issue