001/*
002 * Copyright (c) 2005 Einar Pehrson <einar@pehrson.nu>.
003 *
004 * This file is part of
005 * CleanSheets - a spreadsheet application for the Java platform.
006 *
007 * CleanSheets is free software; you can redistribute it and/or modify
008 * it under the terms of the GNU General Public License as published by
009 * the Free Software Foundation; either version 2 of the License, or
010 * (at your option) any later version.
011 *
012 * CleanSheets is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
015 * GNU General Public License for more details.
016 *
017 * You should have received a copy of the GNU General Public License
018 * along with CleanSheets; if not, write to the Free Software
019 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
020 */
021package csheets.core.formula.lang;
022
023import java.lang.reflect.InvocationTargetException;
024import java.lang.reflect.Method;
025
026import csheets.core.IllegalValueTypeException;
027import csheets.core.Value;
028import csheets.core.formula.Expression;
029import csheets.core.formula.Function;
030import csheets.core.formula.FunctionParameter;
031
032/**
033 * A numeric function that invokes a method object.
034 * @author Einar Pehrson
035 */
036public class NumericFunction implements Function {
037
038        /** The method that the function invokes */
039        private Method method;
040
041        /**
042         * Creates a new math reflection function.
043         */
044        public NumericFunction(Method method) {
045                this.method = method;
046        }
047
048        public String getIdentifier() {
049                return method.getName().toUpperCase();
050        }
051
052        public Value applyTo(Expression[] arguments) throws IllegalValueTypeException {
053                // Fetches values
054                double[] values = new double[arguments.length];
055                for (int i = 0; i < arguments.length; i++)
056                        values[i] = arguments[i].evaluate().toDouble();
057
058                // Invokes method
059                try {
060                        if (values.length == 0)
061                                return new Value((Number)method.invoke(null));
062                        else if (values.length == 1)
063                                return new Value((Number)method.invoke(null, values[0]));
064                        else if (values.length == 2)
065                                return new Value((Number)method.invoke(null, values[0], values[1]));
066                        else
067                                return new Value((Number)method.invoke(null, values[0], values[1], values[2]));
068                } catch (IllegalAccessException e) {
069                        return new Value(e);
070                } catch (IllegalArgumentException e) {
071                        return new Value(e);
072                } catch (InvocationTargetException e) {
073                        return new Value(e);
074                }
075        }
076
077        public FunctionParameter[] getParameters() {
078                Class[] paramTypes = method.getParameterTypes();
079                FunctionParameter[] params = new FunctionParameter[paramTypes.length];
080                for (int i = 0; i < paramTypes.length; i++)
081                        params[i] = new FunctionParameter(Value.Type.NUMERIC, "Parameter " + i, false, "Unknown");
082                return params;
083        }
084
085        public boolean isVarArg() {
086                return method.isVarArgs();
087        }
088}