AbstractThymeleafBuilder.java

1
package fr.sii.ogham.template.thymeleaf.common.buider;
2
3
import java.util.ArrayList;
4
import java.util.List;
5
6
import org.slf4j.Logger;
7
import org.slf4j.LoggerFactory;
8
import org.thymeleaf.TemplateEngine;
9
import org.thymeleaf.templateresolver.ITemplateResolver;
10
11
import fr.sii.ogham.core.builder.Builder;
12
import fr.sii.ogham.core.builder.configuration.ConfigurationValueBuilder;
13
import fr.sii.ogham.core.builder.configuration.ConfigurationValueBuilderHelper;
14
import fr.sii.ogham.core.builder.configurer.Configurer;
15
import fr.sii.ogham.core.builder.context.BuildContext;
16
import fr.sii.ogham.core.builder.context.DefaultBuildContext;
17
import fr.sii.ogham.core.builder.resolution.ClassPathResolutionBuilder;
18
import fr.sii.ogham.core.builder.resolution.FileResolutionBuilder;
19
import fr.sii.ogham.core.builder.resolution.ResourceResolutionBuilder;
20
import fr.sii.ogham.core.builder.resolution.ResourceResolutionBuilderHelper;
21
import fr.sii.ogham.core.builder.resolution.StringResolutionBuilder;
22
import fr.sii.ogham.core.builder.template.DetectorBuilder;
23
import fr.sii.ogham.core.fluent.AbstractParent;
24
import fr.sii.ogham.core.resource.resolver.FirstSupportingResourceResolver;
25
import fr.sii.ogham.core.resource.resolver.ResourceResolver;
26
import fr.sii.ogham.core.template.detector.TemplateEngineDetector;
27
import fr.sii.ogham.core.template.parser.TemplateParser;
28
import fr.sii.ogham.template.thymeleaf.common.SimpleThymeleafContextConverter;
29
import fr.sii.ogham.template.thymeleaf.common.TemplateResolverOptions;
30
import fr.sii.ogham.template.thymeleaf.common.ThymeleafContextConverter;
31
import fr.sii.ogham.template.thymeleaf.common.ThymeleafParser;
32
import fr.sii.ogham.template.thymeleaf.common.adapter.FirstSupportingResolverAdapter;
33
import fr.sii.ogham.template.thymeleaf.common.adapter.TemplateResolverAdapter;
34
35
@SuppressWarnings("squid:S00119")
36
public abstract class AbstractThymeleafBuilder<MYSELF extends AbstractThymeleafBuilder<MYSELF, P, E>, P, E extends AbstractThymeleafEngineConfigBuilder<E, MYSELF>> extends AbstractParent<P>
37
		implements DetectorBuilder<MYSELF>, ResourceResolutionBuilder<MYSELF>, Builder<TemplateParser> {
38
	private static final Logger LOG = LoggerFactory.getLogger(AbstractThymeleafBuilder.class);
39
40
	protected final MYSELF myself;
41
	protected final BuildContext buildContext;
42
	protected TemplateEngineDetector detector;
43
	protected ResourceResolutionBuilderHelper<MYSELF> resourceResolutionBuilderHelper;
44
	protected TemplateEngine engine;
45
	protected ThymeleafContextConverter contextConverter;
46
	protected E engineBuilder;
47
	protected final List<TemplateResolverAdapter> customAdapters;
48
	protected final ConfigurationValueBuilderHelper<MYSELF, Boolean> enableCacheValueBuilder;
49
50
	protected AbstractThymeleafBuilder(Class<?> selfType) {
51
		this(selfType, null, new DefaultBuildContext());
52
	}
53
54
	@SuppressWarnings("unchecked")
55
	protected AbstractThymeleafBuilder(Class<?> selfType, P parent, BuildContext buildContext) {
56
		super(parent);
57
		myself = (MYSELF) selfType.cast(this);
58
		this.buildContext = buildContext;
59
		customAdapters = new ArrayList<>();
60
		enableCacheValueBuilder = buildContext.newConfigurationValueBuilder(myself, Boolean.class);
61
	}
62
63
	protected AbstractThymeleafBuilder(P parent, BuildContext buildContext) {
64
		this(AbstractThymeleafBuilder.class, parent, buildContext);
65
	}
66
67
	/**
68
	 * Enable/disable cache for templates.
69
	 * 
70
	 * <p>
71
	 * The value set using this method takes precedence over any property and
72
	 * default value configured using {@link #cache()}.
73
	 * 
74
	 * <pre>
75
	 * .cache(false)
76
	 * .cache()
77
	 *   .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
78
	 *   .defaultValue(true)
79
	 * </pre>
80
	 * 
81
	 * <pre>
82
	 * .cache(false)
83
	 * .cache()
84
	 *   .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
85
	 *   .defaultValue(true)
86
	 * </pre>
87
	 * 
88
	 * In both cases, {@code cache(false)} is used.
89
	 * 
90
	 * <p>
91
	 * If this method is called several times, only the last value is used.
92
	 * 
93
	 * <p>
94
	 * If {@code null} value is set, it is like not setting a value at all. The
95
	 * property/default value configuration is applied.
96
	 * 
97
	 * @param enable
98
	 *            enable or disable cache
99
	 * @return this instance for fluent chaining
100
	 */
101
	public MYSELF cache(Boolean enable) {
102 1 1. cache : removed call to fr/sii/ogham/core/builder/configuration/ConfigurationValueBuilderHelper::setValue → RUN_ERROR
		enableCacheValueBuilder.setValue(enable);
103 1 1. cache : replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::cache → RUN_ERROR
		return myself;
104
	}
105
106
	/**
107
	 * Enable/disable cache for templates.
108
	 * 
109
	 * <p>
110
	 * This method is mainly used by {@link Configurer}s to register some
111
	 * property keys and/or a default value. The aim is to let developer be able
112
	 * to externalize its configuration (using system properties, configuration
113
	 * file or anything else). If the developer doesn't configure any value for
114
	 * the registered properties, the default value is used (if set).
115
	 * 
116
	 * <pre>
117
	 * .cache()
118
	 *   .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
119
	 *   .defaultValue(true)
120
	 * </pre>
121
	 * 
122
	 * <p>
123
	 * Non-null value set using {@link #cache(Boolean)} takes precedence over
124
	 * property values and default value.
125
	 * 
126
	 * <pre>
127
	 * .cache(false)
128
	 * .cache()
129
	 *   .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
130
	 *   .defaultValue(true)
131
	 * </pre>
132
	 * 
133
	 * The value {@code false} is used regardless of the value of the properties
134
	 * and default value.
135
	 * 
136
	 * <p>
137
	 * See {@link ConfigurationValueBuilder} for more information.
138
	 * 
139
	 * 
140
	 * @return the builder to configure property keys/default value
141
	 */
142
	public ConfigurationValueBuilder<MYSELF, Boolean> cache() {
143 1 1. cache : replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::cache → NO_COVERAGE
		return enableCacheValueBuilder;
144
	}
145
146
	/**
147
	 * Fluent configurer for Thymeleaf engine configuration.
148
	 * 
149
	 * @return the fluent builder for Thymeleaf engine
150
	 */
151
	public E engine() {
152 1 1. engine : negated conditional → NO_COVERAGE
		if (engineBuilder == null) {
153
			engineBuilder = getThymeleafEngineConfigBuilder();
154
		}
155 1 1. engine : replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::engine → NO_COVERAGE
		return engineBuilder;
156
	}
157
158
	/**
159
	 * Sets a Thymeleaf engine.
160
	 * 
161
	 * This value preempts any other value defined by calling {@link #engine()}
162
	 * method.
163
	 * 
164
	 * If this method is called several times, only the last provider is used.
165
	 * 
166
	 * @param engine
167
	 *            the Thymeleaf engine
168
	 * @return this instance for fluent chaining
169
	 */
170
	public MYSELF engine(TemplateEngine engine) {
171
		this.engine = engine;
172 1 1. engine : replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::engine → NO_COVERAGE
		return myself;
173
	}
174
175
	/**
176
	 * Ogham provides a generic context concept for template parsing. Thymeleaf
177
	 * uses also a context concept. A context converter
178
	 * ({@link ThymeleafContextConverter}) is the way to transform an Ogham
179
	 * context into a Thymeleaf context.
180
	 * 
181
	 * <p>
182
	 * Ogham provides and registers the default converter
183
	 * 
184
	 * <p>
185
	 * If this method is called several times, only the last provider is used.
186
	 * 
187
	 * @param converter
188
	 *            the context converter
189
	 * @return this instance for fluent chaining
190
	 */
191
	public MYSELF contextConverter(ThymeleafContextConverter converter) {
192
		this.contextConverter = converter;
193 1 1. contextConverter : replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::contextConverter → NO_COVERAGE
		return myself;
194
	}
195
196
	@Override
197
	public MYSELF detector(TemplateEngineDetector detector) {
198
		this.detector = detector;
199 1 1. detector : replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::detector → NO_COVERAGE
		return myself;
200
	}
201
202
	@Override
203
	public ClassPathResolutionBuilder<MYSELF> classpath() {
204 1 1. classpath : removed call to fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::initResolutionBuilder → RUN_ERROR
		initResolutionBuilder();
205 1 1. classpath : replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::classpath → RUN_ERROR
		return resourceResolutionBuilderHelper.classpath();
206
	}
207
208
	@Override
209
	public FileResolutionBuilder<MYSELF> file() {
210 1 1. file : removed call to fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::initResolutionBuilder → RUN_ERROR
		initResolutionBuilder();
211 1 1. file : replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::file → RUN_ERROR
		return resourceResolutionBuilderHelper.file();
212
	}
213
214
	@Override
215
	public StringResolutionBuilder<MYSELF> string() {
216 1 1. string : removed call to fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::initResolutionBuilder → RUN_ERROR
		initResolutionBuilder();
217 1 1. string : replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::string → RUN_ERROR
		return resourceResolutionBuilderHelper.string();
218
	}
219
220
	@Override
221
	public MYSELF resolver(ResourceResolver resolver) {
222 1 1. resolver : removed call to fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::initResolutionBuilder → NO_COVERAGE
		initResolutionBuilder();
223 1 1. resolver : replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::resolver → NO_COVERAGE
		return resourceResolutionBuilderHelper.resolver(resolver);
224
	}
225
226
	/**
227
	 * Ogham provides a generic resource resolution mechanism
228
	 * ({@link ResourceResolver}). Thymeleaf uses its own template resolution
229
	 * mechanism ({@link ITemplateResolver}). A resolver adapter
230
	 * ({@link TemplateResolverAdapter}) is the way to transform a
231
	 * {@link ResourceResolver} into a {@link ITemplateResolver}.
232
	 * 
233
	 * <p>
234
	 * Ogham provides and registers default resolver adapters but you may need
235
	 * to use a custom {@link ResourceResolver}. So you also need to provide the
236
	 * corresponding {@link TemplateResolverAdapter}.
237
	 * 
238
	 * @param adapter
239
	 *            the resolver adapter
240
	 * @return this instance for fluent chaining
241
	 */
242
	public MYSELF resolverAdapter(TemplateResolverAdapter adapter) {
243
		customAdapters.add(adapter);
244 1 1. resolverAdapter : replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::resolverAdapter → NO_COVERAGE
		return myself;
245
	}
246
247
	@Override
248
	public TemplateParser build() {
249
		LOG.info("Thymeleaf parser is registered");
250 1 1. build : replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::build → RUN_ERROR
		return buildContext.register(new ThymeleafParser(buildEngine(), buildResolver(), buildContext()));
251
	}
252
253
	@Override
254
	public TemplateEngineDetector buildDetector() {
255 2 1. buildDetector : negated conditional → RUN_ERROR
2. buildDetector : replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::buildDetector → RUN_ERROR
		return detector == null ? createTemplateDetector() : detector;
256
	}
257
258
	/**
259
	 * Builds the resolver used by Thymeleaf to resolve resources
260
	 * 
261
	 * @return the resource resolver
262
	 */
263
	public FirstSupportingResourceResolver buildResolver() {
264 1 1. buildResolver : replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::buildResolver → RUN_ERROR
		return buildContext.register(new FirstSupportingResourceResolver(buildResolvers()));
265
	}
266
267
	protected TemplateEngine buildEngine() {
268
		TemplateEngine builtEngine;
269 1 1. buildEngine : negated conditional → RUN_ERROR
		if (engine != null) {
270
			LOG.debug("Using custom Thymeleaf engine");
271
			builtEngine = engine;
272 1 1. buildEngine : negated conditional → RUN_ERROR
		} else if (engineBuilder != null) {
273
			LOG.debug("Using custom Thymeleaf engine built using engine()");
274
			builtEngine = engineBuilder.build();
275
		} else {
276
			LOG.debug("Using default Thymeleaf engine");
277
			builtEngine = buildContext.register(new TemplateEngine());
278
		}
279 1 1. buildEngine : removed call to org/thymeleaf/TemplateEngine::addTemplateResolver → RUN_ERROR
		builtEngine.addTemplateResolver(buildTemplateResolver(builtEngine));
280 1 1. buildEngine : replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::buildEngine → RUN_ERROR
		return builtEngine;
281
	}
282
283
	protected abstract TemplateEngineDetector createTemplateDetector();
284
285
	protected abstract ITemplateResolver buildTemplateResolver(TemplateEngine builtEngine);
286
287
	protected abstract E getThymeleafEngineConfigBuilder();
288
289
	protected ThymeleafContextConverter buildContext() {
290 2 1. buildContext : negated conditional → RUN_ERROR
2. buildContext : replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::buildContext → RUN_ERROR
		return contextConverter == null ? buildContext.register(new SimpleThymeleafContextConverter()) : contextConverter;
291
	}
292
293
	private List<ResourceResolver> buildResolvers() {
294 1 1. buildResolvers : removed call to fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::initResolutionBuilder → RUN_ERROR
		initResolutionBuilder();
295 1 1. buildResolvers : replaced return value with Collections.emptyList for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::buildResolvers → RUN_ERROR
		return resourceResolutionBuilderHelper.buildResolvers();
296
	}
297
298
	protected abstract FirstSupportingResolverAdapter buildAdapters();
299
300
	protected TemplateResolverOptions buildTemplateResolverOptions() {
301
		TemplateResolverOptions options = buildContext.register(new TemplateResolverOptions());
302 1 1. buildTemplateResolverOptions : removed call to fr/sii/ogham/template/thymeleaf/common/TemplateResolverOptions::setCacheable → RUN_ERROR
		options.setCacheable(enableCacheValueBuilder.getValue());
303
		// TODO: handle other options
304 1 1. buildTemplateResolverOptions : replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::buildTemplateResolverOptions → RUN_ERROR
		return options;
305
	}
306
307
	private void initResolutionBuilder() {
308 1 1. initResolutionBuilder : negated conditional → RUN_ERROR
		if (resourceResolutionBuilderHelper == null) {
309
			resourceResolutionBuilderHelper = new ResourceResolutionBuilderHelper<>(myself, buildContext);
310
		}
311
	}
312
}

