/* * Copyright 2013 Guidewire Software, Inc. */ package gw.internal.gosu.template; import gw.internal.gosu.parser.CompiledGosuClassSymbolTable; import gw.internal.gosu.parser.Symbol; import gw.lang.parser.ISymbol; import gw.lang.parser.ISymbolTable; import gw.lang.parser.StandardSymbolTable; import gw.lang.parser.template.ITemplateGenerator; import gw.lang.parser.template.ITemplateObserver; import gw.lang.parser.template.StringEscaper; import gw.lang.parser.template.TemplateParseException; import gw.lang.reflect.IType; import gw.lang.reflect.gs.ITemplateType; import gw.lang.reflect.java.JavaTypes; import gw.util.Stack; import java.io.StringWriter; import java.io.Writer; import java.util.List; /** * Template types forward to this for rendering */ public abstract class TemplateRenderer { static final ThreadLocal<Stack<ITemplateObserver>> OBSERVERS_STACK = new ThreadLocal<Stack<ITemplateObserver>>(); private static final ITemplateObserver BASIC_OBSERVER = new ITemplateObserver() { @Override public boolean beforeTemplateRender(IType type, Writer writer) { return true; } @Override public StringEscaper getEscaper() { return null; } @Override public void afterTemplateRender(IType type, Writer writer) { } }; public static void render( ITemplateType type, Writer writer, Object[] args ) { ISymbolTable symbolTable; symbolTable = new StandardSymbolTable(); ITemplateGenerator templateGenerator = type.getTemplateGenerator(); List<ISymbol> params = templateGenerator.getParameters(); if( args != null ) { for( int i = 0; i < args.length; i++ ) { symbolTable.putSymbol( new Symbol( params.get( i ).getName(), params.get( i ).getType(), args[i] ) ); } } if( symbolTable.getSymbol( "writer" ) == null ) { symbolTable.putSymbol( new Symbol( "writer", JavaTypes.getJreType( Writer.class ), writer ) ); } ITemplateObserver currentObserver = getCurrentObserver(); if (currentObserver.beforeTemplateRender(type, writer)) { CompiledGosuClassSymbolTable.instance().pushCompileTimeSymbolTable( symbolTable ); try { templateGenerator.execute( writer, currentObserver.getEscaper(), CompiledGosuClassSymbolTable.instance() ); } catch( TemplateParseException e ) { throw new RuntimeException( e ); } finally { CompiledGosuClassSymbolTable.instance().popCompileTimeSymbolTable(); } currentObserver.afterTemplateRender(type, writer); } } protected static String renderToString( ITemplateType type, Object... args ) { ISymbolTable symbolTable; symbolTable = new StandardSymbolTable(); ITemplateGenerator templateGenerator = type.getTemplateGenerator(); List<ISymbol> params = templateGenerator.getParameters(); if( args != null ) { for( int i = 0; i < args.length; i++ ) { symbolTable.putSymbol( new Symbol( params.get( i ).getName(), params.get( i ).getType(), args[i] ) ); } } StringWriter writer = new StringWriter(); if( symbolTable.getSymbol( "writer" ) == null ) { symbolTable.putSymbol( new Symbol( "writer", JavaTypes.getJreType( Writer.class ), writer ) ); } ITemplateObserver currentObserver = getCurrentObserver(); if (currentObserver.beforeTemplateRender(type, writer)) { CompiledGosuClassSymbolTable.instance().pushCompileTimeSymbolTable( symbolTable ); try { type.getTemplateGenerator().execute( writer, currentObserver.getEscaper(), CompiledGosuClassSymbolTable.instance() ); } catch( TemplateParseException e ) { throw new RuntimeException( e ); } finally { CompiledGosuClassSymbolTable.instance().popCompileTimeSymbolTable(); } currentObserver.afterTemplateRender(type, writer); } return writer.toString(); } public static ITemplateObserver getCurrentObserver() { Stack<ITemplateObserver> iTemplateObserverStack = OBSERVERS_STACK.get(); if (iTemplateObserverStack == null || iTemplateObserverStack.size() == 0) { return BASIC_OBSERVER; } else { return iTemplateObserverStack.peek(); } } public static void pushTemplateObserver(ITemplateObserver observer) { Stack<ITemplateObserver> iTemplateObserverStack = OBSERVERS_STACK.get(); if (iTemplateObserverStack == null) { iTemplateObserverStack = new Stack<ITemplateObserver>(); OBSERVERS_STACK.set(iTemplateObserverStack); } iTemplateObserverStack.push(observer); } public static void popTemplateObserver() { Stack<ITemplateObserver> iTemplateObserverStack = OBSERVERS_STACK.get(); if (iTemplateObserverStack == null) { iTemplateObserverStack = new Stack<ITemplateObserver>(); OBSERVERS_STACK.set(iTemplateObserverStack); } iTemplateObserverStack.pop(); } }