Search in sources :

Example 1 with ITemplateParser

use of org.thymeleaf.templateparser.ITemplateParser in project sling by apache.

the class TemplateManager method parseStandalone.

/*
     * -------------
     * PARSE methods
     * -------------
     *
     * Parse methods will create 'template models' that are basically collections of events in the form of an
     * immutable IModel implementation.
     */
public TemplateModel parseStandalone(final ITemplateContext context, final String template, final Set<String> templateSelectors, final TemplateMode templateMode, final boolean useCache, final boolean failIfNotExists) {
    Validate.notNull(context, "Context cannot be null");
    Validate.notNull(template, "Template cannot be null");
    // templateSelectors CAN be null if we are going to render the entire template
    // templateMode CAN be null if we are going to use the mode specified by the template resolver
    // templateResolutionAttributes CAN be null
    final String ownerTemplate = context.getTemplateData().getTemplate();
    final Map<String, Object> templateResolutionAttributes = context.getTemplateResolutionAttributes();
    final Set<String> cleanTemplateSelectors;
    if (templateSelectors != null && !templateSelectors.isEmpty()) {
        Validate.containsNoEmpties(templateSelectors, "If specified, the Template Selector set cannot contain any nulls or empties");
        if (templateSelectors.size() == 1) {
            cleanTemplateSelectors = 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
            cleanTemplateSelectors = Collections.unmodifiableSet(new TreeSet<String>(templateSelectors));
        }
    } else {
        cleanTemplateSelectors = null;
    }
    final TemplateCacheKey cacheKey = useCache ? new TemplateCacheKey(ownerTemplate, template, cleanTemplateSelectors, 0, 0, templateMode, templateResolutionAttributes) : null;
    /*
         * First look at the cache - it might be already cached
         */
    if (useCache && this.templateCache != null) {
        final TemplateModel cached = this.templateCache.get(cacheKey);
        if (cached != null) {
            /*
                 * Just at the end, and importantly AFTER CACHING, check if we need to apply any pre-processors
                 * to this model before returning and letting the engine insert the model in any way it needs.
                 */
            return applyPreProcessorsIfNeeded(context, cached);
        }
    }
    /*
         * Resolve the template
         */
    final TemplateResolution templateResolution = resolveTemplate(this.configuration, context, ownerTemplate, template, templateResolutionAttributes, failIfNotExists);
    /*
         * Once the template has been resolved (or tried to), and depending on the value of our 'failIfNotExists'
         * flag, we will check two conditions in which we will be returning null:
         *
         *    1. No template resolver has been able to resolve the template (this can happen if resolvers are
         *       configured with the 'checkExistence' flag to true).
         *    2. If the template was resolved, its existence should be checked in order to avoid exceptions during
         *       the reading phase.
         *
         * NOTE we will not cache this "null" result because the fact that a template is cacheable or not is
         * determined by template resolvers. And in this case there is no template resolver being applied
         * (actually, we are here because no resolver had success).
         */
    if (!failIfNotExists) {
        if (templateResolution == null) {
            // No resolver could resolve this
            return null;
        }
        if (!templateResolution.isTemplateResourceExistenceVerified()) {
            final ITemplateResource resource = templateResolution.getTemplateResource();
            if (resource == null || !resource.exists()) {
                // has not been cached (e.g. when it does not exist)
                return null;
            }
        }
    }
    /*
         * Build the TemplateData object
         */
    final TemplateData templateData = buildTemplateData(templateResolution, template, cleanTemplateSelectors, templateMode, useCache);
    /*
         *  Create the Template Handler that will be in charge of building the TemplateModel
         */
    final ModelBuilderTemplateHandler builderHandler = new ModelBuilderTemplateHandler(this.configuration, templateData);
    /*
         * PROCESS THE TEMPLATE
         */
    final ITemplateParser parser = getParserForTemplateMode(templateData.getTemplateMode());
    parser.parseStandalone(this.configuration, ownerTemplate, template, cleanTemplateSelectors, templateData.getTemplateResource(), templateData.getTemplateMode(), templateResolution.getUseDecoupledLogic(), builderHandler);
    final TemplateModel templateModel = builderHandler.getModel();
    /*
         * Cache the template if it is cacheable
         */
    if (useCache && this.templateCache != null) {
        if (templateResolution.getValidity().isCacheable()) {
            this.templateCache.put(cacheKey, templateModel);
        }
    }
    /*
         * Last step: just at the end, and importantly AFTER CACHING, check if we need to apply any pre-processors
         * to this model before returning and letting the engine insert the model in any way it needs.
         */
    return applyPreProcessorsIfNeeded(context, templateModel);
}
Also used : ITemplateParser(org.thymeleaf.templateparser.ITemplateParser) TemplateCacheKey(org.thymeleaf.cache.TemplateCacheKey) TreeSet(java.util.TreeSet) TemplateResolution(org.thymeleaf.templateresolver.TemplateResolution) ITemplateResource(org.thymeleaf.templateresource.ITemplateResource)

