/* * Copyright 2013 Guidewire Software, Inc. */ package gw.internal.gosu.parser; import gw.lang.parser.IDynamicFunctionSymbol; import gw.lang.parser.IReducedDynamicFunctionSymbol; import gw.lang.parser.IReducedSymbol; import gw.lang.parser.ISymbol; import gw.lang.reflect.IAttributedFeatureInfo; import gw.lang.reflect.IConstructorInfo; import gw.lang.reflect.IDFSBackedFeatureInfo; import gw.lang.reflect.IMethodInfo; import gw.lang.reflect.IModifierInfo; import gw.lang.reflect.IRelativeTypeInfo; import gw.lang.reflect.IType; import gw.lang.reflect.ITypeInfo; import gw.lang.reflect.gs.IGosuClass; import gw.lang.reflect.gs.IGosuProgram; import gw.lang.reflect.gs.IProgramInstance; import gw.util.GosuExceptionUtil; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** */ public class ReducedDynamicFunctionSymbol extends ReducedSymbol implements IReducedDynamicFunctionSymbol { private IType[] _argTypes; private IType _returnType; private List<IReducedSymbol> _args; private IReducedDynamicFunctionSymbol _superDfs; private final boolean _isConstructor; ReducedDynamicFunctionSymbol(DynamicFunctionSymbol dfs) { super( dfs ); _isConstructor = dfs.isConstructor(); _argTypes = dfs.getArgTypes(); _returnType = dfs.getReturnType(); _args = makeArgs(dfs); _fullDescription = dfs.getFullDescription(); DynamicFunctionSymbol superDfs = dfs.getSuperDfs(); if (superDfs != null) { _superDfs = superDfs.createReducedSymbol(); } } private List<IReducedSymbol> makeArgs(IDynamicFunctionSymbol dfs) { List<ISymbol> args = dfs.getArgs(); List<IReducedSymbol> newArgs = new ArrayList<IReducedSymbol>(args.size()); for (ISymbol arg : args) { newArgs.add( arg.createReducedSymbol() ); } return newArgs; } @Override public IType[] getArgTypes() { return _argTypes; } @Override public IType getReturnType() { return _returnType; } @Override public String getFullDescription() { return _fullDescription; } @Override public List<IReducedSymbol> getArgs() { return _args; } @Override public IReducedDynamicFunctionSymbol getSuperDfs() { return _superDfs; } @Override public boolean isSuperOrThisConstructor() { return SuperConstructorFunctionSymbol.class.isAssignableFrom(getSymbolClass()) || ThisConstructorFunctionSymbol.class.isAssignableFrom(getSymbolClass()); } @Override public IReducedDynamicFunctionSymbol getBackingDfs() { return this; } @Override public IAttributedFeatureInfo getMethodOrConstructorInfo() { IGosuClass declaringType = getGosuClass(); if( declaringType == null ) { return null; } ITypeInfo typeInfo = declaringType.getTypeInfo(); List<? extends IMethodInfo> methods; if (typeInfo instanceof IRelativeTypeInfo) { methods = ((IRelativeTypeInfo) typeInfo).getMethods( declaringType ); } else { methods = typeInfo.getMethods(); } for( IMethodInfo mi : methods ) { if (mi instanceof IDFSBackedFeatureInfo) { IReducedDynamicFunctionSymbol dfs = ((IDFSBackedFeatureInfo) mi).getDfs(); if (this.equals(dfs) || getBackingDfs().equals(dfs)) { return mi; } } } List<? extends IConstructorInfo> ctors; if (typeInfo instanceof IRelativeTypeInfo) { ctors = ((IRelativeTypeInfo)typeInfo).getConstructors( declaringType ); } else { ctors = typeInfo.getConstructors(); } for( IConstructorInfo ci : ctors ) { if (ci instanceof IDFSBackedFeatureInfo) { IReducedDynamicFunctionSymbol dfs = ((IDFSBackedFeatureInfo) ci).getDfs(); if (this.equals(dfs) || getBackingDfs().equals(dfs)) { return ci; } else if (((this instanceof ReducedSuperConstructorFunctionSymbol) || (this instanceof ReducedThisConstructorFunctionSymbol)) && (dfs.getArgs().equals(getArgs()))) { return ci; } } } return null; } @Override public int hashCode() { return getName().hashCode(); } public boolean equals( Object o ) { if( this == o ) { return true; } if( o == null || !(o instanceof ReducedDynamicFunctionSymbol)) { return false; } ReducedDynamicFunctionSymbol that = (ReducedDynamicFunctionSymbol)o; String strName = getName(); return !(strName != null ? !strName.equals( that.getName() ) : that.getName() != null); } /** * Invokes the dynamic function. */ public Object invoke( Object[] args ) { return invokeFromBytecode(args); } private Object invokeFromBytecode( Object[] args ) { IGosuClassInternal gsClass = getGosuClass(); if( gsClass == null ) { throw new IllegalStateException( "Did not find Gosu Class/Program" ); } Class<?> javaClass = gsClass.getBackingClass(); IProgramInstance instance = null; if( gsClass instanceof IGosuProgram) { try { instance = (IProgramInstance)javaClass.newInstance(); instance.evaluate(null); } catch( Exception e ) { throw GosuExceptionUtil.forceThrow(e); } } IMethodInfo mi = gsClass.getTypeInfo().getMethod(gsClass, getDisplayName(), getArgTypes()); return mi.getCallHandler().handleCall( instance, args ); } public List<IGosuAnnotation> getAnnotations() { List<IGosuAnnotation> result; IAttributedFeatureInfo featureInfo = getMethodOrConstructorInfo(); if (featureInfo instanceof GosuBaseAttributedFeatureInfo) { IModifierInfo modifierInfo = ((GosuClassTypeInfo)getGosuClass().getTypeInfo()).getModifierInfo((GosuBaseAttributedFeatureInfo) featureInfo); result = modifierInfo != null ? modifierInfo.getAnnotations() : Collections.<IGosuAnnotation>emptyList(); } else { result = Collections.emptyList(); } return result; } public boolean isVarPropertyGet() { return VarPropertyGetFunctionSymbol.class.isAssignableFrom(getSymbolClass()); } public boolean isVarPropertySet() { return VarPropertySetFunctionSymbol.class.isAssignableFrom(getSymbolClass()); } public boolean isConstructor() { return _isConstructor; } }