Mutations

102

1.1
Location : cache
Killed by :
removed call to fr/sii/ogham/core/builder/configuration/ConfigurationValueBuilderHelper::setValue → RUN_ERROR

103

1.1
Location : cache
Killed by :
replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::cache → RUN_ERROR

143

1.1
Location : cache
Killed by :
replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::cache → NO_COVERAGE

152

1.1
Location : engine
Killed by :
negated conditional → NO_COVERAGE

155

1.1
Location : engine
Killed by :
replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::engine → NO_COVERAGE

172

1.1
Location : engine
Killed by :
replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::engine → NO_COVERAGE

193

1.1
Location : contextConverter
Killed by :
replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::contextConverter → NO_COVERAGE

199

1.1
Location : detector
Killed by :
replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::detector → NO_COVERAGE

204

1.1
Location : classpath
Killed by :
removed call to fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::initResolutionBuilder → RUN_ERROR

205

1.1
Location : classpath
Killed by :
replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::classpath → RUN_ERROR

210

1.1
Location : file
Killed by :
removed call to fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::initResolutionBuilder → RUN_ERROR

211

1.1
Location : file
Killed by :
replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::file → RUN_ERROR

216

1.1
Location : string
Killed by :
removed call to fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::initResolutionBuilder → RUN_ERROR

