Make D* functions thread safe, thanks to Patrick Zimmermann for the patch.

https://bz.apache.org/bugzilla/show_bug.cgi?id=58039

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1701055 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
David North 2015-09-03 15:58:00 +00:00
parent 29767eb0c5
commit 984e8d9c76
5 changed files with 25 additions and 25 deletions

View File

@ -98,7 +98,7 @@ public final class FunctionEval {
retval[38] = BooleanFunction.NOT; retval[38] = BooleanFunction.NOT;
retval[39] = NumericFunction.MOD; retval[39] = NumericFunction.MOD;
retval[43] = new DStarRunner(new DMin()); retval[43] = new DStarRunner(DStarRunner.DStarAlgorithmEnum.DMIN);
retval[46] = AggregateFunction.VAR; retval[46] = AggregateFunction.VAR;
retval[48] = TextFunction.TEXT; retval[48] = TextFunction.TEXT;
@ -191,7 +191,7 @@ public final class FunctionEval {
retval[233] = NumericFunction.ACOSH; retval[233] = NumericFunction.ACOSH;
retval[234] = NumericFunction.ATANH; retval[234] = NumericFunction.ATANH;
retval[235] = new DStarRunner(new DGet()); retval[235] = new DStarRunner(DStarRunner.DStarAlgorithmEnum.DGET);
retval[FunctionID.EXTERNAL_FUNC] = null; // ExternalFunction is a FreeREfFunction retval[FunctionID.EXTERNAL_FUNC] = null; // ExternalFunction is a FreeREfFunction

View File

@ -23,18 +23,11 @@ import org.apache.poi.ss.formula.eval.ValueEval;
/** /**
* Implementation of the DGet function: * Implementation of the DGet function:
* Finds the value of a column in an area with given conditions. * Finds the value of a column in an area with given conditions.
*
* TODO:
* - wildcards ? and * in string conditions
* - functions as conditions
*/ */
public final class DGet implements IDStarAlgorithm { public final class DGet implements IDStarAlgorithm {
private ValueEval result; private ValueEval result;
public void reset() { @Override
result = null;
}
public boolean processMatch(ValueEval eval) { public boolean processMatch(ValueEval eval) {
if(result == null) // First match, just set the value. if(result == null) // First match, just set the value.
{ {
@ -49,6 +42,7 @@ public final class DGet implements IDStarAlgorithm {
return true; return true;
} }
@Override
public ValueEval getResult() { public ValueEval getResult() {
if(result == null) { if(result == null) {
return ErrorEval.VALUE_INVALID; return ErrorEval.VALUE_INVALID;

View File

@ -32,10 +32,7 @@ import org.apache.poi.ss.formula.eval.ValueEval;
public final class DMin implements IDStarAlgorithm { public final class DMin implements IDStarAlgorithm {
private ValueEval minimumValue; private ValueEval minimumValue;
public void reset() { @Override
minimumValue = null;
}
public boolean processMatch(ValueEval eval) { public boolean processMatch(ValueEval eval) {
if(eval instanceof NumericValueEval) { if(eval instanceof NumericValueEval) {
if(minimumValue == null) { // First match, just set the value. if(minimumValue == null) { // First match, just set the value.
@ -52,6 +49,7 @@ public final class DMin implements IDStarAlgorithm {
return true; return true;
} }
@Override
public ValueEval getResult() { public ValueEval getResult() {
if(minimumValue == null) { if(minimumValue == null) {
return NumberEval.ZERO; return NumberEval.ZERO;

View File

@ -32,12 +32,21 @@ import org.apache.poi.ss.util.NumberComparer;
* This class performs a D* calculation. It takes an {@link IDStarAlgorithm} object and * This class performs a D* calculation. It takes an {@link IDStarAlgorithm} object and
* uses it for calculating the result value. Iterating a database and checking the * uses it for calculating the result value. Iterating a database and checking the
* entries against the set of conditions is done here. * entries against the set of conditions is done here.
*
* TODO:
* - wildcards ? and * in string conditions
* - functions as conditions
*/ */
public final class DStarRunner implements Function3Arg { public final class DStarRunner implements Function3Arg {
private IDStarAlgorithm algorithm; public enum DStarAlgorithmEnum {
DGET,
DMIN,
// DMAX, // DMAX is not yet implemented
}
private final DStarAlgorithmEnum algoType;
public DStarRunner(IDStarAlgorithm algorithm) { public DStarRunner(DStarAlgorithmEnum algorithm) {
this.algorithm = algorithm; this.algoType = algorithm;
} }
public final ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { public final ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
@ -69,10 +78,14 @@ public final class DStarRunner implements Function3Arg {
return ErrorEval.VALUE_INVALID; return ErrorEval.VALUE_INVALID;
} }
// Reset algorithm. // Create an algorithm runner.
algorithm.reset(); IDStarAlgorithm algorithm = null;
switch(algoType) {
case DGET: algorithm = new DGet(); break;
case DMIN: algorithm = new DMin(); break;
}
// Iterate over all db entries. // Iterate over all DB entries.
for(int row = 1; row < db.getHeight(); ++row) { for(int row = 1; row < db.getHeight(); ++row) {
boolean matches = true; boolean matches = true;
try { try {

View File

@ -24,11 +24,6 @@ import org.apache.poi.ss.formula.eval.ValueEval;
* Each implementing class should correspond to one of the D* functions. * Each implementing class should correspond to one of the D* functions.
*/ */
public interface IDStarAlgorithm { public interface IDStarAlgorithm {
/**
* Reset the state of this algorithm.
* This is called before each run through a database.
*/
void reset();
/** /**
* Process a match that is found during a run through a database. * Process a match that is found during a run through a database.
* @param eval ValueEval of the cell in the matching row. References will already be resolved. * @param eval ValueEval of the cell in the matching row. References will already be resolved.