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