Fixed 2 small bugs in RelationalOperationEval (added junits). Refactored hierarchy.

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@692239 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Josh Micich 2008-09-04 20:58:37 +00:00
parent 409941a8be
commit bd997b1376
13 changed files with 451 additions and 583 deletions

View File

@ -1,67 +1,34 @@
/* /* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Created on May 8, 2005
*
*/
package org.apache.poi.hssf.record.formula.eval;
import org.apache.poi.hssf.record.formula.EqualPtg; http://www.apache.org/licenses/LICENSE-2.0
import org.apache.poi.hssf.record.formula.Ptg;
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;
/** /**
* @author Amol S. Deshmukh < amolweb at ya hoo dot com > * @author Amol S. Deshmukh < amolweb at ya hoo dot com >
* *
*/ */
public class EqualEval extends RelationalOperationEval { public final class EqualEval extends RelationalOperationEval {
private EqualPtg delegate; public static final OperationEval instance = new EqualEval();
private EqualEval() {
}
public EqualEval(Ptg ptg) { protected boolean convertComparisonResult(int cmpResult) {
this.delegate = (EqualPtg) ptg; return cmpResult == 0;
} }
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
ValueEval retval = null;
RelationalValues rvs = super.doEvaluate(operands, srcRow, srcCol);
retval = rvs.ee;
int result = 0;
if (retval == null) {
result = doComparison(rvs.bs);
if (result == 0) {
result = doComparison(rvs.ss);
}
if (result == 0) {
result = doComparison(rvs.ds);
}
retval = (result == 0) ? BoolEval.TRUE : BoolEval.FALSE;
}
return retval;
}
public int getNumberOfOperands() {
return delegate.getNumberOfOperands();
}
public int getType() {
return delegate.getType();
}
} }

View File

@ -1,67 +1,34 @@
/* /* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Created on May 8, 2005
*
*/
package org.apache.poi.hssf.record.formula.eval;
import org.apache.poi.hssf.record.formula.GreaterEqualPtg; http://www.apache.org/licenses/LICENSE-2.0
import org.apache.poi.hssf.record.formula.Ptg;
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;
/** /**
* @author Amol S. Deshmukh < amolweb at ya hoo dot com > * @author Amol S. Deshmukh < amolweb at ya hoo dot com >
* *
*/ */
public class GreaterEqualEval extends RelationalOperationEval { public final class GreaterEqualEval extends RelationalOperationEval {
private GreaterEqualPtg delegate; public static final OperationEval instance = new GreaterEqualEval();
public GreaterEqualEval(Ptg ptg) { private GreaterEqualEval() {
this.delegate = (GreaterEqualPtg) ptg; }
}
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
ValueEval retval = null;
RelationalValues rvs = super.doEvaluate(operands, srcRow, srcCol);
retval = rvs.ee;
int result = 0;
if (retval == null) {
result = doComparison(rvs.bs);
if (result == 0) {
result = doComparison(rvs.ss);
}
if (result == 0) {
result = doComparison(rvs.ds);
}
retval = (result >= 0) ? BoolEval.TRUE : BoolEval.FALSE;
}
return retval;
}
public int getNumberOfOperands() {
return delegate.getNumberOfOperands();
}
public int getType() {
return delegate.getType();
}
protected boolean convertComparisonResult(int cmpResult) {
return cmpResult >= 0;
}
} }

View File

@ -1,67 +1,34 @@
/* /* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Created on May 8, 2005
*
*/
package org.apache.poi.hssf.record.formula.eval;
import org.apache.poi.hssf.record.formula.GreaterThanPtg; http://www.apache.org/licenses/LICENSE-2.0
import org.apache.poi.hssf.record.formula.Ptg;
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;
/** /**
* @author Amol S. Deshmukh < amolweb at ya hoo dot com > * @author Amol S. Deshmukh < amolweb at ya hoo dot com >
* *
*/ */
public class GreaterThanEval extends RelationalOperationEval { public final class GreaterThanEval extends RelationalOperationEval {
private GreaterThanPtg delegate; public static final OperationEval instance = new GreaterThanEval();
public GreaterThanEval(Ptg ptg) { private GreaterThanEval() {
this.delegate = (GreaterThanPtg) ptg; }
}
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
ValueEval retval = null;
RelationalValues rvs = super.doEvaluate(operands, srcRow, srcCol);
retval = rvs.ee;
int result = 0;
if (retval == null) {
result = doComparison(rvs.bs);
if (result == 0) {
result = doComparison(rvs.ss);
}
if (result == 0) {
result = doComparison(rvs.ds);
}
retval = (result > 0) ? BoolEval.TRUE : BoolEval.FALSE;;
}
return retval;
}
public int getNumberOfOperands() {
return delegate.getNumberOfOperands();
}
public int getType() {
return delegate.getType();
}
protected boolean convertComparisonResult(int cmpResult) {
return cmpResult > 0;
}
} }

