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 * // 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 * // extend the generated class 062 * package annotatedpackage; 063 * public class MyTemplateCatalog extends TemplateCatalog {} 064 * </code> </pre> 065 * 066 * <pre><code class="language-java"> 067 * // 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}