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.nio.charset.StandardCharsets; 009 010/** 011 * Set module or package level config for {@link JStache} annotated models that do not 012 * have the configuration explicitly set (e.g. they have something other than the default 013 * of <a href="#_unspecified">unspecified</a> annotation return type). 014 * 015 * <h2 id="_config_resolution">Config Resolution</h2> 016 * 017 * The order of which settings is preferred if set in general is 018 * <code>Class > Package > Module</code>. 019 * <p> 020 * Specifically the resolution is: 021 * 022 * <ol> 023 * <li>Class annotated with JStache and setting is in JStache annotation <em>NOT</em> set 024 * to <a href="#_unspecified">UNSPECIFIED</a>.</li> 025 * <li>Class annotated with JStache and this annotation <em>NOT</em> set to 026 * <a href="#_unspecified">UNSPECIFIED</a>.</li> 027 * <li>{@linkplain Class#getEnclosingClass() Enclosing classes} enclosing the class 028 * annotated with JStache with inner to outer order annotated with this annotation 029 * <em>NOT</em> set to <a href="#_unspecified">UNSPECIFIED</a>.</li> 030 * <li>Package annotated with this annotation <em>NOT</em> set to 031 * <a href="#_unspecified">UNSPECIFIED</a>.</li> 032 * <li>Module annotated with this annotation <em>NOT</em> set to 033 * <a href="#_unspecified">UNSPECIFIED</a>.</li> 034 * <li>If everything is <a href="#_unspecified">unspecified</a> at this point the real 035 * default is used (not the default return of the annotation).</li> 036 * </ol> 037 * 038 * <em>While package hierarchy may seem natural for cascading config this library does not 039 * do it. Package hierarchy does NOT matter to this library! Resolution will NOT check up 040 * parent package directories.</em> If you do not want to copy config to each package it 041 * is recommended you use module annotations or use {@link #using()} to reference other 042 * configuration (see next section). 043 * 044 * <h2 id="_config_using">Config Importing</h2> 045 * 046 * You may import config annotated elsewhere with {@link #using()}. When config is 047 * imported from another class it is essentially a union of NON 048 * <a href="#_unspecified">UNSPECIFIED</a> settings of this annotation instance and the 049 * imported class. Thus <a href="#_config_resolution">config resolution</a> follows as 050 * though the settings are on this instance. 051 * <p> 052 * The referenced config class can be any declared type (interface, enum, etc) but it is 053 * best practice to make it something like an empty Enum to avoid confusing it with 054 * models. 055 * 056 * <h2 id="_unspecified">Unspecified</h2> 057 * 058 * Annotation methods that return symbols prefixed with "<code>Unspecified</code>" (e.g. 059 * {@link JStacheType#UNSPECIFIED}) or have values called <code>UNSPECIFIED</code> or 060 * return an empty array, empty string, or void.class represent unset and will be resolved 061 * through the <a href="#_config_resolution">config resolution</a>. Consequently unlike 062 * other annotation implementations the <code>default</code> return of the annotation is 063 * not really the concrete default. 064 * 065 * 066 * @apiNote This annotation and thus configuration is available during runtime unlike many 067 * of the other annotations in jstachio. 068 * @author agentgt 069 * 070 */ 071@Retention(RetentionPolicy.RUNTIME) 072@Target({ ElementType.PACKAGE, ElementType.MODULE, ElementType.TYPE, ElementType.ANNOTATION_TYPE }) 073@Documented 074public @interface JStacheConfig { 075 076 /** 077 * Imports configuration from another class annotated by <strong>this</strong> or 078 * other JStache annotations. This allows config sharing even across compile 079 * boundaries. 080 * 081 * <p> 082 * The configuration on this annotation instance (the one calling {@link #using()}) 083 * will however take precedence if is not <a href="_unspecified">UNSPECIFIED</a>. 084 * <p> 085 * <em><code>using()</code> is not cascading meaning that the referenced configuration 086 * classes (the using returned on this instance) that have {@link #using()} set will 087 * be ignored!</em> Furthermore configuration set on enclosing classes, packages, 088 * modules on the referenced type are ignored. 089 * @return by default <code>void.class</code> which represents 090 * <a href="_unspecified">UNSPECIFIED</a>. 091 */ 092 Class<?> using() default void.class; 093 094 /** 095 * If {@link JStache#name()} is blank the name of the generated class is derived from 096 * the models class name and then augmented with {@link JStacheName#prefix()} and 097 * {@link JStacheName#suffix()}. 098 * @return by default an empty array which represents 099 * <a href="_unspecified">UNSPECIFIED</a>. 100 * @apiNote the cardinality of the returned array is currently <code>0..1</code>. 101 * additional elements after the first will be ignored. 102 * @see JStacheName 103 */ 104 JStacheName[] naming() default {}; 105 106 /** 107 * If {@link JStache#path()} is not blank the path of the template is resolved by 108 * augmenting with {@link JStachePath#prefix()} and {@link JStachePath#suffix()}. 109 * @return by default an empty array which represents 110 * <a href="_unspecified">UNSPECIFIED</a>. 111 * @apiNote the cardinality of the returned array is currently <code>0..1</code>. 112 * additional elements after the first will be ignored. 113 * @see JStachePath 114 */ 115 JStachePath[] pathing() default {}; 116 117 /** 118 * Configures what interfaces/annotations the model implements and or extends. 119 * @return by default an empty array which represents 120 * <a href="_unspecified">UNSPECIFIED</a>. 121 * @apiNote the cardinality of the returned array is currently <code>0..1</code>. 122 * additional elements after the first will be ignored. 123 * @see JStacheInterfaces 124 */ 125 JStacheInterfaces[] interfacing() default {}; 126 127 /** 128 * Optional content type which determines what <strong>escaper</strong> to use for all 129 * models in the <a href="#_config_resolution">annotated class/package/module</a>. 130 * <p> 131 * The contentType class needs a {@link JStacheContentType} annotation on the type. If 132 * {@link #type()} is resolved to {@link JStacheType#JSTACHIO} a spec based HTML 133 * content type will be used if unspecified. 134 * @return by default an <a href="#_unspecified">UNSPECIFIED</a> content type. 135 * @see JStacheContentType 136 */ 137 Class<?> contentType() default JStacheContentType.UnspecifiedContentType.class; 138 139 /** 140 * Optional formatter if not <a href="#_unspecified">UNSPECIFIED</a> for all models in 141 * the <a href="#_config_resolution">annotated class/package/module</a> . 142 * <p> 143 * The formatter provider class needs a {@link JStacheFormatter} annotation on the 144 * type. If {@link #type()} is resolved to {@link JStacheType#JSTACHIO} a default 145 * formatter that does not allow null will be used. 146 * @return by default an <a href="#_unspecified">UNSPECIFIED</a> formatter. 147 * @see JStacheFormatter 148 */ 149 Class<?> formatter() default JStacheFormatter.UnspecifiedFormatter.class; 150 151 /** 152 * Encoding of template files. 153 * <p> 154 * charset can be omitted. <strong>If not set {@link StandardCharsets#UTF_8} is used 155 * by default.</strong> 156 * @return encoding of given template file 157 */ 158 String charset() default ""; 159 160 /** 161 * Determines what style of of code to generate. See {@link JStacheType}. 162 * @return {@link JStacheType#UNSPECIFIED} by default which means the generated code 163 * will depend on jstachio runtime if no other config overrides (ie is not set to 164 * auto). 165 */ 166 JStacheType type() default JStacheType.UNSPECIFIED; 167 168}