/* * Copyright 2013 Guidewire Software, Inc. */ package gw.internal.gosu.parser; import gw.internal.gosu.ir.nodes.IRMethodFactory; import gw.lang.ir.IRType; import gw.lang.parser.EvaluationException; import gw.lang.parser.IExpression; import gw.lang.parser.IReducedSymbol; import gw.lang.parser.exceptions.ErrantGosuClassException; import gw.lang.reflect.IConstructorHandler; import gw.lang.reflect.IFeatureInfo; import gw.lang.reflect.IType; import gw.lang.reflect.gs.IGenericTypeVariable; import gw.lang.reflect.gs.IGosuConstructorInfo; import gw.lang.reflect.java.GosuTypes; import gw.util.GosuExceptionUtil; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** */ public class GosuConstructorInfo extends AbstractGenericMethodInfo implements IGosuConstructorInfo { private IType _type; private IConstructorHandler _ctorHandler; public GosuConstructorInfo( IFeatureInfo container, DynamicFunctionSymbol dfs ) { super( container, dfs ); _type = getOwnersType(); } public IType getType() { return _type; } public IConstructorHandler getConstructor() { if( _ctorHandler == null ) { IGosuClassInternal gsClass = getGosuClass(); if( !gsClass.isValid() ) { throw new ErrantGosuClassException( gsClass ); } _ctorHandler = new GosuConstructorHandler(); } return _ctorHandler; } @Override public boolean isDefault() { ReducedDynamicFunctionSymbol dfs = getDfs(); return dfs.getType().equals(GosuTypes.DEF_CTOR_TYPE()); } @Override public IExpression[] getDefaultValueExpressions() { List<IExpression> defValues = new ArrayList<IExpression>(); for( IReducedSymbol s : getArgs() ) { IExpression defValue = s.getDefaultValueExpression(); defValues.add( defValue ); } return defValues.toArray( new IExpression[defValues.size()] ); } @Override public String[] getParameterNames() { List<String> names = new ArrayList<String>(); for( IReducedSymbol s : getArgs() ) { names.add( s.getName() ); } return names.toArray( new String[names.size()] ); } @Override public IGosuConstructorInfo getBackingConstructorInfo() { return this; } public class GosuConstructorHandler implements IConstructorHandler { public Object newInstance( Object... args ) { IGosuClassInternal gsClass = (IGosuClassInternal)getType(); if( !gsClass.isValid() ) { throw new EvaluationException( "Cannot construct an instance of " + gsClass.getName() + " because it has compile errors." ); } try { IGosuClassInternal type = getOwnersType(); if( type.isParameterizedType() ) { ArrayList<Object> argList = new ArrayList<Object>( Arrays.asList( getOwnersType().getTypeParameters() ) ); argList.addAll( Arrays.asList( args ) ); args = argList.toArray(); } else { if( type.isGenericType() ) { IGenericTypeVariable[] typeVariables = type.getGenericTypeVariables(); ArrayList<Object> argList = new ArrayList<Object>(); for( IGenericTypeVariable typeVariable : typeVariables ) { argList.add( typeVariable.getBoundingType() ); } argList.addAll( Arrays.asList( args ) ); args = argList.toArray( new Object[argList.size()] ); } } Class<?> aClass = getOwnersType().getBackingClass(); List<IRType> explicitParameterTypes = IRMethodFactory.createIRMethod( GosuConstructorInfo.this ).getAllParameterTypes(); Class[] paramClasses = new Class[explicitParameterTypes.size()]; for( int i = 0; i < explicitParameterTypes.size(); i++ ) { paramClasses[i] = explicitParameterTypes.get( i ).getJavaClass(); } Constructor<?> constructor = aClass.getDeclaredConstructor( paramClasses ); if( !constructor.isAccessible() ) { constructor.setAccessible( true ); } return constructor.newInstance( args ); } catch( InvocationTargetException e ) { throw GosuExceptionUtil.forceThrow( e.getTargetException() ); } catch( Throwable e ) { throw GosuExceptionUtil.forceThrow( e ); } } } }