/* * © Copyright FOCONIS AG, 2014 * * Licensed 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.openntf.formula.impl; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Collection; import org.openntf.formula.FormulaContext; import org.openntf.formula.FormulaReturnException; import org.openntf.formula.ValueHolder; import org.openntf.formula.ValueHolder.DataType; /** * This class does multi value handling for you * * @author Roland Praml, Foconis AG * */ public class AtFunctionSimple extends AtFunctionGeneric { public AtFunctionSimple(final String image, final Method method) { super(image, method); } @SuppressWarnings({ "unchecked", "deprecation" }) @Override public ValueHolder evaluate(final FormulaContext ctx, final ValueHolder[] params) throws FormulaReturnException { ValueHolder ret = null; Object result = null; // Errors cannt be used in a simple function. You must implement them as generic functions if (params != null) { for (int i = 0; i < params.length; i++) { if (params[i].dataType == DataType.ERROR) return params[i]; } } try { if (varArgClass != null) { Collection<Object[]> values = new ParameterCollectionObject<Object>(params, (Class<Object>) varArgClass, false); // Our last parameter is a "varArg" this means, the LAST parameter is an array[] Object[] tmpParams = new Object[paramCount]; for (Object[] value : values) { int i = 0; if (useContext) { tmpParams[i++] = ctx; } if (i == paramCount) { // that's not possible when useContext is true unless you specify FormulaContext... ctx } else if (i == paramCount - 1) { // exactly one parameter left. this is our vararg tmpParams[i++] = value; } result = method.invoke(null, tmpParams); if (result != null) { if (ret == null) { ret = ValueHolder.createValueHolder(result.getClass(), values.size()); } ret.add(result); } } } else { Collection<Object[]> values = new ParameterCollectionObject<Object>(params, Object.class, false); for (Object[] value : values) { if (useContext) { Object[] tmpParams; if (value == null) { tmpParams = new Object[1]; } else { tmpParams = new Object[value.length + 1]; System.arraycopy(value, 0, tmpParams, 1, value.length); } tmpParams[0] = ctx; result = method.invoke(null, tmpParams); } else { result = method.invoke(null, value); } if (result != null) { if (ret == null) { ret = ValueHolder.createValueHolder(result.getClass(), values.size()); } ret.add(result); } } } return ret; } catch (IllegalAccessException iax) { throw new RuntimeException("Unexpected error while invoking method " + method.getName(), iax); } catch (InvocationTargetException e) { if (e.getCause() instanceof RuntimeException) throw (RuntimeException) e.getCause(); if (e.getCause() instanceof FormulaReturnException) throw (FormulaReturnException) e.getCause(); throw new RuntimeException("Unexpected error occured in method " + method.getName(), e); } } @Override protected String getPrefix() { return method.getDeclaringClass().getSimpleName() + " [simple]"; } }