From d1c80a8b8a26c602b8b15f19eb43ccf7c8568688 Mon Sep 17 00:00:00 2001
From: "AD\\aabdoun"
Date: Fri, 3 Jul 2026 10:02:08 +0200
Subject: [PATCH 1/3] 389 [BRIDGE] QueryAst - Create Query from
ConstructQueryAst
---
.../sparql/bridge/CoreseAstQueryBuilder.java | 70 +++++++-
.../CoreseAstQueryBuilderConstructTest.java | 149 ++++++++++++++++++
2 files changed, 218 insertions(+), 1 deletion(-)
create mode 100644 src/test/java/fr/inria/corese/core/next/query/impl/sparql/bridge/CoreseAstQueryBuilderConstructTest.java
diff --git a/src/main/java/fr/inria/corese/core/next/query/impl/sparql/bridge/CoreseAstQueryBuilder.java b/src/main/java/fr/inria/corese/core/next/query/impl/sparql/bridge/CoreseAstQueryBuilder.java
index ce4e43c57..6ef0e4560 100644
--- a/src/main/java/fr/inria/corese/core/next/query/impl/sparql/bridge/CoreseAstQueryBuilder.java
+++ b/src/main/java/fr/inria/corese/core/next/query/impl/sparql/bridge/CoreseAstQueryBuilder.java
@@ -423,4 +423,72 @@ private void applyLimitOffset(Query query, SolutionModifierAst solutionModifier)
query.setOffset(Math.toIntExact(solutionModifier.offset()));
}
}
-}
+
+ /**
+ * Builds a KGRAM {@link Query} from a {@link ConstructQueryAst}.
+ *
+ * Reuses the shared query shell (compiled {@code WHERE} body, dataset, LIMIT/OFFSET) and
+ * {@code ORDER BY} like the other forms, then compiles the {@code CONSTRUCT} template into a
+ * separate {@link Exp} carried by the query. Template variables reuse the runtime node bound by
+ * the body when visible; a template-only variable stays fresh (an unbound template variable is
+ * valid SPARQL, its triple is simply skipped at instantiation time). Clauses that require
+ * dedicated aggregate or values handling are rejected explicitly.
+ */
+ public Query toNextQuery(ConstructQueryAst constructQueryAst) {
+ Objects.requireNonNull(constructQueryAst, "constructQueryAst");
+ rejectUnsupportedConstructClauses(constructQueryAst);
+
+ Query query = createQuery(
+ constructQueryAst.whereClause(),
+ constructQueryAst.datasetClause(),
+ constructQueryAst.solutionModifier());
+ applyOrderBy(query, constructQueryAst.solutionModifier());
+ query.setConstruct(true);
+ query.setConstruct(compileConstructTemplate(query, constructQueryAst.constructTemplate()));
+ return query;
+ }
+
+ private static void rejectUnsupportedConstructClauses(ConstructQueryAst constructQueryAst) {
+ if (!constructQueryAst.valuesClause().mappings().isEmpty()) {
+ throw new UnsupportedOperationException(
+ "Inline VALUES is not supported yet for CONSTRUCT (values handling is a follow-up)");
+ }
+ SolutionModifierAst mod = constructQueryAst.solutionModifier();
+ if (mod.hasGroupBy() || mod.hasHaving() || mod.distinct() || mod.reduced()) {
+ throw new UnsupportedOperationException(
+ "Solution modifiers (GROUP BY, HAVING, DISTINCT, REDUCED) are not supported for CONSTRUCT");
+ }
+ // TODO(#389): inline VALUES needs a dedicated runtime mapping.
+ // TODO(#389): GROUP BY / HAVING would require aggregate-aware CONSTRUCT semantics, not just field copying.
+ // TODO(#389): DISTINCT / REDUCED are SELECT-only in the grammar; kept as a defensive guard.
+ }
+
+ /**
+ * Compiles a {@code CONSTRUCT} template into a KGRAM {@link Exp} (a BGP of edges), kept separate
+ * from the {@code WHERE} body and carried by {@link Query#setConstruct(Exp)}.
+ */
+ private Exp compileConstructTemplate(Query query, ConstructTemplateAst template) {
+ Exp bgp = Exp.create(Type.BGP);
+ for (TriplePatternAst triple : template.triplePatternAsts()) {
+ Node subject = constructNode(query, triple.subject());
+ Node predicate = constructNode(query, triple.predicate());
+ Node object = constructNode(query, triple.object());
+ bgp.add(new AstBackedEdge(subject, predicate, object));
+ }
+ return bgp;
+ }
+
+ /**
+ * Resolves a template term to a runtime {@link Node}. A variable reuses the body node when it is
+ * bound by the {@code WHERE}; otherwise it stays a fresh node (an unbound template variable is
+ * valid SPARQL and simply skips its triple at instantiation, so this does not throw). IRIs, blank
+ * nodes and literals become fresh constant nodes.
+ */
+ private Node constructNode(Query query, TermAst term) {
+ if (term instanceof VarAst(String name)) {
+ Node bound = query.getExtNode(name);
+ return bound != null ? bound : toNode(term);
+ }
+ return toNode(term);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/fr/inria/corese/core/next/query/impl/sparql/bridge/CoreseAstQueryBuilderConstructTest.java b/src/test/java/fr/inria/corese/core/next/query/impl/sparql/bridge/CoreseAstQueryBuilderConstructTest.java
new file mode 100644
index 000000000..622460c50
--- /dev/null
+++ b/src/test/java/fr/inria/corese/core/next/query/impl/sparql/bridge/CoreseAstQueryBuilderConstructTest.java
@@ -0,0 +1,149 @@
+package fr.inria.corese.core.next.query.impl.sparql.bridge;
+
+import fr.inria.corese.core.next.query.impl.parser.AbstractSparqlParserFeatureTest;
+import fr.inria.corese.core.next.query.impl.parser.SparqlParser;
+import fr.inria.corese.core.next.query.impl.sparql.ast.*;
+import fr.inria.corese.core.next.query.kgram.api.core.Edge;
+import fr.inria.corese.core.next.query.kgram.api.core.Node;
+import fr.inria.corese.core.next.query.kgram.core.Exp;
+import fr.inria.corese.core.next.query.kgram.core.Query;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class CoreseAstQueryBuilderConstructTest extends AbstractSparqlParserFeatureTest {
+
+ private final CoreseAstQueryBuilder builder = new CoreseAstQueryBuilder();
+
+ private static GroupGraphPatternAst whereSPO() {
+ return new GroupGraphPatternAst(List.of(new BgpAst(List.of(new TriplePatternAst(new VarAst("x"), new VarAst("p"), new VarAst("o"))))));
+ }
+
+ private static ConstructTemplateAst template(TriplePatternAst... triples) {
+ return new ConstructTemplateAst(List.of(triples));
+ }
+
+ @Test
+ @DisplayName("CONSTRUCT { ?x ?p ?o } WHERE { ?x ?p ?o }: flagged CONSTRUCT, template is a BGP with one edge")
+ void templateCompiledAsBgp() {
+ ConstructQueryAst construct = new ConstructQueryAst(template(new TriplePatternAst(new VarAst("x"), new VarAst("p"), new VarAst("o"))), whereSPO());
+
+ Query query = builder.toNextQuery(construct);
+
+ assertTrue(query.isConstruct(), "query flagged as CONSTRUCT");
+ assertFalse(query.isSelect(), "CONSTRUCT should not also report itself as SELECT");
+ assertTrue(query.getBody().isAnd(), "WHERE compiled into the body");
+ Exp constructExp = query.getConstruct();
+ assertNotNull(constructExp, "template stored via setConstruct(Exp)");
+ assertTrue(constructExp.isBGP(), "template is a BGP");
+ assertEquals(1, constructExp.size(), "one template triple -> one edge");
+ }
+
+ @Test
+ @DisplayName("Parser -> ConstructQueryAst -> Query keeps the CONSTRUCT form")
+ void buildsQueryFromParsedConstruct() {
+ SparqlParser parser = newParserDefault();
+ ConstructQueryAst construct = assertInstanceOf(ConstructQueryAst.class, parser.parse("CONSTRUCT { ?x ?p ?o } WHERE { ?x ?p ?o }"));
+
+ Query query = builder.toNextQuery(construct);
+
+ assertTrue(query.isConstruct());
+ assertFalse(query.isSelect());
+ assertTrue(query.getBody().get(0).isBGP());
+ assertNotNull(query.getConstruct());
+ assertEquals(1, query.getConstruct().size());
+ }
+
+ @Test
+ @DisplayName("Two template triples produce two edges")
+ void templateWithTwoTriples() {
+ ConstructQueryAst construct = new ConstructQueryAst(template(new TriplePatternAst(new VarAst("x"), new IriAst("http://example.org/p"), new VarAst("o")), new TriplePatternAst(new VarAst("x"), new IriAst("http://example.org/q"), new VarAst("o"))), whereSPO());
+
+ Query query = builder.toNextQuery(construct);
+
+ assertEquals(2, query.getConstruct().size());
+ }
+
+ @Test
+ @DisplayName("Template variable bound by WHERE reuses the runtime body node")
+ void templateVariableResolvesToBodyNode() {
+ ConstructQueryAst construct = new ConstructQueryAst(template(new TriplePatternAst(new VarAst("x"), new VarAst("p"), new VarAst("o"))), whereSPO());
+
+ Query query = builder.toNextQuery(construct);
+
+ Edge edge = query.getConstruct().first().getEdge();
+ assertSame(query.getExtNode("x"), edge.getNode(0), "template ?x is the body node");
+ assertSame(query.getExtNode("o"), edge.getNode(1), "template ?o is the body node");
+ }
+
+ @Test
+ @DisplayName("Template-only variable (not in WHERE) stays fresh and does not throw")
+ void templateOnlyVariableStaysFresh() {
+ ConstructQueryAst construct = new ConstructQueryAst(template(new TriplePatternAst(new VarAst("x"), new VarAst("p"), new VarAst("newVar"))), whereSPO());
+
+ Query query = assertDoesNotThrow(() -> builder.toNextQuery(construct));
+
+ assertNull(query.getExtNode("newVar"), "template-only variable is not injected into the body");
+ Node object = query.getConstruct().first().getEdge().getNode(1);
+ assertTrue(object.isVariable(), "template-only variable is still a variable node");
+ }
+
+ @Test
+ @DisplayName("Template IRIs become fixed (non-variable) nodes")
+ void templateWithFixedResources() {
+ ConstructQueryAst construct = new ConstructQueryAst(template(new TriplePatternAst(new IriAst("http://example.org/s"), new IriAst("http://example.org/p"), new VarAst("o"))), whereSPO());
+
+ Query query = builder.toNextQuery(construct);
+
+ Edge edge = query.getConstruct().first().getEdge();
+ assertFalse(edge.getNode(0).isVariable(), "fixed subject IRI");
+ assertFalse(edge.getProperty().isVariable(), "fixed predicate IRI");
+ assertTrue(edge.getNode(1).isVariable(), "object still bound to body ?o");
+ }
+
+ @Test
+ @DisplayName("FROM / FROM NAMED, LIMIT and OFFSET are applied")
+ void appliesDatasetLimitOffset() {
+ DatasetClauseAst dataset = new DatasetClauseAst(Set.of(new IriAst("http://example.org/g")), Set.of(new IriAst("http://example.org/n")));
+ SolutionModifierAst mod = SolutionModifierAst.withoutGroupBy(false, false, List.of(), 5L, 2L);
+ ConstructQueryAst construct = new ConstructQueryAst(template(new TriplePatternAst(new VarAst("x"), new VarAst("p"), new VarAst("o"))), dataset, whereSPO(), mod);
+
+ Query query = builder.toNextQuery(construct);
+
+ assertEquals(List.of("http://example.org/g"), query.getFrom().stream().map(Node::getLabel).toList(), "FROM applied");
+ assertEquals(List.of("http://example.org/n"), query.getNamed().stream().map(Node::getLabel).toList(), "FROM NAMED applied");
+ assertEquals(5, query.getLimit(), "LIMIT applied");
+ assertEquals(2, query.getOffset(), "OFFSET applied");
+ }
+
+ @Test
+ @DisplayName("ORDER BY ?x is applied")
+ void appliesOrderBy() {
+ SolutionModifierAst mod = SolutionModifierAst.withoutGroupBy(false, false, List.of(new OrderConditionAst(ASTConstants.OrderDirection.ASC, new VarAst("x"))), null, null);
+ ConstructQueryAst construct = new ConstructQueryAst(template(new TriplePatternAst(new VarAst("x"), new VarAst("p"), new VarAst("o"))), DatasetClauseAst.none(), whereSPO(), mod);
+
+ Query query = builder.toNextQuery(construct);
+
+ assertFalse(query.getOrderBy().isEmpty(), "ORDER BY applied");
+ }
+
+ @Test
+ @DisplayName("Inline VALUES is not supported yet -> UnsupportedOperationException")
+ void rejectsValuesClause() {
+ ValuesAst values = new ValuesAst(List.of(new ValueMappingAst(Map.of(new VarAst("x"), new IriAst("http://example.org/v")))));
+ ConstructQueryAst construct = new ConstructQueryAst(template(new TriplePatternAst(new VarAst("x"), new VarAst("p"), new VarAst("o"))), DatasetClauseAst.none(), whereSPO(), null, null, values);
+
+ assertThrows(UnsupportedOperationException.class, () -> builder.toNextQuery(construct));
+ }
+
+ @Test
+ @DisplayName("toNextQuery((ConstructQueryAst) null) throws NullPointerException")
+ void rejectsNull() {
+ assertThrows(NullPointerException.class, () -> builder.toNextQuery((ConstructQueryAst) null));
+ }
+}
\ No newline at end of file
From abfc41f4deff4abdaf0bf03d9a17dbb811809731 Mon Sep 17 00:00:00 2001
From: "AD\\aabdoun"
Date: Mon, 6 Jul 2026 10:41:08 +0200
Subject: [PATCH 2/3] 389 [BRIDGE] QueryAst - Create Query from
ConstructQueryAst
---
.../sparql/bridge/CoreseAstQueryBuilder.java | 22 +++++--------------
.../CoreseAstQueryBuilderConstructTest.java | 2 +-
.../CoreseAstQueryBuilderDescribeTest.java | 2 +-
3 files changed, 7 insertions(+), 19 deletions(-)
diff --git a/src/main/java/fr/inria/corese/core/next/query/impl/sparql/bridge/CoreseAstQueryBuilder.java b/src/main/java/fr/inria/corese/core/next/query/impl/sparql/bridge/CoreseAstQueryBuilder.java
index 6ef0e4560..660d145cb 100644
--- a/src/main/java/fr/inria/corese/core/next/query/impl/sparql/bridge/CoreseAstQueryBuilder.java
+++ b/src/main/java/fr/inria/corese/core/next/query/impl/sparql/bridge/CoreseAstQueryBuilder.java
@@ -1,19 +1,6 @@
package fr.inria.corese.core.next.query.impl.sparql.bridge;
-import fr.inria.corese.core.next.query.impl.sparql.ast.AskQueryAst;
-import fr.inria.corese.core.next.query.impl.sparql.ast.ASTConstants;
-import fr.inria.corese.core.next.query.impl.sparql.ast.ConstraintAst;
-import fr.inria.corese.core.next.query.impl.sparql.ast.DatasetClauseAst;
-import fr.inria.corese.core.next.query.impl.sparql.ast.DescribeQueryAst;
-import fr.inria.corese.core.next.query.impl.sparql.ast.FilterAst;
-import fr.inria.corese.core.next.query.impl.sparql.ast.GroupGraphPatternAst;
-import fr.inria.corese.core.next.query.impl.sparql.ast.IriAst;
-import fr.inria.corese.core.next.query.impl.sparql.ast.OrderConditionAst;
-import fr.inria.corese.core.next.query.impl.sparql.ast.ProjectionAst;
-import fr.inria.corese.core.next.query.impl.sparql.ast.SelectQueryAst;
-import fr.inria.corese.core.next.query.impl.sparql.ast.SolutionModifierAst;
-import fr.inria.corese.core.next.query.impl.sparql.ast.TermAst;
-import fr.inria.corese.core.next.query.impl.sparql.ast.VarAst;
+import fr.inria.corese.core.next.query.impl.sparql.ast.*;
import fr.inria.corese.core.next.query.kgram.api.core.ExpType.Type;
import fr.inria.corese.core.next.query.kgram.api.core.Filter;
import fr.inria.corese.core.next.query.kgram.api.core.Node;
@@ -33,8 +20,7 @@
* Builds KGRAM {@code Exp} / {@code Query} structures from Corese-next query AST nodes.
*
* This bridge sits between the parsed SPARQL AST and the KGRAM runtime query model:
- * it does not execute queries, it translates syntax-level query forms ({@code ASK}, {@code SELECT},
- * {@code DESCRIBE}) into runtime-ready {@link Query}/{@link Exp} structures.
+ * it does not execute queries, it translates syntax-level query forms ({@code ASK}, {@code SELECT}, {@code DESCRIBE}, {@code CONSTRUCT}) into runtime-ready {@link Query}/{@link Exp} structures.
*/
public final class CoreseAstQueryBuilder {
@@ -443,8 +429,10 @@ public Query toNextQuery(ConstructQueryAst constructQueryAst) {
constructQueryAst.datasetClause(),
constructQueryAst.solutionModifier());
applyOrderBy(query, constructQueryAst.solutionModifier());
+ Exp template = compileConstructTemplate(query, constructQueryAst.constructTemplate());
query.setConstruct(true);
- query.setConstruct(compileConstructTemplate(query, constructQueryAst.constructTemplate()));
+ query.setConstruct(template);
+ query.setConstructNodes(template.getNodes());
return query;
}
diff --git a/src/test/java/fr/inria/corese/core/next/query/impl/sparql/bridge/CoreseAstQueryBuilderConstructTest.java b/src/test/java/fr/inria/corese/core/next/query/impl/sparql/bridge/CoreseAstQueryBuilderConstructTest.java
index 622460c50..0a4518ffe 100644
--- a/src/test/java/fr/inria/corese/core/next/query/impl/sparql/bridge/CoreseAstQueryBuilderConstructTest.java
+++ b/src/test/java/fr/inria/corese/core/next/query/impl/sparql/bridge/CoreseAstQueryBuilderConstructTest.java
@@ -34,7 +34,7 @@ void templateCompiledAsBgp() {
ConstructQueryAst construct = new ConstructQueryAst(template(new TriplePatternAst(new VarAst("x"), new VarAst("p"), new VarAst("o"))), whereSPO());
Query query = builder.toNextQuery(construct);
-
+ assertFalse(query.getConstructNodes().isEmpty(), "construct nodes populated");
assertTrue(query.isConstruct(), "query flagged as CONSTRUCT");
assertFalse(query.isSelect(), "CONSTRUCT should not also report itself as SELECT");
assertTrue(query.getBody().isAnd(), "WHERE compiled into the body");
diff --git a/src/test/java/fr/inria/corese/core/next/query/impl/sparql/bridge/CoreseAstQueryBuilderDescribeTest.java b/src/test/java/fr/inria/corese/core/next/query/impl/sparql/bridge/CoreseAstQueryBuilderDescribeTest.java
index 1ec39ad97..d3e0d9e8c 100644
--- a/src/test/java/fr/inria/corese/core/next/query/impl/sparql/bridge/CoreseAstQueryBuilderDescribeTest.java
+++ b/src/test/java/fr/inria/corese/core/next/query/impl/sparql/bridge/CoreseAstQueryBuilderDescribeTest.java
@@ -175,7 +175,7 @@ private static void assertLoweredDescribeConstruct(Query query, int describedNod
assertNotNull(query.getConstruct(), "construct template created");
assertEquals(2 * describedNodeCount, query.getConstruct().size(),
"construct template has outgoing and incoming triple patterns per described node");
- assertNotNull(query.getConstructNodes(), "construct nodes collected");
+ assertFalse(query.getConstructNodes().isEmpty(), "construct nodes collected"); // était assertNotNull
}
/**
From ecf60383b9ea854ef2116ad5643a3e2061184522 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20C=C3=A9r=C3=A8s?=
Date: Mon, 6 Jul 2026 17:26:15 +0200
Subject: [PATCH 3/3] Clean up CONSTRUCT bridge review nits
---
.../sparql/bridge/CoreseAstQueryBuilder.java | 58 ++++++++++---------
.../CoreseAstQueryBuilderDescribeTest.java | 2 +-
2 files changed, 31 insertions(+), 29 deletions(-)
diff --git a/src/main/java/fr/inria/corese/core/next/query/impl/sparql/bridge/CoreseAstQueryBuilder.java b/src/main/java/fr/inria/corese/core/next/query/impl/sparql/bridge/CoreseAstQueryBuilder.java
index 660d145cb..8e0ac6508 100644
--- a/src/main/java/fr/inria/corese/core/next/query/impl/sparql/bridge/CoreseAstQueryBuilder.java
+++ b/src/main/java/fr/inria/corese/core/next/query/impl/sparql/bridge/CoreseAstQueryBuilder.java
@@ -20,7 +20,9 @@
* Builds KGRAM {@code Exp} / {@code Query} structures from Corese-next query AST nodes.
*
* This bridge sits between the parsed SPARQL AST and the KGRAM runtime query model:
- * it does not execute queries, it translates syntax-level query forms ({@code ASK}, {@code SELECT}, {@code DESCRIBE}, {@code CONSTRUCT}) into runtime-ready {@link Query}/{@link Exp} structures.
+ * it does not execute queries, it translates syntax-level query forms ({@code ASK},
+ * {@code SELECT}, {@code DESCRIBE}, {@code CONSTRUCT}) into runtime-ready
+ * {@link Query}/{@link Exp} structures.
*/
public final class CoreseAstQueryBuilder {
@@ -111,6 +113,32 @@ public Query toNextQuery(DescribeQueryAst describeQueryAst) {
return query;
}
+ /**
+ * Builds a KGRAM {@link Query} from a {@link ConstructQueryAst}.
+ *
+ * Reuses the shared query shell (compiled {@code WHERE} body, dataset, LIMIT/OFFSET) and
+ * {@code ORDER BY} like the other forms, then compiles the {@code CONSTRUCT} template into a
+ * separate {@link Exp} carried by the query. Template variables reuse the runtime node bound by
+ * the body when visible; a template-only variable stays fresh (an unbound template variable is
+ * valid SPARQL, its triple is simply skipped at instantiation time). Clauses that require
+ * dedicated aggregate or values handling are rejected explicitly.
+ */
+ public Query toNextQuery(ConstructQueryAst constructQueryAst) {
+ Objects.requireNonNull(constructQueryAst, "constructQueryAst");
+ rejectUnsupportedConstructClauses(constructQueryAst);
+
+ Query query = createQuery(
+ constructQueryAst.whereClause(),
+ constructQueryAst.datasetClause(),
+ constructQueryAst.solutionModifier());
+ applyOrderBy(query, constructQueryAst.solutionModifier());
+ Exp template = compileConstructTemplate(query, constructQueryAst.constructTemplate());
+ query.setConstruct(true);
+ query.setConstruct(template);
+ query.setConstructNodes(template.getNodes());
+ return query;
+ }
+
/**
* Converts a SPARQL {@code FILTER} clause by converting {@link FilterAst#operator()} the same way as
* {@link #toNextFilter(TermAst)}.
@@ -410,32 +438,6 @@ private void applyLimitOffset(Query query, SolutionModifierAst solutionModifier)
}
}
- /**
- * Builds a KGRAM {@link Query} from a {@link ConstructQueryAst}.
- *
- * Reuses the shared query shell (compiled {@code WHERE} body, dataset, LIMIT/OFFSET) and
- * {@code ORDER BY} like the other forms, then compiles the {@code CONSTRUCT} template into a
- * separate {@link Exp} carried by the query. Template variables reuse the runtime node bound by
- * the body when visible; a template-only variable stays fresh (an unbound template variable is
- * valid SPARQL, its triple is simply skipped at instantiation time). Clauses that require
- * dedicated aggregate or values handling are rejected explicitly.
- */
- public Query toNextQuery(ConstructQueryAst constructQueryAst) {
- Objects.requireNonNull(constructQueryAst, "constructQueryAst");
- rejectUnsupportedConstructClauses(constructQueryAst);
-
- Query query = createQuery(
- constructQueryAst.whereClause(),
- constructQueryAst.datasetClause(),
- constructQueryAst.solutionModifier());
- applyOrderBy(query, constructQueryAst.solutionModifier());
- Exp template = compileConstructTemplate(query, constructQueryAst.constructTemplate());
- query.setConstruct(true);
- query.setConstruct(template);
- query.setConstructNodes(template.getNodes());
- return query;
- }
-
private static void rejectUnsupportedConstructClauses(ConstructQueryAst constructQueryAst) {
if (!constructQueryAst.valuesClause().mappings().isEmpty()) {
throw new UnsupportedOperationException(
@@ -479,4 +481,4 @@ private Node constructNode(Query query, TermAst term) {
}
return toNode(term);
}
-}
\ No newline at end of file
+}
diff --git a/src/test/java/fr/inria/corese/core/next/query/impl/sparql/bridge/CoreseAstQueryBuilderDescribeTest.java b/src/test/java/fr/inria/corese/core/next/query/impl/sparql/bridge/CoreseAstQueryBuilderDescribeTest.java
index d3e0d9e8c..68135af42 100644
--- a/src/test/java/fr/inria/corese/core/next/query/impl/sparql/bridge/CoreseAstQueryBuilderDescribeTest.java
+++ b/src/test/java/fr/inria/corese/core/next/query/impl/sparql/bridge/CoreseAstQueryBuilderDescribeTest.java
@@ -175,7 +175,7 @@ private static void assertLoweredDescribeConstruct(Query query, int describedNod
assertNotNull(query.getConstruct(), "construct template created");
assertEquals(2 * describedNodeCount, query.getConstruct().size(),
"construct template has outgoing and incoming triple patterns per described node");
- assertFalse(query.getConstructNodes().isEmpty(), "construct nodes collected"); // était assertNotNull
+ assertFalse(query.getConstructNodes().isEmpty(), "construct nodes collected");
}
/**