Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -845,7 +845,9 @@ int eval(Producer p, Node graphNode, Stack stack, Mappings map, int n) throws Sp
send(Event.START, exp, graphNode, stack);
}

if (exp.isFail()) {
// A false filter was detected at compile time, or this expression was
// identified as always failing: no use to evaluate it.
if (!exp.isFail()) {
if (exp.isBGPAble()) {
// @deprecated
// evaluate and record result for next time
Expand Down Expand Up @@ -2092,4 +2094,4 @@ public void setListener(ResultListener listener) {
this.listener = listener;
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package fr.inria.corese.core.next.query.kgram.tool;

import fr.inria.corese.core.next.data.api.Statement;
import fr.inria.corese.core.next.query.kgram.api.core.Edge;
import fr.inria.corese.core.next.query.kgram.api.core.Node;

import java.util.Objects;

/**
* KGRAM edge view over a statement returned by the Corese-next storage layer.
*
* <p>KGRAM models a triple edge with the subject at {@code getNode(0)}, the object at
* {@code getNode(1)}, and the predicate as the edge node. Keeping that contract here
* lets the storage-backed producer feed regular SPO patterns into the next evaluator.</p>
*/
public final class StorageManagerEdge implements Edge {

private final Statement statement;
private final Node subject;
private final Node predicate;
private final Node object;
private final Node graph;

public StorageManagerEdge(Statement statement) {
this.statement = Objects.requireNonNull(statement, "statement");
this.subject = StorageManagerKgramValues.node(statement.getSubject());
this.predicate = StorageManagerKgramValues.node(statement.getPredicate());
this.object = StorageManagerKgramValues.node(statement.getObject());
this.graph = statement.getContext() == null ? null : StorageManagerKgramValues.node(statement.getContext());
}

public Statement getSourceStatement() {
return statement;
}

@Override
public Node getNode(int i) {
return switch (i) {
case 0 -> subject;
case 1 -> object;
default -> throw new IndexOutOfBoundsException(
"Statement edge has nodes 0 (subject) and 1 (object), got: " + i);
};
}

@Override
public Node getProperty() {
return predicate;
}

@Override
public String getEdgeLabel() {
return predicate.getLabel();
}

@Override
public Node getGraph() {
return graph;
}

@Override
public boolean contains(Node node) {
if (node == null) {
return false;
}
return sameNode(subject, node) || sameNode(predicate, node) || sameNode(object, node);
}

@Override
public Edge getEdge() {
return this;
}

private static boolean sameNode(Node left, Node right) {
return left == right || left.same(right);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package fr.inria.corese.core.next.query.kgram.tool;

import fr.inria.corese.core.next.data.api.BNode;
import fr.inria.corese.core.next.data.api.IRI;
import fr.inria.corese.core.next.data.api.Literal;
import fr.inria.corese.core.next.data.api.Value;
import fr.inria.corese.core.next.data.api.ValueFactory;
import fr.inria.corese.core.next.query.kgram.api.core.Node;
import fr.inria.corese.core.sparql.api.IDatatype;
import fr.inria.corese.core.sparql.datatype.DatatypeMap;
import fr.inria.corese.core.sparql.triple.parser.Constant;

/**
* Conversion helpers for the StorageManager/KGRAM boundary.
*
* <p>The storage layer exposes RDF values through the Corese-next data model, while KGRAM
* nodes still carry Corese {@link IDatatype} values. This helper keeps that transitional
* conversion in one place and avoids routing storage results through the legacy KGRAM node API.
*/
final class StorageManagerKgramValues {

private StorageManagerKgramValues() {
}

/**
* Converts a storage RDF value to a KGRAM node.
*
* @param value storage value to wrap
* @return KGRAM node carrying the equivalent Corese datatype
*/
static Node node(Value value) {
return node(datatypeValue(value));
}

/**
* Wraps a Corese datatype as a KGRAM node.
*
* @param datatype Corese datatype to wrap
* @return KGRAM node backed by a parser constant
*/
static Node node(IDatatype datatype) {
return new NodeImpl(Constant.create(datatype));
}

/**
* Converts a KGRAM node to a storage RDF value.
*
* @param node KGRAM node to convert
* @param valueFactory factory used to create storage values
* @return equivalent storage value
*/
static Value rdfValue(Node node, ValueFactory valueFactory) {
return rdfValue(node.getDatatypeValue(), valueFactory);
}

/**
* Converts a Corese datatype to the storage RDF value model.
*
* <p>Language-tagged literals are converted through the language branch, and therefore
* become RDF {@code langString} literals in the storage model.
*
* @param datatype Corese datatype to convert
* @param valueFactory factory used to create storage values
* @return equivalent storage value
* @throws IllegalArgumentException when the datatype cannot be represented as RDF
*/
static Value rdfValue(IDatatype datatype, ValueFactory valueFactory) {
if (datatype.isURI()) {
return valueFactory.createIRI(datatype.getLabel());
}
if (datatype.isBlank()) {
return valueFactory.createBNode(datatype.getLabel());
}
if (datatype.isLiteral()) {
String language = datatype.getLang();
if (language != null && !language.isEmpty()) {
return valueFactory.createLiteral(datatype.getLabel(), language);
}
String datatypeUri = datatype.getDatatypeURI();
if (datatypeUri != null && !datatypeUri.isEmpty()) {
return valueFactory.createLiteral(datatype.getLabel(), valueFactory.createIRI(datatypeUri));
}
return valueFactory.createLiteral(datatype.getLabel());
}
throw new IllegalArgumentException("Unsupported KGRAM datatype value: " + datatype);
}

/**
* Converts a storage RDF value to the Corese datatype model used by KGRAM nodes.
*
* @param value storage value to convert
* @return equivalent Corese datatype
* @throws IllegalArgumentException when the value is not an RDF IRI, blank node or literal
*/
static IDatatype datatypeValue(Value value) {
if (value instanceof IRI iri) {
return DatatypeMap.newResource(iri.stringValue());
}
if (value instanceof BNode bNode) {
return DatatypeMap.createBlank(bNode.getID());
}
if (value instanceof Literal literal) {
return literal.getLanguage()
.<IDatatype>map(language -> DatatypeMap.createLiteral(literal.getLabel(), null, language))
.orElseGet(() -> DatatypeMap.createLiteral(
literal.getLabel(),
literal.getDatatype().stringValue(),
null));
}
throw new IllegalArgumentException("Unsupported RDF value: " + value);
}
}
Loading
Loading