]> source.dussan.org Git - poi.git/commitdiff
Minor fixes for numeric operators - junit added. Some refactoring.
authorJosh Micich <josh@apache.org>
Fri, 5 Sep 2008 18:22:30 +0000 (18:22 +0000)
committerJosh Micich <josh@apache.org>
Fri, 5 Sep 2008 18:22:30 +0000 (18:22 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@692506 13f79535-47bb-0310-9956-ffa450edef68

16 files changed:
src/java/org/apache/poi/hssf/record/formula/eval/AddEval.java
src/java/org/apache/poi/hssf/record/formula/eval/DivideEval.java
src/java/org/apache/poi/hssf/record/formula/eval/MultiplyEval.java
src/java/org/apache/poi/hssf/record/formula/eval/NumericOperationEval.java [deleted file]
src/java/org/apache/poi/hssf/record/formula/eval/PercentEval.java
src/java/org/apache/poi/hssf/record/formula/eval/PowerEval.java
src/java/org/apache/poi/hssf/record/formula/eval/SubtractEval.java
src/java/org/apache/poi/hssf/record/formula/eval/TwoOperandNumericOperation.java [new file with mode: 0644]
src/java/org/apache/poi/hssf/record/formula/eval/UnaryMinusEval.java
src/java/org/apache/poi/hssf/record/formula/eval/UnaryPlusEval.java
src/java/org/apache/poi/hssf/record/formula/eval/ValueEvalToNumericXlator.java
src/java/org/apache/poi/hssf/usermodel/OperationEvaluatorFactory.java
src/testcases/org/apache/poi/hssf/record/formula/eval/AllFormulaEvalTests.java
src/testcases/org/apache/poi/hssf/record/formula/eval/TestDivideEval.java [new file with mode: 0644]
src/testcases/org/apache/poi/hssf/record/formula/eval/TestPercentEval.java
src/testcases/org/apache/poi/hssf/record/formula/eval/TestUnaryPlusEval.java

index 6562263d5474b8acda1fc5322e707fedc3c2ce10..bf1b424214369b5f8265a4d9f3519e369b57327f 100644 (file)
@@ -1,27 +1,22 @@
-/*
-* Licensed to the Apache Software Foundation (ASF) under one or more
-* contributor license agreements.  See the NOTICE file distributed with
-* this work for additional information regarding copyright ownership.
-* The ASF licenses this file to You under the Apache License, Version 2.0
-* (the "License"); you may not use this file except in compliance with
-* the License.  You may obtain a copy of the License at
-*
-*     http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
-/*
- * Created on May 8, 2005
- *
- */
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
 package org.apache.poi.hssf.record.formula.eval;
 
-import org.apache.poi.hssf.record.formula.AddPtg;
-import org.apache.poi.hssf.record.formula.Ptg;
 
 /**
  * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
@@ -37,58 +32,14 @@ import org.apache.poi.hssf.record.formula.Ptg;
  * <li> 1+A1 = 2 if A1 contains TRUE or =TRUE
  * <li> 1+A1 = #VALUE! if A1 contains "TRUE" or ="TRUE"
  */
-public class AddEval extends NumericOperationEval {
-
-    private AddPtg delegate;
-    private static final ValueEvalToNumericXlator NUM_XLATOR = 
-        new ValueEvalToNumericXlator((short)
-                ( ValueEvalToNumericXlator.BOOL_IS_PARSED 
-                | ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
-                | ValueEvalToNumericXlator.STRING_IS_PARSED
-                | ValueEvalToNumericXlator.REF_STRING_IS_PARSED
-                ));
-
-    public AddEval(Ptg ptg) {
-        delegate = (AddPtg) ptg;
-    }
+public final class AddEval extends TwoOperandNumericOperation {
 
-    public ValueEvalToNumericXlator getXlator() {
-        return NUM_XLATOR;
-    }
-    
-    
-    public Eval evaluate(Eval[] args, int srcRow, short srcCol) {
-       if(args.length != 2) {
-               return ErrorEval.VALUE_INVALID;
-       }
-       
-        double d = 0;
-        for (int i = 0; i < 2; i++) {
-            ValueEval ve = singleOperandEvaluate(args[i], srcRow, srcCol);
-            if(ve instanceof ErrorEval) {
-                               return ve;
-            }
-            if (ve instanceof NumericValueEval) {
-                d += ((NumericValueEval) ve).getNumberValue();
-            }
-            else if (ve instanceof BlankEval) {
-                // do nothing
-            }
-            else {
-                return ErrorEval.VALUE_INVALID;
-            }
-        }
-        if(Double.isNaN(d) || Double.isInfinite(d)) {
-               return ErrorEval.NUM_ERROR;
-        }
-        return new NumberEval(d);
-    }
+       public static final OperationEval instance = new AddEval();
 
-    public int getNumberOfOperands() {
-        return delegate.getNumberOfOperands();
-    }
+       private AddEval() {
+       }
 
-    public int getType() {
-        return delegate.getType();
-    }
+       protected double evaluate(double d0, double d1) {
+               return d0 + d1;
+       }
 }
index 021168ad7907edbd771dfb5a367893cf36c8aa2b..ba0b07e7e4a71a1be63e5adb9fb2137c82bc2a4c 100644 (file)
@@ -1,95 +1,36 @@
-/*
-* 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;
 
-import org.apache.poi.hssf.record.formula.Ptg;
-import org.apache.poi.hssf.record.formula.DividePtg;
-
 /**
  * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
- *  
  */
-public final class DivideEval extends NumericOperationEval {
-
-    private DividePtg delegate;
-
-    private static final ValueEvalToNumericXlator NUM_XLATOR = 
-        new ValueEvalToNumericXlator((short)
-                ( ValueEvalToNumericXlator.BOOL_IS_PARSED 
-                | ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
-                | ValueEvalToNumericXlator.STRING_IS_PARSED
-                | ValueEvalToNumericXlator.REF_STRING_IS_PARSED
-                ));
-
-    public DivideEval(Ptg ptg) {
-        delegate = (DividePtg) ptg;
-    }
-    
-    protected ValueEvalToNumericXlator getXlator() {
-        return NUM_XLATOR;
-    }
-
-    public Eval evaluate(Eval[] args, int srcRow, short srcCol) {
-       if(args.length != 2) {
-               return ErrorEval.VALUE_INVALID;
-       }
-        Eval retval = null;
-        double d0 = 0;
-        double d1 = 0;
-        ValueEval ve = singleOperandEvaluate(args[0], srcRow, srcCol);
-        if (ve instanceof NumericValueEval) {
-            d0 = ((NumericValueEval) ve).getNumberValue();
-        }
-        else if (ve instanceof BlankEval) {
-            // do nothing
-        }
-        else {
-            retval = ErrorEval.VALUE_INVALID;
-        }
-        
-        if (retval == null) { // no error yet
-            ve = singleOperandEvaluate(args[1], srcRow, srcCol);
-            if (ve instanceof NumericValueEval) {
-                d1 = ((NumericValueEval) ve).getNumberValue();
-            }
-            else if (ve instanceof BlankEval) {
-                // do nothing
-            }
-            else {
-                retval = ErrorEval.VALUE_INVALID;
-            }
-        }
+public final class DivideEval extends TwoOperandNumericOperation {
 
-        if (retval == null) {
-            retval = (d1 == 0) 
-                ? ErrorEval.DIV_ZERO
-                : (Double.isNaN(d0) || Double.isNaN(d1)) 
-                    ? (ValueEval) ErrorEval.VALUE_INVALID 
-                    : new NumberEval(d0 / d1);
-        }
-        return retval;
-    }
+       public static final OperationEval instance = new DivideEval();
 
-    public int getNumberOfOperands() {
-        return delegate.getNumberOfOperands();
-    }
+       private DivideEval() {
+       }
 
-    public int getType() {
-        return delegate.getType();
-    }
+       protected double evaluate(double d0, double d1) throws EvaluationException {
+               if (d1 == 0.0) {
+                       throw new EvaluationException(ErrorEval.DIV_ZERO);
+               }
+               return d0 / d1;
+       }
 }
index 22d87b7e4d4f2dccec54eb8680c450127f9e9513..83b829c7111cafde460268cd18abe0fca9add97e 100644 (file)
@@ -1,89 +1,33 @@
-/*
-* 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;
 
-import org.apache.poi.hssf.record.formula.Ptg;
-import org.apache.poi.hssf.record.formula.MultiplyPtg;
-
 /**
  * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
- *  
  */
-public final class MultiplyEval extends NumericOperationEval {
-
-    private MultiplyPtg delegate;
-
-    private static final ValueEvalToNumericXlator NUM_XLATOR = 
-        new ValueEvalToNumericXlator((short)
-                ( ValueEvalToNumericXlator.BOOL_IS_PARSED 
-                | ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
-                | ValueEvalToNumericXlator.STRING_IS_PARSED
-                | ValueEvalToNumericXlator.REF_STRING_IS_PARSED
-                ));
-
-    public MultiplyEval(Ptg ptg) {
-        delegate = (MultiplyPtg) ptg;
-    }
-    
-    protected ValueEvalToNumericXlator getXlator() {
-        return NUM_XLATOR;
-    }
+public final class MultiplyEval extends TwoOperandNumericOperation {
 
-    public Eval evaluate(Eval[] args, int srcRow, short srcCol) {
-       if(args.length != 2) {
-               return ErrorEval.VALUE_INVALID;
-       }
-       
-        double d0 = 0;
-        double d1 = 0;
-        ValueEval ve = singleOperandEvaluate(args[0], srcRow, srcCol);
-        if (ve instanceof NumericValueEval) {
-            d0 = ((NumericValueEval) ve).getNumberValue();
-        }
-        else if (ve instanceof BlankEval) {
-            // do nothing
-        }
-        else {
-            return ErrorEval.VALUE_INVALID;
-        }
-        
-        ve = singleOperandEvaluate(args[1], srcRow, srcCol);
-        if (ve instanceof NumericValueEval) {
-            d1 = ((NumericValueEval) ve).getNumberValue();
-        }
-        else if (ve instanceof BlankEval) {
-        // do nothing
-        }
-        else {
-               return ErrorEval.VALUE_INVALID;
-        }
-        if (Double.isNaN(d0) || Double.isNaN(d1)) {
-                       return ErrorEval.NUM_ERROR;
-               }
-               return new NumberEval(d0 * d1);
-    }
+       public static final OperationEval instance = new MultiplyEval();
 
-    public int getNumberOfOperands() {
-        return delegate.getNumberOfOperands();
-    }
+       private MultiplyEval() {
+       }
 
-    public int getType() {
-        return delegate.getType();
-    }
+       protected double evaluate(double d0, double d1) {
+               return d0 * d1;
+       }
 }
diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/NumericOperationEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/NumericOperationEval.java
deleted file mode 100644 (file)
index 6bc1c95..0000000
+++ /dev/null
@@ -1,66 +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.
-*/
-/*
- * Created on May 14, 2005
- *
- */
-package org.apache.poi.hssf.record.formula.eval;
-
-/**
- * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
- *
- */
-public abstract class NumericOperationEval implements OperationEval {
-
-    protected abstract ValueEvalToNumericXlator getXlator();
-    
-    protected ValueEval singleOperandEvaluate(Eval eval, int srcRow, short srcCol) {
-        ValueEval retval;
-        if (eval instanceof AreaEval) {
-            AreaEval ae = (AreaEval) eval;
-            if (ae.contains(srcRow, srcCol)) { // circular ref!
-                retval = ErrorEval.CIRCULAR_REF_ERROR;
-            }
-            else if (ae.isRow()) {
-                if (ae.containsColumn(srcCol)) {
-                    ValueEval ve = ae.getValueAt(ae.getFirstRow(), srcCol);
-                    ve = getXlator().attemptXlateToNumeric(ve);
-                    retval = getXlator().attemptXlateToNumeric(ve);
-                }
-                else {
-                    retval = ErrorEval.VALUE_INVALID;
-                }
-            }
-            else if (ae.isColumn()) {
-                if (ae.containsRow(srcRow)) {
-                    ValueEval ve = ae.getValueAt(srcRow, ae.getFirstColumn());
-                    retval = getXlator().attemptXlateToNumeric(ve);
-                }
-                else {
-                    retval = ErrorEval.VALUE_INVALID;
-                }
-            }
-            else {
-                retval = ErrorEval.VALUE_INVALID;
-            }
-        }
-        else {
-            retval = getXlator().attemptXlateToNumeric((ValueEval) eval);
-        }
-        return retval;
-    }
-}
index c698a4e5020a8440d8222d1392f78b633fdbe89d..d03e4474521a08753ae02bc8df58dc6228ae1c5f 100755 (executable)
 
 package org.apache.poi.hssf.record.formula.eval;
 
-import org.apache.poi.hssf.record.formula.PercentPtg;
-import org.apache.poi.hssf.record.formula.Ptg;
 
 /**
  * Implementation of Excel formula token '%'. <p/>
  * @author Josh Micich
  */
-public final class PercentEval extends NumericOperationEval {
+public final class PercentEval implements OperationEval {
 
-       private PercentPtg _delegate;
+       public static final OperationEval instance = new PercentEval();
 
-       private static final ValueEvalToNumericXlator NUM_XLATOR = new ValueEvalToNumericXlator(
-                       (short) (ValueEvalToNumericXlator.BOOL_IS_PARSED
-                                       | ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
-                                       | ValueEvalToNumericXlator.STRING_IS_PARSED | ValueEvalToNumericXlator.REF_STRING_IS_PARSED));
-
-       public PercentEval(Ptg ptg) {
-               _delegate = (PercentPtg) ptg;
-       }
-
-       protected ValueEvalToNumericXlator getXlator() {
-               return NUM_XLATOR;
+       private PercentEval() {
        }
 
        public Eval evaluate(Eval[] args, int srcRow, short srcCol) {
                if (args.length != 1) {
                        return ErrorEval.VALUE_INVALID;
                }
-
-               ValueEval ve = singleOperandEvaluate(args[0], srcRow, srcCol);
-               if (ve instanceof NumericValueEval) {
-                       double d0 = ((NumericValueEval) ve).getNumberValue();
-                       return new NumberEval(d0 / 100);
+       double d0;
+               try {
+                       ValueEval ve = OperandResolver.getSingleValue(args[0], srcRow, srcCol);
+                       if (ve instanceof BlankEval) {
+                               return NumberEval.ZERO;
+                       }
+                       d0 = OperandResolver.coerceValueToDouble(ve);
+               } catch (EvaluationException e) {
+                       return e.getErrorEval();
                }
-
-               if (ve instanceof BlankEval) {
-                       return NumberEval.ZERO;
-               }
-               if (ve instanceof ErrorEval) {
-                       return ve;
-               }
-               return ErrorEval.VALUE_INVALID;
+               return new NumberEval(d0 / 100);
        }
 
        public int getNumberOfOperands() {
-               return _delegate.getNumberOfOperands();
-       }
-
-       public int getType() {
-               return _delegate.getType();
+               return 1;
        }
+       public final int getType() {
+       // TODO - remove
+        throw new RuntimeException("obsolete code should not be called");
+    }
 }
index 651c5d2aa2c829b87984b7f25fc0ef227b6e960c..685332a053aaa6ed8116ce7dc2159fd08c9e77a5 100644 (file)
@@ -1,90 +1,33 @@
-/*
-* 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;
 
-import org.apache.poi.hssf.record.formula.Ptg;
-import org.apache.poi.hssf.record.formula.PowerPtg;
-
 /**
  * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
- *  
  */
-public final class PowerEval extends NumericOperationEval {
-
-    private PowerPtg delegate;
-
-    private static final ValueEvalToNumericXlator NUM_XLATOR = 
-        new ValueEvalToNumericXlator((short)
-                ( ValueEvalToNumericXlator.BOOL_IS_PARSED 
-                | ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
-                | ValueEvalToNumericXlator.STRING_IS_PARSED
-                | ValueEvalToNumericXlator.REF_STRING_IS_PARSED
-                ));
-
-    public PowerEval(Ptg ptg) {
-        delegate = (PowerPtg) ptg;
-    }
-    
-    protected ValueEvalToNumericXlator getXlator() {
-        return NUM_XLATOR;
-    }
-
-    public Eval evaluate(Eval[] args, int srcRow, short srcCol) {
-       if(args.length != 2) {
-               return ErrorEval.VALUE_INVALID;
-       }
-        double d0 = 0;
-        double d1 = 0;
-        
-        ValueEval ve = singleOperandEvaluate(args[0], srcRow, srcCol);
-        if (ve instanceof NumericValueEval) {
-            d0 = ((NumericValueEval) ve).getNumberValue();
-        }
-        else if (ve instanceof BlankEval) {
-            // do nothing
-        }
-        else {
-            return ErrorEval.VALUE_INVALID;
-        }
-        
-        ve = singleOperandEvaluate(args[1], srcRow, srcCol);
-        if (ve instanceof NumericValueEval) {
-            d1 = ((NumericValueEval) ve).getNumberValue();
-        }
-        else if (ve instanceof BlankEval) {
-        // do nothing
-        }
-        else {
-            return ErrorEval.VALUE_INVALID;
-        }
+public final class PowerEval extends TwoOperandNumericOperation {
 
-        double p = Math.pow(d0, d1);
-        if (Double.isNaN(p)) {
-                       return ErrorEval.VALUE_INVALID;
-               }
-               return new NumberEval(p);
-    }
+       public static final OperationEval instance = new PowerEval();
 
-    public int getNumberOfOperands() {
-        return delegate.getNumberOfOperands();
-    }
+       private PowerEval() {
+       }
 
-    public int getType() {
-        return delegate.getType();
-    }
+       protected double evaluate(double d0, double d1) {
+               return Math.pow(d0, d1);
+       }
 }
index 85a3845299a49686b8308b5832a601875d675cf7..cbd6dc5eec476ec605eeb374d34616af51f381e4 100644 (file)
@@ -1,93 +1,33 @@
-/*
-* 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;
 
-import org.apache.poi.hssf.record.formula.Ptg;
-import org.apache.poi.hssf.record.formula.SubtractPtg;
-
 /**
  * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
- *  
  */
-public final class SubtractEval extends NumericOperationEval {
-
-    private SubtractPtg delegate;
-
-    private static final ValueEvalToNumericXlator NUM_XLATOR = 
-        new ValueEvalToNumericXlator((short)
-                ( ValueEvalToNumericXlator.BOOL_IS_PARSED 
-                | ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
-                | ValueEvalToNumericXlator.STRING_IS_PARSED
-                | ValueEvalToNumericXlator.REF_STRING_IS_PARSED
-                ));
-
-    public SubtractEval(Ptg ptg) {
-        delegate = (SubtractPtg) ptg;
-    }
-    
-    protected ValueEvalToNumericXlator getXlator() {
-        return NUM_XLATOR;
-    }
+public final class SubtractEval extends TwoOperandNumericOperation {
 
-    public Eval evaluate(Eval[] args, int srcRow, short srcCol) {
-       if(args.length != 2) {
-               return ErrorEval.VALUE_INVALID;
-       }
-        Eval retval = null;
-        double d0 = 0;
-        double d1 = 0;
-        ValueEval ve = singleOperandEvaluate(args[0], srcRow, srcCol);
-        if (ve instanceof NumericValueEval) {
-            d0 = ((NumericValueEval) ve).getNumberValue();
-        }
-        else if (ve instanceof BlankEval) {
-            // do nothing
-        }
-        else {
-            retval = ErrorEval.VALUE_INVALID;
-        }
-        
-        if (retval == null) { // no error yet
-            ve = singleOperandEvaluate(args[1], srcRow, srcCol);
-            if (ve instanceof NumericValueEval) {
-                d1 = ((NumericValueEval) ve).getNumberValue();
-            }
-            else if (ve instanceof BlankEval) {
-                // do nothing
-            }
-            else {
-                retval = ErrorEval.VALUE_INVALID;
-            }
-        }
-        if (retval == null) {
-            retval = (Double.isNaN(d0) || Double.isNaN(d1)) 
-                    ? (ValueEval) ErrorEval.VALUE_INVALID 
-                    : new NumberEval(d0 - d1);
-        }
-        return retval;
-    }
+       public static final OperationEval instance = new SubtractEval();
 
-    public int getNumberOfOperands() {
-        return delegate.getNumberOfOperands();
-    }
+       private SubtractEval() {
+       }
 
-    public int getType() {
-        return delegate.getType();
-    }
+       protected double evaluate(double d0, double d1) {
+               return d0 - d1;
+       }
 }
diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/TwoOperandNumericOperation.java b/src/java/org/apache/poi/hssf/record/formula/eval/TwoOperandNumericOperation.java
new file mode 100644 (file)
index 0000000..665ba4b
--- /dev/null
@@ -0,0 +1,55 @@
+/* ====================================================================
+   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;
+
+/**
+ * @author Josh Micich
+ */
+abstract class TwoOperandNumericOperation implements OperationEval {
+
+       public final int getType() {
+       // TODO - remove
+        throw new RuntimeException("obsolete code should not be called");
+    }
+    protected final double singleOperandEvaluate(Eval arg, int srcCellRow, short srcCellCol) throws EvaluationException {
+       ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol);
+               if (ve instanceof BlankEval) {
+                       return 0.0;
+               }
+               return OperandResolver.coerceValueToDouble(ve);
+    }
+    
+    public final Eval evaluate(Eval[] args, int srcCellRow, short srcCellCol) {
+               double result;
+               try {
+                       double d0 = singleOperandEvaluate(args[0], srcCellRow, srcCellCol);
+                       double d1 = singleOperandEvaluate(args[1], srcCellRow, srcCellCol);
+                       result = evaluate(d0, d1);
+                       if (Double.isNaN(result) || Double.isInfinite(result)) {
+                               return ErrorEval.NUM_ERROR;
+                       }
+               } catch (EvaluationException e) {
+                       return e.getErrorEval();
+               }
+       return new NumberEval(result);
+    }
+       protected abstract double evaluate(double d0, double d1) throws EvaluationException;
+       public final int getNumberOfOperands() {
+               return 2;
+       }
+}
index ef6f533ea52d3afff1c69ad0549ffffea3662dc5..8174429e01b2745684bdc778868c8a7a09e767bb 100644 (file)
@@ -1,75 +1,56 @@
-/*
-* 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;
 
-import org.apache.poi.hssf.record.formula.Ptg;
-import org.apache.poi.hssf.record.formula.UnaryMinusPtg;
 
 /**
  * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
  *  
  */
-public final class UnaryMinusEval extends NumericOperationEval {
-
-    private UnaryMinusPtg delegate;
-    private static final ValueEvalToNumericXlator NUM_XLATOR = 
-        new ValueEvalToNumericXlator((short)
-                ( ValueEvalToNumericXlator.BOOL_IS_PARSED 
-                | ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
-                | ValueEvalToNumericXlator.STRING_IS_PARSED
-                | ValueEvalToNumericXlator.REF_STRING_IS_PARSED
-                ));
-
-
-    public UnaryMinusEval(Ptg ptg) {
-        this.delegate = (UnaryMinusPtg) ptg;
-    }
-    
-    protected ValueEvalToNumericXlator getXlator() {
-        return NUM_XLATOR;
-    }
-
-    public Eval evaluate(Eval[] args, int srcRow, short srcCol) {
-       if(args.length != 1) {
-               return ErrorEval.VALUE_INVALID;
-       }
-        double d = 0;
-        
-        ValueEval ve = singleOperandEvaluate(args[0], srcRow, srcCol);
-        if (ve instanceof NumericValueEval) {
-            d = ((NumericValueEval) ve).getNumberValue();
-        }
-        else if (ve instanceof BlankEval) {
-            // do nothing
-        }
-        else if (ve instanceof ErrorEval) {
-            return ve;
-        }
-        
-        return new NumberEval(-d);
+public final class UnaryMinusEval implements OperationEval {
+
+       public static final OperationEval instance = new UnaryMinusEval();
+
+       private UnaryMinusEval() {
+       }
+
+       public Eval evaluate(Eval[] args, int srcRow, short srcCol) {
+               if (args.length != 1) {
+                       return ErrorEval.VALUE_INVALID;
+               }
+       double d;
+               try {
+                       ValueEval ve = OperandResolver.getSingleValue(args[0], srcRow, srcCol);
+                       if (ve instanceof BlankEval) {
+                               return NumberEval.ZERO;
+                       }
+                       d = OperandResolver.coerceValueToDouble(ve);
+               } catch (EvaluationException e) {
+                       return e.getErrorEval();
+               }
+               return new NumberEval(-d);
+       }
+
+       public int getNumberOfOperands() {
+               return 1;
+       }
+       public final int getType() {
+       // TODO - remove
+        throw new RuntimeException("obsolete code should not be called");
     }
-
-    public int getNumberOfOperands() {
-        return delegate.getNumberOfOperands();
-    }
-
-    public int getType() {
-        return delegate.getType();
-    }
-
 }
index edcc7bee790a84cd7dc88a73cdb7fc75a256ba4c..66c5f6801713abf4fada69572cf97b8db5668d97 100644 (file)
@@ -17,8 +17,6 @@
 
 package org.apache.poi.hssf.record.formula.eval;
 
-import org.apache.poi.hssf.record.formula.Ptg;
-import org.apache.poi.hssf.record.formula.UnaryPlusPtg;
 
 /**
  * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
@@ -26,13 +24,9 @@ import org.apache.poi.hssf.record.formula.UnaryPlusPtg;
  */
 public final class UnaryPlusEval implements OperationEval {
 
-    private UnaryPlusPtg delegate;
+    public static final OperationEval instance = new UnaryPlusEval();
     
-    /**
-     * called by reflection
-     */
-    public UnaryPlusEval(Ptg ptg) {
-        this.delegate = (UnaryPlusPtg) ptg;
+    private UnaryPlusEval() {
     }
 
     public Eval evaluate(Eval[] args, int srcCellRow, short srcCellCol) {
@@ -59,10 +53,10 @@ public final class UnaryPlusEval implements OperationEval {
     }
 
     public int getNumberOfOperands() {
-        return delegate.getNumberOfOperands();
+        return 1;
     }
 
     public int getType() {
-        return delegate.getType();
+        throw new RuntimeException("obsolete code should not be called");
     }
 }
index 1abcf34d2b90105392de7543390705e4d2a9a836..46aa0ddf6990e7e72dd968bb0cdc2799a13b8e82 100644 (file)
@@ -55,49 +55,40 @@ public final class ValueEvalToNumericXlator {
      * @param eval
      */
     public ValueEval attemptXlateToNumeric(ValueEval eval) {
-        ValueEval retval = null;
         
         if (eval == null) {
-            retval = BlankEval.INSTANCE;
+            throw new IllegalArgumentException("eval must not be null");
         }
         
         // most common case - least worries :)
-        else if (eval instanceof NumberEval) {
-            retval = eval; 
+        if (eval instanceof NumberEval) {
+            return eval; 
         }
         
-        // booleval
-        else if (eval instanceof BoolEval) {
-            retval = ((flags & BOOL_IS_PARSED) > 0)
+        if (eval instanceof BoolEval) {
+            return ((flags & BOOL_IS_PARSED) > 0)
                 ? (NumericValueEval) eval
                 : xlateBlankEval(BLANK_IS_PARSED);
         } 
         
-        // stringeval 
-        else if (eval instanceof StringEval) {
-            retval = xlateStringEval((StringEval) eval); // TODO: recursive call needed
+        if (eval instanceof StringEval) {
+            return xlateStringEval((StringEval) eval); // TODO: recursive call needed
         }
         
-        // refeval
-        else if (eval instanceof RefEval) {
-            retval = xlateRefEval((RefEval) eval);
+        if (eval instanceof RefEval) {
+            return xlateRefEval((RefEval) eval);
         }
         
-        // erroreval
-        else if (eval instanceof ErrorEval) {
-            retval = eval;
+        if (eval instanceof ErrorEval) {
+            return eval;
         }
         
-        else if (eval instanceof BlankEval) {
-            retval = xlateBlankEval(BLANK_IS_PARSED);
+        if (eval instanceof BlankEval) {
+            return xlateBlankEval(BLANK_IS_PARSED);
         }
         
         // probably AreaEval? then not acceptable.
-        else {
-            throw new RuntimeException("Invalid ValueEval type passed for conversion: " + eval.getClass());
-        }
-        
-        return retval;
+        throw new RuntimeException("Invalid ValueEval type passed for conversion: " + eval.getClass());
     }
     
     /**
index f7d3c9749b31a16de62a7585921ceb5b99fc1bfe..21dc067592d2a29047c09f5034a1ffcf8b611920 100755 (executable)
@@ -79,17 +79,9 @@ final class OperationEvaluatorFactory {
        
        private static Map initialiseConstructorsMap() {
                Map m = new HashMap(32);
-               add(m, AddPtg.class, AddEval.class);
                add(m, ConcatPtg.class, ConcatEval.class);
-               add(m, DividePtg.class, DivideEval.class);
                add(m, FuncPtg.class, FuncVarEval.class);
                add(m, FuncVarPtg.class, FuncVarEval.class);
-               add(m, MultiplyPtg.class, MultiplyEval.class);
-               add(m, PercentPtg.class, PercentEval.class);
-               add(m, PowerPtg.class, PowerEval.class);
-               add(m, SubtractPtg.class, SubtractEval.class);
-               add(m, UnaryMinusPtg.class, UnaryMinusEval.class);
-               add(m, UnaryPlusPtg.class, UnaryPlusEval.class);
                return m;
        }
        private static Map initialiseInstancesMap() {
@@ -100,6 +92,15 @@ final class OperationEvaluatorFactory {
                add(m, LessEqualPtg.class, LessEqualEval.instance);
                add(m, LessThanPtg.class, LessThanEval.instance);
                add(m, NotEqualPtg.class, NotEqualEval.instance);
+
+               add(m, AddPtg.class, AddEval.instance);
+               add(m, DividePtg.class, DivideEval.instance);
+               add(m, MultiplyPtg.class, MultiplyEval.instance);
+               add(m, PercentPtg.class, PercentEval.instance);
+               add(m, PowerPtg.class, PowerEval.instance);
+               add(m, SubtractPtg.class, SubtractEval.instance);
+               add(m, UnaryMinusPtg.class, UnaryMinusEval.instance);
+               add(m, UnaryPlusPtg.class, UnaryPlusEval.instance);
                return m;
        }
 
index 3809a86a69b87375be17f434f33a3a9e72767dc4..75510619420583e3cc3b749dc2e47fbd7ad53975 100755 (executable)
@@ -31,6 +31,7 @@ public class AllFormulaEvalTests {
                TestSuite result = new TestSuite(AllFormulaEvalTests.class.getName());
                result.addTestSuite(TestAreaEval.class);
                result.addTestSuite(TestCircularReferences.class);
+               result.addTestSuite(TestDivideEval.class);
                result.addTestSuite(TestEqualEval.class);
                result.addTestSuite(TestExternalFunction.class);
                result.addTestSuite(TestFormulaBugs.class);
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/eval/TestDivideEval.java b/src/testcases/org/apache/poi/hssf/record/formula/eval/TestDivideEval.java
new file mode 100644 (file)
index 0000000..71bf03e
--- /dev/null
@@ -0,0 +1,62 @@
+/* ====================================================================
+   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.TestCase;
+
+import org.apache.poi.hssf.record.formula.functions.EvalFactory;
+import org.apache.poi.hssf.record.formula.functions.NumericFunctionInvoker;
+
+/**
+ * Test for divide operator evaluator.
+ * 
+ * @author Josh Micich
+ */
+public final class TestDivideEval extends TestCase {
+       
+       private static void confirm(ValueEval arg0, ValueEval arg1, double expectedResult) {
+               Eval[] args = { 
+                       arg0, arg1,      
+               };
+               
+               double result = NumericFunctionInvoker.invoke(DivideEval.instance, args, 0, 0);
+               
+               assertEquals(expectedResult, result, 0);
+       }
+
+       public void testBasic() {
+               confirm(new NumberEval(5), new NumberEval(2), 2.5);
+               confirm(new NumberEval(3), new NumberEval(16), 0.1875);
+               confirm(new NumberEval(-150), new NumberEval(-15), 10.0);
+               confirm(new StringEval("0.2"), new NumberEval(0.05), 4.0);
+               confirm(BoolEval.TRUE, new StringEval("-0.2"), -5.0);
+       }
+
+       public void test1x1Area() {
+               AreaEval ae0 = EvalFactory.createAreaEval("B2:B2", new ValueEval[] { new NumberEval(50), });
+               AreaEval ae1 = EvalFactory.createAreaEval("C2:C2", new ValueEval[] { new NumberEval(10), });
+               confirm(ae0, ae1, 5);
+       }
+       public void testDivZero() {
+               Eval[] args = { 
+                       new NumberEval(5), NumberEval.ZERO,      
+               };
+               Eval result = DivideEval.instance.evaluate(args, 0, (short) 0);
+               assertEquals(ErrorEval.DIV_ZERO, result);
+       }
+}
index 656c7d25a27016f61c6b1dfaa7980ec045dcc1c9..310fce68a613b20c30134abf134da37422888d8b 100755 (executable)
@@ -20,7 +20,7 @@ package org.apache.poi.hssf.record.formula.eval;
 import junit.framework.AssertionFailedError;
 import junit.framework.TestCase;
 
-import org.apache.poi.hssf.record.formula.PercentPtg;
+import org.apache.poi.hssf.record.formula.functions.EvalFactory;
 import org.apache.poi.hssf.record.formula.functions.NumericFunctionInvoker;
 import org.apache.poi.hssf.usermodel.HSSFCell;
 import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
@@ -41,8 +41,8 @@ public final class TestPercentEval extends TestCase {
                        arg,    
                };
                
-               PercentEval opEval = new PercentEval(PercentPtg.instance);
-               double result = NumericFunctionInvoker.invoke(opEval, args, -1, (short)-1);
+               OperationEval opEval = PercentEval.instance;
+               double result = NumericFunctionInvoker.invoke(opEval, args, 0, 0);
                
                assertEquals(expectedResult, result, 0);
        }
@@ -55,6 +55,10 @@ public final class TestPercentEval extends TestCase {
                confirm(BoolEval.TRUE, 0.01);
        }
 
+       public void test1x1Area() {
+               AreaEval ae = EvalFactory.createAreaEval("B2:B2", new ValueEval[] { new NumberEval(50), });
+               confirm(ae, 0.5);
+       }
        public void testInSpreadSheet() {
                HSSFWorkbook wb = new HSSFWorkbook();
                HSSFSheet sheet = wb.createSheet("Sheet1");
index 33c38a6c127a8dfa447440e0c6c900584774b60d..726633c40604f0235398c502cb3ea80591766ab5 100755 (executable)
@@ -1,27 +1,25 @@
-/*
-* 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;
 
 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;
 
@@ -53,7 +51,7 @@ public final class TestUnaryPlusEval extends TestCase {
                        EvalFactory.createAreaEval(areaPtg, values),
                };
 
-               double result = NumericFunctionInvoker.invoke(new UnaryPlusEval(UnaryPlusPtg.instance), args, 10, (short)20);
+               double result = NumericFunctionInvoker.invoke(UnaryPlusEval.instance, args, 10, (short)20);
 
                assertEquals(35, result, 0);
        }