From: Josh Micich Date: Wed, 10 Sep 2008 22:43:30 +0000 (+0000) Subject: Refactored finance functions. X-Git-Tag: REL_3_2_FINAL~70 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=4135c76ee52372ea1a8786e03ea0c38c0b48b590;p=poi.git Refactored finance functions. git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@694050 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/FunctionEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/FunctionEval.java index e78ab5f8e6..6f14a1e856 100644 --- a/src/java/org/apache/poi/hssf/record/formula/eval/FunctionEval.java +++ b/src/java/org/apache/poi/hssf/record/formula/eval/FunctionEval.java @@ -129,10 +129,10 @@ public abstract class FunctionEval implements OperationEval { retval[52] = new Growth(); // GROWTH retval[53] = new Goto(); // GOTO retval[54] = new Halt(); // HALT - retval[56] = new Pv(); // PV - retval[57] = new Fv(); // FV - retval[58] = new Nper(); // NPER - retval[59] = new Pmt(); // PMT + retval[56] = FinanceFunction.PV; + retval[57] = FinanceFunction.FV; + retval[58] = FinanceFunction.NPER; + retval[59] = FinanceFunction.PMT; retval[60] = new Rate(); // RATE retval[61] = new Mirr(); // MIRR retval[62] = new Irr(); // IRR diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/ValueEvalToNumericXlator.java b/src/java/org/apache/poi/hssf/record/formula/eval/ValueEvalToNumericXlator.java index 46aa0ddf69..37f0b9b4b1 100644 --- a/src/java/org/apache/poi/hssf/record/formula/eval/ValueEvalToNumericXlator.java +++ b/src/java/org/apache/poi/hssf/record/formula/eval/ValueEvalToNumericXlator.java @@ -1,23 +1,20 @@ -/* -* 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 - * - */ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + package org.apache.poi.hssf.record.formula.eval; /** @@ -30,11 +27,7 @@ public final class ValueEvalToNumericXlator { public static final int BOOL_IS_PARSED = 0x0002; public static final int BLANK_IS_PARSED = 0x0004; // => blanks are not ignored, converted to 0 - public static final int REF_STRING_IS_PARSED = 0x0008; - public static final int REF_BOOL_IS_PARSED = 0x0010; - public static final int REF_BLANK_IS_PARSED = 0x0020; - - public static final int STRING_IS_INVALID_VALUE = 0x0800; + public static final int REF_BOOL_IS_PARSED = 0x0008; private final int flags; @@ -68,11 +61,11 @@ public final class ValueEvalToNumericXlator { if (eval instanceof BoolEval) { return ((flags & BOOL_IS_PARSED) > 0) ? (NumericValueEval) eval - : xlateBlankEval(BLANK_IS_PARSED); + : xlateBlankEval(); } if (eval instanceof StringEval) { - return xlateStringEval((StringEval) eval); // TODO: recursive call needed + return xlateStringEval((StringEval) eval); } if (eval instanceof RefEval) { @@ -84,7 +77,7 @@ public final class ValueEvalToNumericXlator { } if (eval instanceof BlankEval) { - return xlateBlankEval(BLANK_IS_PARSED); + return xlateBlankEval(); } // probably AreaEval? then not acceptable. @@ -97,8 +90,8 @@ public final class ValueEvalToNumericXlator { * valued numbereval is returned, else BlankEval.INSTANCE * is returned. */ - private ValueEval xlateBlankEval(int flag) { - return ((flags & flag) > 0) + private ValueEval xlateBlankEval() { + return ((flags & BLANK_IS_PARSED) > 0) ? (ValueEval) NumberEval.ZERO : BlankEval.INSTANCE; } @@ -122,7 +115,8 @@ public final class ValueEvalToNumericXlator { } if (eval instanceof StringEval) { - return xlateRefStringEval((StringEval) eval); + // all ref strings are blanks + return BlankEval.INSTANCE; } if (eval instanceof ErrorEval) { @@ -130,7 +124,7 @@ public final class ValueEvalToNumericXlator { } if (eval instanceof BlankEval) { - return xlateBlankEval(REF_BLANK_IS_PARSED); + return xlateBlankEval(); } throw new RuntimeException("Invalid ValueEval type passed for conversion: (" @@ -151,29 +145,7 @@ public final class ValueEvalToNumericXlator { } return new NumberEval(d.doubleValue()); } - // strings are errors? - if ((flags & STRING_IS_INVALID_VALUE) > 0) { - return ErrorEval.VALUE_INVALID; - } - - // ignore strings - return xlateBlankEval(BLANK_IS_PARSED); - } - - /** - * uses the relevant flags to decode the StringEval - * @param eval - */ - private ValueEval xlateRefStringEval(StringEval sve) { - if ((flags & REF_STRING_IS_PARSED) > 0) { - String s = sve.getStringValue(); - Double d = OperandResolver.parseDouble(s); - if(d == null) { - return ErrorEval.VALUE_INVALID; - } - return new NumberEval(d.doubleValue()); - } - // strings are blanks - return BlankEval.INSTANCE; + // else strings are errors? + return ErrorEval.VALUE_INVALID; } } diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/AggregateFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/AggregateFunction.java index be0b1e44c7..f04e64070b 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/AggregateFunction.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/AggregateFunction.java @@ -19,6 +19,7 @@ package org.apache.poi.hssf.record.formula.functions; import org.apache.poi.hssf.record.formula.eval.ErrorEval; import org.apache.poi.hssf.record.formula.eval.EvaluationException; +import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator; /** @@ -32,8 +33,8 @@ public abstract class AggregateFunction extends MultiOperandNumericFunction { | ValueEvalToNumericXlator.STRING_IS_PARSED )); - protected final ValueEvalToNumericXlator getXlator() { - return DEFAULT_NUM_XLATOR; + protected ValueEval attemptXlateToNumeric(ValueEval ve) { + return DEFAULT_NUM_XLATOR.attemptXlateToNumeric(ve); } diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/FinanceFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/FinanceFunction.java index a6956752be..01fcf9ef0b 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/FinanceFunction.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/FinanceFunction.java @@ -1,103 +1,77 @@ -/* -* 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 -package org.apache.poi.hssf.record.formula.functions; + 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. +==================================================================== */ -import org.apache.poi.hssf.record.formula.eval.AreaEval; -import org.apache.poi.hssf.record.formula.eval.BoolEval; -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.Eval; -import org.apache.poi.hssf.record.formula.eval.NumericValueEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator; +package org.apache.poi.hssf.record.formula.functions; +import org.apache.poi.hssf.record.formula.eval.EvaluationException; /** * @author Amol S. Deshmukh < amolweb at ya hoo dot com > * Super class for all Evals for financial function evaluation. - * + * */ -public abstract class FinanceFunction implements Function { - private static final ValueEvalToNumericXlator DEFAULT_NUM_XLATOR = - new ValueEvalToNumericXlator((short) (0 - | ValueEvalToNumericXlator.BOOL_IS_PARSED - | ValueEvalToNumericXlator.REF_BOOL_IS_PARSED - | ValueEvalToNumericXlator.STRING_IS_PARSED - | ValueEvalToNumericXlator.REF_STRING_IS_PARSED - | ValueEvalToNumericXlator.BLANK_IS_PARSED - | ValueEvalToNumericXlator.REF_BLANK_IS_PARSED - //| ValueEvalToNumericXlator.REF_STRING_TO_BOOL_IS_PARSED - //| ValueEvalToNumericXlator.STRING_IS_INVALID_VALUE - //| ValueEvalToNumericXlator.REF_STRING_IS_INVALID_VALUE - )); - - /** - * this is the default impl of the factory(ish) method getXlator. - * Subclasses can override this method - * if they desire to return a different ValueEvalToNumericXlator instance - * than the default. - */ - protected final ValueEvalToNumericXlator getXlator() { - return DEFAULT_NUM_XLATOR; - } - - protected final ValueEval singleOperandNumericAsBoolean(Eval eval, int srcRow, short srcCol) { - ValueEval retval = null; - retval = singleOperandEvaluate(eval, srcRow, srcCol); - if (retval instanceof NumericValueEval) { - NumericValueEval nve = (NumericValueEval) retval; - retval = (nve.getNumberValue() == 0) - ? BoolEval.FALSE - : BoolEval.TRUE; - } - else { - retval = ErrorEval.VALUE_INVALID; - } - return retval; - } - - protected final ValueEval singleOperandEvaluate(Eval eval, int srcRow, short srcCol) { +public abstract class FinanceFunction extends NumericFunction.MultiArg { + + protected FinanceFunction() { + super (3, 5); + } + + protected double evaluate(double[] ds) throws EvaluationException { + // All finance functions have 3 to 5 args, first 4 are numbers, last is boolean + // default for last 2 args are 0.0 and false + // Text boolean literals are not valid for the last arg + + double arg3 = 0.0; + double arg4 = 0.0; + + switch(ds.length) { + case 5: + arg4 = ds[4]; + case 4: + arg3 = ds[3]; + case 3: + break; + default: + throw new IllegalStateException("Wrong number of arguments"); + } + return evaluate(ds[0], ds[1], ds[2], arg3, arg4!=0.0); + } + + protected abstract double evaluate(double rate, double arg1, double arg2, double arg3, boolean type) throws EvaluationException ; + - if (eval instanceof AreaEval) { - AreaEval ae = (AreaEval) eval; - if (ae.contains(srcRow, srcCol)) { // circular ref! - return ErrorEval.CIRCULAR_REF_ERROR; - } - if (ae.isRow()) { - if (ae.isColumn()) { - return ae.getRelativeValue(0, 0); - } - if (ae.containsColumn(srcCol)) { - ValueEval ve = ae.getValueAt(ae.getFirstRow(), srcCol); - ve = getXlator().attemptXlateToNumeric(ve); - return getXlator().attemptXlateToNumeric(ve); - } - return ErrorEval.VALUE_INVALID; - } - if (ae.isColumn()) { - if (ae.containsRow(srcRow)) { - ValueEval ve = ae.getValueAt(srcRow, ae.getFirstColumn()); - return getXlator().attemptXlateToNumeric(ve); - } - return ErrorEval.VALUE_INVALID; - } - return ErrorEval.VALUE_INVALID; - } - return getXlator().attemptXlateToNumeric((ValueEval) eval); - } - + public static final Function FV = new FinanceFunction() { + protected double evaluate(double rate, double arg1, double arg2, double arg3, boolean type) { + return FinanceLib.fv(rate, arg1, arg2, arg3, type); + } + }; + public static final Function NPER = new FinanceFunction() { + protected double evaluate(double rate, double arg1, double arg2, double arg3, boolean type) { + return FinanceLib.nper(rate, arg1, arg2, arg3, type); + } + }; + public static final Function PMT = new FinanceFunction() { + protected double evaluate(double rate, double arg1, double arg2, double arg3, boolean type) { + return FinanceLib.pmt(rate, arg1, arg2, arg3, type); + } + }; + public static final Function PV = new FinanceFunction() { + protected double evaluate(double rate, double arg1, double arg2, double arg3, boolean type) { + return FinanceLib.pv(rate, arg1, arg2, arg3, type); + } + }; } diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Fv.java b/src/java/org/apache/poi/hssf/record/formula/functions/Fv.java deleted file mode 100644 index fd0335c388..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Fv.java +++ /dev/null @@ -1,75 +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 15, 2005 - * - */ -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.BoolEval; -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.Eval; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.NumericValueEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -public class Fv extends FinanceFunction { - - public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { - double rate = 0, nper = 0, pmt = 0, pv = 0, d = 0; - boolean type = false; - ValueEval retval = null; - ValueEval ve = null; - - switch (operands.length) { - default: - retval = ErrorEval.VALUE_INVALID; - break; - case 5: - ve = singleOperandNumericAsBoolean(operands[4], srcRow, srcCol); - if (ve instanceof ErrorEval) { retval = ErrorEval.VALUE_INVALID; break; } - type = ((BoolEval) ve).getBooleanValue(); - case 4: - ve = singleOperandEvaluate(operands[3], srcRow, srcCol); - if (ve instanceof NumericValueEval) pv = ((NumericValueEval) ve).getNumberValue(); - else { retval = ErrorEval.VALUE_INVALID; break; } - case 3: - ve = singleOperandEvaluate(operands[1], srcRow, srcCol); - if (ve instanceof NumericValueEval) nper = ((NumericValueEval) ve).getNumberValue(); - else { retval = ErrorEval.VALUE_INVALID; break; } - - ve = singleOperandEvaluate(operands[2], srcRow, srcCol); - if (ve instanceof NumericValueEval) pmt = ((NumericValueEval) ve).getNumberValue(); - else { retval = ErrorEval.VALUE_INVALID; break; } - - ve = singleOperandEvaluate(operands[0], srcRow, srcCol); - if (ve instanceof NumericValueEval) rate = ((NumericValueEval) ve).getNumberValue(); - else { retval = ErrorEval.VALUE_INVALID; break; } - } - - if (retval == null) { - d = FinanceLib.fv(rate, nper, pmt, pv, type); - retval = (Double.isNaN(d)) - ? (ValueEval) ErrorEval.VALUE_INVALID - : (Double.isInfinite(d)) - ? (ValueEval) ErrorEval.NUM_ERROR - : new NumberEval(d); - } - return retval; - } - -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Maxa.java b/src/java/org/apache/poi/hssf/record/formula/functions/Maxa.java index 9d7011f049..7ae722889e 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Maxa.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Maxa.java @@ -17,6 +17,7 @@ package org.apache.poi.hssf.record.formula.functions; +import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator; /** @@ -29,19 +30,12 @@ public final class Maxa extends MultiOperandNumericFunction { ValueEvalToNumericXlator.BOOL_IS_PARSED | ValueEvalToNumericXlator.REF_BOOL_IS_PARSED | ValueEvalToNumericXlator.STRING_IS_PARSED - //| ValueEvalToNumericXlator.REF_STRING_IS_PARSED - //| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED - //| ValueEvalToNumericXlator.STRING_TO_BOOL_IS_PARSED - //| ValueEvalToNumericXlator.REF_STRING_TO_BOOL_IS_PARSED - | ValueEvalToNumericXlator.STRING_IS_INVALID_VALUE - //| ValueEvalToNumericXlator.REF_STRING_IS_INVALID_VALUE | ValueEvalToNumericXlator.BLANK_IS_PARSED - | ValueEvalToNumericXlator.REF_BLANK_IS_PARSED )); - protected ValueEvalToNumericXlator getXlator() { - return DEFAULT_NUM_XLATOR; - } + protected ValueEval attemptXlateToNumeric(ValueEval ve) { + return DEFAULT_NUM_XLATOR.attemptXlateToNumeric(ve); + } public double evaluate(double[] values) { return values.length > 0 ? MathX.max(values) : 0; diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Mina.java b/src/java/org/apache/poi/hssf/record/formula/functions/Mina.java index bbc7da8248..b3965eefd4 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Mina.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Mina.java @@ -17,31 +17,25 @@ package org.apache.poi.hssf.record.formula.functions; +import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator; /** * @author Amol S. Deshmukh < amolweb at ya hoo dot com > * */ -public class Mina extends MultiOperandNumericFunction { +public final class Mina extends MultiOperandNumericFunction { private static final ValueEvalToNumericXlator DEFAULT_NUM_XLATOR = new ValueEvalToNumericXlator((short) ( ValueEvalToNumericXlator.BOOL_IS_PARSED | ValueEvalToNumericXlator.REF_BOOL_IS_PARSED | ValueEvalToNumericXlator.STRING_IS_PARSED - //| ValueEvalToNumericXlator.REF_STRING_IS_PARSED - //| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED - //| ValueEvalToNumericXlator.STRING_TO_BOOL_IS_PARSED - //| ValueEvalToNumericXlator.REF_STRING_TO_BOOL_IS_PARSED - | ValueEvalToNumericXlator.STRING_IS_INVALID_VALUE - //| ValueEvalToNumericXlator.REF_STRING_IS_INVALID_VALUE - | ValueEvalToNumericXlator.REF_BLANK_IS_PARSED | ValueEvalToNumericXlator.BLANK_IS_PARSED )); - protected ValueEvalToNumericXlator getXlator() { - return DEFAULT_NUM_XLATOR; - } + protected ValueEval attemptXlateToNumeric(ValueEval ve) { + return DEFAULT_NUM_XLATOR.attemptXlateToNumeric(ve); + } public double evaluate(double[] values) { return values.length > 0 ? MathX.min(values) : 0; diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Mode.java b/src/java/org/apache/poi/hssf/record/formula/functions/Mode.java index 940b9f40e6..64f017e8e2 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Mode.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Mode.java @@ -19,6 +19,7 @@ package org.apache.poi.hssf.record.formula.functions; import org.apache.poi.hssf.record.formula.eval.ErrorEval; import org.apache.poi.hssf.record.formula.eval.EvaluationException; +import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator; /** @@ -26,39 +27,25 @@ import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator; * */ public class Mode extends MultiOperandNumericFunction { - private static final ValueEvalToNumericXlator DEFAULT_NUM_XLATOR = - new ValueEvalToNumericXlator((short) (0 - //| ValueEvalToNumericXlator.BOOL_IS_PARSED - //| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED - //| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED - //| ValueEvalToNumericXlator.STRING_IS_PARSED - //| ValueEvalToNumericXlator.REF_STRING_IS_PARSED - //| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED - //| ValueEvalToNumericXlator.STRING_TO_BOOL_IS_PARSED - //| ValueEvalToNumericXlator.REF_STRING_TO_BOOL_IS_PARSED - | ValueEvalToNumericXlator.STRING_IS_INVALID_VALUE - //| ValueEvalToNumericXlator.REF_STRING_IS_INVALID_VALUE - //| ValueEvalToNumericXlator.EVALUATED_REF_BLANK_IS_PARSED - //| ValueEvalToNumericXlator.REF_BLANK_IS_PARSED - //| ValueEvalToNumericXlator.BLANK_IS_PARSED - )); - - /** - * this is the default impl for the factory method getXlator - * of the super class NumericFunction. Subclasses can override this method - * if they desire to return a different ValueEvalToNumericXlator instance - * than the default. - */ - protected ValueEvalToNumericXlator getXlator() { - return DEFAULT_NUM_XLATOR; - } + private static final ValueEvalToNumericXlator DEFAULT_NUM_XLATOR = + new ValueEvalToNumericXlator(0); - protected double evaluate(double[] values) throws EvaluationException { - double d = StatsLib.mode(values); - if (Double.isNaN(d)) { - // TODO - StatsLib is returning NaN to denote 'no duplicate values' - throw new EvaluationException(ErrorEval.NA); - } - return d; - } + /** + * this is the default impl for the factory method getXlator + * of the super class NumericFunction. Subclasses can override this method + * if they desire to return a different ValueEvalToNumericXlator instance + * than the default. + */ + protected ValueEval attemptXlateToNumeric(ValueEval ve) { + return DEFAULT_NUM_XLATOR.attemptXlateToNumeric(ve); + } + + protected double evaluate(double[] values) throws EvaluationException { + double d = StatsLib.mode(values); + if (Double.isNaN(d)) { + // TODO - StatsLib is returning NaN to denote 'no duplicate values' + throw new EvaluationException(ErrorEval.NA); + } + return d; + } } diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/MultiOperandNumericFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/MultiOperandNumericFunction.java index 1337e2fe4d..ec65d0f127 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/MultiOperandNumericFunction.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/MultiOperandNumericFunction.java @@ -27,7 +27,6 @@ import org.apache.poi.hssf.record.formula.eval.NumericValueEval; import org.apache.poi.hssf.record.formula.eval.Ref2DEval; import org.apache.poi.hssf.record.formula.eval.RefEval; import org.apache.poi.hssf.record.formula.eval.ValueEval; -import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator; /** * @author Amol S. Deshmukh < amolweb at ya hoo dot com > @@ -74,9 +73,6 @@ public abstract class MultiOperandNumericFunction implements Function { private static final int DEFAULT_MAX_NUM_OPERANDS = 30; - protected abstract ValueEvalToNumericXlator getXlator(); - - public final Eval evaluate(Eval[] args, int srcCellRow, short srcCellCol) { double d; @@ -185,7 +181,5 @@ public abstract class MultiOperandNumericFunction implements Function { } - protected ValueEval attemptXlateToNumeric(ValueEval ve) { - return getXlator().attemptXlateToNumeric(ve); - } + protected abstract ValueEval attemptXlateToNumeric(ValueEval ve); } diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Nper.java b/src/java/org/apache/poi/hssf/record/formula/functions/Nper.java deleted file mode 100644 index 95411edb77..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Nper.java +++ /dev/null @@ -1,75 +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 15, 2005 - * - */ -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.BoolEval; -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.Eval; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.NumericValueEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -public class Nper extends FinanceFunction { - - public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { - double rate = 0, fv = 0, pmt = 0, pv = 0, d = 0; - boolean type = false; - ValueEval retval = null; - ValueEval ve = null; - - switch (operands.length) { - default: - retval = ErrorEval.VALUE_INVALID; - break; - case 5: - ve = singleOperandNumericAsBoolean(operands[4], srcRow, srcCol); - if (ve instanceof ErrorEval) { retval = ErrorEval.VALUE_INVALID; break; } - type = ((BoolEval) ve).getBooleanValue(); - case 4: - ve = singleOperandEvaluate(operands[0], srcRow, srcCol); - if (ve instanceof NumericValueEval) rate = ((NumericValueEval) ve).getNumberValue(); - else { retval = ErrorEval.VALUE_INVALID; break; } - - ve = singleOperandEvaluate(operands[1], srcRow, srcCol); - if (ve instanceof NumericValueEval) pmt = ((NumericValueEval) ve).getNumberValue(); - else { retval = ErrorEval.VALUE_INVALID; break; } - - ve = singleOperandEvaluate(operands[2], srcRow, srcCol); - if (ve instanceof NumericValueEval) pv = ((NumericValueEval) ve).getNumberValue(); - else { retval = ErrorEval.VALUE_INVALID; break; } - - ve = singleOperandEvaluate(operands[3], srcRow, srcCol); - if (ve instanceof NumericValueEval) fv = ((NumericValueEval) ve).getNumberValue(); - else { retval = ErrorEval.VALUE_INVALID; break; } - } - - if (retval == null) { - d = FinanceLib.nper(rate, pmt, pv, fv, type); - retval = (Double.isNaN(d)) - ? (ValueEval) ErrorEval.VALUE_INVALID - : (Double.isInfinite(d)) - ? (ValueEval) ErrorEval.NUM_ERROR - : new NumberEval(d); - } - return retval; - } - -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Pmt.java b/src/java/org/apache/poi/hssf/record/formula/functions/Pmt.java deleted file mode 100644 index 68a8d43dce..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Pmt.java +++ /dev/null @@ -1,91 +0,0 @@ -/* -* Licensed to the Apache Software Foundation (ASF) under one or more -* contributor license agreements. See the NOTICE file distributed with -* this work for additional information regarding copyright ownership. -* The ASF licenses this file to You under the Apache License, Version 2.0 -* (the "License"); you may not use this file except in compliance with -* the License. You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.BoolEval; -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.Eval; -import org.apache.poi.hssf.record.formula.eval.EvaluationException; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.NumericValueEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -/** - * Implementation for the PMT() Excel function.

- * - * Syntax:
- * PMT(rate, nper, pv, fv, type)

- * - * Returns the constant repayment amount required for a loan assuming a constant interest rate.

- * - * rate the loan interest rate.
- * nper the number of loan repayments.
- * pv the present value of the future payments (or principle).
- * fv the future value (default zero) surplus cash at the end of the loan lifetime.
- * type whether payments are due at the beginning(1) or end(0 - default) of each payment period.
- * - */ -public final class Pmt extends FinanceFunction { - - public Eval evaluate(Eval[] args, int srcRow, short srcCol) { - - if(args.length < 3 || args.length > 5) { - return ErrorEval.VALUE_INVALID; - } - - try { - // evaluate first three (always present) args - double rate = evalArg(args[0], srcRow, srcCol); - double nper = evalArg(args[1], srcRow, srcCol); - double pv = evalArg(args[2], srcRow, srcCol); - double fv = 0; - boolean arePaymentsAtPeriodBeginning = false; - - switch (args.length) { - case 5: - ValueEval ve = singleOperandNumericAsBoolean(args[4], srcRow, srcCol); - if (ve instanceof ErrorEval) { - return ve; - } - arePaymentsAtPeriodBeginning = ((BoolEval) ve).getBooleanValue(); - case 4: - fv = evalArg(args[3], srcRow, srcCol); - } - double d = FinanceLib.pmt(rate, nper, pv, fv, arePaymentsAtPeriodBeginning); - if (Double.isNaN(d)) { - return ErrorEval.VALUE_INVALID; - } - if (Double.isInfinite(d)) { - return ErrorEval.NUM_ERROR; - } - return new NumberEval(d); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - } - - private double evalArg(Eval arg, int srcRow, short srcCol) throws EvaluationException { - ValueEval ve = singleOperandEvaluate(arg, srcRow, srcCol); - if(ve instanceof ErrorEval) { - throw new EvaluationException((ErrorEval) ve); - } - if (ve instanceof NumericValueEval) { - return ((NumericValueEval) ve).getNumberValue(); - } - throw new EvaluationException(ErrorEval.VALUE_INVALID); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Pv.java b/src/java/org/apache/poi/hssf/record/formula/functions/Pv.java deleted file mode 100644 index 1d54bee93d..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Pv.java +++ /dev/null @@ -1,74 +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 15, 2005 - * - */ -package org.apache.poi.hssf.record.formula.functions; - -import org.apache.poi.hssf.record.formula.eval.BoolEval; -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.Eval; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.NumericValueEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; - -public class Pv extends FinanceFunction { - - public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { - double rate = 0, fv = 0, nper = 0, pmt = 0, d = 0; - boolean type = false; - ValueEval retval = null; - ValueEval ve = null; - - switch (operands.length) { - default: - retval = ErrorEval.VALUE_INVALID; - break; - case 5: - ve = singleOperandNumericAsBoolean(operands[4], srcRow, srcCol); - if (ve instanceof ErrorEval) { retval = ErrorEval.VALUE_INVALID; break; } - type = ((BoolEval) ve).getBooleanValue(); - case 4: - ve = singleOperandEvaluate(operands[3], srcRow, srcCol); - if (ve instanceof NumericValueEval) fv = ((NumericValueEval) ve).getNumberValue(); - else { retval = ErrorEval.VALUE_INVALID; break; } - case 3: - ve = singleOperandEvaluate(operands[1], srcRow, srcCol); - if (ve instanceof NumericValueEval) nper = ((NumericValueEval) ve).getNumberValue(); - else { retval = ErrorEval.VALUE_INVALID; break; } - - ve = singleOperandEvaluate(operands[2], srcRow, srcCol); - if (ve instanceof NumericValueEval) pmt = ((NumericValueEval) ve).getNumberValue(); - else { retval = ErrorEval.VALUE_INVALID; break; } - - ve = singleOperandEvaluate(operands[0], srcRow, srcCol); - if (ve instanceof NumericValueEval) rate = ((NumericValueEval) ve).getNumberValue(); - else { retval = ErrorEval.VALUE_INVALID; break; } - } - - if (retval == null) { - d = FinanceLib.pv(rate, nper, pmt, fv, type); - retval = (Double.isNaN(d)) - ? (ValueEval) ErrorEval.VALUE_INVALID - : (Double.isInfinite(d)) - ? (ValueEval) ErrorEval.NUM_ERROR - : new NumberEval(d); - } - return retval; - } -} diff --git a/src/testcases/org/apache/poi/hssf/data/FormulaEvalTestData.xls b/src/testcases/org/apache/poi/hssf/data/FormulaEvalTestData.xls index ad41de8efc..acf9c8b166 100644 Binary files a/src/testcases/org/apache/poi/hssf/data/FormulaEvalTestData.xls and b/src/testcases/org/apache/poi/hssf/data/FormulaEvalTestData.xls differ diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestPmt.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestPmt.java index 2fecef7046..9a4cded9af 100644 --- a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestPmt.java +++ b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestPmt.java @@ -36,7 +36,7 @@ public final class TestPmt extends TestCase { assertEquals(expected, ne.getNumberValue(), 0.00005); } private static Eval invoke(Eval[] args) { - return new Pmt().evaluate(args, -1, (short)-1); + return FinanceFunction.PMT.evaluate(args, -1, (short)-1); } /** * Invocation when not expecting an error result