217

1.1
Location : string
Killed by :
replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::string → RUN_ERROR

222

1.1
Location : resolver
Killed by :
removed call to fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::initResolutionBuilder → NO_COVERAGE

223

1.1
Location : resolver
Killed by :
replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::resolver → NO_COVERAGE

244

1.1
Location : resolverAdapter
Killed by :
replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::resolverAdapter → NO_COVERAGE

250

1.1
Location : build
Killed by :
replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::build → RUN_ERROR

255

1.1
Location : buildDetector
Killed by :
negated conditional → RUN_ERROR

2.2
Location : buildDetector
Killed by :
replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::buildDetector → RUN_ERROR

264

1.1
Location : buildResolver
Killed by :
replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::buildResolver → RUN_ERROR

269

1.1
Location : buildEngine
Killed by :
negated conditional → RUN_ERROR

272

1.1
Location : buildEngine
Killed by :
negated conditional → RUN_ERROR

279

1.1
Location : buildEngine
Killed by :
removed call to org/thymeleaf/TemplateEngine::addTemplateResolver → RUN_ERROR

280

1.1
Location : buildEngine
Killed by :
replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::buildEngine → RUN_ERROR

290

1.1
Location : buildContext
Killed by :
negated conditional → RUN_ERROR

2.2
Location : buildContext
Killed by :
replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::buildContext → RUN_ERROR

294

1.1
Location : buildResolvers
Killed by :
removed call to fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::initResolutionBuilder → RUN_ERROR

295

1.1
Location : buildResolvers
Killed by :
replaced return value with Collections.emptyList for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::buildResolvers → RUN_ERROR

302

1.1
Location : buildTemplateResolverOptions
Killed by :
removed call to fr/sii/ogham/template/thymeleaf/common/TemplateResolverOptions::setCacheable → RUN_ERROR

304

1.1
Location : buildTemplateResolverOptions
Killed by :
replaced return value with null for fr/sii/ogham/template/thymeleaf/common/buider/AbstractThymeleafBuilder::buildTemplateResolverOptions → RUN_ERROR

308

1.1
Location : initResolutionBuilder
Killed by :
negated conditional → RUN_ERROR

Active mutators

Tests examined


Report generated by PIT 1.13.1