JexlFeatures.java
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.commons.jexl3;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Predicate;
/**
* A set of language feature options.
* <p>
* These control <em>syntactical</em> constructs that will throw JexlException.Feature exceptions (a
* subclass of JexlException.Parsing) when disabled.
* </p>
* <p>It is recommended to be explicit in choosing the features you need rather than rely on the default
* constructor: the 2 convenience methods {@link JexlFeatures#createNone()} and {@link JexlFeatures#createAll()}
* are the recommended starting points to selectively enable or disable chosen features.</p>
* <ul>
* <li>Registers: register syntax (#number), used internally for {g,s}etProperty
* <li>Reserved Names: a set of reserved variable names that can not be used as local variable (or parameter) names
* <li>Global Side Effect : assigning/modifying values on global variables (=, += , -=, ...)
* <li>Lexical: lexical scope, prevents redefining local variables
* <li>Lexical Shade: local variables shade globals, prevents confusing a global variable with a local one
* <li>Side Effect : assigning/modifying values on any variables or left-value
* <li>Constant Array Reference: ensures array references only use constants;they should be statically solvable.
* <li>New Instance: creating an instance using new(...)
* <li>Loops: loop constructs (while(true), for(...))
* <li>Lambda: function definitions (()->{...}, function(...) ).
* <li>Method calls: calling methods (obj.method(...) or obj['method'](...)); when disabled, leaves function calls
* - including namespace prefixes - available
* <li>Structured literals: arrays, lists, maps, sets, ranges
* <li>Pragma: pragma construct as in <code>#pragma x y</code>
* <li>Annotation: @annotation statement;
* <li>Thin-arrow: use the thin-arrow, ie <code>-></code> for lambdas as in <code>x -> x + x</code>
* <li>Fat-arrow: use the fat-arrow, ie <code>=></code> for lambdas as in <code>x => x + x</code>
* <li>Namespace pragma: whether the <code>#pragma jexl.namespace.ns namespace</code> syntax is allowed</li>
* <li>Import pragma: whether the <code>#pragma jexl.import fully.qualified.class.name</code> syntax is allowed</li>
* <li>Comparator names: whether the comparator operator names can be used (as in <code>gt</code> for >,
* <code>lt</code> for <, ...)</li>
* <li>Pragma anywhere: whether pragma, that are <em>not</em> statements and handled before execution begins,
* can appear anywhere in the source or before any statements - ie at the beginning of a script.</li>
* <li>Const Capture: whether variables captured by lambdas are read-only (aka const, same as Java) or read-write.</li>
* </ul>
* @since 3.2
*/
public final class JexlFeatures {
/** The false predicate. */
public static final Predicate<String> TEST_STR_FALSE = s -> false;
/** Te feature names (for toString()). */
private static final String[] F_NAMES = {
"register", "reserved variable", "local variable", "assign/modify",
"global assign/modify", "array reference", "create instance", "loop", "function",
"method call", "set/map/array literal", "pragma", "annotation", "script", "lexical", "lexicalShade",
"thin-arrow", "fat-arrow", "namespace pragma", "import pragma", "comparator names", "pragma anywhere",
"const capture"
};
/** Registers feature ordinal. */
private static final int REGISTER = 0;
/** Reserved future feature ordinal (unused as of 3.3.1). */
public static final int RESERVED = 1;
/** Locals feature ordinal. */
public static final int LOCAL_VAR = 2;
/** Side effects feature ordinal. */
public static final int SIDE_EFFECT = 3;
/** Global side effects feature ordinal. */
public static final int SIDE_EFFECT_GLOBAL = 4;
/** Expressions allowed in array reference ordinal. */
public static final int ARRAY_REF_EXPR = 5;
/** New-instance feature ordinal. */
public static final int NEW_INSTANCE = 6;
/** Loops feature ordinal. */
public static final int LOOP = 7;
/** Lambda feature ordinal. */
public static final int LAMBDA = 8;
/** Lambda feature ordinal. */
public static final int METHOD_CALL = 9;
/** Structured literal feature ordinal. */
public static final int STRUCTURED_LITERAL = 10;
/** Pragma feature ordinal. */
public static final int PRAGMA = 11;
/** Annotation feature ordinal. */
public static final int ANNOTATION = 12;
/** Script feature ordinal. */
public static final int SCRIPT = 13;
/** Lexical feature ordinal. */
public static final int LEXICAL = 14;
/** Lexical shade feature ordinal. */
public static final int LEXICAL_SHADE = 15;
/** Thin-arrow lambda syntax. */
public static final int THIN_ARROW = 16;
/** Fat-arrow lambda syntax. */
public static final int FAT_ARROW = 17;
/** Namespace pragma feature ordinal. */
public static final int NS_PRAGMA = 18;
/** Import pragma feature ordinal. */
public static final int IMPORT_PRAGMA = 19;
/** Comparator names (legacy) syntax. */
public static final int COMPARATOR_NAMES = 20;
/** The pragma anywhere feature ordinal. */
public static final int PRAGMA_ANYWHERE = 21;
/** Captured variables are const. */
public static final int CONST_CAPTURE = 22;
/**
* All features.
* N.B. ensure this is updated if additional features are added.
*/
private static final long ALL_FEATURES = (1L << CONST_CAPTURE + 1) - 1L; // MUST REMAIN PRIVATE
/**
* The default features flag mask.
* <p>Meant for compatibility with scripts written before 3.3.1</p>
*/
private static final long DEFAULT_FEATURES = // MUST REMAIN PRIVATE
1L << LOCAL_VAR
| 1L << SIDE_EFFECT
| 1L << SIDE_EFFECT_GLOBAL
| 1L << ARRAY_REF_EXPR
| 1L << NEW_INSTANCE
| 1L << LOOP
| 1L << LAMBDA
| 1L << METHOD_CALL
| 1L << STRUCTURED_LITERAL
| 1L << PRAGMA
| 1L << ANNOTATION
| 1L << SCRIPT
| 1L << THIN_ARROW
| 1L << NS_PRAGMA
| 1L << IMPORT_PRAGMA
| 1L << COMPARATOR_NAMES
| 1L << PRAGMA_ANYWHERE;
/**
* The canonical scripting (since 3.3.1) features flag mask based on the original default.
* <p>Adds lexical, lexical-shade and const-capture but removes comparator-names and pragma-anywhere</p>
*/
private static final long SCRIPT_FEATURES = // MUST REMAIN PRIVATE
( DEFAULT_FEATURES
| 1L << LEXICAL
| 1L << LEXICAL_SHADE
| 1L << CONST_CAPTURE ) // these parentheses are necessary :-)
& ~(1L << COMPARATOR_NAMES)
& ~(1L << PRAGMA_ANYWHERE);
/**
* Protected future syntactic elements.
* <p><em>throw, switch, case, default, class, instanceof, jexl, $jexl</em></p>
* @since 3.3.1
*/
private static final Set<String> RESERVED_WORDS =
Collections.unmodifiableSet(
new HashSet<>(Arrays.asList(
"switch", "case", "default", "class", "jexl", "$jexl")));
/*
* *WARNING*
* Static fields may be inlined by the Java compiler, so their _values_ effectively form part of the external API.
* Classes that reference them need to be recompiled to pick up new values.
* This means that changes in value are not binary compatible.
* Such fields must be private or problems may occur.
*/
/**
* Creates an all features enabled set.
* @return a new instance of all features set
* @since 3.3.1
*/
public static JexlFeatures createAll() {
return new JexlFeatures(ALL_FEATURES, null, null);
}
/**
* Creates a default features set suitable for basic but complete scripting needs.
* <p>Maximizes compatibility with older version scripts (before 3.3), new projects should
* use {@link JexlFeatures#createScript()} or equivalent features as a base.</p>
* <p>The following scripting features are enabled:</p>
* <ul>
* <li>local variable, {@link JexlFeatures#supportsLocalVar()}</li>
* <li>side effect, {@link JexlFeatures#supportsSideEffect()}</li>
* <li>global side effect, {@link JexlFeatures#supportsSideEffectGlobal()}</li>
* <li>array reference expression, {@link JexlFeatures#supportsStructuredLiteral()}</li>
* <li>new instance, {@link JexlFeatures#supportsNewInstance()} </li>
* <li>loop, {@link JexlFeatures#supportsLoops()}</li>
* <li>lambda, {@link JexlFeatures#supportsLambda()}</li>
* <li>method call, {@link JexlFeatures#supportsMethodCall()}</li>
* <li>structured literal, {@link JexlFeatures#supportsStructuredLiteral()}</li>
* <li>pragma, {@link JexlFeatures#supportsPragma()}</li>
* <li>annotation, {@link JexlFeatures#supportsAnnotation()}</li>
* <li>script, {@link JexlFeatures#supportsScript()}</li>
* <li>comparator names, {@link JexlFeatures#supportsComparatorNames()}</li>
* <li>namespace pragma, {@link JexlFeatures#supportsNamespacePragma()}</li>
* <li>import pragma, {@link JexlFeatures#supportsImportPragma()}</li>
* <li>pragma anywhere, {@link JexlFeatures#supportsPragmaAnywhere()}</li>
* </ul>
* @return a new instance of a default scripting features set
* @since 3.3.1
*/
public static JexlFeatures createDefault() {
return new JexlFeatures(DEFAULT_FEATURES, null, null);
}
/**
* Creates an empty feature set.
* <p>This is the strictest base-set since no feature is allowed, suitable as-is only
* for the simplest expressions.</p>
* @return a new instance of an empty features set
* @since 3.3.1
*/
public static JexlFeatures createNone() {
return new JexlFeatures(0L, null, null);
}
/**
* The modern scripting features set.
* <p>This is the recommended set for new projects.</p>
* <p>All default features with the following differences:</p>
* <ul>
* <li><em>disable</em> pragma-anywhere, {@link JexlFeatures#supportsPragmaAnywhere()}</li>
* <li><em>disable</em> comparator-names, {@link JexlFeatures#supportsComparatorNames()}</li>
* <li><em>enable</em> lexical, {@link JexlFeatures#isLexical()}</li>
* <li><em>enable</em> lexical-shade, {@link JexlFeatures#isLexicalShade()} </li>
* <li><em>enable</em> const-capture, {@link JexlFeatures#supportsConstCapture()}</li>
* </ul>
* <p>It also adds a set of reserved words to enable future unencumbered syntax evolution:
* <em>try, catch, throw, finally, switch, case, default, class, instanceof</em>
* </p>
* @return a new instance of a modern scripting features set
* @since 3.3.1
*/
public static JexlFeatures createScript() {
return new JexlFeatures(SCRIPT_FEATURES, RESERVED_WORDS, null);
}
/**
* The text corresponding to a feature code.
* @param feature the feature number
* @return the feature name
*/
public static String stringify(final int feature) {
return feature >= 0 && feature < F_NAMES.length ? F_NAMES[feature] : "unsupported feature";
}
/** The feature flags. */
private long flags;
/** The set of reserved names, aka global variables that can not be masked by local variables or parameters. */
private Set<String> reservedNames;
/** The namespace names. */
private Predicate<String> nameSpaces;
/**
* Creates default instance, equivalent to the result of calling the preferred alternative
* {@link JexlFeatures#createDefault()}
*/
public JexlFeatures() {
this(DEFAULT_FEATURES, null, null);
}
/**
* Copy constructor.
* @param features the feature to copy from
*/
public JexlFeatures(final JexlFeatures features) {
this(features.flags, features.reservedNames, features.nameSpaces);
}
/**
* An all member constructor for derivation.
* <p>Not respecting immutability or thread-safety constraints for this class constructor arguments will
* likely result in unexpected behavior.</p>
* @param f flag
* @param r reserved variable names; must be an immutable Set or thread-safe (concurrent or synchronized set)
* @param n namespace predicate; must be stateless or thread-safe
*/
protected JexlFeatures(final long f, final Set<String> r, final Predicate<String> n) {
this.flags = f;
this.reservedNames = r == null? Collections.emptySet() : r;
this.nameSpaces = n == null? TEST_STR_FALSE : n;
}
/**
* Sets whether annotation constructs are enabled.
* <p>
* When disabled, parsing a script/expression using syntactic annotation constructs (@annotation)
* will throw a parsing exception.
* </p>
* @param flag true to enable, false to disable
* @return this features instance
*/
public JexlFeatures annotation(final boolean flag) {
setFeature(ANNOTATION, flag);
return this;
}
/**
* Sets whether array references expressions are enabled.
* <p>
* When disabled, parsing a script/expression using 'obj[ ref ]' where ref is not a string or integer literal
* will throw a parsing exception;
* </p>
* @param flag true to enable, false to disable
* @return this features instance
*/
public JexlFeatures arrayReferenceExpr(final boolean flag) {
setFeature(ARRAY_REF_EXPR, flag);
return this;
}
/**
* Sets whether the legacy comparison operator names syntax is enabled.
* <p>
* When disabled, comparison operators names (eq;ne;le;lt;ge;gt)
* will be treated as plain identifiers.
* </p>
* @param flag true to enable, false to disable
* @return this features instance
* @since 3.3
*/
public JexlFeatures comparatorNames(final boolean flag) {
setFeature(COMPARATOR_NAMES, flag);
return this;
}
/**
* Sets whether lambda captured-variables are const or not.
* <p>
* When disabled, lambda-captured variables are implicitly converted to read-write local variable (let),
* when enabled, those are implicitly converted to read-only local variables (const).
* </p>
* @param flag true to enable, false to disable
* @return this features instance
*/
public JexlFeatures constCapture(final boolean flag) {
setFeature(CONST_CAPTURE, flag);
return this;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final JexlFeatures other = (JexlFeatures) obj;
if (this.flags != other.flags) {
return false;
}
if (this.nameSpaces != other.nameSpaces) {
return false;
}
if (!Objects.equals(this.reservedNames, other.reservedNames)) {
return false;
}
return true;
}
/**
* Sets whether fat-arrow lambda syntax is enabled.
* <p>
* When disabled, parsing a script/expression using syntactic fat-arrow (=<)
* will throw a parsing exception.
* </p>
* @param flag true to enable, false to disable
* @return this features instance
* @since 3.3
*/
public JexlFeatures fatArrow(final boolean flag) {
setFeature(FAT_ARROW, flag);
return this;
}
/**
* Gets a feature flag value.
* @param feature feature ordinal
* @return true if on, false if off
*/
private boolean getFeature(final int feature) {
return (flags & 1L << feature) != 0L;
}
/**
* @return these features"s flags
*/
public long getFlags() {
return flags;
}
/**
* @return the (unmodifiable) set of reserved names.
*/
public Set<String> getReservedNames() {
return reservedNames;
}
@Override
public int hashCode() { //CSOFF: MagicNumber
int hash = 3;
hash = 53 * hash + (int) (this.flags ^ this.flags >>> 32);
hash = 53 * hash + (this.reservedNames != null ? this.reservedNames.hashCode() : 0);
return hash;
}
/**
* Sets whether import pragma constructs are enabled.
* <p>
* When disabled, parsing a script/expression using syntactic import pragma constructs
* (#pragma jexl.import....) will throw a parsing exception.
* </p>
* @param flag true to enable, false to disable
* @return this features instance
* @since 3.3
*/
public JexlFeatures importPragma(final boolean flag) {
setFeature(IMPORT_PRAGMA, flag);
return this;
}
/** @return whether lexical scope feature is enabled */
public boolean isLexical() {
return getFeature(LEXICAL);
}
/** @return whether lexical shade feature is enabled */
public boolean isLexicalShade() {
return getFeature(LEXICAL_SHADE);
}
/**
* Checks whether a name is reserved.
* @param name the name to check
* @return true if reserved, false otherwise
*/
public boolean isReservedName(final String name) {
return name != null && reservedNames.contains(name);
}
/**
* Sets whether lambda/function constructs are enabled.
* <p>
* When disabled, parsing a script/expression using syntactic lambda constructs (->,function)
* will throw a parsing exception.
* </p>
* @param flag true to enable, false to disable
* @return this features instance
*/
public JexlFeatures lambda(final boolean flag) {
setFeature(LAMBDA, flag);
return this;
}
/**
* Sets whether syntactic lexical mode is enabled.
*
* @param flag true means syntactic lexical function scope is in effect, false implies non-lexical scoping
* @return this features instance
*/
public JexlFeatures lexical(final boolean flag) {
setFeature(LEXICAL, flag);
if (!flag) {
setFeature(LEXICAL_SHADE, false);
}
return this;
}
/**
* Sets whether syntactic lexical shade is enabled.
*
* @param flag true means syntactic lexical shade is in effect and implies lexical scope
* @return this features instance
*/
public JexlFeatures lexicalShade(final boolean flag) {
setFeature(LEXICAL_SHADE, flag);
if (flag) {
setFeature(LEXICAL, true);
}
return this;
}
/**
* Sets whether local variables are enabled.
* <p>
* When disabled, parsing a script/expression using a local variable or parameter syntax
* will throw a parsing exception.
* </p>
* @param flag true to enable, false to disable
* @return this features instance
*/
public JexlFeatures localVar(final boolean flag) {
setFeature(LOCAL_VAR, flag);
return this;
}
/**
* Sets whether looping constructs are enabled.
* <p>
* When disabled, parsing a script/expression using syntactic looping constructs (for,while)
* will throw a parsing exception.
* </p>
* @param flag true to enable, false to disable
* @return this features instance
*/
public JexlFeatures loops(final boolean flag) {
setFeature(LOOP, flag);
return this;
}
/**
* Sets whether method calls expressions are enabled.
* <p>
* When disabled, parsing a script/expression using 'obj.method()'
* will throw a parsing exception;
* </p>
* @param flag true to enable, false to disable
* @return this features instance
*/
public JexlFeatures methodCall(final boolean flag) {
setFeature(METHOD_CALL, flag);
return this;
}
/**
* Sets whether namespace pragma constructs are enabled.
* <p>
* When disabled, parsing a script/expression using syntactic namespace pragma constructs
* (#pragma jexl.namespace....) will throw a parsing exception.
* </p>
* @param flag true to enable, false to disable
* @return this features instance
* @since 3.3
*/
public JexlFeatures namespacePragma(final boolean flag) {
setFeature(NS_PRAGMA, flag);
return this;
}
/**
* @return the declared namespaces test.
*/
public Predicate<String> namespaceTest() {
return nameSpaces;
}
/**
* Sets a test to determine namespace declaration.
* @param names the name predicate
* @return this features instance
*/
public JexlFeatures namespaceTest(final Predicate<String> names) {
nameSpaces = names == null ? TEST_STR_FALSE : names;
return this;
}
/**
* Sets whether creating new instances is enabled.
* <p>
* When disabled, parsing a script/expression using 'new(...)' will throw a parsing exception;
* using a class as functor will fail at runtime.
* </p>
* @param flag true to enable, false to disable
* @return this features instance
*/
public JexlFeatures newInstance(final boolean flag) {
setFeature(NEW_INSTANCE, flag);
return this;
}
/**
* Sets whether pragma constructs are enabled.
* <p>
* When disabled, parsing a script/expression using syntactic pragma constructs (#pragma)
* will throw a parsing exception.
* </p>
* @param flag true to enable, false to disable
* @return this features instance
*/
public JexlFeatures pragma(final boolean flag) {
setFeature(PRAGMA, flag);
if (!flag) {
setFeature(NS_PRAGMA, false);
setFeature(IMPORT_PRAGMA, false);
}
return this;
}
/**
* Sets whether pragma constructs can appear anywhere in the code.
*
* @param flag true to enable, false to disable
* @return this features instance
* @since 3.3
*/
public JexlFeatures pragmaAnywhere(final boolean flag) {
setFeature(PRAGMA_ANYWHERE, flag);
return this;
}
/**
* Sets whether register are enabled.
* <p>
* This is mostly used internally during execution of JexlEngine.{g,s}etProperty.
* </p>
* <p>
* When disabled, parsing a script/expression using the register syntax will throw a parsing exception.
* </p>
* @param flag true to enable, false to disable
* @return this features instance
*/
public JexlFeatures register(final boolean flag) {
setFeature(REGISTER, flag);
return this;
}
/**
* Sets a collection of reserved r precluding those to be used as local variables or parameter r.
* @param names the r to reserve
* @return this features instance
*/
public JexlFeatures reservedNames(final Collection<String> names) {
if (names == null || names.isEmpty()) {
reservedNames = Collections.emptySet();
} else {
reservedNames = Collections.unmodifiableSet(new TreeSet<>(names));
}
return this;
}
/**
* Sets whether scripts constructs are enabled.
* <p>
* When disabled, parsing a script using syntactic script constructs (statements, ...)
* will throw a parsing exception.
* </p>
* @param flag true to enable, false to disable
* @return this features instance
*/
public JexlFeatures script(final boolean flag) {
setFeature(SCRIPT, flag);
return this;
}
/**
* Sets a feature flag.
* @param feature the feature ordinal
* @param flag turn-on, turn off
*/
private void setFeature(final int feature, final boolean flag) {
if (flag) {
flags |= 1L << feature;
} else {
flags &= ~(1L << feature);
}
}
/**
* Sets whether side effect expressions are enabled.
* <p>
* When disabled, parsing a script/expression using syntactical constructs modifying variables
* or members will throw a parsing exception.
* </p>
* @param flag true to enable, false to disable
* @return this features instance
*/
public JexlFeatures sideEffect(final boolean flag) {
setFeature(SIDE_EFFECT, flag);
return this;
}
/**
* Sets whether side effect expressions on global variables (aka non-local) are enabled.
* <p>
* When disabled, parsing a script/expression using syntactical constructs modifying variables
* <em>including all potentially ant-ish variables</em> will throw a parsing exception.
* </p>
* @param flag true to enable, false to disable
* @return this features instance
*/
public JexlFeatures sideEffectGlobal(final boolean flag) {
setFeature(SIDE_EFFECT_GLOBAL, flag);
return this;
}
/**
* Sets whether array/map/set literal expressions are enabled.
* <p>
* When disabled, parsing a script/expression creating one of these literals
* will throw a parsing exception;
* </p>
* @param flag true to enable, false to disable
* @return this features instance
*/
public JexlFeatures structuredLiteral(final boolean flag) {
setFeature(STRUCTURED_LITERAL, flag);
return this;
}
/**
* @return true if annotation are enabled, false otherwise
*/
public boolean supportsAnnotation() {
return getFeature(ANNOTATION);
}
/**
* @return true if array references can contain method call expressions, false otherwise
*/
public boolean supportsArrayReferenceExpr() {
return getFeature(ARRAY_REF_EXPR);
}
/**
* @return true if legacy comparison operator names syntax is enabled, false otherwise
* @since 3.3
*/
public boolean supportsComparatorNames() {
return getFeature(COMPARATOR_NAMES);
}
/**
* @return true if lambda captured-variables are const, false otherwise
*/
public boolean supportsConstCapture() {
return getFeature(CONST_CAPTURE);
}
/**
*
* @return true if expressions (aka not scripts) are enabled, false otherwise
*/
public boolean supportsExpression() {
return !getFeature(SCRIPT);
}
/**
* @return true if fat-arrow lambda syntax is enabled, false otherwise
* @since 3.3
*/
public boolean supportsFatArrow() {
return getFeature(FAT_ARROW);
}
/**
* @return true if import pragma are enabled, false otherwise
* @since 3.3
*/
public boolean supportsImportPragma() {
return getFeature(IMPORT_PRAGMA);
}
/**
* @return true if lambda are enabled, false otherwise
*/
public boolean supportsLambda() {
return getFeature(LAMBDA);
}
/**
* @return true if local variables syntax is enabled
*/
public boolean supportsLocalVar() {
return getFeature(LOCAL_VAR);
}
/**
* @return true if loops are enabled, false otherwise
*/
public boolean supportsLoops() {
return getFeature(LOOP);
}
/**
* @return true if array references can contain expressions, false otherwise
*/
public boolean supportsMethodCall() {
return getFeature(METHOD_CALL);
}
/**
* @return true if namespace pragma are enabled, false otherwise
* @since 3.3
*/
public boolean supportsNamespacePragma() {
return getFeature(NS_PRAGMA);
}
/**
* @return true if creating new instances is enabled, false otherwise
*/
public boolean supportsNewInstance() {
return getFeature(NEW_INSTANCE);
}
/**
* @return true if namespace pragma are enabled, false otherwise
*/
public boolean supportsPragma() {
return getFeature(PRAGMA);
}
/**
* @return true if pragma constructs can appear anywhere in the code, false otherwise
* @since 3.3
*/
public boolean supportsPragmaAnywhere() {
return getFeature(PRAGMA_ANYWHERE);
}
/**
* @return true if register syntax is enabled
*/
public boolean supportsRegister() {
return getFeature(REGISTER);
}
/**
* @return true if scripts are enabled, false otherwise
*/
public boolean supportsScript() {
return getFeature(SCRIPT);
}
/**
* @return true if side effects are enabled, false otherwise
*/
public boolean supportsSideEffect() {
return getFeature(SIDE_EFFECT);
}
/**
* @return true if global variables can be assigned
*/
public boolean supportsSideEffectGlobal() {
return getFeature(SIDE_EFFECT_GLOBAL);
}
/**
* @return true if array/map/set literal expressions are supported, false otherwise
*/
public boolean supportsStructuredLiteral() {
return getFeature(STRUCTURED_LITERAL);
}
/**
* @return true if thin-arrow lambda syntax is enabled, false otherwise
* @since 3.3
*/
public boolean supportsThinArrow() {
return getFeature(THIN_ARROW);
}
/**
* Sets whether thin-arrow lambda syntax is enabled.
* <p>
* When disabled, parsing a script/expression using syntactic thin-arrow (-<)
* will throw a parsing exception.
* </p>
* @param flag true to enable, false to disable
* @return this features instance
* @since 3.3
*/
public JexlFeatures thinArrow(final boolean flag) {
setFeature(THIN_ARROW, flag);
return this;
}
}