View File

@ -1,33 +1,35 @@
/* /* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and See the License for the specific language governing permissions and
* limitations under the License. limitations under the License.
*/ ==================================================================== */
package org.apache.poi.hssf.record.formula.eval; package org.apache.poi.hssf.record.formula.eval;
import org.apache.poi.hssf.record.formula.AreaI; import org.apache.poi.hssf.record.formula.AreaI;
import org.apache.poi.hssf.record.formula.AreaI.OffsetArea; import org.apache.poi.hssf.record.formula.AreaI.OffsetArea;
import org.apache.poi.hssf.usermodel.EvaluationCache;
import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator; import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.CellReference;
/** /**
* @author Amol S. Deshmukh < amolweb at ya hoo dot com > *
* * @author Josh Micich
*/ */
public final class LazyAreaEval extends AreaEvalBase { public final class LazyAreaEval extends AreaEvalBase {
@ -62,4 +64,18 @@ public final class LazyAreaEval extends AreaEvalBase {
return new LazyAreaEval(area, _sheet, _workbook); return new LazyAreaEval(area, _sheet, _workbook);
} }
public String toString() {
CellReference crA = new CellReference(getFirstRow(), getFirstColumn());
CellReference crB = new CellReference(getLastRow(), getLastColumn());
StringBuffer sb = new StringBuffer();
sb.append(getClass().getName()).append("[");
String sheetName = _workbook.getSheetName(_workbook.getSheetIndex(_sheet));
sb.append(sheetName);
sb.append('!');
sb.append(crA.formatAsString());
sb.append(':');
sb.append(crB.formatAsString());
sb.append("]");
return sb.toString();
}
} }

View File

@ -1,15 +1,38 @@
/* ====================================================================
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; package org.apache.poi.hssf.record.formula.eval;
import org.apache.poi.hssf.record.formula.AreaI; import org.apache.poi.hssf.record.formula.AreaI;
import org.apache.poi.hssf.record.formula.AreaI.OffsetArea; import org.apache.poi.hssf.record.formula.AreaI.OffsetArea;
import org.apache.poi.hssf.record.formula.Ref3DPtg; import org.apache.poi.hssf.record.formula.Ref3DPtg;
import org.apache.poi.hssf.record.formula.RefPtg; import org.apache.poi.hssf.record.formula.RefPtg;
import org.apache.poi.hssf.usermodel.EvaluationCache;
import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator; import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.CellReference;
/**
*
* @author Josh Micich
*/
public final class LazyRefEval extends RefEvalBase { public final class LazyRefEval extends RefEvalBase {
private final HSSFSheet _sheet; private final HSSFSheet _sheet;
@ -49,4 +72,16 @@ public final class LazyRefEval extends RefEvalBase {
return new LazyAreaEval(area, _sheet, _workbook); return new LazyAreaEval(area, _sheet, _workbook);
} }
public String toString() {
CellReference cr = new CellReference(getRow(), getColumn());
StringBuffer sb = new StringBuffer();
sb.append(getClass().getName()).append("[");
String sheetName = _workbook.getSheetName(_workbook.getSheetIndex(_sheet));
sb.append(sheetName);
sb.append('!');
sb.append(cr.formatAsString());
sb.append("]");
return sb.toString();
}
} }

View File