Example 2 with ITemplateParser

use of org.thymeleaf.templateparser.ITemplateParser in project sling by apache.

the class TemplateManager method parseAndProcess.

/*
     * -------------------------
     * PARSE-AND-PROCESS methods
     * -------------------------
     *
     * These methods perform the whole cycle of a template's processing: resolving, parsing and processing.
     * This is only meant to be called from the TemplateEngine
     */
public void parseAndProcess(final TemplateSpec templateSpec, final IContext context, final Writer writer) {
    Validate.notNull(templateSpec, "Template Specification cannot be null");
    Validate.notNull(context, "Context cannot be null");
    Validate.notNull(writer, "Writer cannot be null");
    // TemplateSpec will already have validated its contents, so need to do it here (template selectors,
    // resolution attributes, etc.)
    final String template = templateSpec.getTemplate();
    final Set<String> templateSelectors = templateSpec.getTemplateSelectors();
    final TemplateMode templateMode = templateSpec.getTemplateMode();
    final Map<String, Object> templateResolutionAttributes = templateSpec.getTemplateResolutionAttributes();
    final TemplateCacheKey cacheKey = new TemplateCacheKey(// ownerTemplate
    null, template, templateSelectors, // lineOffset, colOffset
    0, // lineOffset, colOffset
    0, templateMode, templateResolutionAttributes);
    /*
         * First look at the cache - it might be already cached
         */
    if (this.templateCache != null) {
        final TemplateModel cached = this.templateCache.get(cacheKey);
        if (cached != null) {
            final IEngineContext engineContext = EngineContextManager.prepareEngineContext(this.configuration, cached.getTemplateData(), templateResolutionAttributes, context);
            /*
                 * Create the handler chain to process the data.
                 * This is PARSE + PROCESS, so its called from the TemplateEngine, and the only case in which we should apply
                 * both pre-processors and post-processors (besides creating a last output-to-writer step)
                 */
            final ProcessorTemplateHandler processorTemplateHandler = new ProcessorTemplateHandler();
            final ITemplateHandler processingHandlerChain = createTemplateProcessingHandlerChain(engineContext, true, true, processorTemplateHandler, writer);
            cached.process(processingHandlerChain);
            EngineContextManager.disposeEngineContext(engineContext);
            return;
        }
    }
    /*
         * Resolve the template
         */
    final TemplateResolution templateResolution = resolveTemplate(this.configuration, context, null, template, templateResolutionAttributes, true);
    /*
         * Build the TemplateData object
         */
    final TemplateData templateData = buildTemplateData(templateResolution, template, templateSelectors, templateMode, true);
    /*
         * Prepare the context instance that corresponds to this execution of the template engine
         */
    final IEngineContext engineContext = EngineContextManager.prepareEngineContext(this.configuration, templateData, templateResolutionAttributes, context);
    /*
         * Create the handler chain to process the data.
         * This is PARSE + PROCESS, so its called from the TemplateEngine, and the only case in which we should apply
         * both pre-processors and post-processors (besides creating a last output-to-writer step)
         */
    final ProcessorTemplateHandler processorTemplateHandler = new ProcessorTemplateHandler();
    final ITemplateHandler processingHandlerChain = createTemplateProcessingHandlerChain(engineContext, true, true, processorTemplateHandler, writer);
    /*
         * Obtain the parser
         */
    final ITemplateParser parser = getParserForTemplateMode(engineContext.getTemplateMode());
    /*
         * If the resolved template is cacheable, so we will first read it as an object, cache it, and then process it
         */
    if (templateResolution.getValidity().isCacheable() && this.templateCache != null) {
        // Create the handler chain to create the Template object
        final ModelBuilderTemplateHandler builderHandler = new ModelBuilderTemplateHandler(this.configuration, templateData);
        // Process the template into a TemplateModel
        parser.parseStandalone(this.configuration, null, template, templateSelectors, templateData.getTemplateResource(), engineContext.getTemplateMode(), templateResolution.getUseDecoupledLogic(), builderHandler);
        // Obtain the TemplateModel
        final TemplateModel templateModel = builderHandler.getModel();
        // Put the new template into cache
        this.templateCache.put(cacheKey, templateModel);
        // Process the read (+cached) template itself
        templateModel.process(processingHandlerChain);
    } else {
        //  Process the template, which is not cacheable (so no worry about caching)
        parser.parseStandalone(this.configuration, null, template, templateSelectors, templateData.getTemplateResource(), engineContext.getTemplateMode(), templateResolution.getUseDecoupledLogic(), processingHandlerChain);
    }
    /*
         * Dispose the engine context now that processing has been done
         */
    EngineContextManager.disposeEngineContext(engineContext);
}
Also used : TemplateMode(org.thymeleaf.templatemode.TemplateMode) TemplateCacheKey(org.thymeleaf.cache.TemplateCacheKey) TemplateResolution(org.thymeleaf.templateresolver.TemplateResolution) ITemplateParser(org.thymeleaf.templateparser.ITemplateParser) IEngineContext(org.thymeleaf.context.IEngineContext)

