Skip to content

Commit

Permalink
Introduce <aas-api:resolved> to control resolution of references.
Browse files Browse the repository at this point in the history
  • Loading branch information
kenwenzel committed Jan 17, 2025
1 parent ef90d3b commit 014407c
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,49 +22,33 @@ public interface AAS {
IRI API_SHELLS = SimpleValueFactory.getInstance().createIRI("aas-api:shells");
IRI API_SUBMODELS = SimpleValueFactory.getInstance().createIRI("aas-api:submodels");

IRI API_RESOLVED = SimpleValueFactory.getInstance().createIRI("aas-api:resolved");

String ASSETADMINISTRATIONSHELL_PREFIX = "urn:aas:AssetAdministrationShell:";
String SUBMODEL_PREFIX = "urn:aas:Submodel:";

static Value toRdfValue(Object value, ValueFactory vf) {
static Value resolveReference(Object value, ValueFactory vf) {
if (value instanceof Record) {
Record r = (Record) value;
Record id = r.first(URIs.createURI(AAS_NAMESPACE + "id"));
String type = null;
String idStr = null;
if (id != Record.NULL) {
idStr = id.getValue() != null ? id.getValue().toString() : null;
URI keysProperty = URIs.createURI(AAS_NAMESPACE + "keys");
Record keys = r.first(keysProperty);
Record firstKey = null;
// there is exactly one aas:keys element
if (keys.getValue() instanceof Record && keys.next().first(keysProperty).getValue() == null) {
firstKey = (Record) keys.getValue();
} else if (keys.getValue() instanceof List<?> && ((List<?>) keys.getValue()).size() == 1) {
firstKey = (Record) ((List<?>) keys.getValue()).get(0);
}
if (idStr == null) {
URI keysProperty = URIs.createURI(AAS_NAMESPACE + "keys");
Record keys = r.first(keysProperty);
Record firstKey = null;
// there is exactly one aas:keys element
if (keys.getValue() instanceof Record && keys.next().first(keysProperty).getValue() == null) {
firstKey = (Record) keys.getValue();
} else if (keys.getValue() instanceof List<?> && ((List<?>) keys.getValue()).size() == 1) {
firstKey = (Record) ((List<?>) keys.getValue()).get(0);
}
if (firstKey != null) {
Object typeValue = firstKey.first(URIs.createURI(AAS_NAMESPACE + "type")).getValue();
if (typeValue != null) {
type = typeValue.toString();
}
Object keyValue = firstKey.first(URIs.createURI(AAS_NAMESPACE + "value")).getValue();
if (keyValue != null) {
idStr = keyValue.toString();
}
if (firstKey != null) {
Object typeValue = firstKey.first(URIs.createURI(AAS_NAMESPACE + "type")).getValue();
if (typeValue != null) {
type = typeValue.toString();
}

if (idStr != null) {
switch (type) {
case "Submodel":
return vf.createIRI("urn:aas:" + type + ":" +
Base64.getEncoder().encodeToString(idStr.getBytes(StandardCharsets.UTF_8)));
default:
// do not convert the reference to an IRI
// drop id string
idStr = null;
}
Object keyValue = firstKey.first(URIs.createURI(AAS_NAMESPACE + "value")).getValue();
if (keyValue != null) {
idStr = keyValue.toString();
}
}

Expand All @@ -73,26 +57,19 @@ static Value toRdfValue(Object value, ValueFactory vf) {
Object modelTypeValue = r.first(URIs.createURI(AAS_NAMESPACE + "modelType")).getValue();
if (modelTypeValue != null) {
type = modelTypeValue.toString();
} else {
Object kindValue = r.first(URIs.createURI(AAS_NAMESPACE + "kind")).getValue();
if ("Instance".equals(kindValue)) {
type = "Submodel";
} else if ("Template".equals(kindValue)) {
type = "Template";
}
}
}

switch (type) {
case "Submodel":
String iriStr = "urn:aas:" + type + ":" +
Base64.getEncoder().encodeToString(idStr.getBytes(StandardCharsets.UTF_8));
return IRIWithValue.create(iriStr, value);
return vf.createIRI(iriStr);
default:
// do not convert the reference to an IRI
}
}
}
return Conversions.toRdfValue(value, vf, true);
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import io.github.linkedfactory.core.kvin.Record;
import io.github.linkedfactory.core.rdf4j.aas.AAS;
import io.github.linkedfactory.core.rdf4j.aas.AasClient;
import io.github.linkedfactory.core.rdf4j.common.Conversions;
import io.github.linkedfactory.core.rdf4j.common.HasValue;
import io.github.linkedfactory.core.rdf4j.common.query.CompositeBindingSet;
import io.github.linkedfactory.core.rdf4j.common.query.InnerJoinIteratorEvaluationStep;
Expand All @@ -25,9 +26,9 @@
import org.eclipse.rdf4j.query.algebra.evaluation.QueryBindingSet;
import org.eclipse.rdf4j.query.algebra.evaluation.QueryEvaluationStep;
import org.eclipse.rdf4j.query.algebra.evaluation.federation.FederatedServiceResolver;
import org.eclipse.rdf4j.query.algebra.evaluation.impl.DefaultEvaluationStrategy;
import org.eclipse.rdf4j.query.algebra.evaluation.impl.QueryEvaluationContext;
import org.eclipse.rdf4j.query.algebra.evaluation.impl.QueryEvaluationContext.Minimal;
import org.eclipse.rdf4j.query.algebra.evaluation.impl.StrictEvaluationStrategy;
import org.eclipse.rdf4j.query.algebra.evaluation.iterator.HashJoinIteration;

import java.io.IOException;
Expand All @@ -39,7 +40,7 @@
import static io.github.linkedfactory.core.rdf4j.common.query.Helpers.compareAndBind;
import static io.github.linkedfactory.core.rdf4j.common.query.Helpers.findFirstFetch;

public class AasEvaluationStrategy extends StrictEvaluationStrategy {
public class AasEvaluationStrategy extends DefaultEvaluationStrategy {

final AasClient client;
final ParameterScanner scanner;
Expand All @@ -61,7 +62,7 @@ public CloseableIteration<BindingSet, QueryEvaluationException> evaluate(Stateme
throws QueryEvaluationException {
// System.out.println("Stmt: " + stmt);
final Var subjectVar = stmt.getSubjectVar();
final Value subjectValue = StrictEvaluationStrategy.getVarValue(subjectVar, bs);
final Value subjectValue = getVarValue(subjectVar, bs);

if (subjectValue == null) {
// this happens for patterns like (:subject :property [ <kvin:value> ?someValue ])
Expand All @@ -74,7 +75,22 @@ public CloseableIteration<BindingSet, QueryEvaluationException> evaluate(Stateme

Object data = subjectValue instanceof HasValue ? ((HasValue) subjectValue).getValue() : valueCache.get(subjectValue);
if (data instanceof Record) {
Value predValue = StrictEvaluationStrategy.getVarValue(stmt.getPredicateVar(), bs);
Var objectVar = stmt.getObjectVar();
Value objectValue = getVarValue(objectVar, bs);

final Value predValue = getVarValue(stmt.getPredicateVar(), bs);
if (AAS.API_RESOLVED.equals(predValue)) {
Value resolved = AAS.resolveReference(data, vf);
if (resolved == null || objectValue != null && !objectValue.equals(resolved)) {
return new EmptyIteration<>();
}
CompositeBindingSet newBs = new CompositeBindingSet(bs);
if (objectValue == null) {
newBs.addBinding(objectVar.getName(), resolved);
}
return new SingletonIteration<>(newBs);
}

final Iterator<Record> it;
if (predValue != null) {
String predValueStr = predValue.stringValue();
Expand All @@ -84,8 +100,6 @@ public CloseableIteration<BindingSet, QueryEvaluationException> evaluate(Stateme
it = ((Record) data).iterator();
}

Var variable = stmt.getObjectVar();
Value objectValue = StrictEvaluationStrategy.getVarValue(variable, bs);
return new AbstractCloseableIteration<>() {
CompositeBindingSet next;

Expand All @@ -104,7 +118,7 @@ public boolean hasNext() throws QueryEvaluationException {
newBs.addBinding(stmt.getPredicateVar().getName(), toRdfValue(r.getProperty()));
}
if (objectValue == null) {
newBs.addBinding(variable.getName(), newObjectValue);
newBs.addBinding(objectVar.getName(), newObjectValue);
}
next = newBs;
}
Expand Down Expand Up @@ -132,10 +146,10 @@ public void remove() throws QueryEvaluationException {
} else if (data instanceof Object[] || data instanceof List<?>) {
List<?> list = data instanceof Object[] ? Arrays.asList((Object[]) data) : (List<?>) data;
Var predVar = stmt.getPredicateVar();
Value predValue = StrictEvaluationStrategy.getVarValue(predVar, bs);
Value predValue = getVarValue(predVar, bs);
if (predValue == null) {
Iterator<?> it = list.iterator();
Value objValue = StrictEvaluationStrategy.getVarValue(stmt.getObjectVar(), bs);
Value objValue = getVarValue(stmt.getObjectVar(), bs);
return new AbstractCloseableIteration<>() {
BindingSet next = null;
int i = 0;
Expand Down Expand Up @@ -176,7 +190,7 @@ public void remove() throws QueryEvaluationException {
if (localName.matches("_[0-9]+")) {
int index = Integer.parseInt(localName.substring(1));
if (index > 0 && index <= list.size()) {
return compareAndBind(bs, stmt.getObjectVar(), AAS.toRdfValue(list.get(index - 1), vf));
return compareAndBind(bs, stmt.getObjectVar(), toRdfValue(list.get(index - 1)));
}
}
}
Expand Down Expand Up @@ -226,8 +240,8 @@ public CloseableIteration<BindingSet, QueryEvaluationException> evaluateFetch(Bi
final Var predVar = stmt.getPredicateVar();
final Var objectVar = stmt.getObjectVar();

final Value subjValue = StrictEvaluationStrategy.getVarValue(stmt.getSubjectVar(), bs);
final Value predValue = StrictEvaluationStrategy.getVarValue(predVar, bs);
final Value subjValue = getVarValue(stmt.getSubjectVar(), bs);
final Value predValue = getVarValue(predVar, bs);

if (subjValue != null) {
final CloseableIteration<BindingSet, QueryEvaluationException> iteration = new AbstractCloseableIteration<>() {
Expand Down Expand Up @@ -373,7 +387,7 @@ public ValueFactory getValueFactory() {
}

public Value toRdfValue(Object value) {
Value rdfValue = AAS.toRdfValue(value, getValueFactory());
Value rdfValue = Conversions.toRdfValue(value, getValueFactory(), true);
if (rdfValue instanceof HasValue) {
valueCache.putIfAbsent(rdfValue, ((HasValue) rdfValue).getValue());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,12 @@ public FederatedService createService(String url) {
"service <aas-api:http://aasx-server:5001> {" +
"<aas-api:endpoint> <aas-api:shells> ?shell ." +
" ?shell aas:idShort ?shellId ." +
" ?shell aas:submodels ?sm." +
" ?sm aas:semanticId/aas:keys/aas:value \"https://admin-shell.io/ZVEI/TechnicalData/Submodel/1/2\"." +
" ?shell aas:submodels [ <aas-api:resolved> ?sm ] ." +
" ?sm aas:semanticId/aas:keys/aas:value \"https://admin-shell.io/ZVEI/TechnicalData/Submodel/1/2\" ." +
" ?sm (!<:>)+ ?element ." +
" { ?element a aas:Property } union { ?element a aas:MultiLanguageProperty }\n" +
" ?element aas:idShort \"ProductClassId\" ; " +
" aas:valueId/aas:keys/aas:value ?productClassId." +
" aas:valueId/aas:keys/aas:value ?productClassId ." +
"}" +
"}");
try (var result = query.evaluate()) {
Expand Down

0 comments on commit 014407c

Please sign in to comment.