@ -1,67 +1,34 @@
/* /* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Created on May 8, 2005
*
*/
package org.apache.poi.hssf.record.formula.eval;
import org.apache.poi.hssf.record.formula.LessEqualPtg; http://www.apache.org/licenses/LICENSE-2.0
import org.apache.poi.hssf.record.formula.Ptg;
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;
/** /**
* @author Amol S. Deshmukh < amolweb at ya hoo dot com > * @author Amol S. Deshmukh < amolweb at ya hoo dot com >
* *
*/ */
public class LessEqualEval extends RelationalOperationEval { public final class LessEqualEval extends RelationalOperationEval {
private LessEqualPtg delegate; public static final OperationEval instance = new LessEqualEval();
public LessEqualEval(Ptg ptg) { private LessEqualEval() {
this.delegate = (LessEqualPtg) ptg; }
}
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
ValueEval retval = null;
RelationalValues rvs = super.doEvaluate(operands, srcRow, srcCol);
retval = rvs.ee;
int result = 0;
if (retval == null) {
result = doComparison(rvs.bs);
if (result == 0) {
result = doComparison(rvs.ss);
}
if (result == 0) {
result = doComparison(rvs.ds);
}
retval = (result <= 0) ? BoolEval.TRUE : BoolEval.FALSE;;
}
return retval;
}
public int getNumberOfOperands() {
return delegate.getNumberOfOperands();
}
public int getType() {
return delegate.getType();
}
protected boolean convertComparisonResult(int cmpResult) {
return cmpResult <= 0;
}
} }

View File

@ -1,68 +1,34 @@
/* /* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Created on May 8, 2005
*
*/
package org.apache.poi.hssf.record.formula.eval;
import org.apache.poi.hssf.record.formula.LessThanPtg; http://www.apache.org/licenses/LICENSE-2.0
import org.apache.poi.hssf.record.formula.Ptg;
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;
/** /**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt; * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class LessThanEval extends RelationalOperationEval { public final class LessThanEval extends RelationalOperationEval {
private LessThanPtg delegate; public static final OperationEval instance = new LessThanEval();
public LessThanEval(Ptg ptg) { private LessThanEval() {
this.delegate = (LessThanPtg) ptg; }
}
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
ValueEval retval = null;
RelationalValues rvs = super.doEvaluate(operands, srcRow, srcCol);
retval = rvs.ee;
int result = 0;
if (retval == null) {
result = doComparison(rvs.bs);
if (result == 0) {
result = doComparison(rvs.ss);
}
if (result == 0) {
result = doComparison(rvs.ds);
}
retval = (result < 0) ? BoolEval.TRUE : BoolEval.FALSE;;
}
return retval;
}
public int getNumberOfOperands() {
return delegate.getNumberOfOperands();
}
public int getType() {
return delegate.getType();
}
protected boolean convertComparisonResult(int cmpResult) {
return cmpResult < 0;
}
} }

View File

@ -1,68 +1,34 @@
/* /* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Created on May 8, 2005
*
*/
package org.apache.poi.hssf.record.formula.eval;
import org.apache.poi.hssf.record.formula.NotEqualPtg; http://www.apache.org/licenses/LICENSE-2.0
import org.apache.poi.hssf.record.formula.Ptg;
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;
/** /**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt; * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* *
*/ */
public class NotEqualEval extends RelationalOperationEval { public final class NotEqualEval extends RelationalOperationEval {
private NotEqualPtg delegate; public static final OperationEval instance = new NotEqualEval();
public NotEqualEval(Ptg ptg) { private NotEqualEval() {
this.delegate = (NotEqualPtg) ptg; }
}
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
ValueEval retval = null;
RelationalValues rvs = super.doEvaluate(operands, srcRow, srcCol);
retval = rvs.ee;
int result = 0;
if (retval == null) {
result = doComparison(rvs.bs);
if (result == 0) {
result = doComparison(rvs.ss);
}
if (result == 0) {
result = doComparison(rvs.ds);
}
retval = (result != 0) ? BoolEval.TRUE : BoolEval.FALSE;
}
return retval;
}
public int getNumberOfOperands() {
return delegate.getNumberOfOperands();
}
public int getType() {
return delegate.getType();
}
protected boolean convertComparisonResult(int cmpResult) {
return cmpResult != 0;
}
} }

View File

