org.thymeleaf.context.AbstractEngineContext Maven / Gradle / Ivy
/*
* =============================================================================
*
* Copyright (c) 2011-2018, The THYMELEAF team (http://www.thymeleaf.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* =============================================================================
*/
package org.thymeleaf.context;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import org.thymeleaf.IEngineConfiguration;
import org.thymeleaf.exceptions.TemplateProcessingException;
import org.thymeleaf.expression.ExpressionObjects;
import org.thymeleaf.expression.IExpressionObjects;
import org.thymeleaf.linkbuilder.ILinkBuilder;
import org.thymeleaf.messageresolver.IMessageResolver;
import org.thymeleaf.model.IModelFactory;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.util.Validate;
/**
*
* Utility abstract class partially implementing {@link IEngineContext}.
*
*
* This class is meant to be used as a base for implementations of {@link IEngineContext}. Note however that creating
* an implementation of {@link IEngineContext} can be very complex and normally unneeded. The default
* implementations should suffice for most scenarios.
*
*
* Note this abstract implementation does not implement basic variable-management methods such as those coming from
* the {@link IContext} interface because that is considered the responsibility of the implementing subclasses.
*
*
* @author Daniel Fernández
* @since 3.0.0
*
*/
public abstract class AbstractEngineContext implements IEngineContext {
// NOTE we are not extending AbstractContext or AbstractExpressionContext on purpose, as the variable-oriented
// methods are going to be handled by the subclasses, not any superclasses.
private final IEngineConfiguration configuration;
private final Map templateResolutionAttributes;
private final Locale locale;
private IExpressionObjects expressionObjects = null;
private IdentifierSequences identifierSequences = null;
protected AbstractEngineContext(
final IEngineConfiguration configuration,
final Map templateResolutionAttributes,
final Locale locale) {
super();
Validate.notNull(configuration, "Configuration cannot be null");
// templateResolutionAttributes CAN be null
Validate.notNull(locale, "Locale cannot be null");
this.configuration = configuration;
this.locale = locale;
this.templateResolutionAttributes = templateResolutionAttributes;
// Most templates will not need this, so we will initialize it lazily
this.identifierSequences = null;
}
public final IEngineConfiguration getConfiguration() {
return this.configuration;
}
public final Map getTemplateResolutionAttributes() {
return this.templateResolutionAttributes;
}
public final Locale getLocale() {
return this.locale;
}
public final IExpressionObjects getExpressionObjects() {
// We delay creation of expression objects in case they are not needed at all
if (this.expressionObjects == null) {
this.expressionObjects = new ExpressionObjects(this, this.configuration.getExpressionObjectFactory());
}
return this.expressionObjects;
}
public final TemplateMode getTemplateMode() {
return getTemplateData().getTemplateMode();
}
public final IModelFactory getModelFactory() {
return this.configuration.getModelFactory(getTemplateMode());
}
public final String getMessage(
final Class> origin, final String key, final Object[] messageParameters, final boolean useAbsentMessageRepresentation) {
// origin CAN be null
Validate.notNull(key, "Message key cannot be null");
// messageParameter CAN be null
final Set messageResolvers = this.configuration.getMessageResolvers();
// Try to resolve the message
for (final IMessageResolver messageResolver : messageResolvers) {
final String resolvedMessage =
messageResolver.resolveMessage(this, origin, key, messageParameters);
if (resolvedMessage != null) {
return resolvedMessage;
}
}
// Message unresolved: try to create an "absent message representation" (if specified to do so)
if (useAbsentMessageRepresentation) {
for (final IMessageResolver messageResolver : messageResolvers) {
final String absentMessageRepresentation =
messageResolver.createAbsentMessageRepresentation(this, origin, key, messageParameters);
if (absentMessageRepresentation != null) {
return absentMessageRepresentation;
}
}
}
return null;
}
public final String buildLink(final String base, final Map parameters) {
// base CAN be null
// parameters CAN be null
final Set linkBuilders = this.configuration.getLinkBuilders();
// Try to resolve the message
for (final ILinkBuilder linkBuilder : linkBuilders) {
final String link = linkBuilder.buildLink(this, base, parameters);
if (link != null) {
return link;
}
}
// Message unresolved: this should never happen, so we should fail
throw new TemplateProcessingException(
"No configured link builder instance was able to build link with base \"" + base + "\" and " +
"parameters " + parameters);
}
public final IdentifierSequences getIdentifierSequences() {
// No problem in lazily initializing this here, as context objects should not be used by
// multiple threads.
if (this.identifierSequences == null) {
this.identifierSequences = new IdentifierSequences();
}
return this.identifierSequences;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy