/* * Copyright 2013 Guidewire Software, Inc. */ package gw.internal.gosu.parser; import gw.internal.gosu.parser.expressions.NewExpression; import gw.internal.gosu.parser.expressions.StringLiteral; import gw.internal.gosu.parser.expressions.TypeLiteral; import gw.lang.Param; import gw.lang.Throws; import gw.lang.reflect.IType; import gw.lang.reflect.TypeSystem; import gw.lang.reflect.gs.ICompilableType; import gw.lang.reflect.java.JavaTypes; import gw.util.GosuEscapeUtil; import java.io.Serializable; /** * Holds annotation information for a feature */ public class GosuDocAnnotation implements Serializable, IGosuAnnotation { private IType _type; private String[] _args; private volatile Expression _expression; private ICompilableType _ownersType; public GosuDocAnnotation( ICompilableType ownersType, IType type, String... args ) { _ownersType = ownersType; _type = type; _args = args; } public String getName() { return getType().getRelativeName(); } public IType getType() { return _type; } @Override public String getNewExpressionAsString() { return "new " + _type.getName() + "(" + makeArgsForNewExpression() + ")"; } @Override public Expression getExpression() { if( _expression == null ) { TypeSystem.lock(); try { if( _expression == null ) { NewExpression newExpression = initLocation( new NewExpression() ); newExpression.setType( _type ); if( _type.getName().equals( Throws.class.getName() ) ) { // throws starts with a type literal, then a string description newExpression.setConstructor( _type.getTypeInfo().getConstructor(JavaTypes.ITYPE(), JavaTypes.STRING() ) ); newExpression.setArgs( exprArray( new TypeLiteral( TypeSystem.getByFullName( _args[0] ) ), new StringLiteral( _args[1] ) ) ); } else if( _type.getName().equals( Param.class.getName() ) ) { // throws starts with a type literal newExpression.setConstructor( _type.getTypeInfo().getConstructor( JavaTypes.STRING(), JavaTypes.STRING() ) ); newExpression.setArgs( exprArray( new StringLiteral( _args[0] ), new StringLiteral( _args[1] ) ) ); } else { // a vanilla annotation newExpression.setConstructor( _type.getTypeInfo().getConstructor( JavaTypes.STRING() ) ); newExpression.setArgs( exprArray( new StringLiteral( _args[0] ) ) ); } _expression = newExpression; } } finally { TypeSystem.unlock(); } } return _expression; } @Override public void clearExpression() { _expression = null; } @Override public boolean shouldPersistToClass() { return false; } @Override public boolean shouldRetainAtRuntime() { return false; } @Override public ICompilableType getOwnersType() { return _ownersType; } private Expression[] exprArray( Expression... exprs ) { for( Expression expr : exprs ) { initLocation( expr ); } return exprs; } private <T extends ParsedElement> T initLocation( T pe ) { pe.setLocation( new ParseTree( pe, 0, 0, null ) ); return pe; } private String makeArgsForNewExpression() { StringBuilder sb = new StringBuilder(); for( int i = 0; i < _args.length; i++ ) { if( i != 0 ) { sb.append( "," ); } if( _type.getName().equals( Throws.class.getName() ) && i == 0 ) { sb.append( _args[i] ); } else { // make a string literal for everything else sb.append( "\"" ).append( GosuEscapeUtil.escapeForGosuStringLiteral( _args[i] ) ).append( "\"" ); } } return sb.toString(); } }