diff --git a/src/main/java/com/dashjoin/jsonata/Jsonata.java b/src/main/java/com/dashjoin/jsonata/Jsonata.java index 5cc6a7e..3808a96 100644 --- a/src/main/java/com/dashjoin/jsonata/Jsonata.java +++ b/src/main/java/com/dashjoin/jsonata/Jsonata.java @@ -37,6 +37,7 @@ import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Supplier; +import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -1628,7 +1629,7 @@ Jsonata getPerThreadInstance() { } } // apply the procedure - var procName = expr.procedure.type == "path" ? expr.procedure.steps.get(0).value : expr.procedure.value; + var procName = "path".equals(expr.procedure.type) ? expr.procedure.steps.get(0).value : expr.procedure.value; // Error if proc is null if (proc==null) @@ -1755,9 +1756,9 @@ Jsonata getPerThreadInstance() { List _res = new ArrayList<>(); for (String s : (List)validatedArgs) { //System.err.println("PAT "+proc+" input "+s); - if (((Pattern)proc).matcher(s).find()) { - //System.err.println("MATCH"); - _res.add(s); + if (s != null) { + Matcher matcher = ((Pattern) proc).matcher(s); + _res.add(regexClosure(matcher)); } } result = _res; @@ -1779,6 +1780,21 @@ Jsonata getPerThreadInstance() { } return result; } + + private static Map regexClosure(Matcher matcher) { + if (matcher.find()) { + String group = matcher.group(); + return Map.of( + "match", group, + "start", matcher.start(), + "end", matcher.end(), + "groups", List.of(group), + "next", (Fn0) () -> regexClosure(matcher) + ); + } else { + return null; + } + } /** * Evaluate lambda against input data diff --git a/src/main/java/com/dashjoin/jsonata/Parser.java b/src/main/java/com/dashjoin/jsonata/Parser.java index ccb05d9..553494f 100644 --- a/src/main/java/com/dashjoin/jsonata/Parser.java +++ b/src/main/java/com/dashjoin/jsonata/Parser.java @@ -998,7 +998,8 @@ Symbol processAST(Symbol expr) { rest.procedure.type.equals("path") && rest.procedure.steps.size() == 1 && rest.procedure.steps.get(0).type.equals("name") && - result.steps.get(result.steps.size() - 1).type.equals("function")) { + result.steps.get(result.steps.size() - 1).type.equals("function") && + rest.procedure.steps.get(0).value instanceof Symbol) { // next function in chain of functions - will override a thenable result.steps.get(result.steps.size() - 1).nextFunction = (Symbol)rest.procedure.steps.get(0).value; } diff --git a/src/test/java/com/dashjoin/jsonata/RegexTest.java b/src/test/java/com/dashjoin/jsonata/RegexTest.java new file mode 100644 index 0000000..26cb51a --- /dev/null +++ b/src/test/java/com/dashjoin/jsonata/RegexTest.java @@ -0,0 +1,71 @@ +package com.dashjoin.jsonata; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.Map; + +public class RegexTest { + @Test + public void testEvalRegex2() { + + Object data = Map.of( + "domain1.test.data", Map.of(), + "domain2.test.data", Map.of() + ); + var expression = Jsonata.jsonata( + "(\n" + + " $matcher := $eval('/^(domain1)\\\\./i');\n" + + " ('domain1.test.data' ~> $matcher)[0].match;\n" + + ")" + ); + Object evaluate = expression.evaluate(data); + String expected = "domain1."; + Assertions.assertEquals(expected, evaluate); + } + + @Test + public void testEvalRegex3() { + + Object data = Map.of( + "domain1.test.data", Map.of(), + "domain2.test.data", Map.of() + ); + var expression = Jsonata.jsonata( + "(\n" + + " $matcher := $eval('/^(domain1)\\\\./i');\n" + + " 'domain1.test.data' ~> $matcher" + + ")" + ); + // TODO: why there evaluate return list but next test return map (object). In js always return object + // maybe problem in braces, but on try.jsonata always return object + Map evaluate = (Map)(((List)expression.evaluate(data)).get(0)); + Assertions.assertEquals("domain1.", evaluate.get("match")); + Assertions.assertEquals(0, evaluate.get("start")); + Assertions.assertEquals(8, evaluate.get("end")); + Assertions.assertEquals(List.of("domain1."), evaluate.get("groups")); + Assertions.assertInstanceOf(Jsonata.Fn0.class, evaluate.get("next")); + } + + @Test + public void testEvalRegexNext() { + + Object data = Map.of( + "domain1.test.data", Map.of(), + "domain2.test.data", Map.of() + ); + var expression = Jsonata.jsonata( + "(\n" + + " $matcher := $eval('/.(domain)./i');\n" + + " ('domain1.test.domain.data.domain.a' ~> $matcher).next();\n" + + ")" + ); + Map evaluate = (Map)(expression.evaluate(data)); + Assertions.assertEquals(".domain.", evaluate.get("match")); + Assertions.assertEquals(24, evaluate.get("start")); + Assertions.assertEquals(32, evaluate.get("end")); + Assertions.assertEquals(List.of(".domain."), evaluate.get("groups")); + Assertions.assertInstanceOf(Jsonata.Fn0.class, evaluate.get("next")); + } +}