Example 3 with ITemplateParser

use of org.thymeleaf.templateparser.ITemplateParser in project sling by apache.

the class TemplateManager method parseString.

public TemplateModel parseString(final TemplateData ownerTemplateData, final String template, final int lineOffset, final int colOffset, final TemplateMode templateMode, final boolean useCache) {
    Validate.notNull(ownerTemplateData, "Owner template cannot be null");
    Validate.notNull(template, "Template cannot be null");
    // NOTE selectors cannot be specified when parsing a nested template
    // templateMode CAN be null (if we are using the owner's)
    final String ownerTemplate = ownerTemplateData.getTemplate();
    final TemplateMode definitiveTemplateMode = (templateMode != null ? templateMode : ownerTemplateData.getTemplateMode());
    final TemplateCacheKey cacheKey = useCache ? new TemplateCacheKey(ownerTemplate, template, null, lineOffset, colOffset, definitiveTemplateMode, // template resolution attributes do not affect string fragments: no resolution!
    null) : null;
    /*
         * First look at the cache - it might be already cached
         */
    if (useCache && this.templateCache != null) {
        final TemplateModel cached = this.templateCache.get(cacheKey);
        if (cached != null) {
            return cached;
        }
    }
    /*
         * Compute the cache validity. In order for a String fragment to be cacheable, we will have to have
         * specified the 'useCache' parameter as true, and the owner template must be cacheable
         */
    final ICacheEntryValidity cacheValidity = (useCache && ownerTemplateData.getValidity().isCacheable() ? AlwaysValidCacheEntryValidity.INSTANCE : NonCacheableCacheEntryValidity.INSTANCE);
    /*
         * Build the TemplateData
         *
         * NOTE how, by default, we are using the owner's TemplateData. And even if the template mode changes
         * and we need to create a new TemplateData object, we will keep the original name and resource.
         * This is because we want the elements inside the fragment to me reported as belonging to the
         * container template, not to the fragment String considered as a fragment in its own (which
         * wouldn't make sense)
         */
    final TemplateData templateData = (templateMode == null ? // No change in Template Mode -> simply use the owner's template data
    ownerTemplateData : // Template Mode changed -> new TemplateData, very similar but different template mode
    new TemplateData(ownerTemplateData.getTemplate(), ownerTemplateData.getTemplateSelectors(), ownerTemplateData.getTemplateResource(), templateMode, cacheValidity));
    /*
         * Create the Template Handler that will be in charge of building the TemplateModel
         *
         * NOTE how we are using the owner's TemplateData and not a new one created for this fragment, because
         * we want the elements inside the fragment to me reported as belonging to the container template,
         * not to the fragment String considered as a fragment in its own (which wouldn't make sense)
         */
    final ModelBuilderTemplateHandler builderHandler = new ModelBuilderTemplateHandler(this.configuration, templateData);
    /*
         * PROCESS THE TEMPLATE
         */
    final ITemplateParser parser = getParserForTemplateMode(templateData.getTemplateMode());
    // NO RESOURCE is sent to the parser, in this case. We simply pass the String template
    parser.parseString(this.configuration, ownerTemplate, template, lineOffset, colOffset, definitiveTemplateMode, builderHandler);
    final TemplateModel parsedTemplate = builderHandler.getModel();
    /*
         * Cache the template if it is cacheable
         */
    if (useCache && this.templateCache != null) {
        if (cacheValidity.isCacheable()) {
            this.templateCache.put(cacheKey, parsedTemplate);
        }
    }
    return parsedTemplate;
}
Also used : ITemplateParser(org.thymeleaf.templateparser.ITemplateParser) TemplateMode(org.thymeleaf.templatemode.TemplateMode) TemplateCacheKey(org.thymeleaf.cache.TemplateCacheKey) ICacheEntryValidity(org.thymeleaf.cache.ICacheEntryValidity)

