
com.mitchellbosecke.pebble.template.EvaluationContext Maven / Gradle / Ivy
/*******************************************************************************
* This file is part of Pebble.
*
* Copyright (c) 2014 by Mitchell Bösecke
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
******************************************************************************/
package com.mitchellbosecke.pebble.template;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import com.mitchellbosecke.pebble.extension.Filter;
import com.mitchellbosecke.pebble.extension.Function;
import com.mitchellbosecke.pebble.extension.Test;
/**
* An evaluation context will store all stateful data that is necessary for the
* evaluation of a template. Passing the entire state around will assist with
* thread safety.
*
* @author Mitchell
*
*/
public class EvaluationContext {
private final boolean strictVariables;
/**
* A template will look to it's parent and children for overridden macros
* and other features; this inheritance chain will help the template keep
* track of where in the inheritance chain it currently is.
*/
private final InheritanceChain inheritanceChain;
/**
* A scope is a set of visible variables. A trivial template will only have
* one scope. New scopes are added with for loops and macros for example.
*
* Most scopes will have a link to their parent scope which allow an
* evaluation to look up the scope chain for variables. A macro is an
* exception to this as it only has access to it's local variables.
*/
private final ScopeChain scopeChain;
/**
* The locale of this template. Will be used by LocaleAware filters,
* functions, etc.
*/
private final Locale locale;
/**
* All the available filters for this template.
*/
private final Map filters;
/**
* All the available tests for this template.
*/
private final Map tests;
/**
* All the available functions for this template.
*/
private final Map functions;
/**
* The user-provided ExecutorService (can be null).
*/
private final ExecutorService executorService;
/**
* The imported templates are used to look up macros.
*/
private final List importedTemplates = new ArrayList<>();
/**
* Constructor used to provide all final variables.
*
* @param self
* The template implementation
* @param strictVariables
* Whether strict variables is to be used
* @param locale
* The locale of the template
* @param filters
* Available filters
* @param tests
* Available tests
* @param functions
* Available functions
* @param executorService
* The optional executor service
* @param scopeChain
* The scope chain
* @param inheritanceChain
* The inheritance chain
*/
public EvaluationContext(PebbleTemplateImpl self, boolean strictVariables, Locale locale,
Map filters, Map tests, Map functions,
ExecutorService executorService, ScopeChain scopeChain, InheritanceChain inheritanceChain) {
if (inheritanceChain == null) {
inheritanceChain = new InheritanceChain(self);
}
this.strictVariables = strictVariables;
this.locale = locale;
this.filters = filters;
this.tests = tests;
this.functions = functions;
this.executorService = executorService;
this.scopeChain = scopeChain;
this.inheritanceChain = inheritanceChain;
}
/**
* Makes an exact copy of the evaluation context EXCEPT for the inheritance
* chain. This is necessary for the "include" tag.
*
* @param self
* The template implementation
* @return A copy of the evaluation context
*/
public EvaluationContext shallowCopyWithoutInheritanceChain(PebbleTemplateImpl self) {
EvaluationContext result = new EvaluationContext(self, strictVariables, locale, filters, tests, functions,
executorService, scopeChain, null);
return result;
}
/**
* Makes an exact copy of the evaluation context except the "scopeChain"
* object will be a deep copy without reference to the original. This is
* used for the "parallel" tag.
*
* @param self
* The template implementation
* @return A copy of the evaluation context
*/
public EvaluationContext deepCopy(PebbleTemplateImpl self) {
EvaluationContext result = new EvaluationContext(self, strictVariables, locale, filters, tests, functions,
executorService, scopeChain.deepCopy(), inheritanceChain);
return result;
}
/**
* This method might be called DURING the evaluation of a template (ex. for
* node, set node, and macro node) and must be thread safe in case there are
* multiple threads evaluating the same template (via parallel tag).
*
* @param key
* Key
* @param value
* Value
*/
public void put(String key, Object value) {
scopeChain.put(key, value);
}
/**
* Will look for a variable, traveling upwards through the scope chain until
* it is found.
*
* @param key
* Key
* @return The object, if found
*/
public Object get(String key) {
return scopeChain.get(key);
}
public void ascendInheritanceChain() {
inheritanceChain.ascend();
}
public void descendInheritanceChain() {
inheritanceChain.descend();
}
public PebbleTemplateImpl getParentTemplate() {
return inheritanceChain.getParent();
}
public PebbleTemplateImpl getChildTemplate() {
return inheritanceChain.getChild();
}
/**
* Creates a new scope that contains a reference to the current scope.
*/
public void pushScope() {
pushScope(new HashMap());
}
public void pushScope(Map map) {
scopeChain.pushScope(map);
}
public boolean currentScopeContainsVariable(String variableName) {
return scopeChain.currentScopeContainsVariable(variableName);
}
/**
* Pushes a new scope that doesn't contain a reference to the current scope.
* This occurs for macros. Variable lookup will end at this scope.
*/
public void pushLocalScope() {
scopeChain.pushLocalScope();
}
public void popScope() {
scopeChain.popScope();
}
public boolean isStrictVariables() {
return strictVariables;
}
public Locale getLocale() {
return locale;
}
public Map getTests() {
return tests;
}
public Map getFilters() {
return filters;
}
public Map getFunctions() {
return functions;
}
public ExecutorService getExecutorService() {
return executorService;
}
public void addImportedTemplate(PebbleTemplateImpl template) {
this.importedTemplates.add(template);
}
public List getImportedTemplates() {
return this.importedTemplates;
}
public void setParent(PebbleTemplateImpl parent) {
inheritanceChain.pushAncestor(parent);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy