All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.thymeleaf.TemplateSpec Maven / Gradle / Ivy

Go to download

Modern server-side Java template engine for both web and standalone environments

There is a newer version: 3.1.3.RELEASE
Show newest version
/*
 * =============================================================================
 * 
 *   Copyright (c) 2011-2016, 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;

import java.io.Serializable;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.util.ContentTypeUtils;
import org.thymeleaf.util.LoggingUtils;
import org.thymeleaf.util.Validate;


/**
 * 

* Specification class containing everything needed by the template engine related to the * template to be processed. Objects of this class are normally used as an argument to the * different process(...) methods at {@link ITemplateEngine}. *

*

* The only required value in a template specification is the template, which normally * represents the template name, but can be the entire template contents if the template * is meant to be specified as a String and resolved by a * {@link org.thymeleaf.templateresolver.StringTemplateResolver}. *

*

* This is not to be mistaken for the template processing context, containing * the data to be used during the processing of the template (variables, locale, etc.) and * modelled by the {@link org.thymeleaf.context.IContext} interface. *

*

* The data contained in a Template Specification relates to and identifies the template itself, * independently of any data (variables, etc.) used for processing it. *

*

* Objects of this class are thread-safe. *

* * @author Daniel Fernández * * @since 3.0.0 * */ public final class TemplateSpec implements Serializable { private static final long serialVersionUID = 51214133L; private final String template; private final Set templateSelectors; private final TemplateMode templateMode; private final Map templateResolutionAttributes; private final String outputContentType; private final boolean outputSSE; /** *

* Build a new object of this class, specifying template and also template mode. *

*

* The template normally represents the template name, but can be the entire template * contents if the template is meant to be specified as a String and resolved by a * {@link org.thymeleaf.templateresolver.StringTemplateResolver}. *

*

* The template mode only needs to be specified in cases when we want to force a template * mode to be used for a template, independently of the mode that is selected for it by the configured * template resolvers. *

*

* This constructor will set no template selectors or template resolution attributes. *

* * @param template the template (usually the template name), required. * @param templateMode the template mode to be forced, can be null. */ public TemplateSpec(final String template, final TemplateMode templateMode) { this(template, null, templateMode, null, null); } /** *

* Build a new object of this class, specifying template and also output content type * (MIME type). Most of the times this will force a template mode for template execution * (e.g. text/html, application/javascript), but not always (e.g. text/event-stream). *

*

* The template normally represents the template name, but can be the entire template * contents if the template is meant to be specified as a String and resolved by a * {@link org.thymeleaf.templateresolver.StringTemplateResolver}. *

*

* Supported relations between template mode and output content type are: *

*
    *
  • HTML: text/html, application/xhtml+xml
  • *
  • XML: application/xml
  • *
  • JAVASCRIPT: application/javascript, application/x-javascript, * application/ecmascript, text/javascript, * text/ecmascript, application/json
  • *
  • CSS: text/css
  • *
  • TEXT: text/plain
  • *
*

* The text/event-stream content type will also be supported, but will have no effect in * forcing a template mode. Instead, it will put the engine into Server-Sent Event (SSE) output mode. *

*

* Note content type parameters will be ignored (only the mime type itself will be used). *

*

* This constructor will set no template selectors or template resolution attributes. *

* * @param template the template (usually the template name), required. * @param outputContentType the expected output content type, can be null. * * @since 3.0.6 */ public TemplateSpec(final String template, final String outputContentType) { this(template, null, null, outputContentType, null); } /** *

* Build a new object of this class, specifying template and also template mode. *

*

* The template normally represents the template name, but can be the entire template * contents if the template is meant to be specified as a String and resolved by a * {@link org.thymeleaf.templateresolver.StringTemplateResolver}. *

*

* The template resolution attributes are meant to be passed to the template resolvers (see * {@link org.thymeleaf.templateresolver.ITemplateResolver} during template resolution, as a way * of configuring their execution for the template being processed. *

*

* Note that template resolution attributes are considered a part of the identifier of a template, * so they will be used as a part of the keys for cached templates. It is therefore * required that template attribute maps contain values with valid {@link #equals(Object)} * and {@link #hashCode()} implementations. Therefore, using simple (and fast) * Map<String,String> maps is the recommended option. *

*

* This constructor will set no template selectors or forced template mode. *

* * @param template the template (usually the template name), required. * @param templateResolutionAttributes the template resolution attributes, can be null. */ public TemplateSpec(final String template, final Map templateResolutionAttributes) { this(template, null, null, null, templateResolutionAttributes); } /** *

* Build a new object of this class, specifying a template mode that should be forced for template * execution, ignoring the mode resolved by template resolvers. *

*

* The template usually represents the template name, but can be the entire template * contents if the template is meant to be specified as a String and resolved by a * {@link org.thymeleaf.templateresolver.StringTemplateResolver}. *

*

* Template selectors allow the possibility to process only a part of the specified template, expressing * this selection in a syntax similar to jQuery, CSS or XPath selectors. Note this is only available for * markup template modes (HTML, XML). For more info on template selectors * syntax, have a look at AttoParser's markup selectors * documentation. *

*

* The template mode only needs to be specified in cases when we want to force a template * mode to be used for a template, independently of the mode that is selected for it by the configured * template resolvers. *

*

* The template resolution attributes are meant to be passed to the template resolvers (see * {@link org.thymeleaf.templateresolver.ITemplateResolver} during template resolution, as a way * of configuring their execution for the template being processed. *

*

* Note that template resolution attributes are considered a part of the identifier of a template, * so they will be used as a part of the keys for cached templates. It is therefore * required that template attribute maps contain values with valid {@link #equals(Object)} * and {@link #hashCode()} implementations. Therefore, using simple (and fast) * Map<String,String> maps is the recommended option. *

* * @param template the template (usually the template name), required. * @param templateSelectors the template selectors to be applied on the template. * @param templateMode the template mode to be forced, can be null. * @param templateResolutionAttributes the template resolution attributes, can be null. */ public TemplateSpec( final String template, final Set templateSelectors, final TemplateMode templateMode, final Map templateResolutionAttributes) { this(template, templateSelectors, templateMode, null, templateResolutionAttributes); } /** *

* Build a new object of this class, specifying an output content type (MIME type). Most of the times this * will force a template mode for template execution (e.g. text/html, application/javascript), * but not always (e.g. text/event-stream). *

*

* The template usually represents the template name, but can be the entire template * contents if the template is meant to be specified as a String and resolved by a * {@link org.thymeleaf.templateresolver.StringTemplateResolver}. *

*

* Template selectors allow the possibility to process only a part of the specified template, expressing * this selection in a syntax similar to jQuery, CSS or XPath selectors. Note this is only available for * markup template modes (HTML, XML). For more info on template selectors * syntax, have a look at AttoParser's markup selectors * documentation. *

*

* The template resolution attributes are meant to be passed to the template resolvers (see * {@link org.thymeleaf.templateresolver.ITemplateResolver} during template resolution, as a way * of configuring their execution for the template being processed. *

*

* Supported relations between template mode and output content type are: *

*
    *
  • HTML: text/html, application/xhtml+xml
  • *
  • XML: application/xml
  • *
  • JAVASCRIPT: application/javascript, application/x-javascript, * application/ecmascript, text/javascript, * text/ecmascript, application/json
  • *
  • CSS: text/css
  • *
  • TEXT: text/plain
  • *
*

* The text/event-stream content type will also be supported, but will have no effect in * forcing a template mode. Instead, it will put the engine into Server-Sent Event (SSE) output mode. *

*

* Note content type parameters will be ignored (only the mime type itself will be used). *

*

* Note that template resolution attributes are considered a part of the identifier of a template, * so they will be used as a part of the keys for cached templates. It is therefore * required that template attribute maps contain values with valid {@link #equals(Object)} * and {@link #hashCode()} implementations. Therefore, using simple (and fast) * Map<String,String> maps is the recommended option. *

* * @param template the template (usually the template name), required. * @param templateSelectors the template selectors to be applied on the template. * @param outputContentType the expected output content type, can be null. * @param templateResolutionAttributes the template resolution attributes, can be null. * * @since 3.0.6 */ public TemplateSpec( final String template, final Set templateSelectors, final String outputContentType, final Map templateResolutionAttributes) { this(template, templateSelectors, null, outputContentType, templateResolutionAttributes); } /** *

* Build a new object of this class, specifying all its attributes. *

* * @param template the template (usually the template name), required. * @param templateSelectors the template selectors to be applied on the template. * @param templateMode the template mode to be forced, can be null. * @param outputContentType the expected output content type, can be null. * @param templateResolutionAttributes the template resolution attributes, can be null. * * @since 3.0.4 */ TemplateSpec( final String template, final Set templateSelectors, final TemplateMode templateMode, final String outputContentType, final Map templateResolutionAttributes) { super(); Validate.notNull(template, "Template cannot be null"); Validate.isTrue(templateMode == null || outputContentType == null, "If template mode or output content type are specified, the other one cannot"); // templateSelectors CAN be null // templateMode CAN be null // outputContentType CAN be null // templateResolutionAttributes CAN be null // ONLY one of templateMode or outputContentType can be not-null this.template = template; if (templateSelectors != null && !templateSelectors.isEmpty()) { Validate.containsNoEmpties( templateSelectors, "If specified, the Template Selector set cannot contain any nulls or empties"); if (templateSelectors.size() == 1) { this.templateSelectors = Collections.singleton(templateSelectors.iterator().next()); } else { // We will be using a TreeSet because we want the selectors to be ORDERED, so that comparison at the // equals(...) method works alright this.templateSelectors = Collections.unmodifiableSet(new TreeSet(templateSelectors)); } } else { this.templateSelectors = null; } this.templateResolutionAttributes = (templateResolutionAttributes != null && !templateResolutionAttributes.isEmpty()? Collections.unmodifiableMap(new HashMap(templateResolutionAttributes)) : null); this.outputContentType = outputContentType; final TemplateMode computedTemplateMode = ContentTypeUtils.computeTemplateModeForContentType(this.outputContentType); if (computedTemplateMode != null) { this.templateMode = computedTemplateMode; } else { this.templateMode = templateMode; } this.outputSSE = ContentTypeUtils.isContentTypeSSE(this.outputContentType); } /** *

* Returns the template (usually the template name). *

*

* This template normally represents the template name, but can be the entire template * contents if the template is meant to be specified as a String and resolved by a * {@link org.thymeleaf.templateresolver.StringTemplateResolver}. *

* * @return the template. Cannot be null. */ public String getTemplate() { return this.template; } /** *

* Returns whether this spec has template selectors specified or not. *

* * @return true of there are template selectors, false if not. */ public boolean hasTemplateSelectors() { // Checking for null is enough, as we have already processed this in the constructor return this.templateSelectors != null; } /** *

* Returns the template selectors, if there are any. *

*

* Template selectors allow the possibility to process only a part of the specified template, expressing * this selection in a syntax similar to jQuery, CSS or XPath selectors. Note this is only available for * markup template modes (HTML, XML). For more info on template selectors * syntax, have a look at AttoParser's markup selectors * documentation. *

* * @return the template selectors, or null if there are none. */ public Set getTemplateSelectors() { return this.templateSelectors; } /** *

* Returns whether this spec has template mode specified or not. *

* * @return true of there is a template mode, false if not. */ public boolean hasTemplateMode() { return this.templateMode != null; } /** *

* Returns the template mode, if it has been specified. *

*

* The template mode only needs to be specified in cases when we want to force a template * mode to be used for a template, independently of the mode that is selected for it by the configured * template resolvers. *

* * @return the template mode specified, or null if there isn't any. */ public TemplateMode getTemplateMode() { return this.templateMode; } /** *

* Returns whether this spec includes template resolution attributes or not. *

* * @return true of there are template resolution attributes, false if not. */ public boolean hasTemplateResolutionAttributes() { // Checking for null is enough, as we have already processed this in the constructor return this.templateResolutionAttributes != null; } /** *

* Returns the template resolution attributes, if any have been specified. *

*

* The template resolution attributes are meant to be passed to the template resolvers (see * {@link org.thymeleaf.templateresolver.ITemplateResolver} during template resolution, as a way * of configuring their execution for the template being processed. *

*

* Note that template resolution attributes are considered a part of the identifier of a template, * so they will be used as a part of the keys for cached templates. It is therefore * required that template attribute maps contain values with valid {@link #equals(Object)} * and {@link #hashCode()} implementations. Therefore, using simple (and fast) * Map<String,String> maps is the recommended option. *

* * @return the template resolution attributes. */ public Map getTemplateResolutionAttributes() { return this.templateResolutionAttributes; } /** *

* Returns the output content type (MIME type). Most of the times this * will force a template mode for template execution (e.g. text/html, application/javascript), * but not always (e.g. text/event-stream). *

*

* Supported relations between template mode and output content type are: *

*
    *
  • HTML: text/html, application/xhtml+xml
  • *
  • XML: application/xml
  • *
  • JAVASCRIPT: application/javascript, application/x-javascript, * application/ecmascript, text/javascript, * text/ecmascript, application/json
  • *
  • CSS: text/css
  • *
  • TEXT: text/plain
  • *
*

* The text/event-stream content type will also be supported, but will have no effect in * forcing a template mode. Instead, it will put the engine into Server-Sent Event (SSE) output mode. *

*

* Note content type parameters will be ignored (only the mime type itself will be used). *

* * @return the output content type, or null if none was specified. */ public String getOutputContentType() { return this.outputContentType; } /** *

* Returns whether output should be Server-Sent Events (SSE) or not. *

*

* Server-Sent Events mode is enabled by setting the text/event-stream mime type * as *output content type* constructor argument. *

* * @return true if output is supposed to be done via Server-Sent Events (SSE), false if not. * * @since 3.0.6 */ public boolean isOutputSSE() { return this.outputSSE; } @Override public boolean equals(final Object o) { if (this == o) { return true; } if (!(o instanceof TemplateSpec)) { return false; } final TemplateSpec that = (TemplateSpec) o; if (!this.template.equals(that.template)) { return false; } if (this.templateSelectors != null ? !this.templateSelectors.equals(that.templateSelectors) : that.templateSelectors != null) { return false; } if (this.templateMode != that.templateMode) { return false; } if (!this.outputContentType.equals(that.outputContentType)) { return false; } // Note how it is important that template resolution attribute values correctly implement equals() and hashCode() return !(this.templateResolutionAttributes != null ? !this.templateResolutionAttributes.equals(that.templateResolutionAttributes) : that.templateResolutionAttributes != null); } @Override public int hashCode() { int result = this.template.hashCode(); result = 31 * result + (this.templateSelectors != null ? this.templateSelectors.hashCode() : 0); result = 31 * result + (this.templateMode != null ? this.templateMode.hashCode() : 0); result = 31 * result + (this.outputContentType != null ? this.outputContentType.hashCode() : 0); result = 31 * result + (this.templateResolutionAttributes != null ? this.templateResolutionAttributes.hashCode() : 0); return result; } @Override public String toString() { final StringBuilder strBuilder = new StringBuilder(); strBuilder.append(LoggingUtils.loggifyTemplateName(this.template)); if (this.templateSelectors != null) { strBuilder.append("::"); strBuilder.append(this.templateSelectors); } if (this.templateMode != null) { strBuilder.append(" @"); strBuilder.append(this.templateMode); } if (this.templateResolutionAttributes != null) { strBuilder.append(" ("); strBuilder.append(this.templateResolutionAttributes); strBuilder.append(")"); } if (this.outputContentType != null) { strBuilder.append(" ["); strBuilder.append(this.outputContentType); strBuilder.append("]"); } return strBuilder.toString(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy