3232import java .util .Set ;
3333
3434/**
35- * Renders a template using the StringTemplate (ST) library.
35+ * Renders a template using the StringTemplate (ST) v4 library.
36+ *
37+ * <p>
38+ * This renderer allows customization of delimiters, validation behavior when template
39+ * variables are missing, and how StringTemplate's built-in functions are handled during
40+ * validation.
41+ *
42+ * <p>
43+ * Use the {@link #builder()} to create and configure instances.
3644 *
3745 * @author Thomas Vitale
3846 * @since 1.0.0
@@ -49,22 +57,23 @@ public class StTemplateRenderer implements TemplateRenderer {
4957
5058 private static final ValidationMode DEFAULT_VALIDATION_MODE = ValidationMode .THROW ;
5159
52- private static final boolean DEFAULT_SKIP_BUILT_IN_FUNCTIONS_VALIDATION = false ;
60+ private static final boolean DEFAULT_SUPPORT_ST_FUNCTIONS = false ;
5361
5462 private final char startDelimiterToken ;
5563
5664 private final char endDelimiterToken ;
5765
5866 private final ValidationMode validationMode ;
5967
60- private final boolean skipBuiltInFunctionsValidation ;
68+ private final boolean supportStFunctions ;
6169
62- StTemplateRenderer (char startDelimiterToken , char endDelimiterToken , ValidationMode validationMode , boolean skipBuiltInFunctionsValidation ) {
70+ StTemplateRenderer (char startDelimiterToken , char endDelimiterToken , ValidationMode validationMode ,
71+ boolean supportStFunctions ) {
6372 Assert .notNull (validationMode , "validationMode cannot be null" );
6473 this .startDelimiterToken = startDelimiterToken ;
6574 this .endDelimiterToken = endDelimiterToken ;
6675 this .validationMode = validationMode ;
67- this .skipBuiltInFunctionsValidation = skipBuiltInFunctionsValidation ;
76+ this .supportStFunctions = supportStFunctions ;
6877 }
6978
7079 @ Override
@@ -120,7 +129,7 @@ private Set<String> getInputVariables(ST st) {
120129 && tokens .get (i + 1 ).getType () == STLexer .ID ) {
121130 if (i + 2 < tokens .size () && tokens .get (i + 2 ).getType () == STLexer .COLON ) {
122131 String text = tokens .get (i + 1 ).getText ();
123- if (!Compiler .funcs .containsKey (text ) || !skipBuiltInFunctionsValidation ) {
132+ if (!Compiler .funcs .containsKey (text ) || !supportStFunctions ) {
124133 inputVariables .add (text );
125134 isInsideList = true ;
126135 }
@@ -130,7 +139,7 @@ else if (token.getType() == STLexer.RDELIM) {
130139 isInsideList = false ;
131140 }
132141 else if (!isInsideList && token .getType () == STLexer .ID ) {
133- if (!Compiler .funcs .containsKey (token .getText ()) || !skipBuiltInFunctionsValidation ) {
142+ if (!Compiler .funcs .containsKey (token .getText ()) || !supportStFunctions ) {
134143 inputVariables .add (token .getText ());
135144 }
136145 }
@@ -143,6 +152,9 @@ public static Builder builder() {
143152 return new Builder ();
144153 }
145154
155+ /**
156+ * Builder for configuring and creating {@link StTemplateRenderer} instances.
157+ */
146158 public static class Builder {
147159
148160 private char startDelimiterToken = DEFAULT_START_DELIMITER_TOKEN ;
@@ -151,33 +163,70 @@ public static class Builder {
151163
152164 private ValidationMode validationMode = DEFAULT_VALIDATION_MODE ;
153165
154- private boolean skipBuiltInFunctionsValidation = DEFAULT_SKIP_BUILT_IN_FUNCTIONS_VALIDATION ;
166+ private boolean supportStFunctions = DEFAULT_SUPPORT_ST_FUNCTIONS ;
155167
156168 private Builder () {
157169 }
158170
171+ /**
172+ * Sets the character used as the start delimiter for template expressions.
173+ * Default is '{'.
174+ * @param startDelimiterToken The start delimiter character.
175+ * @return This builder instance for chaining.
176+ */
159177 public Builder startDelimiterToken (char startDelimiterToken ) {
160178 this .startDelimiterToken = startDelimiterToken ;
161179 return this ;
162180 }
163181
182+ /**
183+ * Sets the character used as the end delimiter for template expressions. Default
184+ * is '}'.
185+ * @param endDelimiterToken The end delimiter character.
186+ * @return This builder instance for chaining.
187+ */
164188 public Builder endDelimiterToken (char endDelimiterToken ) {
165189 this .endDelimiterToken = endDelimiterToken ;
166190 return this ;
167191 }
168192
193+ /**
194+ * Sets the validation mode to control behavior when the provided variables do not
195+ * match the variables required by the template. Default is
196+ * {@link ValidationMode#THROW}.
197+ * @param validationMode The desired validation mode.
198+ * @return This builder instance for chaining.
199+ */
169200 public Builder validationMode (ValidationMode validationMode ) {
170201 this .validationMode = validationMode ;
171202 return this ;
172203 }
173204
174- public Builder skipBuiltInFunctionsValidation () {
175- this .skipBuiltInFunctionsValidation = true ;
205+ /**
206+ * Configures the renderer to support StringTemplate's built-in functions during
207+ * validation.
208+ * <p>
209+ * When enabled (set to true), identifiers in the template that match known ST
210+ * function names (e.g., "first", "rest", "length") will not be treated as
211+ * required input variables during validation.
212+ * <p>
213+ * When disabled (default, false), these identifiers are treated like regular
214+ * variables and must be provided in the input map if validation is enabled
215+ * ({@link ValidationMode#WARN} or {@link ValidationMode#THROW}).
216+ * @return This builder instance for chaining.
217+ */
218+ public Builder supportStFunctions () {
219+ this .supportStFunctions = true ;
176220 return this ;
177221 }
178222
223+ /**
224+ * Builds and returns a new {@link StTemplateRenderer} instance with the
225+ * configured settings.
226+ * @return A configured {@link StTemplateRenderer}.
227+ */
179228 public StTemplateRenderer build () {
180- return new StTemplateRenderer (startDelimiterToken , endDelimiterToken , validationMode , skipBuiltInFunctionsValidation );
229+ return new StTemplateRenderer (startDelimiterToken , endDelimiterToken , validationMode , supportStFunctions );
181230 }
182231
183232 }
0 commit comments