@ -1,216 +1,145 @@
/* /* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and See the License for the specific language governing permissions and
* limitations under the License. limitations under the License.
*/ ==================================================================== */
/*
* Created on May 10, 2005
*
*/
package org.apache.poi.hssf.record.formula.eval; package org.apache.poi.hssf.record.formula.eval;
/** /**
* Base class for all comparison operator evaluators
*
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt; * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
*
*/ */
public abstract class RelationalOperationEval implements OperationEval { public abstract class RelationalOperationEval implements OperationEval {
protected class RelationalValues { /**
public Double[] ds = new Double[2]; * Converts a standard compare result (-1, 0, 1) to <code>true</code> or <code>false</code>
public Boolean[] bs = new Boolean[2]; * according to subclass' comparison type.
public String[] ss = new String[3]; */
public ErrorEval ee = null; protected abstract boolean convertComparisonResult(int cmpResult);
}
/**
/* * This is a description of how the relational operators apply in MS Excel.
* This is a description of how the relational operators apply in MS Excel. * Use this as a guideline when testing/implementing the evaluate methods
* Use this as a guideline when testing/implementing the evaluate methods * for the relational operators Evals.
* for the relational operators Evals. *
* * <pre>
* Bool > any number. ALWAYS * Bool.TRUE > any number.
* Bool > any string. ALWAYS * Bool > any string. ALWAYS
* Bool.TRUE > Bool.FALSE * Bool.TRUE > Bool.FALSE
* * Bool.FALSE == Blank
* String > any number. ALWAYS *
* String > Blank. ALWAYS * Strings are never converted to numbers or booleans
* String are sorted dictionary wise * String > any number. ALWAYS
* * Non-empty String > Blank
* Blank == 0 (numeric) * Empty String == Blank
*/ * String are sorted dictionary wise
public RelationalValues doEvaluate(Eval[] operands, int srcRow, short srcCol) { *
RelationalValues retval = new RelationalValues(); * Blank > Negative numbers
* Blank == 0
switch (operands.length) { * Blank < Positive numbers
default: * </pre>
retval.ee = ErrorEval.VALUE_INVALID; */
break; public final Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
case 2: if (operands.length != 2) {
internalDoEvaluate(operands, srcRow, srcCol, retval, 0); return ErrorEval.VALUE_INVALID;
internalDoEvaluate(operands, srcRow, srcCol, retval, 1); }
} // end switch
return retval;
}
/**
* convenience method to avoid code duplication for multiple operands
* @param operands
* @param srcRow
* @param srcCol
* @param retval
* @param index
*/
private void internalDoEvaluate(Eval[] operands, int srcRow, short srcCol, RelationalValues retval, int index) {
if (operands[index] instanceof BoolEval) {
BoolEval be = (BoolEval) operands[index];
retval.bs[index] = Boolean.valueOf(be.getBooleanValue());
}
else if (operands[index] instanceof NumericValueEval) {
NumericValueEval ne = (NumericValueEval) operands[index];
retval.ds[index] = new Double(ne.getNumberValue());
}
else if (operands[index] instanceof StringValueEval) {
StringValueEval se = (StringValueEval) operands[index];
retval.ss[index] = se.getStringValue();
}
else if (operands[index] instanceof RefEval) {
RefEval re = (RefEval) operands[index];
ValueEval ve = re.getInnerValueEval();
if (ve instanceof BoolEval) {
BoolEval be = (BoolEval) ve;
retval.bs[index] = Boolean.valueOf(be.getBooleanValue());
}
else if (ve instanceof BlankEval) {
retval.ds[index] = new Double(0);
}
else if (ve instanceof NumericValueEval) {
NumericValueEval ne = (NumericValueEval) ve;
retval.ds[index] = new Double(ne.getNumberValue());
}
else if (ve instanceof StringValueEval) {
StringValueEval se = (StringValueEval) ve;
retval.ss[index] = se.getStringValue();
}
}
else if (operands[index] instanceof AreaEval) {
AreaEval ae = (AreaEval) operands[index];
if (ae.isRow()) {
if (ae.containsColumn(srcCol)) {
ValueEval ve = ae.getValueAt(ae.getFirstRow(), srcCol);
if (ve instanceof BoolEval) {
BoolEval be = (BoolEval) ve;
retval.bs[index] = Boolean.valueOf(be.getBooleanValue());
}
else if (ve instanceof BlankEval) {
retval.ds[index] = new Double(0);
}
else if (ve instanceof NumericValueEval) {
NumericValueEval ne = (NumericValueEval) ve;
retval.ds[index] = new Double(ne.getNumberValue());
}
else if (ve instanceof StringValueEval) {
StringValueEval se = (StringValueEval) ve;
retval.ss[index] = se.getStringValue();
}
else {
retval.ee = ErrorEval.VALUE_INVALID;
}
}
else {
retval.ee = ErrorEval.VALUE_INVALID;
}
}
else if (ae.isColumn()) {
if (ae.containsRow(srcRow)) {
ValueEval ve = ae.getValueAt(srcRow, ae.getFirstColumn());
if (ve instanceof BoolEval) {
BoolEval be = (BoolEval) ve;
retval.bs[index] = Boolean.valueOf(be.getBooleanValue());
}
else if (ve instanceof BlankEval) {
retval.ds[index] = new Double(0);
}
else if (ve instanceof NumericValueEval) {
NumericValueEval ne = (NumericValueEval) ve;
retval.ds[index] = new Double(ne.getNumberValue());
}
else if (ve instanceof StringValueEval) {
StringValueEval se = (StringValueEval) ve;
retval.ss[index] = se.getStringValue();
}
else {
retval.ee = ErrorEval.VALUE_INVALID;
}
}
else {
retval.ee = ErrorEval.VALUE_INVALID;
}
}
else {
retval.ee = ErrorEval.VALUE_INVALID;
}
}
}
// if both null return 0, else non null wins, else TRUE wins
protected int doComparison(Boolean[] bs) {
int retval = 0;
if (bs[0] != null || bs[1] != null) {
retval = bs[0] != null
? bs[1] != null
? bs[0].booleanValue()
? bs[1].booleanValue()
? 0
: 1
: bs[1].booleanValue()
? -1
: 0
: 1
: bs[1] != null
? -1
: 0;
}
return retval;
}
// if both null return 0, else non null wins, else string compare ValueEval vA;
protected int doComparison(String[] ss) { ValueEval vB;
int retval = 0; try {
if (ss[0] != null || ss[1] != null) { vA = OperandResolver.getSingleValue(operands[0], srcRow, srcCol);
retval = ss[0] != null vB = OperandResolver.getSingleValue(operands[1], srcRow, srcCol);
? ss[1] != null } catch (EvaluationException e) {
? ss[0].compareTo(ss[1]) return e.getErrorEval();
: 1 }
: ss[1] != null int cmpResult = doCompare(vA, vB);
? -1 boolean result = convertComparisonResult(cmpResult);
: 0; return BoolEval.valueOf(result);
} }
return retval;
}
// if both null return 0, else non null wins, else doublevalue compare private static int doCompare(ValueEval va, ValueEval vb) {
protected int doComparison(Double[] ds) { // special cases when one operand is blank
int retval = 0; if (va == BlankEval.INSTANCE) {
if (ds[0] != null || ds[1] != null) { return compareBlank(vb);
retval = ds[0] != null }
? ds[1] != null if (vb == BlankEval.INSTANCE) {
? ds[0].compareTo(ds[1]) return -compareBlank(va);
: 1 }
: ds[1] != null
? -1 if (va instanceof BoolEval) {
: 0; if (vb instanceof BoolEval) {
} BoolEval bA = (BoolEval) va;
return retval; BoolEval bB = (BoolEval) vb;
} if (bA.getBooleanValue() == bB.getBooleanValue()) {
return 0;
}
return bA.getBooleanValue() ? 1 : -1;
}
return 1;
}
if (vb instanceof BoolEval) {
return -1;
}
if (va instanceof StringEval) {
if (vb instanceof StringEval) {
StringEval sA = (StringEval) va;
StringEval sB = (StringEval) vb;
return sA.getStringValue().compareTo(sB.getStringValue());
}
return 1;
}
if (vb instanceof StringEval) {
return -1;
}
if (va instanceof NumberEval) {
if (vb instanceof NumberEval) {
NumberEval nA = (NumberEval) va;
NumberEval nB = (NumberEval) vb;
return Double.compare(nA.getNumberValue(), nB.getNumberValue());
}
}
throw new IllegalArgumentException("Bad operand types (" + va.getClass().getName() + "), ("
+ vb.getClass().getName() + ")");
}
private static int compareBlank(ValueEval v) {
if (v == BlankEval.INSTANCE) {
return 0;
}
if (v instanceof BoolEval) {
BoolEval boolEval = (BoolEval) v;
return boolEval.getBooleanValue() ? -1 : 0;
}
if (v instanceof NumberEval) {
NumberEval ne = (NumberEval) v;
return Double.compare(0, ne.getNumberValue());
}
if (v instanceof StringEval) {
StringEval se = (StringEval) v;
return se.getStringValue().length() < 1 ? 0 : -1;
}
throw new IllegalArgumentException("bad value class (" + v.getClass().getName() + ")");
}
public final int getNumberOfOperands() {
return 2;
}
public final int getType() {
// TODO - get rid of this method
throw new RuntimeException("Obsolete code - should not be called");
}
} }

