diff --git a/src/main/java/com/ezylang/evalex/config/ExpressionConfiguration.java b/src/main/java/com/ezylang/evalex/config/ExpressionConfiguration.java index 057b5692..92eaf849 100644 --- a/src/main/java/com/ezylang/evalex/config/ExpressionConfiguration.java +++ b/src/main/java/com/ezylang/evalex/config/ExpressionConfiguration.java @@ -57,6 +57,8 @@ import com.ezylang.evalex.functions.string.StringMatchesFunction; import com.ezylang.evalex.functions.string.StringRightFunction; import com.ezylang.evalex.functions.string.StringStartsWithFunction; +import com.ezylang.evalex.functions.string.StringSubstringAfterFunction; +import com.ezylang.evalex.functions.string.StringSubstringBeforeFunction; import com.ezylang.evalex.functions.string.StringSubstringFunction; import com.ezylang.evalex.functions.string.StringTrimFunction; import com.ezylang.evalex.functions.string.StringUpperFunction; @@ -280,6 +282,8 @@ public class ExpressionConfiguration { Map.entry("STR_RIGHT", new StringRightFunction()), Map.entry("STR_STARTS_WITH", new StringStartsWithFunction()), Map.entry("STR_SUBSTRING", new StringSubstringFunction()), + Map.entry("STR_SUBSTRING_AFTER", new StringSubstringAfterFunction()), + Map.entry("STR_SUBSTRING_BEFORE", new StringSubstringBeforeFunction()), Map.entry("STR_TRIM", new StringTrimFunction()), Map.entry("STR_UPPER", new StringUpperFunction()), // date time functions diff --git a/src/main/java/com/ezylang/evalex/functions/string/StringSubstringAfterFunction.java b/src/main/java/com/ezylang/evalex/functions/string/StringSubstringAfterFunction.java new file mode 100644 index 00000000..9ec52d9b --- /dev/null +++ b/src/main/java/com/ezylang/evalex/functions/string/StringSubstringAfterFunction.java @@ -0,0 +1,51 @@ +/* + Copyright 2012-2024 Udo Klimaschewski + + 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 com.ezylang.evalex.functions.string; + +import com.ezylang.evalex.EvaluationException; +import com.ezylang.evalex.Expression; +import com.ezylang.evalex.data.EvaluationValue; +import com.ezylang.evalex.functions.AbstractFunction; +import com.ezylang.evalex.functions.FunctionParameter; +import com.ezylang.evalex.parser.Token; + +/** + * Returns the substring after the first occurrence of another (separator) string, or an empty + * string if the first string does not contain the second string. + * + *

For example: {@code STR_SUBSTRING_AFTER("2024/07/15", "/")} returns {@code "07/15"}. + * + * @author oswaldobapvicjr + */ +@FunctionParameter(name = "string") +@FunctionParameter(name = "separator") +public class StringSubstringAfterFunction extends AbstractFunction { + private static final String STR_EMPTY = ""; + + @Override + public EvaluationValue evaluate( + Expression expression, Token functionToken, EvaluationValue... parameterValues) + throws EvaluationException { + String string = parameterValues[0].getStringValue(); + String separator = parameterValues[1].getStringValue(); + return expression.convertValue(substringAfter(string, separator)); + } + + private String substringAfter(String string, String separator) { + int position = string.indexOf(separator); + return (position == -1) ? STR_EMPTY : string.substring(position + separator.length()); + } +} diff --git a/src/main/java/com/ezylang/evalex/functions/string/StringSubstringBeforeFunction.java b/src/main/java/com/ezylang/evalex/functions/string/StringSubstringBeforeFunction.java new file mode 100644 index 00000000..f3cebfbf --- /dev/null +++ b/src/main/java/com/ezylang/evalex/functions/string/StringSubstringBeforeFunction.java @@ -0,0 +1,49 @@ +/* + Copyright 2012-2024 Udo Klimaschewski + + 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 com.ezylang.evalex.functions.string; + +import com.ezylang.evalex.EvaluationException; +import com.ezylang.evalex.Expression; +import com.ezylang.evalex.data.EvaluationValue; +import com.ezylang.evalex.functions.AbstractFunction; +import com.ezylang.evalex.functions.FunctionParameter; +import com.ezylang.evalex.parser.Token; + +/** + * Returns the substring before the first occurrence of another (separator) string, or the original + * string if it does not contain the second string. + * + *

For example: {@code STR_SUBSTRING_BEFORE("2024/07/15", "/")} returns {@code "2024"}. + * + * @author oswaldobapvicjr + */ +@FunctionParameter(name = "string") +@FunctionParameter(name = "separator") +public class StringSubstringBeforeFunction extends AbstractFunction { + @Override + public EvaluationValue evaluate( + Expression expression, Token functionToken, EvaluationValue... parameterValues) + throws EvaluationException { + String string = parameterValues[0].getStringValue(); + String separator = parameterValues[1].getStringValue(); + return expression.convertValue(substringBefore(string, separator)); + } + + private String substringBefore(String string, String separator) { + int position = string.indexOf(separator); + return (position == -1) ? string : string.substring(0, position); + } +} diff --git a/src/test/java/com/ezylang/evalex/functions/string/StringFunctionsTest.java b/src/test/java/com/ezylang/evalex/functions/string/StringFunctionsTest.java index 974f607a..936c2cd4 100644 --- a/src/test/java/com/ezylang/evalex/functions/string/StringFunctionsTest.java +++ b/src/test/java/com/ezylang/evalex/functions/string/StringFunctionsTest.java @@ -202,6 +202,37 @@ void testMatches(String expression, String expectedResult) assertExpressionHasExpectedResult(expression, expectedResult); } + @ParameterizedTest + @CsvSource( + delimiter = ':', + value = { + "STR_SUBSTRING_AFTER(\"myFile.json\", \".\") : json", + "STR_SUBSTRING_AFTER(\"2024/07/15\", \"/\") : 07/15", + "STR_SUBSTRING_AFTER(\"2024/07/15\", \"20\") : 24/07/15", + "STR_SUBSTRING_AFTER(\"test\", \"\") : 'test'", + "STR_SUBSTRING_AFTER(\"test\", \"a\") : ''", + "STR_SUBSTRING_AFTER(\"\", \"\") : ''" + }) + void testSubstringAfter(String expression, String expectedResult) + throws EvaluationException, ParseException { + assertExpressionHasExpectedResult(expression, expectedResult); + } + + @ParameterizedTest + @CsvSource( + delimiter = ':', + value = { + "STR_SUBSTRING_BEFORE(\"myFile.json\", \".\") : myFile", + "STR_SUBSTRING_BEFORE(\"2024/07/15\", \"/\") : 2024", + "STR_SUBSTRING_BEFORE(\"test\", \"\") : ''", + "STR_SUBSTRING_BEFORE(\"test\", \"a\") : 'test'", + "STR_SUBSTRING_BEFORE(\"\", \"\") : ''" + }) + void testSubstringBefore(String expression, String expectedResult) + throws EvaluationException, ParseException { + assertExpressionHasExpectedResult(expression, expectedResult); + } + @ParameterizedTest @CsvSource( delimiter = ':',