001package io.jstach.jstachio; 002 003import java.nio.charset.Charset; 004import java.nio.charset.StandardCharsets; 005import java.util.function.Function; 006 007import org.eclipse.jdt.annotation.Nullable; 008 009import io.jstach.jstache.JStacheConfig; 010import io.jstach.jstache.JStacheContentType; 011import io.jstach.jstache.JStacheType; 012 013/** 014 * Template meta data like its location, formatters, escapers and or its contents. 015 * <p> 016 * This data is usually available on generated {@link Template}s. 017 * 018 * @author agentgt 019 */ 020public interface TemplateInfo { 021 022 /** 023 * The template instance is accessible to mustache templates with this global binding 024 * name. <strong>This is not bound if template is type 025 * {@link JStacheType#STACHE}.</strong> 026 */ 027 public static String TEMPLATE_BINDING_NAME = "@template"; 028 029 /** 030 * The logical name of the template which maybe different than 031 * {@link #templatePath()}. 032 * @return logical name of template. Never null. 033 */ 034 public String templateName(); 035 036 /** 037 * If the template is a classpath resource file this will return the location that was 038 * originally resolved via {@linkplain JStacheConfig config resolution}. 039 * @return the location of the template or empty if the template is inlined. 040 * @apiNote since the return is the original path resolved by the annotation processor 041 * it may return a path with a starting "/" and thus it is recommend you call 042 * {@link #normalizePath()} if you plan on loading the resource. 043 * 044 * @see #normalizePath() 045 */ 046 public String templatePath(); 047 048 /** 049 * Normalizes the path to used by {@link ClassLoader#getResource(String)}. 050 * 051 * If the templatePath starts with a "/" it is stripped. 052 * @return normalized path 053 */ 054 default String normalizePath() { 055 String p = templatePath(); 056 if (p.startsWith("/")) { 057 return p.substring(1); 058 } 059 return p; 060 } 061 062 /** 063 * The raw contents of the template. Useful if the template is inline. To determine if 064 * the template is actually inline use {@link #templateSource()}. 065 * @apiNote An empty or blank template string maybe a valid inline template and does 066 * not mean it is not inline. 067 * @return the raw contents of the template never null. 068 * @see TemplateSource 069 */ 070 default String templateString() { 071 return ""; 072 } 073 074 /** 075 * The template content type is the class annotated with {@link JStacheContentType} 076 * which also describes the escaper to be used. 077 * @apiNote The class returned must be annotated with {@link JStacheContentType}. 078 * @return the template content type. 079 */ 080 Class<?> templateContentType(); 081 082 /** 083 * The template {@link Charset} which is the original format of the template file and 084 * should ideally be used when encoding an HTTP response or similar. Furthermore 085 * ideally the template charset matches the chosen {@link #templateContentType()} 086 * {@link JStacheContentType#charsets()} otherwise the escaper may not appropriately 087 * escape. 088 * <p> 089 * IF the template is inline or charset was not set this will usually be 090 * {@link StandardCharsets#UTF_8}. 091 * @return the template Charset. 092 * @see JStacheContentType#charsets() 093 * @see JStacheConfig#charset() 094 */ 095 Charset templateCharset(); 096 097 /** 098 * The template media-type from the {@link JStacheContentType}. 099 * @return media type maybe an empty string. 100 */ 101 String templateMediaType(); 102 103 /** 104 * The escaper to be used on the template. See {@link Escaper#of(Function)}. 105 * @apiNote While the return signature is {@link Function} the function is often an 106 * {@link Escaper} but does not have to be. 107 * @return the escaper. 108 * @see Escaper 109 */ 110 Function<String, String> templateEscaper(); 111 112 /** 113 * The base formatter to be used on the template. See {@link Formatter#of(Function)}. 114 * @apiNote While the return signature is {@link Function} the function is often a 115 * {@link Formatter} but does not have to be. 116 * @return the formatter. 117 * @see Formatter 118 */ 119 @SuppressWarnings("exports") 120 Function<@Nullable Object, String> templateFormatter(); 121 122 /** 123 * Checks to see if a template supports the model class. 124 * @param type the class of the model. 125 * @return if this renderer supports the class. 126 */ 127 public boolean supportsType(Class<?> type); 128 129 /** 130 * Return the model class (root context class annotated with JStache) that generated 131 * this template. 132 * @return model class 133 */ 134 public Class<?> modelClass(); 135 136 /** 137 * Where the template contents were retrieved from. 138 * @return an enum never null. 139 */ 140 default TemplateSource templateSource() { 141 return templatePath().isEmpty() ? TemplateSource.STRING : TemplateSource.RESOURCE; 142 } 143 144 /** 145 * Symbols representing where the template was retrieved from. 146 * @author agentgt 147 */ 148 public enum TemplateSource { 149 150 /** 151 * Template was retrieved from the classpath at compile time. 152 */ 153 RESOURCE, 154 /** 155 * Template was inlined as a String literal 156 */ 157 STRING 158 159 } 160 161 /** 162 * The last loaded time if applicable. 163 * 164 * For statically compiled templates this will always be a negative number. For 165 * dynamically loaded templates this more likely will return a non negative number 166 * indicating some hint of when the template was last modified or loaded. 167 * @return the last modified or negative if not applicable 168 */ 169 default long lastLoaded() { 170 return -1; 171 } 172 173 /** 174 * Utility method similar to toString that describes the template meta data. 175 * @return description of the template. 176 */ 177 default String description() { 178 return String.format("TemplateInfo[name=%s, path=%s, contentType=%s, charset=%s]", templateName(), 179 templatePath(), templateContentType(), templateCharset()); 180 } 181 182}