View File

@ -69,8 +69,9 @@ import org.apache.poi.hssf.record.formula.eval.UnaryPlusEval;
*/ */
final class OperationEvaluatorFactory { final class OperationEvaluatorFactory {
private static final Class[] OPERATION_CONSTRUCTOR_CLASS_ARRAY = new Class[] { Ptg.class }; private static final Class[] OPERATION_CONSTRUCTOR_CLASS_ARRAY = new Class[] { Ptg.class };
// TODO - use singleton instances directly instead of reflection
private static final Map _constructorsByPtgClass = initialiseConstructorsMap(); private static final Map _constructorsByPtgClass = initialiseConstructorsMap();
private static final Map _instancesByPtgClass = initialiseInstancesMap();
private OperationEvaluatorFactory() { private OperationEvaluatorFactory() {
// no instances of this class // no instances of this class
@ -81,15 +82,9 @@ final class OperationEvaluatorFactory {
add(m, AddPtg.class, AddEval.class); add(m, AddPtg.class, AddEval.class);
add(m, ConcatPtg.class, ConcatEval.class); add(m, ConcatPtg.class, ConcatEval.class);
add(m, DividePtg.class, DivideEval.class); add(m, DividePtg.class, DivideEval.class);
add(m, EqualPtg.class, EqualEval.class);
add(m, FuncPtg.class, FuncVarEval.class); add(m, FuncPtg.class, FuncVarEval.class);
add(m, FuncVarPtg.class, FuncVarEval.class); add(m, FuncVarPtg.class, FuncVarEval.class);
add(m, GreaterEqualPtg.class, GreaterEqualEval.class);
add(m, GreaterThanPtg.class, GreaterThanEval.class);
add(m, LessEqualPtg.class, LessEqualEval.class);
add(m, LessThanPtg.class, LessThanEval.class);
add(m, MultiplyPtg.class, MultiplyEval.class); add(m, MultiplyPtg.class, MultiplyEval.class);
add(m, NotEqualPtg.class, NotEqualEval.class);
add(m, PercentPtg.class, PercentEval.class); add(m, PercentPtg.class, PercentEval.class);
add(m, PowerPtg.class, PowerEval.class); add(m, PowerPtg.class, PowerEval.class);
add(m, SubtractPtg.class, SubtractEval.class); add(m, SubtractPtg.class, SubtractEval.class);
@ -97,13 +92,30 @@ final class OperationEvaluatorFactory {
add(m, UnaryPlusPtg.class, UnaryPlusEval.class); add(m, UnaryPlusPtg.class, UnaryPlusEval.class);
return m; return m;
} }
private static Map initialiseInstancesMap() {
Map m = new HashMap(32);
add(m, EqualPtg.class, EqualEval.instance);
add(m, GreaterEqualPtg.class, GreaterEqualEval.instance);
add(m, GreaterThanPtg.class, GreaterThanEval.instance);
add(m, LessEqualPtg.class, LessEqualEval.instance);
add(m, LessThanPtg.class, LessThanEval.instance);
add(m, NotEqualPtg.class, NotEqualEval.instance);
return m;
}
private static void add(Map m, Class ptgClass, OperationEval evalInstance) {
if(!Ptg.class.isAssignableFrom(ptgClass)) {
throw new IllegalArgumentException("Expected Ptg subclass");
}
m.put(ptgClass, evalInstance);
}
private static void add(Map m, Class ptgClass, Class evalClass) { private static void add(Map m, Class ptgClass, Class evalClass) {
// perform some validation now, to keep later exception handlers simple // perform some validation now, to keep later exception handlers simple
if(!Ptg.class.isAssignableFrom(ptgClass)) { if(!Ptg.class.isAssignableFrom(ptgClass)) {
throw new IllegalArgumentException("Expected Ptg subclass"); throw new IllegalArgumentException("Expected Ptg subclass");
} }
if(!OperationEval.class.isAssignableFrom(evalClass)) { if(!OperationEval.class.isAssignableFrom(evalClass)) {
throw new IllegalArgumentException("Expected OperationEval subclass"); throw new IllegalArgumentException("Expected OperationEval subclass");
} }
@ -125,7 +137,7 @@ final class OperationEvaluatorFactory {
} }
m.put(ptgClass, constructor); m.put(ptgClass, constructor);
} }
/** /**
* returns the OperationEval concrete impl instance corresponding * returns the OperationEval concrete impl instance corresponding
* to the supplied operationPtg * to the supplied operationPtg
@ -134,9 +146,16 @@ final class OperationEvaluatorFactory {
if(ptg == null) { if(ptg == null) {
throw new IllegalArgumentException("ptg must not be null"); throw new IllegalArgumentException("ptg must not be null");
} }
Object result;
Class ptgClass = ptg.getClass(); Class ptgClass = ptg.getClass();
result = _instancesByPtgClass.get(ptgClass);
if (result != null) {
return (OperationEval) result;
}
Constructor constructor = (Constructor) _constructorsByPtgClass.get(ptgClass); Constructor constructor = (Constructor) _constructorsByPtgClass.get(ptgClass);
if(constructor == null) { if(constructor == null) {
if(ptgClass == ExpPtg.class) { if(ptgClass == ExpPtg.class) {
@ -147,7 +166,6 @@ final class OperationEvaluatorFactory {
throw new RuntimeException("Unexpected operation ptg class (" + ptgClass.getName() + ")"); throw new RuntimeException("Unexpected operation ptg class (" + ptgClass.getName() + ")");
} }
Object result;
Object[] initargs = { ptg }; Object[] initargs = { ptg };
try { try {
result = constructor.newInstance(initargs); result = constructor.newInstance(initargs);

View File

@ -31,6 +31,7 @@ public class AllFormulaEvalTests {
TestSuite result = new TestSuite(AllFormulaEvalTests.class.getName()); TestSuite result = new TestSuite(AllFormulaEvalTests.class.getName());
result.addTestSuite(TestAreaEval.class); result.addTestSuite(TestAreaEval.class);
result.addTestSuite(TestCircularReferences.class); result.addTestSuite(TestCircularReferences.class);
result.addTestSuite(TestEqualEval.class);
result.addTestSuite(TestExternalFunction.class); result.addTestSuite(TestExternalFunction.class);
result.addTestSuite(TestFormulaBugs.class); result.addTestSuite(TestFormulaBugs.class);
result.addTestSuite(TestFormulasFromSpreadsheet.class); result.addTestSuite(TestFormulasFromSpreadsheet.class);

View File

@ -0,0 +1,69 @@
/* ====================================================================
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 junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import org.apache.poi.hssf.record.formula.functions.EvalFactory;
/**
* Test for unary plus operator evaluator.
*
* @author Josh Micich
*/
public final class TestEqualEval extends TestCase {
/**
* Test for bug observable at svn revision 692218 (Sep 2008)<br/>
* The value from a 1x1 area should be taken immediately, regardless of srcRow and srcCol
*/
public void test1x1AreaOperand() {
ValueEval[] values = { BoolEval.FALSE, };
Eval[] args = {
EvalFactory.createAreaEval("B1:B1", values),
BoolEval.FALSE,
};
Eval result = EqualEval.instance.evaluate(args, 10, (short)20);
if (result instanceof ErrorEval) {
if (result == ErrorEval.VALUE_INVALID) {
throw new AssertionFailedError("Identified bug in evaluation of 1x1 area");
}
}
assertEquals(BoolEval.class, result.getClass());
assertTrue(((BoolEval)result).getBooleanValue());
}
/**
* Empty string is equal to blank
*/
public void testBlankEqualToEmptyString() {
Eval[] args = {
new StringEval(""),
BlankEval.INSTANCE,
};
Eval result = EqualEval.instance.evaluate(args, 10, (short)20);
assertEquals(BoolEval.class, result.getClass());
BoolEval be = (BoolEval) result;
if (!be.getBooleanValue()) {
throw new AssertionFailedError("Identified bug blank/empty string equality");
}
assertTrue(be.getBooleanValue());
}
}