From 31ed446e8d3b304e4a071df01aafc64af89a3679 Mon Sep 17 00:00:00 2001 From: "AD\\aabdoun" Date: Wed, 8 Apr 2026 16:48:16 +0200 Subject: [PATCH 1/4] #345 [SPARQL 1.1] - Parser and AST : STRUUID --- .../query/impl/parser/SparqlAstBuilder.java | 2 + .../sparql/ast/constraint/StrUuidAst.java | 9 ++++ .../impl/parser/SparqlParserStrUuidTest.java | 49 +++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 src/main/java/fr/inria/corese/core/next/query/impl/sparql/ast/constraint/StrUuidAst.java create mode 100644 src/test/java/fr/inria/corese/core/next/query/impl/parser/SparqlParserStrUuidTest.java diff --git a/src/main/java/fr/inria/corese/core/next/query/impl/parser/SparqlAstBuilder.java b/src/main/java/fr/inria/corese/core/next/query/impl/parser/SparqlAstBuilder.java index 55057535a..5ad5b36be 100644 --- a/src/main/java/fr/inria/corese/core/next/query/impl/parser/SparqlAstBuilder.java +++ b/src/main/java/fr/inria/corese/core/next/query/impl/parser/SparqlAstBuilder.java @@ -1335,6 +1335,8 @@ public TermAst termFromBuiltInCall(fr.inria.corese.core.next.impl.parser.antlr.S } else { throw new QueryEvaluationException("Unexpected function for a BuiltInCall for token " + ctx.getText()); } + } else if (ctx.STRUUID() != null) { + return new StrUuidAst(); } else { throw new QueryEvaluationException("Unable to resolve BuiltInCall for token " + ctx.getText()); } diff --git a/src/main/java/fr/inria/corese/core/next/query/impl/sparql/ast/constraint/StrUuidAst.java b/src/main/java/fr/inria/corese/core/next/query/impl/sparql/ast/constraint/StrUuidAst.java new file mode 100644 index 000000000..7012a179c --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/query/impl/sparql/ast/constraint/StrUuidAst.java @@ -0,0 +1,9 @@ +package fr.inria.corese.core.next.query.impl.sparql.ast.constraint; + +import fr.inria.corese.core.next.query.impl.sparql.ast.ConstraintAst; + +/** + * Function {@code STRUUID()} in SPARQL 1.1 + * Returns a string form of a UUID. + */ +public record StrUuidAst() implements ConstraintAst {} \ No newline at end of file diff --git a/src/test/java/fr/inria/corese/core/next/query/impl/parser/SparqlParserStrUuidTest.java b/src/test/java/fr/inria/corese/core/next/query/impl/parser/SparqlParserStrUuidTest.java new file mode 100644 index 000000000..f85421289 --- /dev/null +++ b/src/test/java/fr/inria/corese/core/next/query/impl/parser/SparqlParserStrUuidTest.java @@ -0,0 +1,49 @@ +package fr.inria.corese.core.next.query.impl.parser; + +import fr.inria.corese.core.next.query.impl.sparql.ast.BindAst; +import fr.inria.corese.core.next.query.impl.sparql.ast.FilterAst; +import fr.inria.corese.core.next.query.impl.sparql.ast.QueryAst; +import fr.inria.corese.core.next.query.impl.sparql.ast.constraint.StrUuidAst; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +@DisplayName("SPARQL 1.1 - Parser and AST : STRUUID") +public class SparqlParserStrUuidTest extends AbstractSparqlParserFeatureTest { + + @Test + @DisplayName("BIND(STRUUID() AS ?id)") + void shouldParseStrUuid() { + SparqlParser parser = newParserDefault(); + + QueryAst ast = parser.parse(""" + SELECT * WHERE { + ?s ?p ?o . + BIND(STRUUID() AS ?id) + } + """); + + assertNotNull(ast); + BindAst bind = (BindAst) ast.whereClause().patterns().getLast(); + assertInstanceOf(StrUuidAst.class, bind.expression()); + } + + @Test + @DisplayName("FILTER(STRUUID())") + void shouldParseStrUuidInFilter() { + SparqlParser parser = newParserDefault(); + + QueryAst ast = parser.parse(""" + SELECT * WHERE { + ?s ?p ?o . + FILTER(STRUUID()) + } + """); + + assertNotNull(ast); + FilterAst filter = (FilterAst) ast.whereClause().patterns().getLast(); + assertInstanceOf(StrUuidAst.class, filter.operator()); + } +} \ No newline at end of file From 3074c31ccaf53e2b8b093920f54d59ce6aea1dbe Mon Sep 17 00:00:00 2001 From: "AD\\aabdoun" Date: Fri, 10 Apr 2026 12:20:41 +0200 Subject: [PATCH 2/4] #345 [SPARQL 1.1] - Parser and AST : STRUUID --- .../corese/core/next/query/impl/parser/SparqlAstBuilder.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/fr/inria/corese/core/next/query/impl/parser/SparqlAstBuilder.java b/src/main/java/fr/inria/corese/core/next/query/impl/parser/SparqlAstBuilder.java index 5ad5b36be..a4894804b 100644 --- a/src/main/java/fr/inria/corese/core/next/query/impl/parser/SparqlAstBuilder.java +++ b/src/main/java/fr/inria/corese/core/next/query/impl/parser/SparqlAstBuilder.java @@ -1261,6 +1261,8 @@ public TermAst termFromBuiltInCall(fr.inria.corese.core.next.impl.parser.antlr.S return new RandAst(); } else if (ctx.UUID() != null) { return new UuidAst(); + } else if (ctx.STRUUID() != null) { + return new StrUuidAst(); } else if (ctx.CONCAT() != null) { List args = ctx.expression().stream().map(this::termFromExpression).toList(); return this.createConstraint(ASTConstants.FUNCTION_CALL.CONCAT, args); @@ -1335,8 +1337,6 @@ public TermAst termFromBuiltInCall(fr.inria.corese.core.next.impl.parser.antlr.S } else { throw new QueryEvaluationException("Unexpected function for a BuiltInCall for token " + ctx.getText()); } - } else if (ctx.STRUUID() != null) { - return new StrUuidAst(); } else { throw new QueryEvaluationException("Unable to resolve BuiltInCall for token " + ctx.getText()); } From 01f0f6c9c8cbd2218a824322e86033b797cc7e7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20C=C3=A9r=C3=A8s?= Date: Fri, 10 Apr 2026 16:42:36 +0200 Subject: [PATCH 3/4] Remove public modifier from SparqlParserStrUuidTest class --- .../core/next/query/impl/parser/SparqlParserStrUuidTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/fr/inria/corese/core/next/query/impl/parser/SparqlParserStrUuidTest.java b/src/test/java/fr/inria/corese/core/next/query/impl/parser/SparqlParserStrUuidTest.java index f85421289..76686abbe 100644 --- a/src/test/java/fr/inria/corese/core/next/query/impl/parser/SparqlParserStrUuidTest.java +++ b/src/test/java/fr/inria/corese/core/next/query/impl/parser/SparqlParserStrUuidTest.java @@ -11,7 +11,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; @DisplayName("SPARQL 1.1 - Parser and AST : STRUUID") -public class SparqlParserStrUuidTest extends AbstractSparqlParserFeatureTest { +class SparqlParserStrUuidTest extends AbstractSparqlParserFeatureTest { @Test @DisplayName("BIND(STRUUID() AS ?id)") From a95f4f5a5a920d64ae95e2677a76714774b103f4 Mon Sep 17 00:00:00 2001 From: "AD\\aabdoun" Date: Mon, 4 May 2026 11:30:30 +0200 Subject: [PATCH 4/4] #345 [SPARQL 1.1] - Parser and AST : STRUUID --- .../impl/parser/SparqlParserStrUuidTest.java | 39 ++++++++++++++++--- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/src/test/java/fr/inria/corese/core/next/query/impl/parser/SparqlParserStrUuidTest.java b/src/test/java/fr/inria/corese/core/next/query/impl/parser/SparqlParserStrUuidTest.java index 76686abbe..0c6e5cdb6 100644 --- a/src/test/java/fr/inria/corese/core/next/query/impl/parser/SparqlParserStrUuidTest.java +++ b/src/test/java/fr/inria/corese/core/next/query/impl/parser/SparqlParserStrUuidTest.java @@ -3,10 +3,16 @@ import fr.inria.corese.core.next.query.impl.sparql.ast.BindAst; import fr.inria.corese.core.next.query.impl.sparql.ast.FilterAst; import fr.inria.corese.core.next.query.impl.sparql.ast.QueryAst; +import fr.inria.corese.core.next.query.impl.sparql.ast.SelectQueryAst; +import fr.inria.corese.core.next.query.impl.sparql.ast.VarAst; +import fr.inria.corese.core.next.query.impl.sparql.ast.constraint.EqualsAst; +import fr.inria.corese.core.next.query.impl.sparql.ast.constraint.StrAst; import fr.inria.corese.core.next.query.impl.sparql.ast.constraint.StrUuidAst; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -26,24 +32,47 @@ void shouldParseStrUuid() { """); assertNotNull(ast); - BindAst bind = (BindAst) ast.whereClause().patterns().getLast(); + BindAst bind = assertInstanceOf(BindAst.class, ast.whereClause().patterns().getLast()); assertInstanceOf(StrUuidAst.class, bind.expression()); + assertEquals("id", bind.variable().name()); } @Test - @DisplayName("FILTER(STRUUID())") + @DisplayName("FILTER(STRUUID() = STR(?s))") void shouldParseStrUuidInFilter() { SparqlParser parser = newParserDefault(); QueryAst ast = parser.parse(""" SELECT * WHERE { ?s ?p ?o . - FILTER(STRUUID()) + FILTER(STRUUID() = STR(?s)) } """); assertNotNull(ast); - FilterAst filter = (FilterAst) ast.whereClause().patterns().getLast(); - assertInstanceOf(StrUuidAst.class, filter.operator()); + FilterAst filter = assertInstanceOf(FilterAst.class, ast.whereClause().patterns().getLast()); + EqualsAst equals = assertInstanceOf(EqualsAst.class, filter.operator()); + assertInstanceOf(StrUuidAst.class, equals.getLeftArgument()); + StrAst str = assertInstanceOf(StrAst.class, equals.getRightArgument()); + assertEquals("s", assertInstanceOf(VarAst.class, str.getArgument()).name()); + } + + @Test + @DisplayName("SELECT (STRUUID() AS ?id) ?s WHERE { ?s ?p ?o }") + void shouldParseStrUuidInProjectionBinding() { + SparqlParser parser = newParserDefault(); + + QueryAst ast = parser.parse(""" + SELECT (STRUUID() AS ?id) ?s WHERE { + ?s ?p ?o . + } + """); + + assertNotNull(ast); + SelectQueryAst selectAst = assertInstanceOf(SelectQueryAst.class, ast); + assertFalse(selectAst.projection().selectAll()); + assertEquals(2, selectAst.projection().variables().size()); + assertEquals("id", selectAst.projection().variables().getFirst().name()); + assertEquals("s", selectAst.projection().variables().getLast().name()); } } \ No newline at end of file