diff --git a/pom.xml b/pom.xml index e8a7ab0..0a041cf 100644 --- a/pom.xml +++ b/pom.xml @@ -105,6 +105,10 @@ io.smallrye.common smallrye-common-cpu + + io.smallrye.common + smallrye-common-expression + io.smallrye.common smallrye-common-net diff --git a/src/main/java/org/wildfly/common/expression/CompositeNode.java b/src/main/java/org/wildfly/common/expression/CompositeNode.java deleted file mode 100644 index 5bcfe7e..0000000 --- a/src/main/java/org/wildfly/common/expression/CompositeNode.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * JBoss, Home of Professional Open Source. - * Copyright 2017 Red Hat, Inc., and individual contributors - * as indicated by the @author tags. - * - * 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.wildfly.common.expression; - -import java.util.HashSet; -import java.util.List; - -import org.wildfly.common.function.ExceptionBiConsumer; - -/** - * @author David M. Lloyd - */ -final class CompositeNode extends Node { - private final Node[] subNodes; - - CompositeNode(final Node[] subNodes) { - this.subNodes = subNodes; - } - - CompositeNode(final List subNodes) { - this.subNodes = subNodes.toArray(NO_NODES); - } - - void emit(final ResolveContext context, final ExceptionBiConsumer, StringBuilder, E> resolveFunction) throws E { - for (Node subNode : subNodes) { - subNode.emit(context, resolveFunction); - } - } - - void catalog(final HashSet strings) { - for (Node node : subNodes) { - node.catalog(strings); - } - } - - public String toString() { - StringBuilder b = new StringBuilder(); - b.append('*'); - for (Node subNode : subNodes) { - b.append('<').append(subNode.toString()).append('>'); - } - return b.toString(); - } -} diff --git a/src/main/java/org/wildfly/common/expression/Expression.java b/src/main/java/org/wildfly/common/expression/Expression.java index aa201b9..b059b3f 100644 --- a/src/main/java/org/wildfly/common/expression/Expression.java +++ b/src/main/java/org/wildfly/common/expression/Expression.java @@ -18,16 +18,11 @@ package org.wildfly.common.expression; -import java.util.ArrayList; -import java.util.Collections; import java.util.EnumSet; -import java.util.HashSet; -import java.util.List; +import java.util.NoSuchElementException; import java.util.Set; import java.util.function.BiConsumer; -import org.wildfly.common.Assert; -import org.wildfly.common._private.CommonMessages; import org.wildfly.common.function.ExceptionBiConsumer; /** @@ -35,16 +30,15 @@ * segments, which are wrapped by the sequence "{@code ${ ... }}". * * @author David M. Lloyd + * + * @deprecated Use {@link io.smallrye.common.expression.Expression} instead. */ +@Deprecated(forRemoval = true) public final class Expression { - private final Node content; - private final Set referencedStrings; + private final io.smallrye.common.expression.Expression expr; - Expression(Node content) { - this.content = content; - HashSet strings = new HashSet<>(); - content.catalog(strings); - referencedStrings = strings.isEmpty() ? Collections.emptySet() : strings.size() == 1 ? Collections.singleton(strings.iterator().next()) : Collections.unmodifiableSet(strings); + Expression(final io.smallrye.common.expression.Expression expr) { + this.expr = expr; } /** @@ -55,7 +49,7 @@ public final class Expression { * @return the immutable set of strings (not {@code null}) */ public Set getReferencedStrings() { - return referencedStrings; + return expr.getReferencedStrings(); } /** @@ -70,10 +64,7 @@ public Set getReferencedStrings() { * @throws E if the expansion function throws an exception */ public String evaluateException(final ExceptionBiConsumer, StringBuilder, E> expandFunction) throws E { - Assert.checkNotNullParam("expandFunction", expandFunction); - final StringBuilder b = new StringBuilder(); - content.emit(new ResolveContext(expandFunction, b), expandFunction); - return b.toString(); + return expr.evaluateException((resolveContext, stringBuilder) -> expandFunction.accept(new ResolveContext(resolveContext), stringBuilder)); } /** @@ -99,31 +90,7 @@ public String evaluate(BiConsumer, StringBuilde * @return the expanded string */ public String evaluateWithPropertiesAndEnvironment(boolean failOnNoDefault) { - return evaluate((c, b) -> { - final String key = c.getKey(); - if (key.startsWith("env.")) { - final String env = key.substring(4); - final String val = System.getenv(env); - if (val == null) { - if (failOnNoDefault && ! c.hasDefault()) { - throw CommonMessages.msg.unresolvedEnvironmentProperty(env); - } - c.expandDefault(); - } else { - b.append(val); - } - } else { - final String val = System.getProperty(key); - if (val == null) { - if (failOnNoDefault && ! c.hasDefault()) { - throw CommonMessages.msg.unresolvedSystemProperty(key); - } - c.expandDefault(); - } else { - b.append(val); - } - } - }); + return expr.evaluateWithPropertiesAndEnvironment(failOnNoDefault); } /** @@ -135,18 +102,7 @@ public String evaluateWithPropertiesAndEnvironment(boolean failOnNoDefault) { * @return the expanded string */ public String evaluateWithProperties(boolean failOnNoDefault) { - return evaluate((c, b) -> { - final String key = c.getKey(); - final String val = System.getProperty(key); - if (val == null) { - if (failOnNoDefault && ! c.hasDefault()) { - throw CommonMessages.msg.unresolvedSystemProperty(key); - } - c.expandDefault(); - } else { - b.append(val); - } - }); + return expr.evaluateWithProperties(failOnNoDefault); } /** @@ -158,18 +114,7 @@ public String evaluateWithProperties(boolean failOnNoDefault) { * @return the expanded string */ public String evaluateWithEnvironment(boolean failOnNoDefault) { - return evaluate((c, b) -> { - final String key = c.getKey(); - final String val = System.getenv(key); - if (val == null) { - if (failOnNoDefault && ! c.hasDefault()) { - throw CommonMessages.msg.unresolvedEnvironmentProperty(key); - } - c.expandDefault(); - } else { - b.append(val); - } - }); + return expr.evaluateWithEnvironment(failOnNoDefault); } /** @@ -180,7 +125,7 @@ public String evaluateWithEnvironment(boolean failOnNoDefault) { * @return the compiled expression (not {@code null}) */ public static Expression compile(String string, Flag... flags) { - return compile(string, flags == null || flags.length == 0 ? NO_FLAGS : EnumSet.of(flags[0], flags)); + return new Expression(io.smallrye.common.expression.Expression.compile(string, Flag.mapFlagsArray(flags))); } /** @@ -191,477 +136,9 @@ public static Expression compile(String string, Flag... flags) { * @return the compiled expression (not {@code null}) */ public static Expression compile(String string, EnumSet flags) { - Assert.checkNotNullParam("string", string); - Assert.checkNotNullParam("flags", flags); - final Node content; - final Itr itr; - if (flags.contains(Flag.NO_TRIM)) { - itr = new Itr(string); - } else { - itr = new Itr(string.trim()); - } - content = parseString(itr, true, false, false, flags); - return content == Node.NULL ? EMPTY : new Expression(content); - } - - private static final Expression EMPTY = new Expression(Node.NULL); - - static final class Itr { - private final String str; - private int idx; - - Itr(final String str) { - this.str = str; - } - - boolean hasNext() { - return idx < str.length(); - } - - int next() { - final int idx = this.idx; - try { - return str.codePointAt(idx); - } finally { - this.idx = str.offsetByCodePoints(idx, 1); - } - } - - int prev() { - final int idx = this.idx; - try { - return str.codePointBefore(idx); - } finally { - this.idx = str.offsetByCodePoints(idx, -1); - } - } - - int getNextIdx() { - return idx; - } - - int getPrevIdx() { - return str.offsetByCodePoints(idx, -1); - } - - String getStr() { - return str; - } - - int peekNext() { - return str.codePointAt(idx); - } - - int peekPrev() { - return str.codePointBefore(idx); - } - - void rewind(final int newNext) { - idx = newNext; - } - } - - private static Node parseString(Itr itr, final boolean allowExpr, final boolean endOnBrace, final boolean endOnColon, final EnumSet flags) { - int ignoreBraceLevel = 0; - final List list = new ArrayList<>(); - int start = itr.getNextIdx(); - while (itr.hasNext()) { - // index of this character - int idx = itr.getNextIdx(); - int ch = itr.next(); - switch (ch) { - case '$': { - if (! allowExpr) { - // TP 1 - // treat as plain content - continue; - } - // check to see if it's a dangling $ - if (! itr.hasNext()) { - if (! flags.contains(Flag.LENIENT_SYNTAX)) { - // TP 2 - throw invalidExpressionSyntax(itr.getStr(), idx); - } - // TP 3 - list.add(new LiteralNode(itr.getStr(), start, itr.getNextIdx())); - start = itr.getNextIdx(); - continue; - } - // enqueue what we have acquired so far - if (idx > start) { - // TP 4 - list.add(new LiteralNode(itr.getStr(), start, idx)); - } - // next char should be an expression starter of some sort - idx = itr.getNextIdx(); - ch = itr.next(); - switch (ch) { - case '{': { - // ${ - boolean general = flags.contains(Flag.GENERAL_EXPANSION) && itr.hasNext() && itr.peekNext() == '{'; - // consume double-{ - if (general) itr.next(); - // set start to the beginning of the key for later - start = itr.getNextIdx(); - // the expression name starts in the next position - Node keyNode = parseString(itr, ! flags.contains(Flag.NO_RECURSE_KEY), true, true, flags); - if (! itr.hasNext()) { - if (! flags.contains(Flag.LENIENT_SYNTAX)) { - // TP 5 - throw invalidExpressionSyntax(itr.getStr(), itr.getNextIdx()); - } - // TP 6 - // otherwise treat it as a properly terminated expression - list.add(new ExpressionNode(general, keyNode, Node.NULL)); - start = itr.getNextIdx(); - continue; - } else if (itr.peekNext() == ':') { - if (flags.contains(Flag.DOUBLE_COLON) && itr.hasNext() && itr.peekNext() == ':') { - // TP 7 - // OK actually the whole thing is really going to be part of the key - // Best approach is, rewind and do it over again, but without end-on-colon - itr.rewind(start); - keyNode = parseString(itr, ! flags.contains(Flag.NO_RECURSE_KEY), true, false, flags); - list.add(new ExpressionNode(general, keyNode, Node.NULL)); - } else { - // TP 8 - itr.next(); // consume it - final Node defaultValueNode = parseString(itr, ! flags.contains(Flag.NO_RECURSE_DEFAULT), true, false, flags); - list.add(new ExpressionNode(general, keyNode, defaultValueNode)); - } - // now expect } - if (! itr.hasNext()) { - if (! flags.contains(Flag.LENIENT_SYNTAX)) { - // TP 9 - throw invalidExpressionSyntax(itr.getStr(), itr.getNextIdx()); - } - // TP 10 - // otherwise treat it as a properly terminated expression - start = itr.getNextIdx(); - continue; - } else { - // TP 11 - assert itr.peekNext() == '}'; - itr.next(); // consume - if (general) { - if (! itr.hasNext()) { - if (! flags.contains(Flag.LENIENT_SYNTAX)) { - // TP 11_1 - throw invalidExpressionSyntax(itr.getStr(), itr.getNextIdx()); - } - // TP 11_2 - // otherwise treat it as a properly terminated expression - start = itr.getNextIdx(); - continue; - } else { - if (itr.peekNext() == '}') { - itr.next(); // consume it - // TP 11_3 - start = itr.getNextIdx(); - continue; - } else { - if (! flags.contains(Flag.LENIENT_SYNTAX)) { - // TP 11_4 - throw invalidExpressionSyntax(itr.getStr(), itr.getNextIdx()); - } - // otherwise treat it as a properly terminated expression - start = itr.getNextIdx(); - continue; - } - } - } else { - start = itr.getNextIdx(); - continue; - } - //throw Assert.unreachableCode(); - } - } else { - // TP 12 - assert itr.peekNext() == '}'; - itr.next(); // consume - list.add(new ExpressionNode(general, keyNode, Node.NULL)); - if (general) { - if (! itr.hasNext()) { - if (! flags.contains(Flag.LENIENT_SYNTAX)) { - // TP 12_1 - throw invalidExpressionSyntax(itr.getStr(), itr.getNextIdx()); - } - // TP 12_2 - // otherwise treat it as a properly terminated expression - start = itr.getNextIdx(); - continue; - } else { - if (itr.peekNext() == '}') { - itr.next(); // consume it - // TP 12_3 - start = itr.getNextIdx(); - continue; - } else { - if (! flags.contains(Flag.LENIENT_SYNTAX)) { - // TP 12_4 - throw invalidExpressionSyntax(itr.getStr(), itr.getNextIdx()); - } - // otherwise treat it as a properly terminated expression - start = itr.getNextIdx(); - continue; - } - } - } - start = itr.getNextIdx(); - continue; - } - //throw Assert.unreachableCode(); - } - case '$': { - // $$ - if (flags.contains(Flag.MINI_EXPRS)) { - // TP 13 - list.add(new ExpressionNode(false, LiteralNode.DOLLAR, Node.NULL)); - } else { - // just resolve $$ to $ - // TP 14 - list.add(LiteralNode.DOLLAR); - } - start = itr.getNextIdx(); - continue; - } - case '}': { - // $} - if (flags.contains(Flag.MINI_EXPRS)) { - // TP 15 - list.add(new ExpressionNode(false, LiteralNode.CLOSE_BRACE, Node.NULL)); - start = itr.getNextIdx(); - continue; - } else if (endOnBrace) { - if (flags.contains(Flag.LENIENT_SYNTAX)) { - // TP 16 - // just treat the $ that we got like plain text, and return - list.add(LiteralNode.DOLLAR); - itr.prev(); // back up to point at } again - return Node.fromList(list); - } else { - // TP 17 - throw invalidExpressionSyntax(itr.getStr(), idx); - } - } else { - if (flags.contains(Flag.LENIENT_SYNTAX)) { - // TP 18 - // just treat $} like plain text - list.add(LiteralNode.DOLLAR); - list.add(LiteralNode.CLOSE_BRACE); - start = itr.getNextIdx(); - continue; - } else { - // TP 19 - throw invalidExpressionSyntax(itr.getStr(), idx); - } - } - //throw Assert.unreachableCode(); - } - case ':': { - // $: - if (flags.contains(Flag.MINI_EXPRS)) { - // $: is an expression - // TP 20 - list.add(new ExpressionNode(false, LiteralNode.COLON, Node.NULL)); - start = itr.getNextIdx(); - continue; - } else if (endOnColon) { - if (flags.contains(Flag.LENIENT_SYNTAX)) { - // TP 21 - // just treat the $ that we got like plain text, and return - itr.prev(); // back up to point at : again - list.add(LiteralNode.DOLLAR); - return Node.fromList(list); - } else { - // TP 22 - throw invalidExpressionSyntax(itr.getStr(), idx); - } - } else { - if (flags.contains(Flag.LENIENT_SYNTAX)) { - // TP 23 - // just treat $: like plain text - list.add(LiteralNode.DOLLAR); - list.add(LiteralNode.COLON); - start = itr.getNextIdx(); - continue; - } else { - // TP 24 - throw invalidExpressionSyntax(itr.getStr(), idx); - } - } - //throw Assert.unreachableCode(); - } - default: { - // $ followed by anything else - if (flags.contains(Flag.MINI_EXPRS)) { - // TP 25 - list.add(new ExpressionNode(false, new LiteralNode(itr.getStr(), idx, itr.getNextIdx()), Node.NULL)); - start = itr.getNextIdx(); - continue; - } else if (flags.contains(Flag.LENIENT_SYNTAX)) { - // TP 26 - // just treat it as literal - start = itr.getPrevIdx() - 1; // we can use 1 here because unicode '$' is one char in size - continue; - } else { - // TP 27 - throw invalidExpressionSyntax(itr.getStr(), idx); - } - //throw Assert.unreachableCode(); - } - } - //throw Assert.unreachableCode(); - } - case ':': { - if (endOnColon) { - // TP 28 - itr.prev(); // back up to point at : again - if (idx > start) { - list.add(new LiteralNode(itr.getStr(), start, idx)); - } - return Node.fromList(list); - } else { - // TP 29 - // plain content always - continue; - } - //throw Assert.unreachableCode(); - } - case '{': { - if (! flags.contains(Flag.NO_SMART_BRACES)) { - // TP 1.2 - ignoreBraceLevel++; - } - // TP 1.3 - continue; - } - case '}': { - if (! flags.contains(Flag.NO_SMART_BRACES) && ignoreBraceLevel > 0) { - // TP 1.1 - ignoreBraceLevel--; - continue; - } else if (endOnBrace) { - // TP 30 - itr.prev(); // back up to point at } again - // TP 46 // allow an empty default value - if (idx >= start) { - list.add(new LiteralNode(itr.getStr(), start, idx)); - } - return Node.fromList(list); - } else { - // TP 31 - // treat as plain content - continue; - } - //throw Assert.unreachableCode(); - } - case '\\': { - if (flags.contains(Flag.ESCAPES)) { - if (idx > start) { - list.add(new LiteralNode(itr.getStr(), start, idx)); - start = idx; - } - if (! itr.hasNext()) { - if (flags.contains(Flag.LENIENT_SYNTAX)) { - // just treat it like plain content - // TP 33 - continue; - } else { - // TP 34 - throw invalidExpressionSyntax(itr.getStr(), idx); - } - } else { - ch = itr.next(); - final LiteralNode node; - switch (ch) { - case 'n': { - // TP 35 - node = LiteralNode.NEWLINE; - break; - } - case 'r': { - // TP 36 - node = LiteralNode.CARRIAGE_RETURN; - break; - } - case 't': { - // TP 37 - node = LiteralNode.TAB; - break; - } - case 'b': { - // TP 38 - node = LiteralNode.BACKSPACE; - break; - } - case 'f': { - // TP 39 - node = LiteralNode.FORM_FEED; - break; - } - case '\\': { - // TP 45 - node = LiteralNode.BACKSLASH; - break; - } - default: { - if (flags.contains(Flag.LENIENT_SYNTAX)) { - // TP 40 - // just append the literal character after the \, whatever it was - start = itr.getPrevIdx(); - continue; - } - // TP 41 - throw invalidExpressionSyntax(itr.getStr(), idx); - } - } - list.add(node); - start = itr.getNextIdx(); - continue; - } - } - // TP 42 - // otherwise, just... - continue; - } - default: { - // TP 43 - // treat as plain content - //noinspection UnnecessaryContinue - continue; - } - } - //throw Assert.unreachableCode(); - } - final int length = itr.getStr().length(); - if (length > start) { - // TP 44 - list.add(new LiteralNode(itr.getStr(), start, length)); - } - return Node.fromList(list); + return new Expression(io.smallrye.common.expression.Expression.compile(string, Flag.mapFlags(flags))); } - private static IllegalArgumentException invalidExpressionSyntax(final String string, final int index) { - String msg = CommonMessages.msg.invalidExpressionSyntax(index); - StringBuilder b = new StringBuilder(msg.length() + string.length() + string.length() + 5); - b.append(msg); - b.append('\n').append('\t').append(string); - b.append('\n').append('\t'); - for (int i = 0; i < index; i = string.offsetByCodePoints(i, 1)) { - final int cp = string.codePointAt(i); - if (Character.isWhitespace(cp)) { - b.append(cp); - } else if (Character.isValidCodePoint(cp) && ! Character.isISOControl(cp)) { - b.append(' '); - } - } - b.append('^'); - return new IllegalArgumentException(b.toString()); - } - - private static final EnumSet NO_FLAGS = EnumSet.noneOf(Flag.class); - /** * Flags that can apply to a property expression compilation */ @@ -669,39 +146,81 @@ public enum Flag { /** * Do not trim leading and trailing whitespace off of the expression string before parsing it. */ - NO_TRIM, + NO_TRIM(io.smallrye.common.expression.Expression.Flag.NO_TRIM), /** * Ignore syntax problems instead of throwing an exception. */ - LENIENT_SYNTAX, + LENIENT_SYNTAX(io.smallrye.common.expression.Expression.Flag.LENIENT_SYNTAX), /** * Support single-character expressions that can be interpreted without wrapping in curly braces. */ - MINI_EXPRS, + MINI_EXPRS(io.smallrye.common.expression.Expression.Flag.MINI_EXPRS), /** * Do not support recursive expression expansion in the key part of the expression. */ - NO_RECURSE_KEY, + NO_RECURSE_KEY(io.smallrye.common.expression.Expression.Flag.NO_RECURSE_KEY), /** * Do not support recursion in default values. */ - NO_RECURSE_DEFAULT, + NO_RECURSE_DEFAULT(io.smallrye.common.expression.Expression.Flag.NO_RECURSE_DEFAULT), /** * Do not support smart braces. */ - NO_SMART_BRACES, + NO_SMART_BRACES(io.smallrye.common.expression.Expression.Flag.NO_SMART_BRACES), /** * Support {@code Policy} file style "general" expansion alternate expression syntax. "Smart" braces * will only work if the opening brace is not the first character in the expression key. */ - GENERAL_EXPANSION, + GENERAL_EXPANSION(io.smallrye.common.expression.Expression.Flag.GENERAL_EXPANSION), /** * Support standard escape sequences in plain text and default value fields, which begin with a backslash ("{@code \}") character. */ - ESCAPES, + ESCAPES(io.smallrye.common.expression.Expression.Flag.ESCAPES), /** * Treat expressions containing a double-colon delimiter as special, encoding the entire content into the key. */ - DOUBLE_COLON, + DOUBLE_COLON(io.smallrye.common.expression.Expression.Flag.DOUBLE_COLON), + ; + + private final io.smallrye.common.expression.Expression.Flag flag; + + Flag(final io.smallrye.common.expression.Expression.Flag flag) { + this.flag = flag; + } + + static Flag of(io.smallrye.common.expression.Expression.Flag flag) { + switch (flag) { + case NO_TRIM: return NO_TRIM; + case LENIENT_SYNTAX: return LENIENT_SYNTAX; + case MINI_EXPRS: return MINI_EXPRS; + case NO_RECURSE_KEY: return NO_RECURSE_KEY; + case NO_RECURSE_DEFAULT: return NO_RECURSE_DEFAULT; + case NO_SMART_BRACES: return NO_SMART_BRACES; + case GENERAL_EXPANSION: return GENERAL_EXPANSION; + case ESCAPES: return ESCAPES; + case DOUBLE_COLON: return DOUBLE_COLON; + default: throw new NoSuchElementException(flag.toString()); + } + } + + io.smallrye.common.expression.Expression.Flag flag() { + return flag; + } + + static EnumSet mapFlagsArray(Flag[] array) { + EnumSet set = EnumSet.noneOf(io.smallrye.common.expression.Expression.Flag.class); + for (Flag f : array) { + set.add(f.flag()); + } + return set; + } + + static EnumSet mapFlags(final EnumSet flags) { + EnumSet set = EnumSet.noneOf(io.smallrye.common.expression.Expression.Flag.class); + for (Flag f : flags) { + set.add(f.flag()); + } + return set; + } } } diff --git a/src/main/java/org/wildfly/common/expression/ExpressionNode.java b/src/main/java/org/wildfly/common/expression/ExpressionNode.java deleted file mode 100644 index 676e7b5..0000000 --- a/src/main/java/org/wildfly/common/expression/ExpressionNode.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * JBoss, Home of Professional Open Source. - * Copyright 2017 Red Hat, Inc., and individual contributors - * as indicated by the @author tags. - * - * 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.wildfly.common.expression; - -import java.util.HashSet; - -import org.wildfly.common.function.ExceptionBiConsumer; - -/** - * @author David M. Lloyd - */ -class ExpressionNode extends Node { - private final boolean generalExpression; - private final Node key; - private final Node defaultValue; - - ExpressionNode(final boolean generalExpression, final Node key, final Node defaultValue) { - this.generalExpression = generalExpression; - this.key = key; - this.defaultValue = defaultValue; - } - - void emit(final ResolveContext context, final ExceptionBiConsumer, StringBuilder, E> resolveFunction) throws E { - ExpressionNode oldCurrent = context.setCurrent(this); - try { - resolveFunction.accept(context, context.getStringBuilder()); - } finally { - context.setCurrent(oldCurrent); - } - } - - void catalog(final HashSet strings) { - if (key instanceof LiteralNode) { - strings.add(key.toString()); - } else { - key.catalog(strings); - } - defaultValue.catalog(strings); - } - - boolean isGeneralExpression() { - return generalExpression; - } - - Node getKey() { - return key; - } - - Node getDefaultValue() { - return defaultValue; - } - - public String toString() { - return String.format("Expr<%s:%s>", key, defaultValue); - } -} diff --git a/src/main/java/org/wildfly/common/expression/LiteralNode.java b/src/main/java/org/wildfly/common/expression/LiteralNode.java deleted file mode 100644 index ff05353..0000000 --- a/src/main/java/org/wildfly/common/expression/LiteralNode.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * JBoss, Home of Professional Open Source. - * Copyright 2017 Red Hat, Inc., and individual contributors - * as indicated by the @author tags. - * - * 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.wildfly.common.expression; - -import java.io.File; -import java.util.HashSet; - -import org.wildfly.common.function.ExceptionBiConsumer; - -/** - * @author David M. Lloyd - */ -class LiteralNode extends Node { - static final LiteralNode DOLLAR = new LiteralNode("$"); - static final LiteralNode CLOSE_BRACE = new LiteralNode("}"); - static final LiteralNode FILE_SEP = new LiteralNode(File.separator); - static final LiteralNode COLON = new LiteralNode(":"); - static final LiteralNode NEWLINE = new LiteralNode("\n"); - static final LiteralNode CARRIAGE_RETURN = new LiteralNode("\r"); - static final LiteralNode TAB = new LiteralNode("\t"); - static final LiteralNode BACKSPACE = new LiteralNode("\b"); - static final LiteralNode FORM_FEED = new LiteralNode("\f"); - static final LiteralNode BACKSLASH = new LiteralNode("\\"); - - private final String literalValue; - private final int start; - private final int end; - private String toString; - - LiteralNode(final String literalValue, final int start, final int end) { - this.literalValue = literalValue; - this.start = start; - this.end = end; - } - - LiteralNode(final String literalValue) { - this(literalValue, 0, literalValue.length()); - } - - void emit(final ResolveContext context, final ExceptionBiConsumer, StringBuilder, E> resolveFunction) throws E { - context.getStringBuilder().append(literalValue, start, end); - } - - void catalog(final HashSet strings) { - } - - public String toString() { - final String toString = this.toString; - return toString != null ? toString : (this.toString = literalValue.substring(start, end)); - } -} diff --git a/src/main/java/org/wildfly/common/expression/Node.java b/src/main/java/org/wildfly/common/expression/Node.java deleted file mode 100644 index 79b507f..0000000 --- a/src/main/java/org/wildfly/common/expression/Node.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * JBoss, Home of Professional Open Source. - * Copyright 2017 Red Hat, Inc., and individual contributors - * as indicated by the @author tags. - * - * 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.wildfly.common.expression; - -import java.util.HashSet; -import java.util.List; - -import org.wildfly.common.function.ExceptionBiConsumer; - -/** - * @author David M. Lloyd - */ -abstract class Node { - - static final Node[] NO_NODES = new Node[0]; - - Node() { - } - - static Node fromList(List list) { - if (list == null || list.isEmpty()) { - return NULL; - } else if (list.size() == 1) { - return list.get(0); - } else { - return new CompositeNode(list); - } - } - - static final Node NULL = new Node() { - void emit(final ResolveContext context, final ExceptionBiConsumer, StringBuilder, E> resolveFunction) throws E { - } - - void catalog(final HashSet strings) { - } - - public String toString() { - return "<>"; - } - }; - - abstract void emit(final ResolveContext context, final ExceptionBiConsumer, StringBuilder, E> resolveFunction) throws E; - - abstract void catalog(final HashSet strings); -} - diff --git a/src/main/java/org/wildfly/common/expression/ResolveContext.java b/src/main/java/org/wildfly/common/expression/ResolveContext.java index 18f20c6..9f2ef14 100644 --- a/src/main/java/org/wildfly/common/expression/ResolveContext.java +++ b/src/main/java/org/wildfly/common/expression/ResolveContext.java @@ -18,8 +18,6 @@ package org.wildfly.common.expression; -import org.wildfly.common.function.ExceptionBiConsumer; - /** * The expression resolve context, which can be used to query the current expression key, write out expansions or * default values, or perform validation. @@ -29,15 +27,15 @@ * @param the exception type that can be thrown by the expansion function * * @author David M. Lloyd + * + * @deprecated Use {@link io.smallrye.common.expression.ResolveContext} instead. */ +@Deprecated(forRemoval = true) public final class ResolveContext { - private final ExceptionBiConsumer, StringBuilder, E> function; - private StringBuilder builder; - private ExpressionNode current; + private final io.smallrye.common.expression.ResolveContext delegate; - ResolveContext(final ExceptionBiConsumer, StringBuilder, E> function, final StringBuilder builder) { - this.function = function; - this.builder = builder; + ResolveContext(final io.smallrye.common.expression.ResolveContext delegate) { + this.delegate = delegate; } /** @@ -49,16 +47,7 @@ public final class ResolveContext { * @throws E if the recursive expansion threw an exception */ public String getKey() throws E { - if (current == null) throw new IllegalStateException(); - final Node key = current.getKey(); - if (key instanceof LiteralNode) { - return key.toString(); - } else if (key == Node.NULL) { - return ""; - } - final StringBuilder b = new StringBuilder(); - emitToBuilder(b, key); - return b.toString(); + return delegate.getKey(); } /** @@ -70,25 +59,7 @@ public String getKey() throws E { * @throws E if the recursive expansion threw an exception */ public void expandDefault(StringBuilder target) throws E { - if (current == null) throw new IllegalStateException(); - emitToBuilder(target, current.getDefaultValue()); - } - - private void emitToBuilder(final StringBuilder target, final Node node) throws E { - if (node == Node.NULL) { - return; - } else if (node instanceof LiteralNode) { - target.append(node.toString()); - return; - } else { - final StringBuilder old = builder; - try { - builder = target; - node.emit(this, function); - } finally { - builder = old; - } - } + delegate.expandDefault(target); } /** @@ -99,7 +70,7 @@ private void emitToBuilder(final StringBuilder target, final Node node) throws E * @throws E if the recursive expansion threw an exception */ public void expandDefault() throws E { - expandDefault(builder); + delegate.expandDefault(); } /** @@ -111,16 +82,7 @@ public void expandDefault() throws E { * @throws E if the recursive expansion threw an exception */ public String getExpandedDefault() throws E { - if (current == null) throw new IllegalStateException(); - final Node defaultValue = current.getDefaultValue(); - if (defaultValue instanceof LiteralNode) { - return defaultValue.toString(); - } else if (defaultValue == Node.NULL) { - return ""; - } - final StringBuilder b = new StringBuilder(); - emitToBuilder(b, defaultValue); - return b.toString(); + return delegate.getExpandedDefault(); } /** @@ -129,18 +91,6 @@ public String getExpandedDefault() throws E { * @return {@code true} if there is a default value, {@code false} otherwise */ public boolean hasDefault() { - return current.getDefaultValue() != Node.NULL; - } - - StringBuilder getStringBuilder() { - return builder; - } - - ExpressionNode setCurrent(final ExpressionNode current) { - try { - return this.current; - } finally { - this.current = current; - } + return delegate.hasDefault(); } } diff --git a/src/main/java/org/wildfly/common/expression/package-info.java b/src/main/java/org/wildfly/common/expression/package-info.java index d9c282e..698ee33 100644 --- a/src/main/java/org/wildfly/common/expression/package-info.java +++ b/src/main/java/org/wildfly/common/expression/package-info.java @@ -20,6 +20,8 @@ * Expression string parsing and expansion classes. * * @author David M. Lloyd + * + * @deprecated Use {@link io.smallrye.common.expression} instead. */ - +@Deprecated(forRemoval = true) package org.wildfly.common.expression; diff --git a/src/test/java/org/wildfly/common/expression/ExpressionTestCase.java b/src/test/java/org/wildfly/common/expression/ExpressionTestCase.java deleted file mode 100644 index 535571f..0000000 --- a/src/test/java/org/wildfly/common/expression/ExpressionTestCase.java +++ /dev/null @@ -1,552 +0,0 @@ -/* - * JBoss, Home of Professional Open Source. - * Copyright 2017 Red Hat, Inc., and individual contributors - * as indicated by the @author tags. - * - * 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.wildfly.common.expression; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import org.junit.Test; -import org.wildfly.common.Assert; - -/** - * @author David M. Lloyd - */ -public class ExpressionTestCase { - @Test - public void testEmpty() throws Exception { - final Expression expression = Expression.compile(""); - assertEquals("Should expand to empty string", "", expression.evaluate((c, b) -> { - fail("No expressions should be found"); - })); - } - - @Test - public void testLiteral() throws Exception { - final String expected = "this is a literal"; - final Expression expression = Expression.compile(expected); - assertEquals(expected, expression.evaluate((c, b) -> { - fail("No expressions should be found"); - })); - } - - @Test - public void testExpr1() throws Exception { - final Expression expression = Expression.compile("${foo.bar}"); - assertEquals("Should expand to empty string", "", expression.evaluate((c, b) -> { - assertEquals("foo.bar", c.getKey()); - })); - } - - @Test - public void testExpr1a() throws Exception { - final Expression expression = Expression.compile("${foo.bar}"); - assertEquals("fuzz", expression.evaluate((c, b) -> { - assertEquals("foo.bar", c.getKey()); - b.append("fuzz"); - })); - } - - @Test - public void testNoTrim1() throws Exception { - final Expression expression1 = Expression.compile(" ${foo.bar} "); - assertEquals("", expression1.evaluate((c, b) -> {})); - final Expression expression2 = Expression.compile(" ${foo.bar} ", Expression.Flag.NO_TRIM); - assertEquals(" ", expression2.evaluate((c, b) -> {})); - } - - @Test - public void testNoTrim2() throws Exception { - final Expression expression1 = Expression.compile(" this is a literal "); - assertEquals("this is a literal", expression1.evaluate((c, b) -> {})); - final Expression expression2 = Expression.compile(" this is a literal ", Expression.Flag.NO_TRIM); - assertEquals(" this is a literal ", expression2.evaluate((c, b) -> {})); - } - - @Test - public void testExpr2() throws Exception { - final Expression expression = Expression.compile("foo${foo.bar}bar"); - assertEquals("foobazbar", expression.evaluate((c, b) -> { - assertEquals("foo.bar", c.getKey()); - b.append("baz"); - })); - } - - @Test - public void testExpr3() throws Exception { - final Expression expression = Expression.compile("foo${foo.bar}"); - assertEquals("foobaz", expression.evaluate((c, b) -> { - assertEquals("foo.bar", c.getKey()); - b.append("baz"); - })); - } - - @Test - public void testExpr4() throws Exception { - final Expression expression = Expression.compile("${foo.bar}bar"); - assertEquals("bazbar", expression.evaluate((c, b) -> { - assertEquals("foo.bar", c.getKey()); - b.append("baz"); - })); - } - - @Test - public void testRecurseKey1() throws Exception { - final Expression expression = Expression.compile("${${foo}.bar}bar"); - assertEquals("bazbar", expression.evaluate((c, b) -> { - final String key = c.getKey(); - switch (key) { - case "foo": b.append("bzz"); return; - case "bzz.bar": b.append("baz"); return; - default: throw Assert.impossibleSwitchCase(key); - } - })); - } - - @Test - public void testRecurseDefault1() throws Exception { - final Expression expression = Expression.compile("${foo:${bar}}bar"); - assertEquals("bazbar", expression.evaluate((c, b) -> { - final String key = c.getKey(); - switch (key) { - case "foo": c.expandDefault(); return; - case "bar": b.append("baz"); return; - default: throw Assert.impossibleSwitchCase(key); - } - })); - } - - @Test - public void testGeneralExpansion1() throws Exception { - final Expression expression = Expression.compile("foo${{zip}}${bar}", Expression.Flag.GENERAL_EXPANSION); - assertEquals("foobazrab", expression.evaluate((c, b) -> { - final String key = c.getKey(); - switch (key) { - case "zip": b.append("baz"); return; - case "bar": b.append("rab"); return; - default: throw Assert.impossibleSwitchCase(key); - } - })); - } - - @Test - public void testPoint1() throws Exception { - final Expression expression = Expression.compile("${${foo}}", Expression.Flag.NO_RECURSE_KEY); - expression.evaluate((c, b) -> { - assertEquals("${foo}", c.getKey()); - }); - } - - @Test - public void testPoint2() throws Exception { - try { - final Expression expression = Expression.compile("$"); - fail("expected exception"); - } catch (IllegalArgumentException e) { - // OK - } - } - - @Test - public void testPoint3() throws Exception { - final Expression expression = Expression.compile("$", Expression.Flag.LENIENT_SYNTAX); - assertEquals("$", expression.evaluate((c, b) -> { - fail("unexpected expansion"); - })); - final Expression expression2 = Expression.compile("foo$", Expression.Flag.LENIENT_SYNTAX); - assertEquals("foo$", expression2.evaluate((c, b) -> { - fail("unexpected expansion"); - })); - } - - @Test - public void testPoint3_1() throws Exception { - final Expression expression = Expression.compile("$$"); - assertEquals("$", expression.evaluate((c, b) -> { - fail("unexpected expansion"); - })); - final Expression expression2 = Expression.compile("foo$$"); - assertEquals("foo$", expression2.evaluate((c, b) -> { - fail("unexpected expansion"); - })); - } - - // no testPoint4 - - @Test - public void testPoint5() throws Exception { - try { - Expression.compile("${expr"); - fail("expected exception"); - } catch (IllegalArgumentException e) { - // OK - } - } - - @Test - public void testPoint6() throws Exception { - final Expression expression = Expression.compile("${expr", Expression.Flag.LENIENT_SYNTAX); - assertEquals("result", expression.evaluate((c, b) -> { - assertEquals("expr", c.getKey()); - b.append("result"); - })); - } - - @Test - public void testPoint7() throws Exception { - final Expression expression = Expression.compile("${expr::baz}", Expression.Flag.DOUBLE_COLON); - assertEquals("result", expression.evaluate((c, b) -> { - assertEquals("expr::baz", c.getKey()); - b.append("result"); - })); - } - - @Test - public void testPoint8() throws Exception { - final Expression expression = Expression.compile("${expr::baz}"); - assertEquals(":baz", expression.evaluate((c, b) -> { - assertEquals("expr", c.getKey()); - c.expandDefault(); - })); - } - - @Test - public void testPoint9() throws Exception { - try { - Expression.compile("${expr:foo"); - fail("expected exception"); - } catch (IllegalArgumentException e) { - // OK - } - } - - @Test - public void testPoint10() throws Exception { - final Expression expression = Expression.compile("${expr:foo", Expression.Flag.LENIENT_SYNTAX); - assertEquals("foo", expression.evaluate((c, b) -> { - assertEquals("expr", c.getKey()); - c.expandDefault(); - })); - } - - @Test - public void testPoint11() throws Exception { - final Expression expression = Expression.compile("${expr:foo}bar"); - assertEquals("foobar", expression.evaluate((c, b) -> { - assertEquals("expr", c.getKey()); - c.expandDefault(); - })); - } - - @Test - public void testPoint12() throws Exception { - final Expression expression = Expression.compile("${expr}bar"); - assertEquals("foobar", expression.evaluate((c, b) -> { - assertEquals("expr", c.getKey()); - b.append("foo"); - })); - } - - @Test - public void testPoint13() throws Exception { - final Expression expression = Expression.compile("foo$$bar", Expression.Flag.MINI_EXPRS); - assertEquals("foorizbar", expression.evaluate((c, b) -> { - assertEquals("$", c.getKey()); - b.append("riz"); - })); - } - - @Test - public void testPoint14() throws Exception { - final Expression expression = Expression.compile("foo$$bar"); - assertEquals("foo$bar", expression.evaluate((c, b) -> { - fail("unexpected expansion"); - })); - } - - @Test - public void testPoint15() throws Exception { - final Expression expression = Expression.compile("foo$}bar", Expression.Flag.MINI_EXPRS); - assertEquals("foorizbar", expression.evaluate((c, b) -> { - assertEquals("}", c.getKey()); - b.append("riz"); - })); - } - - @Test - public void testPoint16() throws Exception { - final Expression expression = Expression.compile("foo${bar$}baz", Expression.Flag.LENIENT_SYNTAX); - assertEquals("foorizbaz", expression.evaluate((c, b) -> { - assertEquals("bar$", c.getKey()); - b.append("riz"); - })); - } - - @Test - public void testPoint17() throws Exception { - try { - Expression.compile("foo${bar$}baz"); - fail("expected exception"); - } catch (IllegalArgumentException e) { - // OK - } - } - - @Test - public void testPoint18() throws Exception { - final Expression expression = Expression.compile("foo$}bar", Expression.Flag.LENIENT_SYNTAX); - assertEquals("foo$}bar", expression.evaluate((c, b) -> { - fail("unexpected expansion"); - })); - } - - @Test - public void testPoint19() throws Exception { - try { - Expression.compile("foobar$}baz"); - fail("expected exception"); - } catch (IllegalArgumentException e) { - // OK - } - } - - @Test - public void testPoint20() throws Exception { - final Expression expression = Expression.compile("foo$:baz", Expression.Flag.MINI_EXPRS); - assertEquals("foobarbaz", expression.evaluate((c, b) -> { - assertEquals(":", c.getKey()); - b.append("bar"); - })); - } - - @Test - public void testPoint21() throws Exception { - final Expression expression = Expression.compile("${foo$:bar}", Expression.Flag.LENIENT_SYNTAX); - assertEquals("baz", expression.evaluate((c, b) -> { - assertEquals("foo$", c.getKey()); - assertEquals("bar", c.getExpandedDefault()); - b.append("baz"); - })); - } - - @Test - public void testPoint22() throws Exception { - try { - Expression.compile("${foo$:bar}"); - fail("expected exception"); - } catch (IllegalArgumentException e) { - // OK - } - } - - @Test - public void testPoint23() throws Exception { - final Expression expression = Expression.compile("foo$:bar", Expression.Flag.LENIENT_SYNTAX); - assertEquals("foo$:bar", expression.evaluate((c, b) -> { - fail("unexpected expansion"); - })); - } - - @Test - public void testPoint24() throws Exception { - try { - Expression.compile("foo$:bar"); - fail("expected exception"); - } catch (IllegalArgumentException e) { - // OK - } - } - - @Test - public void testPoint25() throws Exception { - final Expression expression = Expression.compile("foo$xbar", Expression.Flag.MINI_EXPRS); - assertEquals("foobazbar", expression.evaluate((c, b) -> { - assertEquals("x", c.getKey()); - b.append("baz"); - })); - } - - @Test - public void testPoint26() throws Exception { - final Expression expression = Expression.compile("foo$xbar", Expression.Flag.LENIENT_SYNTAX); - assertEquals("foo$xbar", expression.evaluate((c, b) -> { - fail("unexpected expansion"); - })); - } - - @Test - public void testPoint27() throws Exception { - try { - Expression.compile("foo$xbar"); - fail("expected exception"); - } catch (IllegalArgumentException e) { - // OK - } - } - - @Test - public void testPoint28() throws Exception { - final Expression expression = Expression.compile("${foo:bar}"); - assertEquals("bar", expression.evaluate((c, b) -> { - assertEquals("foo", c.getKey()); - assertEquals("bar", c.getExpandedDefault()); - c.expandDefault(); - })); - } - - @Test - public void testPoint29() throws Exception { - final Expression expression = Expression.compile("foo:bar"); - assertEquals("foo:bar", expression.evaluate((c, b) -> { - fail("unexpected expansion"); - })); - } - - @Test - public void testPoint1_2() throws Exception { - final Expression expression = Expression.compile("{${foo{bar}}}"); - assertEquals("{xxx}", expression.evaluate((c, b) -> { - assertEquals("foo{bar}", c.getKey()); - b.append("xxx"); - })); - } - - @Test - public void testPoint1_3() throws Exception { - // also TP 30, 31 - final Expression expression = Expression.compile("{${foo{bar}}}", Expression.Flag.NO_SMART_BRACES); - assertEquals("{xxx}}", expression.evaluate((c, b) -> { - assertEquals("foo{bar", c.getKey()); - b.append("xxx"); - })); - } - - // no tp 32 - - @Test - public void testPoint33() throws Exception { - final Expression expression = Expression.compile("foo\\", Expression.Flag.LENIENT_SYNTAX, Expression.Flag.ESCAPES); - assertEquals("foo\\", expression.evaluate((c, b) -> { - fail("unexpected expansion"); - })); - } - - @Test - public void testPoint34() throws Exception { - try { - Expression.compile("foo\\", Expression.Flag.ESCAPES); - fail("expected exception"); - } catch (IllegalArgumentException e) { - // OK - } - } - - @Test - public void testPoint35() throws Exception { - final Expression expression = Expression.compile("foo\\nbar", Expression.Flag.ESCAPES); - assertEquals("foo\nbar", expression.evaluate((c, b) -> { - fail("unexpected expansion"); - })); - } - - @Test - public void testPoint36() throws Exception { - final Expression expression = Expression.compile("foo\\rbar", Expression.Flag.ESCAPES); - assertEquals("foo\rbar", expression.evaluate((c, b) -> { - fail("unexpected expansion"); - })); - } - - @Test - public void testPoint37() throws Exception { - final Expression expression = Expression.compile("foo\\tbar", Expression.Flag.ESCAPES); - assertEquals("foo\tbar", expression.evaluate((c, b) -> { - fail("unexpected expansion"); - })); - } - - @Test - public void testPoint38() throws Exception { - final Expression expression = Expression.compile("foo\\bbar", Expression.Flag.ESCAPES); - assertEquals("foo\bbar", expression.evaluate((c, b) -> { - fail("unexpected expansion"); - })); - } - - @Test - public void testPoint39() throws Exception { - final Expression expression = Expression.compile("foo\\fbar", Expression.Flag.ESCAPES); - assertEquals("foo\fbar", expression.evaluate((c, b) -> { - fail("unexpected expansion"); - })); - } - - @Test - public void testPoint40() throws Exception { - final Expression expression = Expression.compile("foo\\?bar", Expression.Flag.ESCAPES, Expression.Flag.LENIENT_SYNTAX); - assertEquals("foo?bar", expression.evaluate((c, b) -> { - fail("unexpected expansion"); - })); - } - - @Test - public void testPoint41() throws Exception { - try { - Expression.compile("foo\\?bar", Expression.Flag.ESCAPES); - fail("expected exception"); - } catch (IllegalArgumentException e) { - // OK - } - } - - @Test - public void testPoint42() throws Exception { - final Expression expression = Expression.compile("foo\\?bar"); - assertEquals("foo\\?bar", expression.evaluate((c, b) -> { - fail("unexpected expansion"); - })); - } - - @Test - public void testPoint43() throws Exception { - // also tp 44 - final Expression expression = Expression.compile("plain-content"); - assertEquals("plain-content", expression.evaluate((c, b) -> { - fail("unexpected expansion"); - })); - } - - @Test - public void testPoint45() throws Exception { - final Expression expression = Expression.compile("W:\\\\workspace\\\\some-path\\\\xxxxyyyy", Expression.Flag.ESCAPES); - assertEquals("W:\\workspace\\some-path\\xxxxyyyy", expression.evaluate((c, b) -> { - fail("unexpected expansion"); - })); - } - - @Test - public void testPoint46() throws Exception { - // an empty default value is valid - final Expression expression = Expression.compile("${foo.bar:}"); - assertEquals("Should expand to empty string", "", expression.evaluate((c, b) -> { - assertTrue(c.hasDefault()); - assertEquals("", c.getExpandedDefault()); - })); - } -}