From: Josh Micich Date: Mon, 17 Aug 2009 18:29:40 +0000 (+0000) Subject: Combined FuncVarEval into FunctionEval. Simplified selection of free ref functions. X-Git-Tag: REL_3_5-FINAL~43 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=f4c028c5a3491301349513f96d6a0e3f80c2a0d6;p=poi.git Combined FuncVarEval into FunctionEval. Simplified selection of free ref functions. git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@805088 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/ExternalFunction.java b/src/java/org/apache/poi/hssf/record/formula/eval/ExternalFunction.java deleted file mode 100755 index d4d6de6a6d..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/eval/ExternalFunction.java +++ /dev/null @@ -1,84 +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.eval; - -import org.apache.poi.hssf.record.formula.atp.AnalysisToolPak; -import org.apache.poi.hssf.record.formula.functions.FreeRefFunction; -import org.apache.poi.ss.formula.EvaluationWorkbook; -import org.apache.poi.ss.formula.eval.NotImplementedException; -/** - * - * Common entry point for all user-defined (non-built-in) functions (where - * AbstractFunctionPtg.field_2_fnc_index == 255) - * - * TODO rename to UserDefinedFunction - * @author Josh Micich - */ -final class ExternalFunction implements FreeRefFunction { - - public ValueEval evaluate(Eval[] args, EvaluationWorkbook workbook, - int srcCellSheet, int srcCellRow,int srcCellCol) { - - int nIncomingArgs = args.length; - if(nIncomingArgs < 1) { - throw new RuntimeException("function name argument missing"); - } - - Eval nameArg = args[0]; - FreeRefFunction targetFunc; - if (nameArg instanceof NameEval) { - targetFunc = findInternalUserDefinedFunction((NameEval) nameArg); - } else if (nameArg instanceof NameXEval) { - targetFunc = findExternalUserDefinedFunction(workbook, (NameXEval) nameArg); - } else { - throw new RuntimeException("First argument should be a NameEval, but got (" - + nameArg.getClass().getName() + ")"); - } - int nOutGoingArgs = nIncomingArgs -1; - Eval[] outGoingArgs = new Eval[nOutGoingArgs]; - System.arraycopy(args, 1, outGoingArgs, 0, nOutGoingArgs); - return targetFunc.evaluate(outGoingArgs, workbook, srcCellSheet, srcCellRow, srcCellCol); - } - - private static FreeRefFunction findExternalUserDefinedFunction(EvaluationWorkbook workbook, - NameXEval n) { - String functionName = workbook.resolveNameXText(n.getPtg()); - - if(false) { - System.out.println("received call to external user defined function (" + functionName + ")"); - } - // currently only looking for functions from the 'Analysis TookPak' e.g. "YEARFRAC" or "ISEVEN" - // not sure how much this logic would need to change to support other or multiple add-ins. - FreeRefFunction result = AnalysisToolPak.findFunction(functionName); - if (result != null) { - return result; - } - throw new NotImplementedException(functionName); - } - - private static FreeRefFunction findInternalUserDefinedFunction(NameEval functionNameEval) { - - String functionName = functionNameEval.getFunctionName(); - if(false) { - System.out.println("received call to internal user defined function (" + functionName + ")"); - } - // TODO find the implementation for the user defined function - - throw new NotImplementedException(functionName); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/FuncVarEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/FuncVarEval.java deleted file mode 100644 index 76cfe7bb61..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/eval/FuncVarEval.java +++ /dev/null @@ -1,51 +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.eval; - -import org.apache.poi.hssf.record.formula.AbstractFunctionPtg; -import org.apache.poi.hssf.record.formula.functions.Function; -import org.apache.poi.ss.formula.eval.NotImplementedException; - -/** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - * - */ -public final class FuncVarEval extends FunctionEval { - - private AbstractFunctionPtg delegate; - - public FuncVarEval(AbstractFunctionPtg funcPtg) { - delegate = funcPtg; - } - - public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { - Function f = getFunction(); - if (f == null) { - throw new NotImplementedException("FuncIx=" + getFunctionIndex()); - } - return f.evaluate(operands, srcRow, srcCol); - } - - public int getNumberOfOperands() { - return delegate.getNumberOfOperands(); - } - - public short getFunctionIndex() { - return delegate.getFunctionIndex(); - } -} 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 3b74cc9a95..93f1a7624a 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 @@ -17,17 +17,16 @@ package org.apache.poi.hssf.record.formula.eval; -import java.util.HashMap; -import java.util.Map; - +import org.apache.poi.hssf.record.formula.AbstractFunctionPtg; import org.apache.poi.hssf.record.formula.function.FunctionMetadata; import org.apache.poi.hssf.record.formula.function.FunctionMetadataRegistry; import org.apache.poi.hssf.record.formula.functions.*; +import org.apache.poi.ss.formula.eval.NotImplementedException; /** * @author Amol S. Deshmukh < amolweb at ya hoo dot com > */ -public abstract class FunctionEval implements OperationEval { +public final class FunctionEval implements OperationEval { /** * Some function IDs that require special treatment */ @@ -44,35 +43,27 @@ public abstract class FunctionEval implements OperationEval { // convenient access to namespace private static final FunctionID ID = null; - protected static final Function[] functions ; - - private static Map freeRefFunctionsByIdMap; - - static { - Map m = new HashMap(); - m.put(createFRFKey(ID.INDIRECT), new Indirect()); - m.put(createFRFKey(ID.EXTERNAL_FUNC), new ExternalFunction()); - freeRefFunctionsByIdMap = m; - functions = produceFunctions(); - } - private static Integer createFRFKey(int functionIndex) { - return new Integer(functionIndex); - } + protected static final Function[] functions = produceFunctions(); - public Function getFunction() { + /** + * @return null if specified function + */ + private Function getFunction() { short fidx = getFunctionIndex(); return functions[fidx]; } public boolean isFreeRefFunction() { - return freeRefFunctionsByIdMap.containsKey(createFRFKey(getFunctionIndex())); + return getFreeRefFunction() != null; } public FreeRefFunction getFreeRefFunction() { - return freeRefFunctionsByIdMap.get(createFRFKey(getFunctionIndex())); + switch (getFunctionIndex()) { + case FunctionID.INDIRECT: return Indirect.instance; + case FunctionID.EXTERNAL_FUNC: return UserDefinedFunction.instance; + } + return null; } - public abstract short getFunctionIndex(); - private static Function[] produceFunctions() { Function[] retval = new Function[368]; @@ -245,4 +236,26 @@ public abstract class FunctionEval implements OperationEval { } return retval; } + + private AbstractFunctionPtg _delegate; + + public FunctionEval(AbstractFunctionPtg funcPtg) { + _delegate = funcPtg; + } + + public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { + Function f = getFunction(); + if (f == null) { + throw new NotImplementedException("FuncIx=" + getFunctionIndex()); + } + return f.evaluate(operands, srcRow, srcCol); + } + + public int getNumberOfOperands() { + return _delegate.getNumberOfOperands(); + } + + private short getFunctionIndex() { + return _delegate.getFunctionIndex(); + } } diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/UserDefinedFunction.java b/src/java/org/apache/poi/hssf/record/formula/eval/UserDefinedFunction.java new file mode 100755 index 0000000000..4e32d98891 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/eval/UserDefinedFunction.java @@ -0,0 +1,89 @@ +/* ==================================================================== + 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.atp.AnalysisToolPak; +import org.apache.poi.hssf.record.formula.functions.FreeRefFunction; +import org.apache.poi.ss.formula.EvaluationWorkbook; +import org.apache.poi.ss.formula.eval.NotImplementedException; +/** + * + * Common entry point for all user-defined (non-built-in) functions (where + * AbstractFunctionPtg.field_2_fnc_index == 255) + * + * @author Josh Micich + */ +final class UserDefinedFunction implements FreeRefFunction { + + public static final FreeRefFunction instance = new UserDefinedFunction(); + + private UserDefinedFunction() { + // enforce singleton + } + + public ValueEval evaluate(Eval[] args, EvaluationWorkbook workbook, + int srcCellSheet, int srcCellRow,int srcCellCol) { + + int nIncomingArgs = args.length; + if(nIncomingArgs < 1) { + throw new RuntimeException("function name argument missing"); + } + + Eval nameArg = args[0]; + FreeRefFunction targetFunc; + if (nameArg instanceof NameEval) { + targetFunc = findInternalUserDefinedFunction((NameEval) nameArg); + } else if (nameArg instanceof NameXEval) { + targetFunc = findExternalUserDefinedFunction(workbook, (NameXEval) nameArg); + } else { + throw new RuntimeException("First argument should be a NameEval, but got (" + + nameArg.getClass().getName() + ")"); + } + int nOutGoingArgs = nIncomingArgs -1; + Eval[] outGoingArgs = new Eval[nOutGoingArgs]; + System.arraycopy(args, 1, outGoingArgs, 0, nOutGoingArgs); + return targetFunc.evaluate(outGoingArgs, workbook, srcCellSheet, srcCellRow, srcCellCol); + } + + private static FreeRefFunction findExternalUserDefinedFunction(EvaluationWorkbook workbook, + NameXEval n) { + String functionName = workbook.resolveNameXText(n.getPtg()); + + if(false) { + System.out.println("received call to external user defined function (" + functionName + ")"); + } + // currently only looking for functions from the 'Analysis TookPak' e.g. "YEARFRAC" or "ISEVEN" + // not sure how much this logic would need to change to support other or multiple add-ins. + FreeRefFunction result = AnalysisToolPak.findFunction(functionName); + if (result != null) { + return result; + } + throw new NotImplementedException(functionName); + } + + private static FreeRefFunction findInternalUserDefinedFunction(NameEval functionNameEval) { + + String functionName = functionNameEval.getFunctionName(); + if(false) { + System.out.println("received call to internal user defined function (" + functionName + ")"); + } + // TODO find the implementation for the user defined function + + throw new NotImplementedException(functionName); + } +} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Indirect.java b/src/java/org/apache/poi/hssf/record/formula/functions/Indirect.java index 4640a099a2..11a4c46cc7 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Indirect.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Indirect.java @@ -40,6 +40,12 @@ import org.apache.poi.ss.formula.eval.NotImplementedException; */ public final class Indirect implements FreeRefFunction { + public static final FreeRefFunction instance = new Indirect(); + + private Indirect() { + // enforce singleton + } + public ValueEval evaluate(Eval[] args, EvaluationWorkbook workbook, int srcCellSheet, int srcCellRow, int srcCellCol) { // TODO - implement INDIRECT() throw new NotImplementedException("INDIRECT"); diff --git a/src/java/org/apache/poi/ss/formula/OperationEvaluatorFactory.java b/src/java/org/apache/poi/ss/formula/OperationEvaluatorFactory.java index 22e1b1cb9a..c98ed3277a 100755 --- a/src/java/org/apache/poi/ss/formula/OperationEvaluatorFactory.java +++ b/src/java/org/apache/poi/ss/formula/OperationEvaluatorFactory.java @@ -20,12 +20,11 @@ package org.apache.poi.ss.formula; import java.util.HashMap; import java.util.Map; +import org.apache.poi.hssf.record.formula.AbstractFunctionPtg; import org.apache.poi.hssf.record.formula.AddPtg; import org.apache.poi.hssf.record.formula.ConcatPtg; import org.apache.poi.hssf.record.formula.DividePtg; import org.apache.poi.hssf.record.formula.EqualPtg; -import org.apache.poi.hssf.record.formula.FuncPtg; -import org.apache.poi.hssf.record.formula.FuncVarPtg; import org.apache.poi.hssf.record.formula.GreaterEqualPtg; import org.apache.poi.hssf.record.formula.GreaterThanPtg; import org.apache.poi.hssf.record.formula.LessEqualPtg; @@ -44,7 +43,7 @@ import org.apache.poi.hssf.record.formula.eval.AddEval; import org.apache.poi.hssf.record.formula.eval.ConcatEval; import org.apache.poi.hssf.record.formula.eval.DivideEval; import org.apache.poi.hssf.record.formula.eval.EqualEval; -import org.apache.poi.hssf.record.formula.eval.FuncVarEval; +import org.apache.poi.hssf.record.formula.eval.FunctionEval; import org.apache.poi.hssf.record.formula.eval.GreaterEqualEval; import org.apache.poi.hssf.record.formula.eval.GreaterThanEval; import org.apache.poi.hssf.record.formula.eval.LessEqualEval; @@ -114,11 +113,8 @@ final class OperationEvaluatorFactory { return result; } - if (ptgClass == FuncPtg.class) { - return new FuncVarEval((FuncPtg)ptg); - } - if (ptgClass == FuncVarPtg.class) { - return new FuncVarEval((FuncVarPtg)ptg); + if (ptg instanceof AbstractFunctionPtg) { + return new FunctionEval((AbstractFunctionPtg)ptg); } throw new RuntimeException("Unexpected operation ptg class (" + ptgClass.getName() + ")"); }