/* * Copyright 2013 Guidewire Software, Inc. */ package gw.internal.gosu.parser.expressions; import gw.internal.gosu.parser.*; import gw.lang.parser.MemberAccessKind; import gw.lang.parser.IExpressionRuntime; import gw.lang.parser.expressions.IBeanMethodCallExpression; import gw.lang.reflect.*; import gw.lang.reflect.gs.IGosuClass; import gw.lang.reflect.gs.IGosuMethodInfo; import gw.lang.reflect.java.JavaTypes; /** * An expression representing a bean method call: * <pre> * <i>bean-method-call-expression</i> * <member-access> <b>(</b> [<argument-list>] <b>)</b> * <p/> * <i>member-access</i> * <root-expression>.<member> * <root-expression>*.<member> * <root-expression>[member-name] * <p/> * <i>root-expression</i> * <bean-reference> * <type-literal> * <p/> * <i>member</i> * <member-access> * <identifier> * <p/> * <i>bean-reference</i> * <primary-expression> * <p/> * <i>member-name</i> * <expression> * </pre> * * @see gw.lang.parser.IGosuParser */ public final class BeanMethodCallExpression extends Expression implements IBeanMethodCallExpression, IHasOperatorLineNumber { private Expression _rootExpression; private IType[] _argTypes; private String _accessPath; private Expression[] _args; private IMethodInfo _md; private IFunctionType _funcType; private MemberAccessKind _kind; private int[] _namedArgOrder; private int _iArgPos; /** * Start offset of array list (without leading '.') */ protected int _startOffset; private static final IType[] EMPTY_ARG_TYPES = new IType[0]; private IExpressionRuntime _expressionRuntime; private int _opLineNum; public IFunctionType getFunctionType() { return _funcType; } public void setFunctionType(IFunctionType funcType) { _funcType = funcType; } public Expression getRootExpression() { return _rootExpression; } public void setRootExpression(Expression rootExpression) { _rootExpression = rootExpression; } /** * @return An array of IIntrinsicITyperguments of the method call. */ public IType[] getArgTypes() { return _argTypes; } /** * @param argTypes An array of IIntrinsicType for the arguments of the method call. */ public void setArgTypes(IType[] argTypes) { _argTypes = argTypes.length == 0 ? EMPTY_ARG_TYPES : argTypes; } /** * @return A list of Strings representing the member access path. Note the * member access path for the expression Root.foo.bar() is {foo, bar}. */ public String getMemberName() { return _accessPath; } /** * @param accessPath A list of Strings representing the member access path. */ public void setAccessPath(String accessPath) { assert accessPath != null; _accessPath = StringCache.get(accessPath); } public String getAccessPath() { return _accessPath; } public int getStartOffset() { return _startOffset; } public void setExpressionRuntime(IExpressionRuntime expressionRuntime) { _expressionRuntime = expressionRuntime; } @Override public IPropertyInfo getPropertyInfo() { return null; //To change body of implemented methods use File | Settings | File Templates. } public IExpressionRuntime getExpressionRuntime() { return _expressionRuntime; } public void setStartOffset(int startOffset) { _startOffset = startOffset; } /** * @return An array of expressions for corresponding to the arguments in the * expression. */ public Expression[] getArgs() { return _args; } /** * @param args An array of expressions for corresponding to the arguments in * the expression. */ public void setArgs(Expression[] args) { _args = args == null || args.length == 0 ? null : args; } public int[] getNamedArgOrder() { return _namedArgOrder; } public void setNamedArgOrder( int[] namedArgOrder ) { _namedArgOrder = namedArgOrder; } public void setMethodDescriptor(IMethodInfo md) { _md = md; if (md != null) { IType type = JavaTypes.IGOSU_OBJECT(); if (_md.getOwnersType() == IGosuClassInternal.Util.getGosuClassFrom(type)) { _md = type.getTypeInfo().getMethod(_md.getDisplayName(), ((FunctionType) ((IGosuMethodInfo) _md).getDfs().getType()).getParameterTypes()); } } } public IMethodInfo getMethodDescriptor() { return _md; } public IMethodInfo getGenericMethodDescriptor() { if (_md instanceof GosuMethodInfo) { ReducedDynamicFunctionSymbol dfs = ((GosuMethodInfo) _md).getDfs(); if (dfs instanceof ReducedParameterizedDynamicFunctionSymbol) { return (IMethodInfo) ((ReducedParameterizedDynamicFunctionSymbol) dfs).getBackingDfs().getMethodOrConstructorInfo(); } } return _md; } /** */ public IType getRootType() { IType rootType = getRootExpression().getType(); rootType = IGosuClass.ProxyUtil.isProxy(rootType) && rootType instanceof IGosuClass ? ((IGosuClass) rootType).getJavaType() : rootType; return rootType; } public MemberAccessKind getMemberAccessKind() { return _kind; } public void setMemberAccessKind( MemberAccessKind kind ) { _kind = kind; } @Override public boolean isNullSafe() { return getMemberAccessKind() == MemberAccessKind.NULL_SAFE || isExpansion(); } public boolean isExpansion() { return _kind == MemberAccessKind.EXPANSION; } /** * Evaluates the bean method call. * * @return The value of the expression. */ public Object evaluate() { if (!isCompileTimeConstant() ) { return super.evaluate(); } throw new CannotExecuteGosuException(); } @Override public String toString() { String strOut = getRootExpression().toString(); if (_accessPath != null) { strOut += "." + _accessPath; } strOut += "("; if (_args != null && _args.length > 0) { strOut += " "; for (int i = 0; i < _args.length; i++) { if (i != 0) { strOut += ", "; } strOut += _args[i].toString(); } strOut += " "; } return strOut += ")"; } public int getArgPosition() { return _iArgPos; } public void setArgPosition(int iArgPos) { _iArgPos = iArgPos; } @Override public int getOperatorLineNumber() { return _opLineNum; } @Override public void setOperatorLineNumber( int operatorLineNumber ) { _opLineNum = operatorLineNumber; } }