156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson/* 256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Copyright (C) 2010 Google Inc. 356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * 456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Licensed under the Apache License, Version 2.0 (the "License"); 556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * you may not use this file except in compliance with the License. 656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * You may obtain a copy of the License at 756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * 856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * http://www.apache.org/licenses/LICENSE-2.0 956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * 1056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Unless required by applicable law or agreed to in writing, software 1156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * distributed under the License is distributed on an "AS IS" BASIS, 1256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * See the License for the specific language governing permissions and 1456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * limitations under the License. 1556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 1656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 1756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonpackage com.google.clearsilver.jsilver.compiler; 1856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 1956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.autoescape.AutoEscapeOptions; 2056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.autoescape.EscapeMode; 2156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.data.Data; 2256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.data.DataContext; 2356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.data.DefaultDataContext; 2456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.data.TypeConverter; 2556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.exceptions.ExceptionUtil; 2656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.exceptions.JSilverInterpreterException; 2756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.functions.FunctionExecutor; 2856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.resourceloader.ResourceLoader; 2956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.template.DefaultRenderingContext; 3056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.template.Macro; 3156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.template.RenderingContext; 3256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.template.Template; 3356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.template.TemplateLoader; 3456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.values.Value; 3556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 3656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport java.io.IOException; 3756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport java.util.Collections; 3856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 3956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson/** 4056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Base class providing help to generated templates. 4156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * 4256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Note, many of the methods are public as they are also used by macros. 4356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 4456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonpublic abstract class BaseCompiledTemplate implements Template { 4556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 4656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson private FunctionExecutor functionExecutor; 4756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson private String templateName; 4856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson private TemplateLoader templateLoader; 4956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson private EscapeMode escapeMode = EscapeMode.ESCAPE_NONE; 5056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson private AutoEscapeOptions autoEscapeOptions; 5156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 5256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void setFunctionExecutor(FunctionExecutor functionExecutor) { 5356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson this.functionExecutor = functionExecutor; 5456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 5556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 5656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void setTemplateName(String templateName) { 5756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson this.templateName = templateName; 5856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 5956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 6056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void setTemplateLoader(TemplateLoader templateLoader) { 6156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson this.templateLoader = templateLoader; 6256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 6356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 6456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson /** 6556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Set auto escaping options so they can be passed to the rendering context. 6656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * 6756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * @see AutoEscapeOptions 6856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 6956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void setAutoEscapeOptions(AutoEscapeOptions autoEscapeOptions) { 7056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson this.autoEscapeOptions = autoEscapeOptions; 7156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 7256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 7356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 7456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void render(Data data, Appendable out, ResourceLoader resourceLoader) throws IOException { 7556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 7656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson render(createRenderingContext(data, out, resourceLoader)); 7756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 7856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 7956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 8056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public RenderingContext createRenderingContext(Data data, Appendable out, 8156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson ResourceLoader resourceLoader) { 8256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson DataContext dataContext = new DefaultDataContext(data); 8356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return new DefaultRenderingContext(dataContext, resourceLoader, out, functionExecutor, 8456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson autoEscapeOptions); 8556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 8656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 8756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 8856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public String getTemplateName() { 8956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return templateName; 9056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 9156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 9256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson /** 9356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Sets the EscapeMode in which this template was generated. 9456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * 9556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * @param mode EscapeMode 9656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 9756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void setEscapeMode(EscapeMode mode) { 9856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson this.escapeMode = mode; 9956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 10056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 10156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 10256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public EscapeMode getEscapeMode() { 10356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return escapeMode; 10456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 10556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 10656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 10756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public String getDisplayName() { 10856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return templateName; 10956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 11056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 11156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson /** 11256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Verify that the loop arguments are valid. If not, we will skip the loop. 11356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 11456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public static boolean validateLoopArgs(int start, int end, int increment) { 11556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (increment == 0) { 11656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return false; // No increment. Avoid infinite loop. 11756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 11856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (increment > 0 && start > end) { 11956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return false; // Incrementing the wrong way. Avoid infinite loop. 12056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 12156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (increment < 0 && start < end) { 12256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return false; // Incrementing the wrong way. Avoid infinite loop. 12356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 12456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return true; 12556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 12656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 12756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 12856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public static boolean exists(Data data) { 12956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return TypeConverter.exists(data); 13056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 13156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 13256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public static int asInt(String value) { 13356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return TypeConverter.asNumber(value); 13456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 13556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 13656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public static int asInt(int value) { 13756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return value; 13856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 13956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 14056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public static int asInt(boolean value) { 14156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return value ? 1 : 0; 14256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 14356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 14456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public static int asInt(Value value) { 14556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return value.asNumber(); 14656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 14756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 14856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public static int asInt(Data data) { 14956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return TypeConverter.asNumber(data); 15056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 15156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 15256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public static String asString(String value) { 15356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return value; 15456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 15556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 15656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public static String asString(int value) { 15756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return Integer.toString(value); 15856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 15956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 16056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public static String asString(boolean value) { 16156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return value ? "1" : "0"; 16256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 16356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 16456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public static String asString(Value value) { 16556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return value.asString(); 16656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 16756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 16856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public static String asString(Data data) { 16956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return TypeConverter.asString(data); 17056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 17156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 17256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public static Value asValue(String value) { 17356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson // Compiler mode does not use the Value's escapeMode or partiallyEscaped 17456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson // variables. TemplateTranslator uses other means to determine the proper 17556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson // escaping to apply. So just set the default escaping flags here. 17656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return Value.literalValue(value, EscapeMode.ESCAPE_NONE, false); 17756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 17856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 17956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public static Value asValue(int value) { 18056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson // Compiler mode does not use the Value's escapeMode or partiallyEscaped 18156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson // variables. TemplateTranslator uses other means to determine the proper 18256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson // escaping to apply. So just set the default escaping flags here. 18356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return Value.literalValue(value, EscapeMode.ESCAPE_NONE, false); 18456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 18556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 18656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public static Value asValue(boolean value) { 18756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson // Compiler mode does not use the Value's escapeMode or partiallyEscaped 18856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson // variables. TemplateTranslator uses other means to determine the proper 18956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson // escaping to apply. So just set the default escaping flags here. 19056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return Value.literalValue(value, EscapeMode.ESCAPE_NONE, false); 19156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 19256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 19356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public static Value asValue(Value value) { 19456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return value; 19556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 19656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 19756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public static Value asVariableValue(String variableName, DataContext context) { 19856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return Value.variableValue(variableName, context); 19956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 20056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 20156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public static boolean asBoolean(boolean value) { 20256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return value; 20356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 20456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 20556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public static boolean asBoolean(String value) { 20656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return TypeConverter.asBoolean(value); 20756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 20856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 20956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public static boolean asBoolean(int value) { 21056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return value != 0; 21156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 21256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 21356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public static boolean asBoolean(Value value) { 21456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return value.asBoolean(); 21556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 21656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 21756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public static boolean asBoolean(Data data) { 21856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return TypeConverter.asBoolean(data); 21956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 22056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 22156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson /** 22256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Gets the name of the node for writing. Used by cs name command. Returns empty string if not 22356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * found. 22456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 22556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public static String getNodeName(Data data) { 22656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return data == null ? "" : data.getSymlink().getName(); 22756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 22856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 22956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson /** 23056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Returns child nodes of parent. Parent may be null, in which case an empty iterable is returned. 23156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 23256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public Iterable<? extends Data> getChildren(Data parent) { 23356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (parent == null) { 23456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return Collections.emptySet(); 23556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } else { 23656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return parent.getChildren(); 23756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 23856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 23956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 24056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson protected TemplateLoader getTemplateLoader() { 24156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return templateLoader; 24256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 24356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 24456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public abstract class CompiledMacro implements Macro { 24556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 24656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson private final String macroName; 24756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson private final String[] argumentsNames; 24856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 24956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson protected CompiledMacro(String macroName, String... argumentsNames) { 25056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson this.macroName = macroName; 25156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson this.argumentsNames = argumentsNames; 25256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 25356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 25456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 25556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void render(Data data, Appendable out, ResourceLoader resourceLoader) throws IOException { 25656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson render(createRenderingContext(data, out, resourceLoader)); 25756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 25856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 25956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 26056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public RenderingContext createRenderingContext(Data data, Appendable out, 26156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson ResourceLoader resourceLoader) { 26256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return BaseCompiledTemplate.this.createRenderingContext(data, out, resourceLoader); 26356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 26456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 26556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 26656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public String getTemplateName() { 26756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return BaseCompiledTemplate.this.getTemplateName(); 26856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 26956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 27056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 27156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public String getMacroName() { 27256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return macroName; 27356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 27456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 27556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 27656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public String getArgumentName(int index) { 27756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (index >= argumentsNames.length) { 27856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson // TODO: Make sure this behavior of failing if too many 27956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson // arguments are passed to a macro is consistent with JNI / interpreter. 28056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson throw new JSilverInterpreterException("Too many arguments supplied to macro " + macroName); 28156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 28256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return argumentsNames[index]; 28356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 28456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 28556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public int getArgumentCount() { 28656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return argumentsNames.length; 28756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 28856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 28956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson protected TemplateLoader getTemplateLoader() { 29056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return templateLoader; 29156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 29256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 29356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 29456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public EscapeMode getEscapeMode() { 29556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return BaseCompiledTemplate.this.getEscapeMode(); 29656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 29756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 29856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 29956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public String getDisplayName() { 30056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return BaseCompiledTemplate.this.getDisplayName() + ":" + macroName; 30156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 30256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 30356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 30456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson /** 30556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Code common to all three include commands. 30656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * 30756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * @param templateName String representing name of file to include. 30856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * @param ignoreMissingFile {@code true} if any FileNotFound error generated by the template 30956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * loader should be ignored, {@code false} otherwise. 31056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * @param context Rendering context to use for the included template. 31156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 31256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson protected void include(String templateName, boolean ignoreMissingFile, RenderingContext context) { 31356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (!context.pushIncludeStackEntry(templateName)) { 31456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson throw new JSilverInterpreterException(createIncludeLoopErrorMessage(templateName, context 31556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson .getIncludedTemplateNames())); 31656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 31756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 31856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson loadAndRenderIncludedTemplate(templateName, ignoreMissingFile, context); 31956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 32056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (!context.popIncludeStackEntry(templateName)) { 32156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson // Include stack trace is corrupted 32256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson throw new IllegalStateException("Unable to find on include stack: " + templateName); 32356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 32456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 32556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 32656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson // This method should ONLY be called from include() 32756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson private void loadAndRenderIncludedTemplate(String templateName, boolean ignoreMissingFile, 32856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson RenderingContext context) { 32956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson Template template = null; 33056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson try { 33156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson template = 33256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson templateLoader.load(templateName, context.getResourceLoader(), context 33356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson .getAutoEscapeMode()); 33456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } catch (RuntimeException e) { 33556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (ignoreMissingFile && ExceptionUtil.isFileNotFoundException(e)) { 33656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return; 33756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } else { 33856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson throw e; 33956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 34056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 34156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson // Intepret loaded template. 34256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson try { 34356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson template.render(context); 34456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } catch (IOException e) { 34556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson throw new JSilverInterpreterException(e.getMessage()); 34656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 34756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 34856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 34956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson private String createIncludeLoopErrorMessage(String templateName, Iterable<String> includeStack) { 35056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson StringBuilder message = new StringBuilder(); 35156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson message.append("File included twice: "); 35256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson message.append(templateName); 35356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 35456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson message.append(" Include stack:"); 35556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson for (String fileName : includeStack) { 35656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson message.append("\n -> "); 35756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson message.append(fileName); 35856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 35956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson message.append("\n -> "); 36056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson message.append(templateName); 36156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return message.toString(); 36256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 36356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson} 364