diff --git a/admin-ui/src/main/java/eu/knowledge/engine/admin/MetadataKB.java b/admin-ui/src/main/java/eu/knowledge/engine/admin/MetadataKB.java index 0a9421bf..a6316d8c 100644 --- a/admin-ui/src/main/java/eu/knowledge/engine/admin/MetadataKB.java +++ b/admin-ui/src/main/java/eu/knowledge/engine/admin/MetadataKB.java @@ -6,7 +6,6 @@ import org.apache.jena.rdf.model.Model; import org.apache.jena.rdf.model.Resource; -import org.apache.jena.rdf.model.ResourceFactory; import org.apache.jena.shared.PrefixMapping; import org.apache.jena.sparql.graph.PrefixMappingMem; import org.apache.jena.sparql.lang.arq.javacc.ParseException; @@ -122,7 +121,7 @@ public BindingSet handleNewKnowledgeBase(ReactExchangeInfo ei) { try { Model model = eu.knowledge.engine.smartconnector.impl.Util.generateModel(this.aKI.getPattern(), - ei.getArgumentBindings()); + eu.knowledge.engine.smartconnector.impl.Util.translateFromApiBindingSet(ei.getArgumentBindings())); Resource kb = model.listSubjectsWithProperty(RDF.type, Vocab.KNOWLEDGE_BASE).next(); this.metadata.add(model); @@ -141,7 +140,7 @@ public BindingSet handleChangedKnowledgeBase(ReactExchangeInfo ei) { try { Model model = eu.knowledge.engine.smartconnector.impl.Util.generateModel(this.aKI.getPattern(), - ei.getArgumentBindings()); + eu.knowledge.engine.smartconnector.impl.Util.translateFromApiBindingSet(ei.getArgumentBindings())); // this is a little more complex... we have to: // - extract the knowledge base that this message is about @@ -206,7 +205,8 @@ public void fetchInitialData() { // using the BindingSet#generateModel() helper method, we can combine the graph // pattern and the bindings for its variables into a valid RDF Model. this.metadata = eu.knowledge.engine.smartconnector.impl.Util.generateModel(this.aKI.getPattern(), - askResult.getBindings()); + eu.knowledge.engine.smartconnector.impl.Util + .translateFromApiBindingSet(askResult.getBindings())); this.metadata.setNsPrefixes(this.prefixes); } catch (ParseException e) { diff --git a/reasoner/src/main/java/eu/knowledge/engine/reasoner/Match.java b/reasoner/src/main/java/eu/knowledge/engine/reasoner/Match.java index 1290fdd3..fdb08b6d 100644 --- a/reasoner/src/main/java/eu/knowledge/engine/reasoner/Match.java +++ b/reasoner/src/main/java/eu/knowledge/engine/reasoner/Match.java @@ -147,13 +147,13 @@ private Map mergeContexts(Map ex for (Map.Entry newEntry : newContext.entrySet()) { Node node; if ((node = getOtherNode(existingContext, newEntry.getKey().node)) != null) { - if (!node.equals(newEntry.getValue().node)) { + if (!node.sameValueAs(newEntry.getValue().node)) { return null; } } else { for (TripleNode tn : existingContextValues) { - if (tn.node.equals(newEntry.getValue().node)) { + if (tn.node.sameValueAs(newEntry.getValue().node)) { return null; } } @@ -167,7 +167,7 @@ private Map mergeContexts(Map ex public Node getOtherNode(Map aContext, Node aNode) { for (Map.Entry entry : aContext.entrySet()) { - if (entry.getKey().node.equals(aNode)) { + if (entry.getKey().node.sameValueAs(aNode)) { return entry.getValue().node; } } diff --git a/reasoner/src/main/java/eu/knowledge/engine/reasoner/api/Binding.java b/reasoner/src/main/java/eu/knowledge/engine/reasoner/api/Binding.java index d1391a1a..db2108a4 100644 --- a/reasoner/src/main/java/eu/knowledge/engine/reasoner/api/Binding.java +++ b/reasoner/src/main/java/eu/knowledge/engine/reasoner/api/Binding.java @@ -1,9 +1,12 @@ package eu.knowledge.engine.reasoner.api; import java.util.HashMap; +import java.util.Iterator; import java.util.Map; +import java.util.Set; import org.apache.jena.graph.Node; +import org.apache.jena.query.QuerySolution; import org.apache.jena.sparql.core.Var; import org.apache.jena.sparql.graph.PrefixMappingZero; import org.apache.jena.sparql.sse.SSE; @@ -17,6 +20,14 @@ public Binding() { super(); } + public Binding(QuerySolution qs) { + Iterator vars = qs.varNames(); + while (vars.hasNext()) { + String var = vars.next(); + super.put(Var.alloc(var), qs.get(var).asNode()); + } + } + public Binding(Var variable, Node lit) { super(); if (!lit.isConcrete()) @@ -72,4 +83,24 @@ public void putMap(Map map) { } + public boolean isSubBindingOf(Binding other) { + if (!other.keySet().containsAll(this.keySet())) { + return false; + } + + return other.entrySet().stream().allMatch(b -> { + Var variable = b.getKey(); + Node value = b.getValue(); + return !this.containsKey(variable) || value.sameValueAs(this.get(variable)); + }); + } + + public Binding keepOnly(Set variables) { + var b = new Binding(); + for (var a : variables) { + b.put(a, this.get(a)); + } + return b; + } + } diff --git a/reasoner/src/main/java/eu/knowledge/engine/reasoner/api/BindingSet.java b/reasoner/src/main/java/eu/knowledge/engine/reasoner/api/BindingSet.java index 4460def7..a9a5a6a2 100644 --- a/reasoner/src/main/java/eu/knowledge/engine/reasoner/api/BindingSet.java +++ b/reasoner/src/main/java/eu/knowledge/engine/reasoner/api/BindingSet.java @@ -5,6 +5,9 @@ import java.util.Map; import java.util.Set; +import org.apache.jena.query.QuerySolution; +import org.apache.jena.query.ResultSet; + public class BindingSet extends HashSet { private static final long serialVersionUID = 8263643495419009027L; @@ -17,6 +20,14 @@ public BindingSet(Collection bindings) { this.addAll(bindings); } + public BindingSet(ResultSet rs) { + QuerySolution qs = null; + while (rs.hasNext()) { + qs = rs.next(); + this.add(new Binding(qs)); + } + } + public BindingSet(Binding... bindings) { super(); for (Binding binding : bindings) { diff --git a/reasoner/src/main/java/eu/knowledge/engine/reasoner/api/TripleNode.java b/reasoner/src/main/java/eu/knowledge/engine/reasoner/api/TripleNode.java index b2e0c658..1d858854 100644 --- a/reasoner/src/main/java/eu/knowledge/engine/reasoner/api/TripleNode.java +++ b/reasoner/src/main/java/eu/knowledge/engine/reasoner/api/TripleNode.java @@ -38,7 +38,7 @@ public String toString() { sb.append(" "); } var truncatedNode = TriplePattern.trunc(n); - if (this.node.equals(n)) { + if (this.node.sameValueAs(n)) { sb.append("|").append(truncatedNode).append("|"); } else { sb.append(truncatedNode); diff --git a/reasoner/src/main/java/eu/knowledge/engine/reasoner/api/TriplePattern.java b/reasoner/src/main/java/eu/knowledge/engine/reasoner/api/TriplePattern.java index 890aa733..fbc4b586 100644 --- a/reasoner/src/main/java/eu/knowledge/engine/reasoner/api/TriplePattern.java +++ b/reasoner/src/main/java/eu/knowledge/engine/reasoner/api/TriplePattern.java @@ -70,7 +70,7 @@ public Map findMatches(TriplePattern other) { substitutionMap.put(new TripleNode(this, this.getSubject(), 0), new TripleNode(other, other.getSubject(), 0)); } else { - if (!this.getSubject().equals(other.getSubject())) { + if (!this.getSubject().sameValueAs(other.getSubject())) { return null; } } @@ -79,7 +79,7 @@ public Map findMatches(TriplePattern other) { substitutionMap.put(new TripleNode(this, this.getPredicate(), 1), new TripleNode(other, other.getPredicate(), 1)); } else { - if (!this.getPredicate().equals(other.getPredicate())) { + if (!this.getPredicate().sameValueAs(other.getPredicate())) { return null; } } @@ -87,7 +87,7 @@ public Map findMatches(TriplePattern other) { if (this.getObject() instanceof Var || other.getObject() instanceof Var) { substitutionMap.put(new TripleNode(this, this.getObject(), 2), new TripleNode(other, other.getObject(), 2)); } else { - if (!this.getObject().equals(other.getObject())) { + if (!this.getObject().sameValueAs(other.getObject())) { return null; } } @@ -162,21 +162,21 @@ public boolean equals(Object obj) { if (other.object != null) { return false; } - } else if (!object.equals(other.object)) { + } else if (!object.sameValueAs(other.object)) { return false; } if (predicate == null) { if (other.predicate != null) { return false; } - } else if (!predicate.equals(other.predicate)) { + } else if (!predicate.sameValueAs(other.predicate)) { return false; } if (subject == null) { if (other.subject != null) { return false; } - } else if (!subject.equals(other.subject)) { + } else if (!subject.sameValueAs(other.subject)) { return false; } return true; diff --git a/reasoner/src/main/java/eu/knowledge/engine/reasoner/api/TripleVarBinding.java b/reasoner/src/main/java/eu/knowledge/engine/reasoner/api/TripleVarBinding.java index 0abd8e9a..f6d03c9f 100644 --- a/reasoner/src/main/java/eu/knowledge/engine/reasoner/api/TripleVarBinding.java +++ b/reasoner/src/main/java/eu/knowledge/engine/reasoner/api/TripleVarBinding.java @@ -118,7 +118,7 @@ public boolean isConflicting(TripleVarBinding tvb) { assert e.getKey().node.isVariable(); l = tvb.getVarValue((Var) e.getKey().node); - if (l != null && !e.getValue().equals(l)) { + if (l != null && !e.getValue().sameValueAs(l)) { return true; } } @@ -159,7 +159,7 @@ public boolean containsVar(Var aVar) { assert aVar instanceof Var; for (TripleNode tNode : this.tripleVarMapping.keySet()) { - if (tNode.node.equals(aVar)) { + if (tNode.node.sameValueAs(aVar)) { return true; } } diff --git a/reasoner/src/main/java/eu/knowledge/engine/reasoner/api/TripleVarBindingSet.java b/reasoner/src/main/java/eu/knowledge/engine/reasoner/api/TripleVarBindingSet.java index 101c9ec2..f671d6a4 100644 --- a/reasoner/src/main/java/eu/knowledge/engine/reasoner/api/TripleVarBindingSet.java +++ b/reasoner/src/main/java/eu/knowledge/engine/reasoner/api/TripleVarBindingSet.java @@ -281,21 +281,21 @@ public Map translate(Set aGraphPatter var toTVar = new TripleNode(toTriple, (Var) toTNode.node, toTNode.nodeIdx); var toBVarValue = toB.getVarValue((Var) toTVar.node); if (fromB.containsKey(fromTVar) && !toB.containsKey(toTVar) - && (toBVarValue == null || toBVarValue.equals(fromB.get(fromTVar)))) { + && (toBVarValue == null || toBVarValue.sameValueAs(fromB.get(fromTVar)))) { toB.put(toTVar, fromB.get(fromTVar)); } else if (fromB.containsKey(fromTVar) && toB.containsVar((Var) toTVar.node) - && !fromB.get(fromTVar).equals(toBVarValue)) { + && !fromB.get(fromTVar).sameValueAs(toBVarValue)) { skip = true; // conflict, so skip } } else if (fromTNode.node instanceof Var && toTNode.node.isConcrete()) { var fromTVar = new TripleNode(fromTriple, (Var) fromTNode.node, fromTNode.nodeIdx); - if (fromB.containsKey(fromTVar) && !fromB.get(fromTVar).equals(toTNode.node)) { + if (fromB.containsKey(fromTVar) && !fromB.get(fromTVar).sameValueAs(toTNode.node)) { skip = true; // conflict, so skip } } else if (fromTNode.node.isConcrete() && toTNode.node instanceof Var) { var toTVar = new TripleNode(toTriple, (Var) toTNode.node, toTNode.nodeIdx); if (toB.containsVar((Var) toTVar.node) - && !toB.getVarValue((Var) toTVar.node).equals(fromTNode.node)) { + && !toB.getVarValue((Var) toTVar.node).sameValueAs(fromTNode.node)) { skip = true; } else toB.put(toTVar, fromTNode.node); diff --git a/reasoner/src/test/java/eu/knowledge/engine/reasoner/DynamicSemanticConfigurationTest.java b/reasoner/src/test/java/eu/knowledge/engine/reasoner/DynamicSemanticConfigurationTest.java index 15052910..4ef6880a 100644 --- a/reasoner/src/test/java/eu/knowledge/engine/reasoner/DynamicSemanticConfigurationTest.java +++ b/reasoner/src/test/java/eu/knowledge/engine/reasoner/DynamicSemanticConfigurationTest.java @@ -112,14 +112,14 @@ public CompletableFuture handle(BindingSet bs) { Node id; if (incomingB.containsKey("id") - && incomingB.get("id").equals(SSE.parseNode(""))) { + && incomingB.get("id").sameValueAs(SSE.parseNode(""))) { id = incomingB.get("id"); resultBinding.put("id", FmtUtils.stringForNode(id, new PrefixMappingZero())); resultBinding.put("c", "\"Russia\""); resultBinding.put("lang", "\"Russian\""); } else if (incomingB.containsKey("id") - && incomingB.get("id").equals(SSE.parseNode(""))) { + && incomingB.get("id").sameValueAs(SSE.parseNode(""))) { id = incomingB.get("id"); resultBinding.put("id", FmtUtils.stringForNode(id, new PrefixMappingZero())); resultBinding.put("c", "\"Holland\""); diff --git a/reasoner/src/test/java/eu/knowledge/engine/reasoner/api/RuleStoreTest.java b/reasoner/src/test/java/eu/knowledge/engine/reasoner/api/RuleStoreTest.java index 48f7dade..50787e3a 100644 --- a/reasoner/src/test/java/eu/knowledge/engine/reasoner/api/RuleStoreTest.java +++ b/reasoner/src/test/java/eu/knowledge/engine/reasoner/api/RuleStoreTest.java @@ -112,13 +112,13 @@ public CompletableFuture handle(BindingSet bs) { Node id; if (incomingB.containsKey("id") - && incomingB.get("id").equals(SSE.parseNode(""))) { + && incomingB.get("id").sameValueAs(SSE.parseNode(""))) { id = incomingB.get("id"); resultBinding.put("id", FmtUtils.stringForNode(id, new PrefixMappingZero())); resultBinding.put("c", "\"Russia\""); } else if (incomingB.containsKey("id") - && incomingB.get("id").equals(SSE.parseNode(""))) { + && incomingB.get("id").sameValueAs(SSE.parseNode(""))) { id = incomingB.get("id"); resultBinding.put("id", FmtUtils.stringForNode(id, new PrefixMappingZero())); resultBinding.put("c", "\"Holland\""); diff --git a/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/Binding.java b/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/Binding.java index 35db907d..2e1037b0 100644 --- a/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/Binding.java +++ b/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/Binding.java @@ -74,18 +74,6 @@ public String get(String aVariableName) { return this.map.get(aVariableName); } - public boolean isSubBindingOf(Binding other) { - if (!other.getVariables().containsAll(this.getVariables())) { - return false; - } - - return other.map.entrySet().stream().allMatch(b -> { - var variable = b.getKey(); - var value = b.getValue(); - return !this.containsKey(variable) || value.equals(this.get(variable)); - }); - } - public Binding keepOnly(Set variables) { var b = new Binding(); for (var a : variables) { diff --git a/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/BindingValidator.java b/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/BindingValidator.java index bf836e35..3492c0e5 100644 --- a/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/BindingValidator.java +++ b/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/BindingValidator.java @@ -4,12 +4,17 @@ import java.util.Set; import java.util.regex.Pattern; -import org.apache.jena.sparql.graph.PrefixMappingMem; +import org.apache.jena.graph.Node_Variable; +import org.apache.jena.sparql.core.Var; +import org.apache.jena.sparql.graph.PrefixMappingZero; import org.apache.jena.sparql.sse.SSE; import org.apache.jena.sparql.sse.SSE_ParseException; +import org.apache.jena.sparql.util.FmtUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import eu.knowledge.engine.reasoner.api.BindingSet; + public class BindingValidator { private static final Logger LOG = LoggerFactory.getLogger(BindingValidator.class); @@ -17,8 +22,8 @@ public class BindingValidator { private static Pattern UNPREFIXED_URI_PATTERN = Pattern.compile("^<[^>]+>$"); /** - * Throws an {@link InvalidArgumentException} if one of the bindings uses a - * key that is not one of the graph pattern's variables. + * Throws an {@link InvalidArgumentException} if one of the bindings uses a key + * that is not one of the graph pattern's variables. * * * @param pattern @@ -33,17 +38,18 @@ public void validatePartialBindings(GraphPattern pattern, BindingSet bindings) { } return; } - Set variables = pattern.getVariables(); + Set variables = pattern.getVariables(); bindings.forEach(b -> { b.forEach((k, v) -> { - this.validateValidBindingValue(v); if (!variables.contains(k)) { - throw new IllegalArgumentException(String.format("Given binding set uses key '%s', but this does not occur as a variable in graph pattern '%s'.", k, pattern.getPattern())); + throw new IllegalArgumentException(String.format( + "Given binding set uses key '%s', but this does not occur as a variable in graph pattern '%s'.", + k, pattern.getPattern())); } }); }); } - + public void validateCompleteBindings(GraphPattern pattern, BindingSet bindings) { if (pattern == null) { if (bindings == null) { @@ -53,52 +59,30 @@ public void validateCompleteBindings(GraphPattern pattern, BindingSet bindings) } return; } - Set variables = pattern.getVariables(); + Set variables = pattern.getVariables(); bindings.forEach(b -> { - var notSeenYet = new HashSet(variables); + var notSeenYet = new HashSet(variables); b.forEach((k, v) -> { - this.validateValidBindingValue(v); if (!variables.contains(k)) { - throw new IllegalArgumentException(String.format("Given binding set uses key '%s', but this does not occur as a variable in graph pattern '%s'.", k, pattern.getPattern())); + throw new IllegalArgumentException(String.format( + "Given binding set uses key '%s', but this does not occur as a variable in graph pattern '%s'.", + k, pattern.getPattern())); } notSeenYet.remove(k); }); if (!notSeenYet.isEmpty()) { - throw new IllegalArgumentException(String.format("Expected a complete binding, but was missing some variable(s) that ARE in the graph " - + "pattern ('%s'), but are missing from the binding, namely: %s. Note that the question mark should NOT be included in your binding keys.", pattern.getPattern(), notSeenYet.toString())); + throw new IllegalArgumentException(String.format( + "Expected a complete binding, but was missing some variable(s) that ARE in the graph " + + "pattern ('%s'), but are missing from the binding, namely: %s. Note that the question mark should NOT be included in your binding keys.", + pattern.getPattern(), notSeenYet.toString())); } }); } - /** - * Throws an {@link InvalidArgumentException} if the given value is not either: - * - an unprefixed IRI, or - * - a valid literal. - * @param value - */ - public void validateValidBindingValue(String value) { - LOG.trace("Validating binding value: {}", value); - try { - var node = SSE.parseNode(value, new PrefixMappingMem()); - if (!(node.isLiteral() || node.isURI())) { - LOG.debug("{} is not valid because Jena said it is not a literal or URI", value); - throw new IllegalArgumentException(String.format("'%s' is not an unprefixed URI or literal.", value)); - } else if (node.isURI()) { - var matcher = UNPREFIXED_URI_PATTERN.matcher(value.strip()); - if (!matcher.matches()) { - LOG.debug("{} is not valid because matcher said no (even though Jena accepted it as an URI)", value); - throw new IllegalArgumentException(String.format("'%s' is not a valid unprefixed URI.", value)); - } - } - } catch (SSE_ParseException spe) { - LOG.debug("{} is not valid because Jena could not parse it", value); - throw new IllegalArgumentException(String.format("'%s' is not an unprefixed URI or literal.", value)); - } - } - public void validateIncomingOutgoingAnswer(GraphPattern pattern, BindingSet incoming, BindingSet outgoing) { - // make sure each of the outgoing bindings 'fits' on at least 1 incoming binding. - + // make sure each of the outgoing bindings 'fits' on at least 1 incoming + // binding. + // TODO: Is an empty binding set, [], simply 'syntactic sugar' for a binding // set with the empty binding, [{}]? Then this would be consistent. if (incoming.size() == 0) { @@ -107,15 +91,18 @@ public void validateIncomingOutgoingAnswer(GraphPattern pattern, BindingSet inco } outgoing.forEach(outgoingBinding -> { - // Check if there is an incoming binding that is matches (is a 'sub-binding' of) the outgoing binding. + // Check if there is an incoming binding that is matches (is a 'sub-binding' of) + // the outgoing binding. if (incoming.stream().allMatch(incomingBinding -> !incomingBinding.isSubBindingOf(outgoingBinding))) { // If not, it is invalid. - throw new IllegalArgumentException("KB gave outgoing binding " + outgoingBinding + ", but this doesn't have a matching incoming binding!"); + throw new IllegalArgumentException("KB gave outgoing binding " + outgoingBinding + + ", but this doesn't have a matching incoming binding!"); } }); } - public void validateIncomingOutgoingReact(GraphPattern argumentPattern, GraphPattern resultPattern, BindingSet incoming, BindingSet outgoing) { + public void validateIncomingOutgoingReact(GraphPattern argumentPattern, GraphPattern resultPattern, + BindingSet incoming, BindingSet outgoing) { // this one is different, because only the variables that occur in both the // argument and result patterns have to 'fit'. @@ -131,8 +118,10 @@ public void validateIncomingOutgoingReact(GraphPattern argumentPattern, GraphPat // match with the outgoing binding. This is because the argument // (incoming) graph pattern can have variables that do not occur in the // result (outgoing) graph pattern. - if (incoming.stream().map(incomingBinding -> incomingBinding.keepOnly(overlappingVariables)).allMatch(b -> !b.isSubBindingOf(outgoingBinding))) { - throw new IllegalArgumentException("KB gave outgoing binding " + outgoingBinding + ", but this doesn't have a matching incoming binding!"); + if (incoming.stream().map(incomingBinding -> incomingBinding.keepOnly(overlappingVariables)) + .allMatch(b -> !b.isSubBindingOf(outgoingBinding))) { + throw new IllegalArgumentException("KB gave outgoing binding " + outgoingBinding + + ", but this doesn't have a matching incoming binding!"); } }); } diff --git a/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/GraphPattern.java b/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/GraphPattern.java index 9370d20a..3ad05085 100644 --- a/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/GraphPattern.java +++ b/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/GraphPattern.java @@ -10,6 +10,7 @@ import org.apache.jena.query.QueryFactory; import org.apache.jena.query.Syntax; import org.apache.jena.shared.PrefixMapping; +import org.apache.jena.sparql.core.Var; import org.apache.jena.sparql.graph.PrefixMappingZero; import org.apache.jena.sparql.lang.arq.javacc.ParseException; import org.apache.jena.sparql.syntax.Element; @@ -105,7 +106,7 @@ public String getPattern() { * @return A list of all the variable names (excluding the '?') occurring in * this {@link GraphPattern}. */ - public Set getVariables() { + public Set getVariables() { var triples = this.getGraphPattern().getPattern().getList(); return triples.stream() // Redirect the subjects, predicates and objects to a single stream of nodes. @@ -113,7 +114,7 @@ public Set getVariables() { // Map the nodes to variable names if they're variables, and otherwise `null`. .map(n -> { if (n instanceof Node_Variable) { - return ((Node_Variable) n).getName(); + return (Var.alloc(n.getName())); } else { return null; } diff --git a/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/SmartConnectorConfig.java b/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/SmartConnectorConfig.java index bb660735..507b3248 100644 --- a/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/SmartConnectorConfig.java +++ b/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/SmartConnectorConfig.java @@ -125,20 +125,6 @@ public class SmartConnectorConfig { */ public static final String CONF_KEY_KE_DOMAIN_KNOWLEDGE_PATH = "ke.domain.knowledge.path"; - /** - * Configure the maximum number of entries in the node cache that is being used - * to speed up converting from graph patterns and bindingsets to RDF. See: - * {@code eu.knowledge.engine.smartconnector.impl.Util.nodeCache} - * - */ - public static final String CONF_KEY_KE_CACHE_NODE_SIZE = "ke.cache.node.size"; - - /** - * Configure the number of minutes of being idle (not accessed) after which a - * cache entry can be evicted from cache. - */ - public static final String CONF_KEY_KE_CACHE_NODE_EXPIRYMINUTES = "ke.cache.node.expiryminutes"; - /** * The main thread pool of the Knowledge Engine Runtime that is used to, among * other things, deliver messages. diff --git a/smart-connector-rest-server/src/main/java/eu/knowledge/engine/rest/api/impl/HandleRequest.java b/smart-connector-rest-server/src/main/java/eu/knowledge/engine/rest/api/impl/HandleRequest.java index 9123fce2..589ecad9 100644 --- a/smart-connector-rest-server/src/main/java/eu/knowledge/engine/rest/api/impl/HandleRequest.java +++ b/smart-connector-rest-server/src/main/java/eu/knowledge/engine/rest/api/impl/HandleRequest.java @@ -14,6 +14,7 @@ import eu.knowledge.engine.smartconnector.api.GraphPattern; import eu.knowledge.engine.smartconnector.api.KnowledgeInteraction; import eu.knowledge.engine.smartconnector.api.ReactKnowledgeInteraction; +import eu.knowledge.engine.smartconnector.impl.Util; public class HandleRequest { private static final Logger LOG = LoggerFactory.getLogger(HandleRequest.class); @@ -27,7 +28,8 @@ public class HandleRequest { private KnowledgeInteractionType knowledgeInteractionType; public HandleRequest(int aHandleRequestId, KnowledgeInteraction aKI, KnowledgeInteractionType type, - List> aBindingSet, URI aRequestingKnowledgeBaseId, CompletableFuture future) { + List> aBindingSet, URI aRequestingKnowledgeBaseId, + CompletableFuture future) { this.future = future; this.handleRequestId = aHandleRequestId; this.knowledgeInteractionType = type; @@ -87,7 +89,7 @@ public void validateBindings(BindingSet bindings) { this.knowledgeInteractionType)); } var validator = new BindingValidator(); - validator.validateCompleteBindings(graphPattern, bindings); + validator.validateCompleteBindings(graphPattern, Util.translateFromApiBindingSet(bindings)); } @Override diff --git a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/AskPlanImpl.java b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/AskPlanImpl.java index a473c07c..f5ee06dc 100644 --- a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/AskPlanImpl.java +++ b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/AskPlanImpl.java @@ -20,7 +20,7 @@ public CompletableFuture execute(BindingSet bindingSet) { if (bindingSet == null) { throw new IllegalArgumentException("the binding set should be non-null"); } - return this.processor.executeAskInteraction(bindingSet); + return this.processor.executeAskInteraction(Util.translateFromApiBindingSet(bindingSet)); } @Override diff --git a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/InteractionProcessorImpl.java b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/InteractionProcessorImpl.java index 04f3be83..6e98061f 100644 --- a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/InteractionProcessorImpl.java +++ b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/InteractionProcessorImpl.java @@ -16,6 +16,7 @@ import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; +import org.apache.jena.graph.Node; import org.apache.jena.graph.NodeFactory; import org.apache.jena.query.Query; import org.apache.jena.query.QueryExecution; @@ -30,22 +31,25 @@ import org.apache.jena.rdf.model.ResourceFactory; import org.apache.jena.reasoner.Reasoner; import org.apache.jena.reasoner.ReasonerRegistry; +import org.apache.jena.shared.PrefixMapping; import org.apache.jena.sparql.core.Var; import org.apache.jena.sparql.engine.binding.BindingFactory; +import org.apache.jena.sparql.graph.PrefixMappingZero; import org.apache.jena.sparql.syntax.ElementData; import org.apache.jena.sparql.syntax.ElementGroup; +import org.apache.jena.sparql.util.FmtUtils; import org.apache.jena.vocabulary.RDF; import org.eclipse.microprofile.config.ConfigProvider; import org.slf4j.Logger; import eu.knowledge.engine.reasoner.BaseRule; import eu.knowledge.engine.reasoner.Rule; +import eu.knowledge.engine.reasoner.api.Binding; +import eu.knowledge.engine.reasoner.api.BindingSet; import eu.knowledge.engine.reasoner.util.JenaRules; import eu.knowledge.engine.smartconnector.api.AnswerExchangeInfo; import eu.knowledge.engine.smartconnector.api.AnswerKnowledgeInteraction; import eu.knowledge.engine.smartconnector.api.AskPlan; -import eu.knowledge.engine.smartconnector.api.Binding; -import eu.knowledge.engine.smartconnector.api.BindingSet; import eu.knowledge.engine.smartconnector.api.BindingValidator; import eu.knowledge.engine.smartconnector.api.CommunicativeAct; import eu.knowledge.engine.smartconnector.api.GraphPattern; @@ -169,7 +173,8 @@ private Set filterOtherKnowledgeBases(Set processAskFromMessageRouter(AskMessage a AnswerKnowledgeInteraction answerKnowledgeInteraction; answerKnowledgeInteraction = (AnswerKnowledgeInteraction) knowledgeInteractionById.getKnowledgeInteraction(); - CompletableFuture future; + CompletableFuture future; var handler = this.myKnowledgeBaseStore.getAnswerHandler(answerKnowledgeInteractionId); // TODO This should happen in the single thread for the knowledge base @@ -241,23 +248,25 @@ public CompletableFuture processAskFromMessageRouter(AskMessage a LOG.info("Contacting my KB to answer KI <{}>", answerKnowledgeInteractionId); } - var aei = new AnswerExchangeInfo(anAskMsg.getBindings(), anAskMsg.getFromKnowledgeBase(), - anAskMsg.getFromKnowledgeInteraction()); + var aei = new AnswerExchangeInfo(Util.translateToApiBindingSet(anAskMsg.getBindings()), + anAskMsg.getFromKnowledgeBase(), anAskMsg.getFromKnowledgeInteraction()); future = handler.answerAsync(answerKnowledgeInteraction, aei); return future.handle((b, e) -> { if (b != null && e == null) { LOG.debug("Received ANSWER from KB for KI <{}>: {}", answerKnowledgeInteractionId, b); + BindingSet translatedB = Util.translateFromApiBindingSet(b); + if (this.shouldValidateInputOutputBindings()) { var validator = new BindingValidator(); - validator.validateCompleteBindings(answerKnowledgeInteraction.getPattern(), b); + validator.validateCompleteBindings(answerKnowledgeInteraction.getPattern(), translatedB); validator.validateIncomingOutgoingAnswer(answerKnowledgeInteraction.getPattern(), - anAskMsg.getBindings(), b); + anAskMsg.getBindings(), translatedB); } return new AnswerMessage(anAskMsg.getToKnowledgeBase(), answerKnowledgeInteractionId, anAskMsg.getFromKnowledgeBase(), anAskMsg.getFromKnowledgeInteraction(), - anAskMsg.getMessageId(), b); + anAskMsg.getMessageId(), translatedB); } else { String errorMessage; if (e == null) @@ -341,11 +350,11 @@ public CompletableFuture processPostFromMessageRouter(PostMessage ReactKnowledgeInteraction reactKnowledgeInteraction; reactKnowledgeInteraction = (ReactKnowledgeInteraction) knowledgeInteractionById.getKnowledgeInteraction(); - CompletableFuture future; + CompletableFuture future; var handler = this.myKnowledgeBaseStore.getReactHandler(reactKnowledgeInteractionId); - var rei = new ReactExchangeInfo(aPostMsg.getArgument(), aPostMsg.getFromKnowledgeBase(), - aPostMsg.getFromKnowledgeInteraction()); + var rei = new ReactExchangeInfo(Util.translateToApiBindingSet(aPostMsg.getArgument()), + aPostMsg.getFromKnowledgeBase(), aPostMsg.getFromKnowledgeInteraction()); // TODO This should happen in the single thread for the knowledge base if (reactKnowledgeInteraction.isMeta()) { @@ -359,15 +368,17 @@ public CompletableFuture processPostFromMessageRouter(PostMessage return future.handle((b, e) -> { if (b != null && e == null) { LOG.debug("Received REACT from KB for KI <{}>: {}", reactKnowledgeInteraction, b); + BindingSet translatedB = Util.translateFromApiBindingSet(b); + if (this.shouldValidateInputOutputBindings()) { var validator = new BindingValidator(); - validator.validateCompleteBindings(reactKnowledgeInteraction.getResult(), b); + validator.validateCompleteBindings(reactKnowledgeInteraction.getResult(), translatedB); validator.validateIncomingOutgoingReact(reactKnowledgeInteraction.getArgument(), - reactKnowledgeInteraction.getResult(), aPostMsg.getArgument(), b); + reactKnowledgeInteraction.getResult(), aPostMsg.getArgument(), translatedB); } return new ReactMessage(aPostMsg.getToKnowledgeBase(), reactKnowledgeInteractionId, aPostMsg.getFromKnowledgeBase(), aPostMsg.getFromKnowledgeInteraction(), - aPostMsg.getMessageId(), b); + aPostMsg.getMessageId(), translatedB); } else { String errorMessage; if (e == null) diff --git a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/MetaKnowledgeBaseImpl.java b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/MetaKnowledgeBaseImpl.java index a34e878d..f446ecfb 100644 --- a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/MetaKnowledgeBaseImpl.java +++ b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/MetaKnowledgeBaseImpl.java @@ -35,7 +35,7 @@ import eu.knowledge.engine.smartconnector.api.AnswerKnowledgeInteraction; import eu.knowledge.engine.smartconnector.api.AskKnowledgeInteraction; -import eu.knowledge.engine.smartconnector.api.BindingSet; +import eu.knowledge.engine.reasoner.api.BindingSet; import eu.knowledge.engine.smartconnector.api.CommunicativeAct; import eu.knowledge.engine.smartconnector.api.GraphPattern; import eu.knowledge.engine.smartconnector.api.KnowledgeEngineRuntimeException; @@ -90,9 +90,12 @@ public MetaKnowledgeBaseImpl(LoggerProvider loggerProvider, MessageRouter aMessa this.metaAnswerKI = new AnswerKnowledgeInteraction(new CommunicativeAct(), this.metaGraphPattern, null, true, true, MatchStrategy.ENTRY_LEVEL); - this.knowledgeBaseStore.register(this.metaAnswerKI, - (anAKI, anAnswerExchangeInfo) -> this.fillMetaBindings(anAnswerExchangeInfo.getIncomingBindings()), - true); + this.knowledgeBaseStore + .register( + this.metaAnswerKI, (anAKI, + anAnswerExchangeInfo) -> Util.translateToApiBindingSet(this.fillMetaBindings( + Util.translateFromApiBindingSet(anAnswerExchangeInfo.getIncomingBindings()))), + true); this.metaAskKI = new AskKnowledgeInteraction(new CommunicativeAct(), this.metaGraphPattern, null, true, true, false, MatchStrategy.ENTRY_LEVEL); @@ -130,10 +133,11 @@ public MetaKnowledgeBaseImpl(LoggerProvider loggerProvider, MessageRouter aMessa throw new KnowledgeEngineRuntimeException( "Received meta bindings from non-meta (or incorrect meta) KI."); } - var newKb = this.constructOtherKnowledgeBaseFromBindingSet(aReactExchangeInfo.getArgumentBindings(), + var newKb = this.constructOtherKnowledgeBaseFromBindingSet( + Util.translateFromApiBindingSet(aReactExchangeInfo.getArgumentBindings()), aReactExchangeInfo.getPostingKnowledgeBaseId()); this.otherKnowledgeBaseStore.addKnowledgeBase(newKb); - return new BindingSet(); + return Util.translateToApiBindingSet(new BindingSet()); }, true); this.metaReactChangedKI = new ReactKnowledgeInteraction( @@ -150,10 +154,11 @@ public MetaKnowledgeBaseImpl(LoggerProvider loggerProvider, MessageRouter aMessa throw new KnowledgeEngineRuntimeException( "Received meta bindings from non-meta (or incorrect meta) KI."); } - var changedKb = this.constructOtherKnowledgeBaseFromBindingSet(aReactExchangeInfo.getArgumentBindings(), + var changedKb = this.constructOtherKnowledgeBaseFromBindingSet( + Util.translateFromApiBindingSet(aReactExchangeInfo.getArgumentBindings()), aReactExchangeInfo.getPostingKnowledgeBaseId()); this.otherKnowledgeBaseStore.updateKnowledgeBase(changedKb); - return new BindingSet(); + return Util.translateToApiBindingSet(new BindingSet()); }, true); this.metaReactRemovedKI = new ReactKnowledgeInteraction( @@ -170,10 +175,11 @@ public MetaKnowledgeBaseImpl(LoggerProvider loggerProvider, MessageRouter aMessa throw new KnowledgeEngineRuntimeException( "Received meta bindings from non-meta (or incorrect meta) KI."); } - var removedKb = this.constructOtherKnowledgeBaseFromBindingSet(aReactExchangeInfo.getArgumentBindings(), + var removedKb = this.constructOtherKnowledgeBaseFromBindingSet( + Util.translateFromApiBindingSet(aReactExchangeInfo.getArgumentBindings()), aReactExchangeInfo.getPostingKnowledgeBaseId()); this.otherKnowledgeBaseStore.removeKnowledgeBase(removedKb); - return new BindingSet(); + return Util.translateToApiBindingSet(new BindingSet()); }, true); } @@ -548,7 +554,7 @@ private OtherKnowledgeBase constructOtherKnowledgeBaseFromBindingSet(BindingSet public CompletableFuture postNewKnowledgeBase() { var kiInfo = this.knowledgeBaseStore.getKnowledgeInteractionByObject(this.metaPostNewKI); return this.interactionProcessor.planPostFromKnowledgeBase(kiInfo, new RecipientSelector()) - .execute(this.fillMetaBindings(null)).handle((r, e) -> { + .execute(Util.translateToApiBindingSet(this.fillMetaBindings(null))).handle((r, e) -> { if (r == null) { LOG.error("An exception has occured while posting new Knowledge Base ", e); @@ -565,7 +571,7 @@ public void knowledgeInteractionRegistered(KnowledgeInteractionInfo ki) { var kiInfo = this.knowledgeBaseStore.getKnowledgeInteractionByObject(this.metaPostChangedKI); try { this.interactionProcessor.planPostFromKnowledgeBase(kiInfo, new RecipientSelector()) - .execute(this.fillMetaBindings(null)).get(); + .execute(Util.translateToApiBindingSet(this.fillMetaBindings(null))).get(); } catch (InterruptedException | ExecutionException e) { LOG.error("No error should occur while notifying others of a registered knowledge interaction."); } @@ -578,7 +584,7 @@ public void knowledgeInteractionUnregistered(KnowledgeInteractionInfo ki) { var kiInfo = this.knowledgeBaseStore.getKnowledgeInteractionByObject(this.metaPostChangedKI); try { this.interactionProcessor.planPostFromKnowledgeBase(kiInfo, new RecipientSelector()) - .execute(this.fillMetaBindings(null)).get(); + .execute(Util.translateToApiBindingSet(this.fillMetaBindings(null))).get(); } catch (InterruptedException | ExecutionException e) { LOG.error("No error should occur while notifying others of an unregistered knowledge interaction."); } @@ -594,8 +600,8 @@ public CompletableFuture smartConnectorStopping() { + otherKnowledgeBases.size() * POST_REMOVED_TIMEOUT_MILLIS_PER_OTHERKB; LOG.debug("Waiting for max {}ms for other KBs to ack my termination message.", timeout); return this.interactionProcessor.planPostFromKnowledgeBase(kiInfo, new RecipientSelector()) - .execute(this.fillMetaBindings(null)).orTimeout(timeout, TimeUnit.MILLISECONDS) - .exceptionally((Throwable e) -> { + .execute(Util.translateToApiBindingSet(this.fillMetaBindings(null))) + .orTimeout(timeout, TimeUnit.MILLISECONDS).exceptionally((Throwable e) -> { LOG.error("An error occured while informing other KBs about our " + "termination. Proceeding to stop the smart connector regardless.", e); return (PostResult) null; diff --git a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/PostPlanImpl.java b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/PostPlanImpl.java index d85b5cc3..6e50188f 100644 --- a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/PostPlanImpl.java +++ b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/PostPlanImpl.java @@ -25,7 +25,7 @@ public CompletableFuture execute(BindingSet someArguments) { if (someArguments == null) { throw new IllegalArgumentException("the binding set should be non-null"); } - return this.processor.executePostInteraction(someArguments).handle((r, e) -> { + return this.processor.executePostInteraction(Util.translateFromApiBindingSet(someArguments)).handle((r, e) -> { if (r == null) { LOG.error("An exception has occured while executing Post Plan", e); diff --git a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/ReasonerProcessor.java b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/ReasonerProcessor.java index 117dd251..ed912ece 100644 --- a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/ReasonerProcessor.java +++ b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/ReasonerProcessor.java @@ -38,8 +38,8 @@ import eu.knowledge.engine.smartconnector.api.AskExchangeInfo; import eu.knowledge.engine.smartconnector.api.AskKnowledgeInteraction; import eu.knowledge.engine.smartconnector.api.AskResult; -import eu.knowledge.engine.smartconnector.api.Binding; -import eu.knowledge.engine.smartconnector.api.BindingSet; +import eu.knowledge.engine.reasoner.api.Binding; +import eu.knowledge.engine.reasoner.api.BindingSet; import eu.knowledge.engine.smartconnector.api.ExchangeInfo.Initiator; import eu.knowledge.engine.smartconnector.api.ExchangeInfo.Status; import eu.knowledge.engine.smartconnector.api.GraphPattern; @@ -91,7 +91,7 @@ public class ReasonerProcessor extends SingleInteractionProcessor { * The future returned to the caller of this class which keeps track of when all * the futures of outstanding messages are completed. */ - private CompletableFuture finalBindingSetFuture; + private CompletableFuture finalBindingSetFuture; public ReasonerProcessor(Set knowledgeInteractions, MessageRouter messageRouter, Set someDomainKnowledge) { @@ -167,7 +167,7 @@ public void planAskInteraction(MyKnowledgeInteractionInfo aAKI) { this.reasonerPlan = new ReasonerPlan(this.store, aRule, aStrategy.toConfig(true)); } else { LOG.warn("Type should be Ask, not {}", this.myKnowledgeInteraction.getType()); - this.finalBindingSetFuture.complete(new eu.knowledge.engine.reasoner.api.BindingSet()); + this.finalBindingSetFuture.complete(new BindingSet()); } } @@ -190,21 +190,21 @@ public void planAskInteraction(MyKnowledgeInteractionInfo aAKI) { @Override public CompletableFuture executeAskInteraction(BindingSet someBindings) { - this.finalBindingSetFuture = new CompletableFuture(); + this.finalBindingSetFuture = new CompletableFuture(); // this.reasonerPlan.optimize(); - continueReasoningBackward(translateBindingSetTo(someBindings)); + continueReasoningBackward(someBindings); return this.finalBindingSetFuture.thenApply((bs) -> { if (myKnowledgeInteraction.getKnowledgeInteraction().knowledgeGapsEnabled()) { this.knowledgeGaps = bs.isEmpty() ? getKnowledgeGaps(this.reasonerPlan.getStartNode()) : new HashSet(); } - return new AskResult(translateBindingSetFrom(bs), this.askExchangeInfos, this.reasonerPlan, + return new AskResult(Util.translateToApiBindingSet(bs), this.askExchangeInfos, this.reasonerPlan, this.knowledgeGaps); }); } - private void continueReasoningBackward(eu.knowledge.engine.reasoner.api.BindingSet incomingBS) { + private void continueReasoningBackward(BindingSet incomingBS) { boolean isComplete; TaskBoard taskboard; @@ -215,7 +215,7 @@ private void continueReasoningBackward(eu.knowledge.engine.reasoner.api.BindingS taskboard.executeScheduledTasks().thenAccept(Void -> { LOG.debug("All ask tasks finished."); if (isComplete) { - eu.knowledge.engine.reasoner.api.BindingSet bs = this.reasonerPlan.getResults(); + BindingSet bs = this.reasonerPlan.getResults(); this.finalBindingSetFuture.complete(bs); } else continueReasoningBackward(incomingBS); @@ -261,26 +261,24 @@ public void planPostInteraction(MyKnowledgeInteractionInfo aPKI) { } else { LOG.warn("Type should be Post, not {}", this.myKnowledgeInteraction.getType()); - this.finalBindingSetFuture.complete(new eu.knowledge.engine.reasoner.api.BindingSet()); + this.finalBindingSetFuture.complete(new BindingSet()); } } @Override public CompletableFuture executePostInteraction(BindingSet someBindings) { - this.finalBindingSetFuture = new CompletableFuture(); - eu.knowledge.engine.reasoner.api.BindingSet translatedBindingSet = translateBindingSetTo(someBindings); + this.finalBindingSetFuture = new CompletableFuture(); // this.reasonerPlan.optimize(); - continueReasoningForward(translatedBindingSet, this.captureResultBindingSetHandler); + continueReasoningForward(someBindings, this.captureResultBindingSetHandler); return this.finalBindingSetFuture.thenApply((bs) -> { - return new PostResult(translateBindingSetFrom(bs), this.postExchangeInfos, this.reasonerPlan); + return new PostResult(Util.translateToApiBindingSet(bs), this.postExchangeInfos, this.reasonerPlan); }); } - private void continueReasoningForward(eu.knowledge.engine.reasoner.api.BindingSet incomingBS, - CaptureBindingSetHandler aBindingSetHandler) { + private void continueReasoningForward(BindingSet incomingBS, CaptureBindingSetHandler aBindingSetHandler) { String msg = "Executing (scheduled) tasks for the reasoner should not result in errors."; boolean isComplete; @@ -291,7 +289,7 @@ private void continueReasoningForward(eu.knowledge.engine.reasoner.api.BindingSe taskboard.executeScheduledTasks().thenAccept(Void -> { LOG.debug("All post tasks finished."); if (isComplete) { - eu.knowledge.engine.reasoner.api.BindingSet resultBS = new eu.knowledge.engine.reasoner.api.BindingSet(); + BindingSet resultBS = new BindingSet(); if (aBindingSetHandler != null && aBindingSetHandler.getBindingSet() != null) { resultBS = aBindingSetHandler.getBindingSet(); } @@ -308,57 +306,12 @@ private void continueReasoningForward(eu.knowledge.engine.reasoner.api.BindingSe } - /** - * Translate bindingset from the reasoner bindingsets to the ke bindingsets. - * - * @param bs a reasoner bindingset - * @return a ke bindingset - */ - protected BindingSet translateBindingSetFrom(eu.knowledge.engine.reasoner.api.BindingSet bs) { - BindingSet newBS = new BindingSet(); - Binding newB; - - SerializationContext context = new SerializationContext(); - context.setUsePlainLiterals(false); - - for (eu.knowledge.engine.reasoner.api.Binding b : bs) { - newB = new Binding(); - for (Map.Entry entry : b.entrySet()) { - newB.put(entry.getKey().getName(), FmtUtils.stringForNode(entry.getValue(), context)); - } - newBS.add(newB); - } - return newBS; - } - - /** - * Translate bindingset from the ke bindingset to the reasoner bindingset. - * - * @param someBindings a ke bindingset - * @return a reasoner bindingset - */ - protected eu.knowledge.engine.reasoner.api.BindingSet translateBindingSetTo(BindingSet someBindings) { - - eu.knowledge.engine.reasoner.api.BindingSet newBindingSet = new eu.knowledge.engine.reasoner.api.BindingSet(); - eu.knowledge.engine.reasoner.api.Binding newBinding; - for (Binding b : someBindings) { - - newBinding = new eu.knowledge.engine.reasoner.api.Binding(); - for (String var : b.getVariables()) { - newBinding.put(var, b.get(var)); - } - newBindingSet.add(newBinding); - } - - return newBindingSet; - } - public static class CaptureBindingSetHandler implements SinkBindingSetHandler { - private eu.knowledge.engine.reasoner.api.BindingSet bs; + private BindingSet bs; @Override - public CompletableFuture handle(eu.knowledge.engine.reasoner.api.BindingSet bs) { + public CompletableFuture handle(BindingSet bs) { this.bs = bs; var future = new CompletableFuture(); @@ -376,13 +329,13 @@ public CompletableFuture handle(eu.knowledge.engine.reasoner.api.BindingSe return future; } - public eu.knowledge.engine.reasoner.api.BindingSet getBindingSet() { + public BindingSet getBindingSet() { return bs; } } - private AskExchangeInfo convertMessageToExchangeInfo(BindingSet someConvertedBindings, AnswerMessage aMessage, + private AskExchangeInfo convertMessageToExchangeInfo(BindingSet someBindings, AnswerMessage aMessage, Instant aPreviousSend) { Status status = Status.SUCCEEDED; String failedMessage = aMessage.getFailedMessage(); @@ -392,12 +345,12 @@ private AskExchangeInfo convertMessageToExchangeInfo(BindingSet someConvertedBin } return new AskExchangeInfo(Initiator.KNOWLEDGEBASE, aMessage.getFromKnowledgeBase(), - aMessage.getFromKnowledgeInteraction(), someConvertedBindings, aPreviousSend, Instant.now(), status, - failedMessage); + aMessage.getFromKnowledgeInteraction(), Util.translateToApiBindingSet(someBindings), aPreviousSend, + Instant.now(), status, failedMessage); } - private PostExchangeInfo convertMessageToExchangeInfo(BindingSet someConvertedArgumentBindings, - BindingSet someConvertedResultBindings, ReactMessage aMessage, Instant aPreviousSend) { + private PostExchangeInfo convertMessageToExchangeInfo(BindingSet someArgumentBindings, + BindingSet someResultBindings, ReactMessage aMessage, Instant aPreviousSend) { Status status = Status.SUCCEEDED; String failedMessage = aMessage.getFailedMessage(); @@ -406,8 +359,8 @@ private PostExchangeInfo convertMessageToExchangeInfo(BindingSet someConvertedAr } return new PostExchangeInfo(Initiator.KNOWLEDGEBASE, aMessage.getFromKnowledgeBase(), - aMessage.getFromKnowledgeInteraction(), someConvertedArgumentBindings, someConvertedResultBindings, - aPreviousSend, Instant.now(), status, failedMessage); + aMessage.getFromKnowledgeInteraction(), Util.translateToApiBindingSet(someArgumentBindings), + Util.translateToApiBindingSet(someResultBindings), aPreviousSend, Instant.now(), status, failedMessage); } /** @@ -429,14 +382,12 @@ public KnowledgeInteractionInfo getKnowledgeInteractionInfo() { } @Override - public CompletableFuture handle( - eu.knowledge.engine.reasoner.api.BindingSet bs) { - CompletableFuture bsFuture; - BindingSet newBS = translateBindingSetFrom(bs); + public CompletableFuture handle(BindingSet bs) { + CompletableFuture bsFuture; AskMessage askMessage = new AskMessage(ReasonerProcessor.this.myKnowledgeInteraction.getKnowledgeBaseId(), ReasonerProcessor.this.myKnowledgeInteraction.getId(), this.kii.getKnowledgeBaseId(), - this.kii.getId(), newBS); + this.kii.getId(), bs); try { CompletableFuture sendAskMessage = ReasonerProcessor.this.messageRouter @@ -464,7 +415,7 @@ public CompletableFuture handle( ReasonerProcessor.this.askExchangeInfos .add(convertMessageToExchangeInfo(resultBindingSet, answerMessage, aPreviousSend)); - return translateBindingSetTo(resultBindingSet); + return resultBindingSet; }); } catch (IOException e) { @@ -474,8 +425,8 @@ public CompletableFuture handle( ReasonerProcessor.this.myKnowledgeInteraction.getKnowledgeBaseId(), this.kii.getKnowledgeBaseId()); LOG.trace("Detailed error information.", e); - bsFuture = new CompletableFuture(); - bsFuture.complete(new eu.knowledge.engine.reasoner.api.BindingSet()); + bsFuture = new CompletableFuture(); + bsFuture.complete(new BindingSet()); } return bsFuture; } @@ -522,17 +473,13 @@ public KnowledgeInteractionInfo getKnowledgeInteractionInfo() { } @Override - public CompletableFuture handle( - eu.knowledge.engine.reasoner.api.BindingSet bs) { - - CompletableFuture bsFuture; + public CompletableFuture handle(BindingSet bs) { - BindingSet newBS = translateBindingSetFrom(bs); + CompletableFuture bsFuture; PostMessage postMessage = new PostMessage( ReasonerProcessor.this.myKnowledgeInteraction.getKnowledgeBaseId(), - ReasonerProcessor.this.myKnowledgeInteraction.getId(), kii.getKnowledgeBaseId(), kii.getId(), - newBS); + ReasonerProcessor.this.myKnowledgeInteraction.getId(), kii.getKnowledgeBaseId(), kii.getId(), bs); try { CompletableFuture sendPostMessage = ReasonerProcessor.this.messageRouter @@ -553,10 +500,10 @@ public CompletableFuture handle( assert reactMessage != null; BindingSet resultBindingSet = reactMessage.getResult(); - ReasonerProcessor.this.postExchangeInfos.add( - convertMessageToExchangeInfo(newBS, reactMessage.getResult(), reactMessage, aPreviousSend)); + ReasonerProcessor.this.postExchangeInfos + .add(convertMessageToExchangeInfo(bs, resultBindingSet, reactMessage, aPreviousSend)); - return translateBindingSetTo(resultBindingSet); + return resultBindingSet; }); } catch (IOException e) { @@ -566,8 +513,8 @@ public CompletableFuture handle( ReasonerProcessor.this.myKnowledgeInteraction.getKnowledgeBaseId(), this.kii.getKnowledgeBaseId()); LOG.trace("Detailed error information.", e); - bsFuture = new CompletableFuture(); - bsFuture.complete(new eu.knowledge.engine.reasoner.api.BindingSet()); + bsFuture = new CompletableFuture(); + bsFuture.complete(new BindingSet()); } return bsFuture; } @@ -593,16 +540,13 @@ public KnowledgeInteractionInfo getKnowledgeInteractionInfo() { } @Override - public CompletableFuture handle(eu.knowledge.engine.reasoner.api.BindingSet bs) { + public CompletableFuture handle(BindingSet bs) { CompletableFuture bsFuture; - BindingSet newBS = translateBindingSetFrom(bs); - PostMessage postMessage = new PostMessage( ReasonerProcessor.this.myKnowledgeInteraction.getKnowledgeBaseId(), - ReasonerProcessor.this.myKnowledgeInteraction.getId(), kii.getKnowledgeBaseId(), kii.getId(), - newBS); + ReasonerProcessor.this.myKnowledgeInteraction.getId(), kii.getKnowledgeBaseId(), kii.getId(), bs); try { CompletableFuture sendPostMessage = ReasonerProcessor.this.messageRouter @@ -622,7 +566,7 @@ public CompletableFuture handle(eu.knowledge.engine.reasoner.api.BindingSe }).thenApply((reactMessage) -> { assert reactMessage != null; ReasonerProcessor.this.postExchangeInfos.add( - convertMessageToExchangeInfo(newBS, reactMessage.getResult(), reactMessage, aPreviousSend)); + convertMessageToExchangeInfo(bs, reactMessage.getResult(), reactMessage, aPreviousSend)); return (Void) null; }); diff --git a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/SingleInteractionProcessor.java b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/SingleInteractionProcessor.java index 5a50d190..89ec4b90 100644 --- a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/SingleInteractionProcessor.java +++ b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/SingleInteractionProcessor.java @@ -4,7 +4,7 @@ import java.util.concurrent.CompletableFuture; import eu.knowledge.engine.smartconnector.api.AskResult; -import eu.knowledge.engine.smartconnector.api.BindingSet; +import eu.knowledge.engine.reasoner.api.BindingSet; import eu.knowledge.engine.smartconnector.api.GraphPattern; import eu.knowledge.engine.smartconnector.api.KnowledgeInteraction; import eu.knowledge.engine.smartconnector.api.PostResult; diff --git a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/Util.java b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/Util.java index 19932b21..246fa7ce 100644 --- a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/Util.java +++ b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/Util.java @@ -4,62 +4,31 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Set; -import javax.cache.Cache; -import javax.cache.CacheManager; -import javax.cache.Caching; -import javax.cache.configuration.Configuration; -import javax.cache.spi.CachingProvider; - import org.apache.jena.graph.Node; import org.apache.jena.graph.Triple; import org.apache.jena.rdf.model.Model; import org.apache.jena.rdf.model.ModelFactory; import org.apache.jena.sparql.core.TriplePath; +import org.apache.jena.sparql.core.Var; import org.apache.jena.sparql.graph.PrefixMappingZero; import org.apache.jena.sparql.lang.arq.javacc.ParseException; -import org.apache.jena.sparql.sse.SSE; +import org.apache.jena.sparql.serializer.SerializationContext; import org.apache.jena.sparql.syntax.ElementPathBlock; import org.apache.jena.sparql.util.FmtUtils; -import org.eclipse.microprofile.config.Config; -import org.eclipse.microprofile.config.ConfigProvider; -import org.ehcache.config.builders.CacheConfigurationBuilder; -import org.ehcache.config.builders.ExpiryPolicyBuilder; -import org.ehcache.config.builders.ResourcePoolsBuilder; -import org.ehcache.jsr107.Eh107Configuration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import eu.knowledge.engine.reasoner.api.Binding; +import eu.knowledge.engine.reasoner.api.BindingSet; import eu.knowledge.engine.reasoner.api.TriplePattern; -import eu.knowledge.engine.smartconnector.api.Binding; -import eu.knowledge.engine.smartconnector.api.BindingSet; import eu.knowledge.engine.smartconnector.api.GraphPattern; -import eu.knowledge.engine.smartconnector.api.SmartConnectorConfig; public class Util { private static final Logger LOG = LoggerFactory.getLogger(Util.class); - static { - CachingProvider cachingProvider = Caching.getCachingProvider(); - CacheManager cacheManager = cachingProvider.getCacheManager(); - - long cacheSize = Long.parseLong( - ConfigProvider.getConfig().getConfigValue(SmartConnectorConfig.CONF_KEY_KE_CACHE_NODE_SIZE).getValue()); - - long timeInMinutes = Long.parseLong(ConfigProvider.getConfig() - .getConfigValue(SmartConnectorConfig.CONF_KEY_KE_CACHE_NODE_EXPIRYMINUTES).getValue()); - - CacheConfigurationBuilder ehConfig = CacheConfigurationBuilder - .newCacheConfigurationBuilder(String.class, Node.class, ResourcePoolsBuilder.heap(cacheSize)) - .withExpiry(ExpiryPolicyBuilder.timeToIdleExpiration(java.time.Duration.ofMinutes(timeInMinutes))); - - Configuration config = Eh107Configuration.fromEhcacheCacheConfiguration(ehConfig); - nodeCache = cacheManager.createCache("nodeCache", config); - } - - private static Cache nodeCache; - /** * Convert a KnowledgeIO and a Set of bindings into a RDF model with actual * triples. @@ -90,20 +59,10 @@ public static Model generateModel(GraphPattern graphPattern, BindingSet variable Node n = oldNodes[i]; Node newN = n; if (n.isVariable()) { - - String repr; - if (b.containsKey(n.getName())) { - repr = b.get(n.getName()); - - LOG.trace("Parsing: {}", repr); - - if ((newN = nodeCache.get(repr)) == null) { - newN = SSE.parseNode(repr); - nodeCache.put(repr, newN); - } - + if (b.containsKey(n)) { + newN = b.get(n); } else { - LOG.error("The variable {} in the Knowledge should be bound.", n.getName()); + LOG.error("The variable '{}' in the Knowledge should be bound.", n.getName()); } } newNodes[i] = newN; @@ -153,4 +112,52 @@ public static void removeRedundantBindingsAnswer(BindingSet incoming, BindingSet outgoing.removeAll(toBeRemoved); } + /** + * Translate bindingset from the internal KE/reasoner bindingsets to the API + * bindingset. + * + * @param bs a reasoner bindingset + * @return a ke bindingset + */ + public static eu.knowledge.engine.smartconnector.api.BindingSet translateToApiBindingSet(BindingSet bs) { + eu.knowledge.engine.smartconnector.api.BindingSet newBS = new eu.knowledge.engine.smartconnector.api.BindingSet(); + eu.knowledge.engine.smartconnector.api.Binding newB; + + SerializationContext context = new SerializationContext(); + context.setUsePlainLiterals(false); + + for (Binding b : bs) { + newB = new eu.knowledge.engine.smartconnector.api.Binding(); + for (Map.Entry entry : b.entrySet()) { + newB.put(entry.getKey().getName(), FmtUtils.stringForNode(entry.getValue(), context)); + } + newBS.add(newB); + } + return newBS; + } + + /** + * Translate bindingset from the API bindingset to the internal KE/reasoner + * bindingset. + * + * @param someBindings a ke bindingset + * @return a reasoner bindingset + */ + public static BindingSet translateFromApiBindingSet( + eu.knowledge.engine.smartconnector.api.BindingSet someBindings) { + + BindingSet newBindingSet = new BindingSet(); + Binding newBinding; + for (eu.knowledge.engine.smartconnector.api.Binding b : someBindings) { + + newBinding = new Binding(); + for (String var : b.getVariables()) { + newBinding.put(var, b.get(var)); + } + newBindingSet.add(newBinding); + } + + return newBindingSet; + } + } diff --git a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/messaging/AnswerMessage.java b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/messaging/AnswerMessage.java index 43067eb7..8c05cf36 100644 --- a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/messaging/AnswerMessage.java +++ b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/messaging/AnswerMessage.java @@ -3,7 +3,7 @@ import java.net.URI; import java.util.UUID; -import eu.knowledge.engine.smartconnector.api.BindingSet; +import eu.knowledge.engine.reasoner.api.BindingSet; public class AnswerMessage extends KnowledgeMessage { diff --git a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/messaging/AskMessage.java b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/messaging/AskMessage.java index 9974021b..70459111 100644 --- a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/messaging/AskMessage.java +++ b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/messaging/AskMessage.java @@ -3,7 +3,7 @@ import java.net.URI; import java.util.UUID; -import eu.knowledge.engine.smartconnector.api.BindingSet; +import eu.knowledge.engine.reasoner.api.BindingSet; public class AskMessage extends KnowledgeMessage { diff --git a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/messaging/PostMessage.java b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/messaging/PostMessage.java index d76e36f1..3b8fb923 100644 --- a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/messaging/PostMessage.java +++ b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/messaging/PostMessage.java @@ -3,7 +3,7 @@ import java.net.URI; import java.util.UUID; -import eu.knowledge.engine.smartconnector.api.BindingSet; +import eu.knowledge.engine.reasoner.api.BindingSet; public class PostMessage extends KnowledgeMessage { diff --git a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/messaging/ReactMessage.java b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/messaging/ReactMessage.java index edde9b50..d85e4885 100644 --- a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/messaging/ReactMessage.java +++ b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/messaging/ReactMessage.java @@ -3,7 +3,7 @@ import java.net.URI; import java.util.UUID; -import eu.knowledge.engine.smartconnector.api.BindingSet; +import eu.knowledge.engine.reasoner.api.BindingSet; public class ReactMessage extends KnowledgeMessage { diff --git a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/runtime/messaging/MessageConverter.java b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/runtime/messaging/MessageConverter.java index aedc3f63..8e640d0f 100644 --- a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/runtime/messaging/MessageConverter.java +++ b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/runtime/messaging/MessageConverter.java @@ -9,8 +9,13 @@ import java.util.Map.Entry; import java.util.UUID; -import eu.knowledge.engine.smartconnector.api.Binding; -import eu.knowledge.engine.smartconnector.api.BindingSet; +import org.apache.jena.shared.PrefixMapping; +import org.apache.jena.sparql.core.Var; +import org.apache.jena.sparql.graph.PrefixMappingZero; +import org.apache.jena.sparql.util.FmtUtils; + +import eu.knowledge.engine.reasoner.api.Binding; +import eu.knowledge.engine.reasoner.api.BindingSet; import eu.knowledge.engine.smartconnector.messaging.AnswerMessage; import eu.knowledge.engine.smartconnector.messaging.AskMessage; import eu.knowledge.engine.smartconnector.messaging.ErrorMessage; @@ -53,7 +58,8 @@ public static AnswerMessage fromJson( return new AnswerMessage(UUID.fromString(msg.getMessageId()), new URI(msg.getFromKnowledgeBase()), new URI(msg.getFromKnowledgeInteraction()), new URI(msg.getToKnowledgeBase()), new URI(msg.getToKnowledgeInteraction()), UUID.fromString(msg.getReplyToAskMessage()), - fromJson(msg.getBindingSet()), msg.getFailedMessage()); // TODO: Remove failedMessage when using ErrorMessage + fromJson(msg.getBindingSet()), msg.getFailedMessage()); // TODO: Remove failedMessage when using + // ErrorMessage } public static eu.knowledge.engine.smartconnector.runtime.messaging.inter_ker.model.AnswerMessage toJson( @@ -99,7 +105,8 @@ public static ReactMessage fromJson( return new ReactMessage(UUID.fromString(msg.getMessageId()), new URI(msg.getFromKnowledgeBase()), new URI(msg.getFromKnowledgeInteraction()), new URI(msg.getToKnowledgeBase()), new URI(msg.getToKnowledgeInteraction()), UUID.fromString(msg.getReplyToPostMessage()), - fromJson(msg.getResult()), msg.getFailedMessage()); // TODO: Remove failedMessage when using ErrorMessage + fromJson(msg.getResult()), msg.getFailedMessage()); // TODO: Remove failedMessage when using + // ErrorMessage } public static eu.knowledge.engine.smartconnector.runtime.messaging.inter_ker.model.ReactMessage toJson( @@ -169,10 +176,11 @@ private static BindingSet fromJson(List> input) { private static List> toJson(BindingSet bindingSet) { var result = new ArrayList>(); + PrefixMapping prefixMap = new PrefixMappingZero(); for (Binding binding : bindingSet) { HashMap map = new HashMap(); - for (String key : binding.getVariables()) { - map.put(key, binding.get(key)); + for (Var key : binding.keySet()) { + map.put(key.getName(), FmtUtils.stringForNode(binding.get(key), prefixMap)); } result.add(map); } diff --git a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/util/KnowledgeBaseImpl.java b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/util/KnowledgeBaseImpl.java index 3082af34..44eb8dbf 100644 --- a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/util/KnowledgeBaseImpl.java +++ b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/util/KnowledgeBaseImpl.java @@ -292,7 +292,8 @@ public boolean isUpToDate(AskKnowledgeInteraction askKnowledgeInteraction, LOG.trace("before ask metadata"); AskResult result = this.getSC().ask(askKnowledgeInteraction, new BindingSet()).get(); LOG.trace("after ask metadata"); - Model m = Util.generateModel(askKnowledgeInteraction.getPattern(), result.getBindings()); + Model m = Util.generateModel(askKnowledgeInteraction.getPattern(), + Util.translateFromApiBindingSet(result.getBindings())); // System.out.println("----------" + this.getKnowledgeBaseName() + "-------------"); // m.write(System.out, "turtle"); diff --git a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestAskAnswerDatatype.java b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestAskAnswerDatatype.java new file mode 100644 index 00000000..91e650a4 --- /dev/null +++ b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestAskAnswerDatatype.java @@ -0,0 +1,74 @@ +package eu.knowledge.engine.smartconnector.api; + +import java.util.concurrent.ExecutionException; + +import org.apache.jena.shared.PrefixMapping; +import org.apache.jena.sparql.graph.PrefixMappingMem; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import eu.knowledge.engine.smartconnector.util.KnowledgeBaseImpl; +import eu.knowledge.engine.smartconnector.util.KnowledgeNetwork; + +class TestAskAnswerDatatype { + + private static final Logger LOG = LoggerFactory.getLogger(TestAskAnswerDatatype.class); + + @Test + void test() throws InterruptedException, ExecutionException { + + System.setProperty("ke.kb.wait.timeout", "0"); + + KnowledgeNetwork kn = new KnowledgeNetwork(); + + KnowledgeBaseImpl kb1 = new KnowledgeBaseImpl("kb1"); + kn.addKB(kb1); + KnowledgeBaseImpl kb2 = new KnowledgeBaseImpl("kb2"); + kn.addKB(kb2); + + PrefixMapping pm = new PrefixMappingMem(); + pm.setNsPrefix("ex", "https://www.example.com/"); + + GraphPattern gp = new GraphPattern(pm, + "?input ex:hasValue ?value . ?input ex:hasTestValue ?testValue . ?input ex:hasReverseResult ?reverseResult ."); + AskKnowledgeInteraction askKI = new AskKnowledgeInteraction(new CommunicativeAct(), gp); + kb1.register(askKI); + + AnswerKnowledgeInteraction answerKI = new AnswerKnowledgeInteraction(new CommunicativeAct(), gp); + kb2.register(answerKI, (aKI, exchangeInfo) -> { + + BindingSet incomingBS = exchangeInfo.getIncomingBindings(); + + LOG.info("Incoming bs: {}", incomingBS); + + BindingSet bs = new BindingSet(); + + Binding b1 = new Binding(); + b1.put("value", "\"My string value\"^^"); + b1.put("testValue", "\"7\"^^"); + b1.put("input", ""); + b1.put("reverseResult", "\"eulav gnirts yM\"^^"); + bs.add(b1); + return bs; + }); + + kn.sync(); + + BindingSet bs = new BindingSet(); + Binding b1 = new Binding(); + b1.put("value", "\"My string value\"^^"); + b1.put("testValue", "\"7\"^^"); + bs.add(b1); + + AskResult askResult = kb1.ask(askKI, bs).get(); + + LOG.info("AskResult: {}", askResult); + + assert askResult.getBindings().size() > 0 : "There should be bindings returned."; + + kn.stop().get(); + + } + +} diff --git a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestBindingValidation.java b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestBindingValidation.java index 6409c030..b6b7c493 100644 --- a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestBindingValidation.java +++ b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestBindingValidation.java @@ -4,45 +4,10 @@ import org.junit.jupiter.api.Test; -public class TestBindingValidation { - - @Test - void testBindingNormalIri() { - var b = new BindingValidator(); - b.validateValidBindingValue(""); - } - - @Test - void testBindingPrefixedIri() { - assertThrows(IllegalArgumentException.class, () -> { - var b = new BindingValidator(); - b.validateValidBindingValue("rdf:type"); - }); - } - - @Test - void testBindingTwoIrisSeparatedWithSemicolon() { - assertThrows(IllegalArgumentException.class, () -> { - var b = new BindingValidator(); - b.validateValidBindingValue(";"); - }); - } - - @Test - void testBindingTwoIrisSeparatedWithComma() { - assertThrows(IllegalArgumentException.class, () -> { - var b = new BindingValidator(); - b.validateValidBindingValue(","); - }); - } +import eu.knowledge.engine.reasoner.api.Binding; +import eu.knowledge.engine.reasoner.api.BindingSet; - @Test - void testBindingTwoIrisSeparatedWithDot() { - assertThrows(IllegalArgumentException.class, () -> { - var b = new BindingValidator(); - b.validateValidBindingValue("."); - }); - } +public class TestBindingValidation { @Test void testIncomingOutgoingAnswerValid1() { diff --git a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestComplexGraphPatternMatching.java b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestComplexGraphPatternMatching.java index d7b14ced..2dc7c98c 100644 --- a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestComplexGraphPatternMatching.java +++ b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestComplexGraphPatternMatching.java @@ -342,7 +342,9 @@ private void createDevicesKB(PrefixMappingMem prefixes, KnowledgeNetwork kn) { binding.put("propH", ""); bindingSet.add(binding); - Util.removeRedundantBindingsAnswer(anAnswerExchangeInfo.getIncomingBindings(), bindingSet); + Util.removeRedundantBindingsAnswer( + Util.translateFromApiBindingSet(anAnswerExchangeInfo.getIncomingBindings()), + Util.translateFromApiBindingSet(bindingSet)); return bindingSet; }); @@ -374,7 +376,9 @@ private void createDevicesKB(PrefixMappingMem prefixes, KnowledgeNetwork kn) { binding.put("y", ""); bindingSet.add(binding); - Util.removeRedundantBindingsAnswer(anAnswerExchangeInfo.getIncomingBindings(), bindingSet); + Util.removeRedundantBindingsAnswer( + Util.translateFromApiBindingSet(anAnswerExchangeInfo.getIncomingBindings()), + Util.translateFromApiBindingSet(bindingSet)); return bindingSet; }); @@ -418,7 +422,9 @@ private void createObservationsKB(PrefixMappingMem prefixes, KnowledgeNetwork kn binding.put("val", "\"69.0\"^^"); binding.put("prop", ""); bindingSet.add(binding); - Util.removeRedundantBindingsAnswer(anAnswerExchangeInfo.getIncomingBindings(), bindingSet); + Util.removeRedundantBindingsAnswer( + Util.translateFromApiBindingSet(anAnswerExchangeInfo.getIncomingBindings()), + Util.translateFromApiBindingSet(bindingSet)); return bindingSet; }); } diff --git a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestReactMetadata.java b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestReactMetadata.java index 826e3e46..044ab9e2 100644 --- a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestReactMetadata.java +++ b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestReactMetadata.java @@ -67,7 +67,7 @@ public BindingSet react(ReactKnowledgeInteraction anRKI, ReactExchangeInfo aReac var argument = aReactExchangeInfo.getArgumentBindings(); Model m; try { - m = Util.generateModel(anRKI.getArgument(), argument); + m = Util.generateModel(anRKI.getArgument(), Util.translateFromApiBindingSet(argument)); m.setNsPrefixes(prefixes); var kbIter = m.listStatements(null, RDF.type, m.getResource(m.expandPrefix("kb:KnowledgeBase"))); diff --git a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestRequestMetadata.java b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestRequestMetadata.java index 5814dd1a..5253fa6f 100644 --- a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestRequestMetadata.java +++ b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestRequestMetadata.java @@ -66,7 +66,7 @@ public void testRequestMetadata() throws InterruptedException, ExecutionExceptio LOG.info("Bindings: {}", result.getBindings()); - Model m = Util.generateModel(aKI.getPattern(), result.getBindings()); + Model m = Util.generateModel(aKI.getPattern(), Util.translateFromApiBindingSet(result.getBindings())); List i = m .listSubjectsWithProperty(RDF.type, diff --git a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/impl/InteractionProcessorImplTest.java b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/impl/InteractionProcessorImplTest.java index 7196a8d3..de70bd11 100644 --- a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/impl/InteractionProcessorImplTest.java +++ b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/impl/InteractionProcessorImplTest.java @@ -233,7 +233,7 @@ public CompletableFuture sendAskMessage(AskMessage askMessage) th try { msg = new AnswerMessage(askMessage.getToKnowledgeBase(), askMessage.getToKnowledgeInteraction(), InteractionProcessorImplTest.this.knowledgeBaseId1, new URI("https://www.tno.nl/ki1"), - askMessage.getMessageId(), bindings); + askMessage.getMessageId(), Util.translateFromApiBindingSet(bindings)); future.complete(msg); } catch (URISyntaxException e) { fail("No exception should occur.", e); diff --git a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/impl/TestBindingSetConversions.java b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/impl/TestBindingSetConversions.java index 4ef09a7c..a24e39fb 100644 --- a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/impl/TestBindingSetConversions.java +++ b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/impl/TestBindingSetConversions.java @@ -1,9 +1,7 @@ package eu.knowledge.engine.smartconnector.impl; import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.util.HashSet; -import java.util.Set; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.apache.jena.datatypes.xsd.XSDDatatype; import org.apache.jena.graph.Node; @@ -11,14 +9,11 @@ import org.apache.jena.sparql.core.Var; import org.junit.jupiter.api.Test; -import eu.knowledge.engine.reasoner.Rule; import eu.knowledge.engine.smartconnector.api.Binding; import eu.knowledge.engine.smartconnector.api.BindingSet; class TestBindingSetConversions { - private OpenReasonerProcessor rp = new OpenReasonerProcessor(new HashSet<>(), null, new HashSet<>()); - /** * Test whether converting typed literals between reasoner and knowledge engine * binding sets works correctly. @@ -35,33 +30,42 @@ void testTypedLiteral() { Binding b = new Binding(); b.put(varStringVersion, literalStringVersion); bs.add(b); - eu.knowledge.engine.reasoner.api.BindingSet reasonerBS = rp.testerTo(bs); + eu.knowledge.engine.reasoner.api.BindingSet reasonerBS = Util.translateFromApiBindingSet(bs); assertEquals(literalNodeVersion, reasonerBS.iterator().next().get(varStringVersion)); eu.knowledge.engine.reasoner.api.BindingSet bsR = new eu.knowledge.engine.reasoner.api.BindingSet(); eu.knowledge.engine.reasoner.api.Binding bR = new eu.knowledge.engine.reasoner.api.Binding(); bR.put(varNodeVersion, (Node) literalNodeVersion); bsR.add(bR); - BindingSet otherBS = rp.testerFrom(bsR); + BindingSet otherBS = Util.translateToApiBindingSet(bsR); assertEquals(literalStringVersion, otherBS.iterator().next().get(varStringVersion)); } /** - * Make some binding set translation methods available. + * Test whether converting typed literals between reasoner and knowledge engine + * binding sets works correctly. */ - public static class OpenReasonerProcessor extends ReasonerProcessor { - public OpenReasonerProcessor(Set knowledgeInteractions, MessageRouter messageRouter, - Set someDomainKnowledge) { - super(knowledgeInteractions, messageRouter, someDomainKnowledge); - } + @Test + void testTypedLiteralString() { - public eu.knowledge.engine.reasoner.api.BindingSet testerTo(BindingSet bs) { - return this.translateBindingSetTo(bs); - } + String varStringVersion = "a"; + Var varNodeVersion = Var.alloc(varStringVersion); + Node literalNodeVersion = NodeFactory.createLiteral("bla", XSDDatatype.XSDstring); + var literalStringVersion = "\"bla\"^^"; + var literalSimpleStringVersion = "\"bla\""; - public BindingSet testerFrom(eu.knowledge.engine.reasoner.api.BindingSet bs) { - return this.translateBindingSetFrom(bs); - } - } + BindingSet bs = new BindingSet(); + Binding b = new Binding(); + b.put(varStringVersion, literalStringVersion); + bs.add(b); + eu.knowledge.engine.reasoner.api.BindingSet reasonerBS = Util.translateFromApiBindingSet(bs); + assertTrue(literalNodeVersion.sameValueAs(reasonerBS.iterator().next().get(varStringVersion))); + eu.knowledge.engine.reasoner.api.BindingSet bsR = new eu.knowledge.engine.reasoner.api.BindingSet(); + eu.knowledge.engine.reasoner.api.Binding bR = new eu.knowledge.engine.reasoner.api.Binding(); + bR.put(varNodeVersion, (Node) literalNodeVersion); + bsR.add(bR); + BindingSet otherBS = Util.translateToApiBindingSet(bsR); + assertEquals(literalSimpleStringVersion, otherBS.iterator().next().get(varStringVersion)); + } } diff --git a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/misc/ConfigurationTest.java b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/misc/ConfigurationTest.java index f4558c67..b58086fe 100644 --- a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/misc/ConfigurationTest.java +++ b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/misc/ConfigurationTest.java @@ -50,6 +50,7 @@ public void beforeTest() { @Test public void testConfigValidateTrue() { + LOG.info("Test: testConfigValidateTrue"); System.setProperty(SmartConnectorConfig.CONF_KEY_VALIDATE_OUTGOING_BINDINGS_WRT_INCOMING_BINDINGS, "true"); BindingSet bs = new BindingSet(); @@ -79,6 +80,7 @@ public void testConfigValidateTrue() { @Test public void testConfigValidateFalse() { + LOG.info("Test: testConfigValidateFalse"); System.setProperty(SmartConnectorConfig.CONF_KEY_VALIDATE_OUTGOING_BINDINGS_WRT_INCOMING_BINDINGS, "false"); BindingSet bs = new BindingSet(); @@ -108,6 +110,7 @@ public void testConfigValidateFalse() { @Test public void testConfigWaitForKnowledgeBaseNegative() { + LOG.info("Test: testConfigWaitForKnowledgeBaseNegative"); System.setProperty(SmartConnectorConfig.CONF_KEY_KE_KB_WAIT_TIMEOUT, "1"); waitTimeout = 2000; @@ -140,6 +143,7 @@ public void testConfigWaitForKnowledgeBaseNegative() { @Test public void testConfigWaitForKnowledgeBasePositive() { + LOG.info("Test: testConfigWaitForKnowledgeBasePositive"); System.setProperty(SmartConnectorConfig.CONF_KEY_KE_KB_WAIT_TIMEOUT, "2"); waitTimeout = 0; BindingSet bs = new BindingSet(); @@ -169,6 +173,7 @@ public void testConfigWaitForKnowledgeBasePositive() { @Test public void testConfigReasonerLevelOutOfRange() { + LOG.info("Test: testConfigReasonerLevelOutOfRange"); var kb = new KnowledgeBaseImpl("kb11"); this.kn.addKB(kb); kb.setReasonerLevel(0); diff --git a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/runtime/messaging/DistributedMessageDispatcherTest.java b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/runtime/messaging/DistributedMessageDispatcherTest.java index 3e7265aa..b74764d9 100644 --- a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/runtime/messaging/DistributedMessageDispatcherTest.java +++ b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/runtime/messaging/DistributedMessageDispatcherTest.java @@ -9,8 +9,8 @@ import org.junit.jupiter.api.Test; import eu.knowledge.engine.knowledgedirectory.KnowledgeDirectory; -import eu.knowledge.engine.smartconnector.api.Binding; -import eu.knowledge.engine.smartconnector.api.BindingSet; +import eu.knowledge.engine.reasoner.api.Binding; +import eu.knowledge.engine.reasoner.api.BindingSet; import eu.knowledge.engine.smartconnector.messaging.AnswerMessage; import eu.knowledge.engine.smartconnector.messaging.AskMessage; import eu.knowledge.engine.smartconnector.messaging.KnowledgeMessage;