Skip to content

Commit

Permalink
Add STRING_TEMPLATE function and add two more cases for STRING_CASE f…
Browse files Browse the repository at this point in the history
…unction
  • Loading branch information
taodong committed Sep 11, 2024
1 parent d11dc8e commit 907595e
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ public abstract class EvalExOperation<T> {
Map.entry("PAST_TIME_AFTER", new PastTimeAfterFunction()),
Map.entry("TIME_BETWEEN", new TimeBetweenFunction()),
Map.entry("STRING_CASE", new StringCaseFunction()),
Map.entry("FULL_EMAIL_ADDRESS", new FullEmailAddressFunction())
Map.entry("FULL_EMAIL_ADDRESS", new FullEmailAddressFunction()),
Map.entry("STRING_TEMPLATE", new StringTemplateFunction())
);

protected final Set<String> parameters = new HashSet<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
import com.ezylang.evalex.parser.Token;
import org.apache.commons.lang3.StringUtils;

import java.util.Arrays;
import java.util.stream.Collectors;

@FunctionParameter(name= "str")
@FunctionParameter(name = "case")
public class StringCaseFunction extends AbstractFunction {
Expand All @@ -18,9 +21,17 @@ public EvaluationValue evaluate(Expression expression, Token token, EvaluationVa
var result = switch (StringUtils.trim(StringUtils.lowerCase(caseType))) {
case "upper" -> StringUtils.upperCase(str);
case "lower" -> StringUtils.lowerCase(str);
case "pascal" -> toPascalCase(str);
case "title" -> StringUtils.capitalize(StringUtils.lowerCase(str));
default -> str;
};

return EvaluationValue.stringValue(result);
}

private String toPascalCase(String str) {
return Arrays.stream(str.split(" "))
.map(value -> StringUtils.capitalize(StringUtils.lowerCase(value)))
.collect(Collectors.joining(" "));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package tao.dong.dataconjurer.common.evalex;

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;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringSubstitutor;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@FunctionParameter(name = "template")
@FunctionParameter(name = "values", isVarArg = true)
public class StringTemplateFunction extends AbstractFunction {

private static final String DOUBLE_DOLLAR = "$$";
private static final String INTERNAL_REPLACE = "<???TEMP???>";
private static final String DOLLAR = "$";

@Override
public EvaluationValue evaluate(Expression expression, Token token, EvaluationValue... evaluationValues) {
var template = evaluationValues[0].getStringValue();
var modifiedTemplate = StringUtils.replace(template, DOUBLE_DOLLAR, INTERNAL_REPLACE);
var values = evaluationValues[1].getArrayValue();
if (values.size() % 2 != 0) {
throw new IllegalArgumentException("Invalid number of arguments for function STRING_TEMPLATE");
}

final var valueMap = createValueMap(values);
var substitutor = new StringSubstitutor(key -> valueMap.getOrDefault(key, ""));
substitutor.setEnableUndefinedVariableException(false);
substitutor.setValueDelimiter("");
var result = substitutor.replace(modifiedTemplate);
var modifiedResult = StringUtils.replace(result, INTERNAL_REPLACE, DOLLAR);

return EvaluationValue.stringValue(modifiedResult);
}

private Map<String, String> createValueMap(List<EvaluationValue> values) {
Map<String, String> valueMap = new HashMap<>();
for (int i = 0; i < values.size(); i += 2) {
valueMap.put(values.get(i).getStringValue(), values.get(i + 1).getStringValue());
}
return valueMap;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ private static Stream<Arguments> evaluate() {
Arguments.of("HELLO", "lower", "hello"),
Arguments.of("Hello", "LOWER", "hello"),
Arguments.of("Hello", "UPper", "HELLO"),
Arguments.of("Hello", "unknown", "Hello")
Arguments.of("Hello", "unknown", "Hello"),
Arguments.of("hello", "pascal", "Hello"),
Arguments.of("HELLO world 2 yOu", "pascal", "Hello World 2 You"),
Arguments.of("hello world", "title", "Hello world"),
Arguments.of("HELLO WORLD", "title", "Hello world")
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package tao.dong.dataconjurer.common.evalex;

import com.ezylang.evalex.EvaluationException;
import com.ezylang.evalex.Expression;
import com.ezylang.evalex.config.ExpressionConfiguration;
import com.ezylang.evalex.parser.ParseException;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

import java.util.Map;
import java.util.stream.Stream;

import static org.junit.jupiter.api.Assertions.*;

class StringTemplateFunctionTest {

private static final ExpressionConfiguration EXPRESSION_CONFIGURATION = ExpressionConfiguration.defaultConfiguration()
.withAdditionalFunctions(
Map.entry("STRING_TEMPLATE", new StringTemplateFunction())
);


private static Stream<Arguments> evaluate() {
return Stream.of(
Arguments.of("hello${name}world", new String[]{"name", "new"}, "hellonewworld"),
Arguments.of("Hello, ${name}!", new String[]{"name", "world"}, "Hello, world!"),
Arguments.of("Hello, ${name}! How are you ${name}?", new String[]{"name", "world"}, "Hello, world! How are you world?"),
Arguments.of("Hello, ${name}! How are you ${name1}?", new String[]{"name", "world", "name1", "today"}, "Hello, world! How are you today?"),
Arguments.of("Hello, ${name}! How are you ${name1}?", new String[]{"name", "world", "name2", "today"}, "Hello, world! How are you ?"),
Arguments.of("Hello, ${name}! How are you ${name1}?", new String[]{}, "Hello, ! How are you ?"),
Arguments.of("Hello, ${name}! How are you $${name1}?", new String[]{"name", "world", "name1", "today"}, "Hello, world! How are you ${name1}?"),
Arguments.of("Hello, ${name}! How are you $$${name1}?", new String[]{"name", "world", "name1", "today"}, "Hello, world! How are you $today?")
);
}

@ParameterizedTest
@MethodSource("evaluate")
void evaluate(String template, String[] values, String expected) throws EvaluationException, ParseException {
var expr = new Expression("STRING_TEMPLATE(template, values)", EXPRESSION_CONFIGURATION);
var result = expr.with("template", template).with("values", values).evaluate().getStringValue();
assertEquals(expected, result);
}

}
4 changes: 3 additions & 1 deletion release.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@
5. Enable single quote literals in alternation
6. Bug fix: looped strategy was ignored when using linked reference
7. Add `extra` field to DataOutputControl
8. Add FULL_EMAIL_ADDRESS function for alternation
8. Add FULL_EMAIL_ADDRESS function for alternation
9. Add STRING_TEMPLATE function for alternation
10. Add "pascal" and "title" case to STRING_CASE function

0 comments on commit 907595e

Please sign in to comment.