/******************************************************************************* * Copyright (c) 2004, 2012 BREDEX GmbH. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * BREDEX GmbH - initial API and implementation and/or initial documentation *******************************************************************************/ package org.eclipse.jubula.client.core.utils; import java.util.ArrayList; import java.util.List; import org.eclipse.jubula.client.core.functions.AbstractFunctionEvaluator; import org.eclipse.jubula.client.core.functions.FunctionContext; import org.eclipse.jubula.client.core.functions.FunctionDefinition; import org.eclipse.jubula.client.core.functions.FunctionRegistry; import org.eclipse.jubula.client.core.functions.IFunctionEvaluator; import org.eclipse.jubula.client.core.i18n.Messages; import org.eclipse.jubula.client.core.model.IExecTestCasePO; import org.eclipse.jubula.client.core.model.INodePO; import org.eclipse.jubula.client.core.model.IParamDescriptionPO; import org.eclipse.jubula.client.core.utils.ParamValueConverter.ConvValidationState; import org.eclipse.jubula.tools.internal.exception.InvalidDataException; import org.eclipse.jubula.tools.internal.messagehandling.MessageIDs; import org.eclipse.osgi.util.NLS; /** * Token that represents a function call. */ public class FunctionToken extends AbstractParamValueToken implements INestableParamValueToken { /** the tokens comprising the function arguments */ private IParamValueToken[] m_argTokens; /** the string at the beginning of the function : ?<name>(*/ private String m_prefix; /** the string at the end of the function : ) */ private String m_suffix; /** the name of the called Function */ private String m_functionName; /** * Constructor * * @param s the entire token * @param functionPrefix the text at the beginning of the token * @param functionSuffix the text at the end of the token * @param pos index of first character of token in entire string * @param desc param description belonging to currently edited parameter value * @param functionName the name of the called Function * @param argTokens the tokens that comprise the arguments for the function */ public FunctionToken(String s, String functionPrefix, String functionSuffix, int pos, IParamDescriptionPO desc, String functionName, IParamValueToken[] argTokens) { super(s, pos, desc); m_argTokens = argTokens; m_prefix = functionPrefix; m_suffix = functionSuffix; m_functionName = functionName; } /** * * {@inheritDoc} */ public ConvValidationState validate() { FunctionDefinition function = FunctionRegistry.getInstance().getFunction(m_functionName); if (function == null) { setErrorKey(MessageIDs.E_FUNCTION_NOT_REGISTERED); return ConvValidationState.invalid; } int paramCount = function.getParameters().length; boolean hasVarArgs = function.getVarArgs() != null; int argCount = getArgumentCount(); if ((!hasVarArgs && argCount != paramCount) || (hasVarArgs && argCount < paramCount)) { setErrorKey(MessageIDs.E_WRONG_NUM_FUNCTION_ARGS); return ConvValidationState.invalid; } ConvValidationState state = ConvValidationState.valid; Integer errorKey = null; for (IParamValueToken childToken : getNestedTokens()) { ConvValidationState childState = childToken.validate(); if (childState == ConvValidationState.invalid) { setErrorKey(childToken.getErrorKey()); return childState; } if (childState == ConvValidationState.undecided) { state = childState; errorKey = childToken.getErrorKey(); } } setErrorKey(errorKey); return state; } /** * * {@inheritDoc} */ public String getExecutionString(List<ExecObject> stack) throws InvalidDataException { FunctionDefinition function = FunctionRegistry.getInstance().getFunction(m_functionName); if (function == null) { throw new InvalidDataException( NLS.bind(Messages.FunctionNotDefined, m_functionName), MessageIDs.E_NO_FUNCTION); } IFunctionEvaluator evaluator = function.getEvaluator(); if (evaluator instanceof AbstractFunctionEvaluator && stack.size() > 0) { AbstractFunctionEvaluator aEvaluator = (AbstractFunctionEvaluator) evaluator; ExecObject currentExecObject = getLastExecTCFromStack(stack); INodePO execNode = currentExecObject.getExecNode(); INodePO actualNode; int innerIndex = currentExecObject.getIndex(); if (innerIndex < 0) { actualNode = execNode; } else { actualNode = ((IExecTestCasePO) execNode) .getSpecTestCase().getUnmodifiableNodeList() .get(innerIndex); } aEvaluator.setContext(new FunctionContext(actualNode)); } List<String> argList = new ArrayList<String>(); StringBuilder argBuilder = new StringBuilder(); for (IParamValueToken argToken : getNestedTokens()) { if (argToken instanceof FunctionArgumentSeparatorToken) { argList.add(argBuilder.toString()); argBuilder.setLength(0); } else { argBuilder.append(argToken.getExecutionString(stack)); } } argList.add(argBuilder.toString()); try { return evaluator.evaluate( argList.toArray(new String[argList.size()])); } catch (Throwable t) { if (t instanceof InvalidDataException) { throw (InvalidDataException)t; } throw new InvalidDataException(t.getLocalizedMessage(), MessageIDs.E_FUNCTION_EVAL_ERROR); } } /** * Returns the last IExecTestCasePO from the stack * @param stack the stack * @return the last ExecTestCasePO (or null if none exists) */ private ExecObject getLastExecTCFromStack(List<ExecObject> stack) { ExecObject currentExecObject = null; int posInStack = stack.size(); do { posInStack--; currentExecObject = stack.get(posInStack); } while (!(currentExecObject.getExecNode() instanceof IExecTestCasePO) && posInStack > 0); return currentExecObject; } /** * * {@inheritDoc} */ public String getGuiString() { StringBuilder guiStringBuilder = new StringBuilder(); guiStringBuilder.append(m_prefix); for (IParamValueToken nestedToken : getNestedTokens()) { guiStringBuilder.append(nestedToken.getGuiString()); } guiStringBuilder.append(m_suffix); return guiStringBuilder.toString(); } /** * * {@inheritDoc} */ public String getModelString() { StringBuilder modelStringBuilder = new StringBuilder(); modelStringBuilder.append(m_prefix); for (IParamValueToken nestedToken : getNestedTokens()) { modelStringBuilder.append(nestedToken.getModelString()); } modelStringBuilder.append(m_suffix); return modelStringBuilder.toString(); } /** * * {@inheritDoc} */ public IParamValueToken[] getNestedTokens() { return m_argTokens; } /** * * @return the number of arguments entered for this Function. */ private int getArgumentCount() { if (m_argTokens.length == 0) { return 0; } int argCount = 1; for (IParamValueToken token : m_argTokens) { if (token instanceof FunctionArgumentSeparatorToken) { argCount++; } } return argCount; } /** * @return the arguments */ public IParamValueToken[] getArguments() { return m_argTokens; } /** * @return the function name */ public String getFunctionName() { return m_functionName; } }