Example 4 with ITemplateParser

use of org.thymeleaf.templateparser.ITemplateParser in project sling by apache.

the class TemplateManager method parseAndProcessThrottled.

public ThrottledTemplateProcessor parseAndProcessThrottled(final TemplateSpec templateSpec, final IContext context) {
    Validate.notNull(templateSpec, "Template Specification cannot be null");
    Validate.notNull(context, "Context cannot be null");
    // TemplateSpec will already have validated its contents, so need to do it here (template selectors,
    // resolution attributes, etc.)
    final String template = templateSpec.getTemplate();
    final Set<String> templateSelectors = templateSpec.getTemplateSelectors();
    final TemplateMode templateMode = templateSpec.getTemplateMode();
    final Map<String, Object> templateResolutionAttributes = templateSpec.getTemplateResolutionAttributes();
    final TemplateCacheKey cacheKey = new TemplateCacheKey(// ownerTemplate
    null, template, templateSelectors, // lineOffset, colOffset
    0, // lineOffset, colOffset
    0, templateMode, templateResolutionAttributes);
    /*
         * Instantiate the throttling artifacts
         */
    final TemplateFlowController flowController = new TemplateFlowController();
    final ThrottledTemplateWriter throttledTemplateWriter = new ThrottledTemplateWriter(template, flowController);
    /*
         * First look at the cache - it might be already cached
         */
    if (this.templateCache != null) {
        final TemplateModel cached = this.templateCache.get(cacheKey);
        if (cached != null) {
            final IEngineContext engineContext = EngineContextManager.prepareEngineContext(this.configuration, cached.getTemplateData(), templateResolutionAttributes, context);
            /*
                 * Create the handler chain to process the data.
                 * This is PARSE + PROCESS, so its called from the TemplateEngine, and the only case in which we should apply
                 * both pre-processors and post-processors (besides creating a last output-to-writer step)
                 */
            final ProcessorTemplateHandler processorTemplateHandler = new ProcessorTemplateHandler();
            processorTemplateHandler.setFlowController(flowController);
            final ITemplateHandler processingHandlerChain = createTemplateProcessingHandlerChain(engineContext, true, true, processorTemplateHandler, throttledTemplateWriter);
            /*
                 * Return the throttled template processor
                 */
            return new ThrottledTemplateProcessor(templateSpec, engineContext, cached, processingHandlerChain, processorTemplateHandler, flowController, throttledTemplateWriter);
        }
    }
    /*
         * Resolve the template
         */
    final TemplateResolution templateResolution = resolveTemplate(this.configuration, context, null, template, templateResolutionAttributes, true);
    /*
         * Build the TemplateData object
         */
    final TemplateData templateData = buildTemplateData(templateResolution, template, templateSelectors, templateMode, true);
    /*
         * Prepare the context instance that corresponds to this execution of the template engine
         */
    final IEngineContext engineContext = EngineContextManager.prepareEngineContext(this.configuration, templateData, templateResolutionAttributes, context);
    /*
         * Create the handler chain to process the data.
         * This is PARSE + PROCESS, so its called from the TemplateEngine, and the only case in which we should apply
         * both pre-processors and post-processors (besides creating a last output-to-writer step)
         */
    final ProcessorTemplateHandler processorTemplateHandler = new ProcessorTemplateHandler();
    processorTemplateHandler.setFlowController(flowController);
    final ITemplateHandler processingHandlerChain = createTemplateProcessingHandlerChain(engineContext, true, true, processorTemplateHandler, throttledTemplateWriter);
    /*
         * Obtain the parser
         */
    final ITemplateParser parser = getParserForTemplateMode(engineContext.getTemplateMode());
    /*
         * Parse the template into a TemplateModel. Even if we are not using the cache, throttled template processings
         * will always be processed first into a TemplateModel, so that throttling can then be applied on an
         * already-in-memory sequence of events
         */
    final ModelBuilderTemplateHandler builderHandler = new ModelBuilderTemplateHandler(this.configuration, templateData);
    parser.parseStandalone(this.configuration, null, template, templateSelectors, templateData.getTemplateResource(), engineContext.getTemplateMode(), templateResolution.getUseDecoupledLogic(), builderHandler);
    final TemplateModel templateModel = builderHandler.getModel();
    /*
         * If cache is active, put the cached TemplateModel into cache
         */
    if (templateResolution.getValidity().isCacheable() && this.templateCache != null) {
        // Put the new template into cache
        this.templateCache.put(cacheKey, templateModel);
    }
    /*
         * Return the throttled template processor
         */
    return new ThrottledTemplateProcessor(templateSpec, engineContext, templateModel, processingHandlerChain, processorTemplateHandler, flowController, throttledTemplateWriter);
}
Also used : TemplateMode(org.thymeleaf.templatemode.TemplateMode) TemplateCacheKey(org.thymeleaf.cache.TemplateCacheKey) TemplateResolution(org.thymeleaf.templateresolver.TemplateResolution) ITemplateParser(org.thymeleaf.templateparser.ITemplateParser) IEngineContext(org.thymeleaf.context.IEngineContext)

Aggregations

TemplateCacheKey (org.thymeleaf.cache.TemplateCacheKey)4 ITemplateParser (org.thymeleaf.templateparser.ITemplateParser)4 TemplateMode (org.thymeleaf.templatemode.TemplateMode)3 TemplateResolution (org.thymeleaf.templateresolver.TemplateResolution)3 IEngineContext (org.thymeleaf.context.IEngineContext)2 TreeSet (java.util.TreeSet)1 ICacheEntryValidity (org.thymeleaf.cache.ICacheEntryValidity)1 ITemplateResource (org.thymeleaf.templateresource.ITemplateResource)1