001package io.jstach.jstache;
002
003import java.lang.annotation.Documented;
004import java.lang.annotation.ElementType;
005import java.lang.annotation.Retention;
006import java.lang.annotation.RetentionPolicy;
007import java.lang.annotation.Target;
008import java.util.ServiceLoader;
009
010/**
011 * Place on package to generate a TemplateProvider/JStachioTemplateFinder that will have a
012 * catalog of all public generated JStache templates in the compile time boundary that are
013 * of type {@link JStacheType#JSTACHIO}.
014 * <p>
015 * The class will be put in the annotated package and implements both
016 * <code>io.jstach.jstachio.spi.TemplateProvider</code> and
017 * <code>io.jstach.jstachio.spi.JStachioTemplateFinder</code>.
018 * <p>
019 * This is useful for:
020 *
021 * <ol>
022 * <li>Modular applications that use <code>module-info.java</code> instead of
023 * <code>META-INF/services</code> for service loader registration.</li>
024 * <li>Application wishing to avoid reflection altogether but still wanting to use
025 * JStachio runtime particularly the model to template loookup.</li>
026 * <li>Allow access and rendering of package protected models from other parts of the
027 * application.</li>
028 * </ol>
029 *
030 * <h2>Modular applications</h2>
031 *
032 * Modular applications that do not want to allow reflective access
033 * (<code> opens ... to io.jstach.jstachio;</code>) to the JStachio runtime can instead
034 * register the generated template provider in the <code>module-info.java</code> as a
035 * service provider like:
036 *
037 * <pre><code class="language-java">
038 * provides io.jstach.jstachio.spi.TemplateProvider with annotatedpackage.TemplateCatalog;
039 * </code> </pre>
040 *
041 * or as a <code>JStachioTemplateFinder</code>:
042 *
043 * <pre><code class="language-java">
044 * &#47;&#47; module-info.java
045 * provides io.jstach.jstachio.spi.JStachioTemplateFinder with annotatedpackage.TemplateCatalog;
046 * </code> </pre>
047 *
048 * In general the <code>TemplateProvider</code> is preferred as it will allow reflective
049 * access (either {@link ServiceLoader} or direct constructor reflection) to other models
050 * that are perhaps not in the same compile time boundary as well as caching. Note that
051 * the generated code does not implement caching so if going the
052 * <code>JStachioTemplateFinder</code> route caching will be the implementers
053 * responsibility.
054 * <p>
055 * <strong>Tip:</strong><em> Some tools do not like generated classes being referenced in
056 * <code>module-info.java</code> therefore a general recommendation is to extend the
057 * generated class and reference the class doing the extending in the
058 * <code>module-info.java</code>.</em> Below is an example:
059 *
060 * <pre><code class="language-java">
061 * &#47;&#47; extend the generated class
062 * package annotatedpackage;
063 * public class MyTemplateCatalog extends TemplateCatalog {}
064 * </code> </pre>
065 *
066 * <pre><code class="language-java">
067 * &#47;&#47; register the extended class
068 * provides io.jstach.jstachio.spi.TemplateProvider with annotatedpackage.MyTemplateCatalog;
069 * </code> </pre>
070 *
071 * <h2>Avoiding reflection</h2>
072 *
073 * For those wanting to avoid reflection a custom JStachio can be created from the
074 * generated catalog.
075 *
076 * <pre><code class="language-java">
077 * JStachio j = JStachioFactory.builder()
078 *     .add(new annotatedpackage.TemplateCatalog())
079 *     .build();
080 * </code> </pre>
081 *
082 * <h2>Package protected models</h2>
083 *
084 * If the package annotated has models that are package protected those models will still
085 * be added to the generated template catalog as the generated class will have access.
086 * Normally JStachio uses either the Service Loader which requires public access to the
087 * generated template or reflection which may or may not require public access depending
088 * on modularization.
089 * <p>
090 * <em>Multiple packages can be annotated and thus multiple TemplateProvider/Finder can be
091 * referenced.</em>
092 *
093 *
094 * @author agentgt
095 */
096@Retention(RetentionPolicy.SOURCE)
097@Target({ ElementType.PACKAGE })
098@Documented
099public @interface JStacheCatalog {
100
101        /**
102         * Name of the generated class that will be put in the annotated package.
103         * @return name of the class to be generated. The default is
104         * <code>TemplateCatalog</code>.
105         */
106        public String name() default "TemplateCatalog";
107
108        /**
109         * Configuration flags for generating template catalogs.
110         * @return an array of flags.
111         * @see CatalogFlag
112         */
113        public CatalogFlag[] flags() default {};
114
115        /**
116         * Configuration flags for generating template catalogs such
117         * <code>META-INF/services</code> files.
118         * @author agentgt
119         */
120        public enum CatalogFlag {
121
122                /**
123                 * Option that will generate a legacy service loader registration:
124                 * <code>META-INF/services/io.jstach.jstachio.spi.TemplateProvider</code> pointing
125                 * to the generated template catalog.
126                 */
127
128                GENERATE_PROVIDER_META_INF_SERVICE, //
129
130                /**
131                 * Option that will generate a legacy service loader registration:
132                 * <code>META-INF/services/io.jstach.jstachio.spi.JStachioTemplateFinder</code>
133                 * pointing to the generated template catalog.
134                 */
135                GENERATE_FINDER_META_INF_SERVICE
136
137        }
138
139}