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>{@link Class#getEnclosingClass() Enclosing classes} enclosing the class annotated
028 * with JStache with inner to outer order annotated with this annotation <em>NOT</em> set
029 * 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 for all models in the <a href="#_config_resolution">annotated
129         * class/package/module</a>.
130         * <p>
131         * The content type provider class needs a {@link JStacheContentType} annotation on
132         * the type.
133         * @return by default an <a href="_unspecified">UNSPECIFIED</a> content type.
134         * @see JStacheContentType
135         */
136        Class<?> contentType() default JStacheContentType.UnspecifiedContentType.class;
137
138        /**
139         * Optional formatter if not <a href="_unspecified">UNSPECIFIED</a> for all models in
140         * the <a href="#_config_resolution">annotated class/package/module</a> .
141         * <p>
142         * The formatter provider class needs a {@link JStacheFormatter} annotation on the
143         * type.
144         * @return by default an <a href="_unspecified">UNSPECIFIED</a> formatter.
145         * @see JStacheFormatter
146         */
147        Class<?> formatter() default JStacheFormatter.UnspecifiedFormatter.class;
148
149        /**
150         * Encoding of template files.
151         * <p>
152         * charset can be omitted. <strong>If not set {@link StandardCharsets#UTF_8} is used
153         * by default.</strong>
154         * @return encoding of given template file
155         */
156        String charset() default "";
157
158        /**
159         * Determines what style of of code to generate. See {@link JStacheType}.
160         * @return {@link JStacheType#UNSPECIFIED} by default which means the generated code
161         * will depend on jstachio runtime if no other config overrides (ie is not set to
162         * auto).
163         */
164        JStacheType type() default JStacheType.UNSPECIFIED;
165
166}