Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow override core operators #456

Merged
merged 1 commit into from
Aug 8, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 41 additions & 15 deletions pebble/src/main/java/com/mitchellbosecke/pebble/PebbleEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,8 @@ public class PebbleEngine {
* Constructor for the Pebble Engine given an instantiated Loader. This method does only load
* those userProvidedExtensions listed here.
*
* @param loader The template loader for this engine
* @param syntax the syntax to use for parsing the templates.
* @param extensions The userProvidedExtensions which should be loaded.
* @param loader The template loader for this engine
* @param syntax the syntax to use for parsing the templates.
*/
private PebbleEngine(Loader<?> loader,
Syntax syntax,
Expand All @@ -90,7 +89,7 @@ private PebbleEngine(Loader<?> loader,
PebbleCache<CacheKey, Object> tagCache,
PebbleCache<Object, PebbleTemplate> templateCache,
ExecutorService executorService,
Collection<? extends Extension> extensions,
ExtensionRegistry extensionRegistry,
ParserOptions parserOptions,
EvaluationOptions evaluationOptions) {

Expand All @@ -101,7 +100,7 @@ private PebbleEngine(Loader<?> loader,
this.tagCache = tagCache;
this.executorService = executorService;
this.templateCache = templateCache;
this.extensionRegistry = new ExtensionRegistry(extensions);
this.extensionRegistry = extensionRegistry;
this.parserOptions = parserOptions;
this.evaluationOptions = evaluationOptions;
}
Expand Down Expand Up @@ -283,6 +282,8 @@ public static class Builder {

private boolean greedyMatchMethod = false;

private boolean allowOverrideCoreOperators = false;

/**
* Creates the builder.
*/
Expand Down Expand Up @@ -422,6 +423,17 @@ public Builder autoEscaping(boolean autoEscaping) {
return this;
}

/**
* Sets whether or not core operators overrides should be allowed.
*
* @param allowOverrideCoreOperators Whether or not core operators overrides should be allowed.
* @return This builder object
*/
public Builder allowOverrideCoreOperators(boolean allowOverrideCoreOperators) {
this.allowOverrideCoreOperators = allowOverrideCoreOperators;
return this;
}

/**
* Sets the default escaping strategy of the built-in escaper extension.
*
Expand All @@ -436,7 +448,7 @@ public Builder defaultEscapingStrategy(String strategy) {
/**
* Adds an escaping strategy to the built-in escaper extension.
*
* @param name The name of the escaping strategy
* @param name The name of the escaping strategy
* @param strategy The strategy implementation
* @return This builder object
*/
Expand Down Expand Up @@ -472,7 +484,7 @@ public Builder allowGetClass(boolean allowGetClass) {
* Enable/disable treat literal decimal as Integer. Default is disabled, treated as Long.
*
* @param literalDecimalTreatedAsInteger toggle to enable/disable literal decimal treated as
* integer
* integer
* @return This builder object
*/
public Builder literalDecimalTreatedAsInteger(boolean literalDecimalTreatedAsInteger) {
Expand Down Expand Up @@ -513,13 +525,7 @@ public Builder greedyMatchMethod(boolean greedyMatchMethod) {
*/
public PebbleEngine build() {

// core extensions
List<Extension> extensions = new ArrayList<>();
extensions.add(new CoreExtension());
extensions.add(this.escaperExtension);
extensions.add(new I18nExtension());
extensions.addAll(this.userProvidedExtensions);
extensions.add(new AttributeResolverExtension());
ExtensionRegistry extensionRegistry = buildExtensionRegistry();

// default loader
if (this.loader == null) {
Expand Down Expand Up @@ -562,7 +568,27 @@ public PebbleEngine build() {

return new PebbleEngine(this.loader, this.syntax, this.strictVariables, this.defaultLocale,
this.tagCache, this.templateCache,
this.executorService, extensions, parserOptions, evaluationOptions);
this.executorService, extensionRegistry, parserOptions, evaluationOptions);
}

private ExtensionRegistry buildExtensionRegistry() {
ExtensionRegistry extensionRegistry = new ExtensionRegistry();

extensionRegistry.addExtension(new CoreExtension());
extensionRegistry.addExtension(this.escaperExtension);
extensionRegistry.addExtension(new I18nExtension());

for (Extension userProvidedExtension : this.userProvidedExtensions) {
if (allowOverrideCoreOperators) {
extensionRegistry.addOperatorOverridingExtension(userProvidedExtension);
} else {
extensionRegistry.addExtension(userProvidedExtension);
}
}

extensionRegistry.addExtension(new AttributeResolverExtension());

return extensionRegistry;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,74 +59,91 @@ public class ExtensionRegistry {

private final List<AttributeResolver> attributeResolver = new ArrayList<>();

public ExtensionRegistry() {
}

public ExtensionRegistry(Collection<? extends Extension> extensions) {

for (Extension extension : extensions) {
// token parsers
List<TokenParser> tokenParsers = extension.getTokenParsers();
if (tokenParsers != null) {
for (TokenParser tokenParser : tokenParsers) {
this.tokenParsers.put(tokenParser.getTag(), tokenParser);
}
addExtension(extension);
}
}

public void addOperatorOverridingExtension(Extension extension) {
addExtension(extension, true);
}

public void addExtension(Extension extension) {
addExtension(extension, false);
}

private void addExtension(Extension extension, boolean operatorOverriding) {
// token parsers
List<TokenParser> tokenParsers = extension.getTokenParsers();
if (tokenParsers != null) {
for (TokenParser tokenParser : tokenParsers) {
this.tokenParsers.put(tokenParser.getTag(), tokenParser);
}
}

// binary operators
List<BinaryOperator> binaryOperators = extension.getBinaryOperators();
if (binaryOperators != null) {
for (BinaryOperator operator : binaryOperators) {
if (!this.binaryOperators
.containsKey(operator.getSymbol())) { // disallow overriding core operators
this.binaryOperators.put(operator.getSymbol(), operator);
}
// binary operators
List<BinaryOperator> binaryOperators = extension.getBinaryOperators();
if (binaryOperators != null) {
for (BinaryOperator operator : binaryOperators) {
if (operatorOverriding) {
this.binaryOperators.put(operator.getSymbol(), operator);
} else {
this.binaryOperators.putIfAbsent(operator.getSymbol(), operator);
}
}
}

// unary operators
List<UnaryOperator> unaryOperators = extension.getUnaryOperators();
if (unaryOperators != null) {
for (UnaryOperator operator : unaryOperators) {
if (!this.unaryOperators
.containsKey(operator.getSymbol())) { // disallow override core operators
this.unaryOperators.put(operator.getSymbol(), operator);
}
// unary operators
List<UnaryOperator> unaryOperators = extension.getUnaryOperators();
if (unaryOperators != null) {
for (UnaryOperator operator : unaryOperators) {
if (operatorOverriding) {
this.unaryOperators.put(operator.getSymbol(), operator);
} else {
this.unaryOperators.putIfAbsent(operator.getSymbol(), operator);
}
}
}

// filters
Map<String, Filter> filters = extension.getFilters();
if (filters != null) {
this.filters.putAll(filters);
}
// filters
Map<String, Filter> filters = extension.getFilters();
if (filters != null) {
this.filters.putAll(filters);
}

// tests
Map<String, Test> tests = extension.getTests();
if (tests != null) {
this.tests.putAll(tests);
}
// tests
Map<String, Test> tests = extension.getTests();
if (tests != null) {
this.tests.putAll(tests);
}

// tests
Map<String, Function> functions = extension.getFunctions();
if (functions != null) {
this.functions.putAll(functions);
}
// functions
Map<String, Function> functions = extension.getFunctions();
if (functions != null) {
this.functions.putAll(functions);
}

// global variables
Map<String, Object> globalVariables = extension.getGlobalVariables();
if (globalVariables != null) {
this.globalVariables.putAll(globalVariables);
}
// global variables
Map<String, Object> globalVariables = extension.getGlobalVariables();
if (globalVariables != null) {
this.globalVariables.putAll(globalVariables);
}

// node visitors
List<NodeVisitorFactory> nodeVisitors = extension.getNodeVisitors();
if (nodeVisitors != null) {
this.nodeVisitors.addAll(nodeVisitors);
}
// node visitors
List<NodeVisitorFactory> nodeVisitors = extension.getNodeVisitors();
if (nodeVisitors != null) {
this.nodeVisitors.addAll(nodeVisitors);
}

// attribute resolver
List<AttributeResolver> attributeResolvers = extension.getAttributeResolver();
if (attributeResolvers != null) {
this.attributeResolver.addAll(attributeResolvers);
}
// attribute resolver
List<AttributeResolver> attributeResolvers = extension.getAttributeResolver();
if (attributeResolvers != null) {
this.attributeResolver.addAll(attributeResolvers);
}
}

Expand Down
Loading