diff --git a/reasoner/src/main/java/eu/knowledge/engine/reasoner/BaseRule.java b/reasoner/src/main/java/eu/knowledge/engine/reasoner/BaseRule.java index d3108c421..07bec683d 100644 --- a/reasoner/src/main/java/eu/knowledge/engine/reasoner/BaseRule.java +++ b/reasoner/src/main/java/eu/knowledge/engine/reasoner/BaseRule.java @@ -13,8 +13,10 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; import org.apache.jena.sparql.core.Var; import org.slf4j.Logger; @@ -34,6 +36,11 @@ public class BaseRule { public static final String ARROW = "->"; + /** + * Precalculated hashcode to improve performance of the matching algorithm. + */ + private int hashCodeValue; + /** * A comparator to make sure the smaller matches collection is ordered from big * to small. @@ -147,6 +154,7 @@ protected BaseRule(Set anAntecedent, Set aConseque this.antecedent = anAntecedent; this.consequent = aConsequent; + this.hashCodeValue = this.calcHashCode(); } public static Set getVars(Set aPattern) { @@ -287,8 +295,7 @@ public String getName() { return name; } - @Override - public int hashCode() { + private int calcHashCode() { final int prime = 31; int result = 1; result = prime * result + ((antecedent == null) ? 0 : antecedent.hashCode()); @@ -297,6 +304,11 @@ public int hashCode() { return result; } + @Override + public int hashCode() { + return this.hashCodeValue; + } + @Override public boolean equals(Object obj) { if (this == obj) @@ -393,13 +405,14 @@ public static Map> getMatches(BaseRule aTargetRule, Set> combiMatchesPerTriple = getMatchesPerTriplePerRule(targetGP, new ArrayList<>(someCandidateRules), antecedentOfTarget); - printCombiMatchesPerTriple(combiMatchesPerTriple); - // if not every triple pattern can be matched, we stop the process if we require // a full match. - if (config.contains(MatchFlag.FULLY_COVERED) && combiMatchesPerTriple.keySet().size() < targetGP.size()) + if (targetGP.isEmpty() || (config.contains(MatchFlag.FULLY_COVERED) + && combiMatchesPerTriple.keySet().size() < targetGP.size())) return new HashMap<>(); + printCombiMatchesPerTriple(aTargetRule, combiMatchesPerTriple); + List biggestMatches = new ArrayList<>(); List smallerMatches = new ArrayList<>(); List toBeAddedToBiggestMatches = null, toBeAddedToSmallerMatches = null; @@ -453,31 +466,36 @@ public static Map> getMatches(BaseRule aTargetRule, Set { + return mergeCombiMatches(candidateCombiMatch, aSmallerMatch, config); + }).filter(Objects::nonNull).sorted(new CombiMatchSizeComparator()).collect(Collectors.toList()); + + // determine where to add new combi matches + for (CombiMatch newCombiMatch : newCombiMatches) { + + // merge successful, add to smaller matches + if (candidateWasMerged) { + if (isSubCombiMatch(newCombiMatch, toBeAddedToBiggestMatches)) { + toBeAddedToSmallerMatches.add(newCombiMatch); } else { - // add to biggest matches - candidateWasMerged = true; toBeAddedToBiggestMatches.add(newCombiMatch); + candidateWasMerged = true; } - + } else { + // add to biggest matches + candidateWasMerged = true; + toBeAddedToBiggestMatches.add(newCombiMatch); } } } - if (!candidateWasMerged && !config.contains(MatchFlag.FULLY_COVERED)) - toBeAddedToBiggestMatches.add(candidateCombiMatch); - else - toBeAddedToSmallerMatches.add(candidateCombiMatch); + if (!config.contains(MatchFlag.FULLY_COVERED)) { + if (!candidateWasMerged) + toBeAddedToBiggestMatches.add(candidateCombiMatch); + else + toBeAddedToSmallerMatches.add(candidateCombiMatch); + } } // update collections @@ -494,8 +512,6 @@ public static Map> getMatches(BaseRule aTargetRule, Set> combiMatchesPerTriple) { + private static void printCombiMatchesPerTriple(BaseRule aTargetRule, + Map> combiMatchesPerTriple) { StringBuilder sb = new StringBuilder(); int total = 1; @@ -547,7 +564,7 @@ private static void printCombiMatchesPerTriple(Map> antecedentNeighbors = this.store.getAntecedentNeighbors(aRule, this.matchConfig); + if (aParent != null && antecedentNeighbors.containsKey(aParent)) { ourAntecedentFullyMatchesParentConsequent = antecedentFullyMatchesConsequent(aRule, aParent, - this.store.getAntecedentNeighbors(aRule, this.matchConfig).get(aParent)); + antecedentNeighbors.get(aParent)); } if (!ourAntecedentFullyMatchesParentConsequent) { - this.store.getAntecedentNeighbors(aRule, this.matchConfig).forEach((rule, matches) -> { + antecedentNeighbors.forEach((rule, matches) -> { if (!(rule instanceof ProactiveRule)) { assert reasonerNode instanceof AntSide; var newNode = createOrGetReasonerNode(rule, aRule); @@ -357,4 +358,9 @@ public RuleStore getStore() { return this.store; } + @Override + public String toString() { + return "ReasonerPlan [link=" + this.store.getGraphVizCode(this, true) + "]"; + } + } diff --git a/reasoner/src/main/java/eu/knowledge/engine/reasoner/rulestore/RuleStore.java b/reasoner/src/main/java/eu/knowledge/engine/reasoner/rulestore/RuleStore.java index 319943139..123116de0 100644 --- a/reasoner/src/main/java/eu/knowledge/engine/reasoner/rulestore/RuleStore.java +++ b/reasoner/src/main/java/eu/knowledge/engine/reasoner/rulestore/RuleStore.java @@ -6,12 +6,13 @@ import java.net.URI; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; -import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -69,7 +70,7 @@ public void addRules(Set someRules) { */ public Set getRules() { - return this.ruleToRuleNode.values().stream().map(rn -> rn.getRule()).collect(Collectors.toSet()); + return this.ruleToRuleNode.keySet(); } /** @@ -155,30 +156,34 @@ public void reset() { } } + public void printGraphVizCode(ReasonerPlan aPlan) { + LOG.info(getGraphVizCode(aPlan, false)); + } + /** * Prints all the rules and the connections between them in GraphViz encoding. - * Use code in: {@link http://viz-js.com/} + * Use code in: {@link https://dreampuf.github.io/GraphvizOnline/} */ - public void printGraphVizCode(ReasonerPlan aPlan) { + public void printGraphVizCode(ReasonerPlan aPlan, boolean urlOnly) { + LOG.info(getGraphVizCode(aPlan, urlOnly)); + } + + public String getGraphVizCode(ReasonerPlan aPlan, boolean urlOnly) { String color = "red"; String width = "2"; StringBuilder sb = new StringBuilder(); - sb.append("digraph {\n"); + sb.append("strict digraph {\n"); Map ruleToName = new HashMap<>(); - int ruleNumber = 1; - for (MatchNode r : ruleToRuleNode.values()) { String currentName = ruleToName.get(r.getRule()); - boolean sourceInPlan = false, destInPlan = false; if (currentName == null) { currentName = /* "rule" + ruleNumber; */ generateName(r.getRule()); assert !currentName.isEmpty(); - ruleNumber++; String replaceAll = toStringRule(r.getRule()).replaceAll("\\\"", "\\\\\""); // check the colouring @@ -187,7 +192,6 @@ public void printGraphVizCode(ReasonerPlan aPlan) { RuleNode rn = aPlan.getRuleNodeForRule(r.getRule()); if (rn != null) { pen = "color=\"" + color + "\", penwidth=\"" + width + "\","; - sourceInPlan = true; } } @@ -201,16 +205,17 @@ public void printGraphVizCode(ReasonerPlan aPlan) { ruleToName.put(r.getRule(), currentName); } - + Map> antecedentNeighbors = r.getAntecedentNeighbors(); Set anteNeigh = antecedentNeighbors.keySet(); String neighName; + for (BaseRule neighR : anteNeigh) { neighName = ruleToName.get(neighR); + if (neighName == null) { neighName = /* "rule" + ruleNumber; */ generateName(neighR); assert !neighName.isEmpty(); - ruleNumber++; String replaceAll = toStringRule(neighR).replaceAll("\\\"", "\\\\\""); // check the colouring @@ -219,7 +224,6 @@ public void printGraphVizCode(ReasonerPlan aPlan) { RuleNode rn = aPlan.getRuleNodeForRule(neighR); if (rn != null) { pen = "color=\"" + color + "\", penwidth=\"" + width + "\","; - destInPlan = true; } } @@ -230,6 +234,7 @@ public void printGraphVizCode(ReasonerPlan aPlan) { sb.append(neighName).append("[").append(shape).append(pen).append("tooltip=").append("\"") .append(replaceAll).append("\"").append("]").append("\n"); + ruleToName.put(neighR, neighName); } @@ -251,9 +256,9 @@ public void printGraphVizCode(ReasonerPlan aPlan) { sb.append("}"); - LOG.info("Visualize on website: https://dreampuf.github.io/GraphvizOnline/#" - + URLEncoder.encode(sb.toString(), StandardCharsets.UTF_8).replaceAll("\\+", "%20") + "\n" - + sb.toString()); + return "Visualize on website: https://dreampuf.github.io/GraphvizOnline/#" + + URLEncoder.encode(sb.toString(), StandardCharsets.UTF_8).replaceAll("\\+", "%20") + + (urlOnly ? "" : "\n" + sb.toString()); } private String toStringRule(BaseRule neighR) { @@ -277,6 +282,7 @@ private String trimAtLength(String aString, int aLength) { * * @param r * @return + * @throws NoSuchAlgorithmException */ private String generateName(BaseRule r) { @@ -302,7 +308,29 @@ private String generateName(BaseRule r) { String consequent = trimAtLength(sb.toString(), MAX_STR_LENGTH); - return "\"" + Integer.toHexString(r.hashCode()) + "\\n" + antecedent + "->\\n" + consequent + "\""; + String name = r.getName(); + MessageDigest digest; + byte[] encodedhash = new byte[0]; + try { + digest = MessageDigest.getInstance("SHA-256"); + encodedhash = digest.digest(name.getBytes(StandardCharsets.UTF_8)); + } catch (NoSuchAlgorithmException e) { + LOG.error("{}", e); + } + + return "\"" + bytesToHex(encodedhash) + "\\n" + antecedent + "->\\n" + consequent + "\""; + } + + private static String bytesToHex(byte[] hash) { + StringBuilder hexString = new StringBuilder(2 * hash.length); + for (int i = 0; i < hash.length; i++) { + String hex = Integer.toHexString(0xff & hash[i]); + if (hex.length() == 1) { + hexString.append('0'); + } + hexString.append(hex); + } + return hexString.toString(); } private String generateName(TriplePattern tp) { 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 3a9e7d044..d6ca242e8 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 @@ -119,14 +119,15 @@ public AskPlan planAskFromKnowledgeBase(MyKnowledgeInteractionInfo anAKI, Recipi for (OtherKnowledgeBase otherKB : filteredOtherKnowledgeBases) { // Use the knowledge interactions from the other KB var knowledgeInteractions = otherKB.getKnowledgeInteractions().stream().filter((r) -> { - // But filter on the communicative act. These have to match! - return communicativeActMatcher(anAKI, r); - }).filter((r) -> { return anAKI.getKnowledgeInteraction().includeMetaKIs() ? true : !r.isMeta(); }); + otherKnowledgeInteractions.addAll(knowledgeInteractions.collect(Collectors.toList())); } + // But filter on the communicative act. These have to match! + filterWithCommunicativeActMatcher(anAKI, otherKnowledgeInteractions); + // create a new SingleInteractionProcessor to handle this ask. SingleInteractionProcessor processor; if (this.reasonerEnabled) { @@ -289,14 +290,14 @@ public PostPlan planPostFromKnowledgeBase(MyKnowledgeInteractionInfo aPKI, Recip for (OtherKnowledgeBase otherKB : filteredOtherKnowledgeBases) { // Use the knowledge interactions from the other KB var knowledgeInteractions = otherKB.getKnowledgeInteractions().stream().filter((r) -> { - // But filter on the communicative act. These have to match! - return communicativeActMatcher(aPKI, r); - }).filter((r) -> { return aPKI.getKnowledgeInteraction().includeMetaKIs() ? true : !r.isMeta(); }); otherKnowledgeInteractions.addAll(knowledgeInteractions.collect(Collectors.toList())); } + // But filter on the communicative act. These have to match! + filterWithCommunicativeActMatcher(aPKI, otherKnowledgeInteractions); + // create a new SingleInteractionProcessor to handle this ask. SingleInteractionProcessor processor; if (this.reasonerEnabled) { @@ -408,11 +409,11 @@ public void unsetMessageRouter() { * model. * * @param myKI - * @param otherKI - * @return {@code true} if the communicative acts of the given - * KnowledgeInteractions match, {@code false} otherwise. + * @param otherKIs The collection that will be modified by removing all + * non-matching KIs. */ - private boolean communicativeActMatcher(MyKnowledgeInteractionInfo myKI, KnowledgeInteractionInfo otherKI) { + private void filterWithCommunicativeActMatcher(MyKnowledgeInteractionInfo myKI, + Set otherKIs) { Instant start = Instant.now(); @@ -441,23 +442,25 @@ private boolean communicativeActMatcher(MyKnowledgeInteractionInfo myKI, Knowled } // then add the other knowledge interaction communicative act - CommunicativeAct otherAct = otherKI.getKnowledgeInteraction().getAct(); - Resource otherActResource = ResourceFactory.createResource(otherKI.id + "/act"); + for (KnowledgeInteractionInfo otherKI : otherKIs) { + CommunicativeAct otherAct = otherKI.getKnowledgeInteraction().getAct(); + Resource otherActResource = ResourceFactory.createResource(otherKI.id + "/act"); - m.add(otherActResource, RDF.type, Vocab.COMMUNICATIVE_ACT); + m.add(otherActResource, RDF.type, Vocab.COMMUNICATIVE_ACT); - Resource otherRequirementPurpose = ResourceFactory.createResource(otherActResource + "/requirement"); - Resource otherSatisfactionPurpose = ResourceFactory.createResource(otherActResource + "/satisfaction"); + Resource otherRequirementPurpose = ResourceFactory.createResource(otherActResource + "/requirement"); + Resource otherSatisfactionPurpose = ResourceFactory.createResource(otherActResource + "/satisfaction"); - m.add(otherActResource, Vocab.HAS_REQ, otherRequirementPurpose); - m.add(otherSatisfactionPurpose, Vocab.HAS_SAT, otherSatisfactionPurpose); + m.add(otherActResource, Vocab.HAS_REQ, otherRequirementPurpose); + m.add(otherSatisfactionPurpose, Vocab.HAS_SAT, otherSatisfactionPurpose); - // give the purposes the correct types - for (Resource r : otherAct.getRequirementPurposes()) { - m.add(otherRequirementPurpose, RDF.type, r); - } - for (Resource r : otherAct.getSatisfactionPurposes()) { - m.add(otherSatisfactionPurpose, RDF.type, r); + // give the purposes the correct types + for (Resource r : otherAct.getRequirementPurposes()) { + m.add(otherRequirementPurpose, RDF.type, r); + } + for (Resource r : otherAct.getSatisfactionPurposes()) { + m.add(otherSatisfactionPurpose, RDF.type, r); + } } // then apply the reasoner @@ -468,32 +471,42 @@ private boolean communicativeActMatcher(MyKnowledgeInteractionInfo myKI, Knowled // faster. either we set multiple iris for the same params. Or we change the ASK // to include myReq/otherReq and mySat/otherSat vars. - // my perspective - Var reqVar = Var.alloc("req"); - Var satVar = Var.alloc("sat"); - org.apache.jena.sparql.engine.binding.Binding theFirstBinding = BindingFactory.binding(reqVar, - NodeFactory.createURI(myRequirementPurpose.toString()), satVar, - NodeFactory.createURI(otherSatisfactionPurpose.toString())); + // my and other perspective + var iter = otherKIs.iterator(); + while (iter.hasNext()) { + KnowledgeInteractionInfo otherKI = iter.next(); + Resource otherActResource = ResourceFactory.createResource(otherKI.id + "/act"); + Resource otherRequirementPurpose = ResourceFactory.createResource(otherActResource + "/requirement"); + Resource otherSatisfactionPurpose = ResourceFactory.createResource(otherActResource + "/satisfaction"); - org.apache.jena.sparql.engine.binding.Binding theSecondBinding = BindingFactory.binding(reqVar, - NodeFactory.createURI(otherRequirementPurpose.toString()), satVar, - NodeFactory.createURI(mySatisfactionPurpose.toString())); + Var reqVar = Var.alloc("req"); + Var satVar = Var.alloc("sat"); + org.apache.jena.sparql.engine.binding.Binding theFirstBinding = BindingFactory.binding(reqVar, + NodeFactory.createURI(myRequirementPurpose.toString()), satVar, + NodeFactory.createURI(otherSatisfactionPurpose.toString())); - Query q = (Query) query.clone(); - ElementData de = ((ElementData) ((ElementGroup) q.getQueryPattern()).getLast()); + org.apache.jena.sparql.engine.binding.Binding theSecondBinding = BindingFactory.binding(reqVar, + NodeFactory.createURI(otherRequirementPurpose.toString()), satVar, + NodeFactory.createURI(mySatisfactionPurpose.toString())); - List data = de.getRows(); - data.add(theFirstBinding); - data.add(theSecondBinding); + Query q = (Query) query.clone(); + ElementData de = ((ElementData) ((ElementGroup) q.getQueryPattern()).getLast()); - QueryExecution myQe = QueryExecutionFactory.create(q, infModel); - boolean execAskMy = myQe.execAsk(); - myQe.close(); + List data = de.getRows(); + data.add(theFirstBinding); + data.add(theSecondBinding); - doTheyMatch = !execAskMy; - LOG.trace("Communicative Act time ({}): {}ms", doTheyMatch, Duration.between(start, Instant.now()).toMillis()); + QueryExecution myQe = QueryExecutionFactory.create(q, infModel); + boolean execAskMy = myQe.execAsk(); + myQe.close(); + + doTheyMatch = !execAskMy; - return doTheyMatch; + if (!doTheyMatch) { + iter.remove(); + } + } + LOG.trace("Communicative Act time ({}): {}ms", doTheyMatch, Duration.between(start, Instant.now()).toMillis()); } @Override diff --git a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/MessageRouterImpl.java b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/MessageRouterImpl.java index 62d7152ab..e4114a92d 100644 --- a/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/MessageRouterImpl.java +++ b/smart-connector/src/main/java/eu/knowledge/engine/smartconnector/impl/MessageRouterImpl.java @@ -8,6 +8,7 @@ import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import org.slf4j.Logger; @@ -104,6 +105,17 @@ public CompletableFuture sendAskMessage(AskMessage askMessage) th } future.whenComplete((m, e) -> { + if (m == null) + if (e != null) + if (e instanceof TimeoutException) + LOG.error("KB '{}' did not respond within {}s to AskMessage '{}'.", + askMessage.getToKnowledgeBase(), this.getWaitTimeout(), askMessage.getMessageId(), e); + else + LOG.error("A {} occurred while sending an AskMessage.", e.getClass().getSimpleName(), e); + else + LOG.error( + "The AnswerMessage future should complete either exceptionally or normally. Not with both AnswerMessage and Exception null."); + this.openAskMessages.remove(askMessage.getMessageId()); }); @@ -130,6 +142,16 @@ public CompletableFuture sendPostMessage(PostMessage postMessage) } future.whenComplete((m, e) -> { + if (m == null) + if (e != null) + if (e instanceof TimeoutException) + LOG.error("KB '{}' did not respond within {}s to PostMessage '{}'.", + postMessage.getToKnowledgeBase(), this.getWaitTimeout(), postMessage.getMessageId(), e); + else + LOG.error("A {} occurred while sending an PostMessage.", e.getClass().getSimpleName(), e); + else + LOG.error( + "The ReactMessage future should complete either exceptionally or normally. Not with both ReactMessage and Exception null."); this.openAskMessages.remove(postMessage.getMessageId()); }); @@ -210,20 +232,12 @@ public void handlePostMessage(PostMessage message) { */ @Override public void handleAnswerMessage(AnswerMessage answerMessage) { - CompletableFuture future = this.openAskMessages.remove(answerMessage.getReplyToAskMessage()); + CompletableFuture future = this.openAskMessages.get(answerMessage.getReplyToAskMessage()); if (future == null) { this.LOG.warn("I received a reply for an AskMessage with ID " + answerMessage.getReplyToAskMessage() - + ", but I don't remember sending a message with that ID"); + + ", but I don't remember sending a message with that ID. It might have taken more than {}s to respond.", + this.getWaitTimeout()); } else { - future.handle((r, e) -> { - - if (r == null) { - LOG.error("An exception has occured while handling Answer Message ", e); - return null; - } else { - return r; - } - }); LOG.debug("Received AnswerMessage: {}", answerMessage); future.complete(answerMessage); } @@ -235,22 +249,14 @@ public void handleAnswerMessage(AnswerMessage answerMessage) { */ @Override public void handleReactMessage(ReactMessage reactMessage) { - CompletableFuture future = this.openPostMessages.remove(reactMessage.getReplyToPostMessage()); + CompletableFuture future = this.openPostMessages.get(reactMessage.getReplyToPostMessage()); if (future == null) { this.LOG.warn("I received a reply for a PostMessage with ID " + reactMessage.getReplyToPostMessage() - + ", but I don't remember sending a message with that ID"); + + ", but I don't remember sending a message with that ID. It might have take more than {}s to respond.", + this.getWaitTimeout()); } else { assert reactMessage != null; assert future != null; - future.handle((r, e) -> { - - if (r == null) { - LOG.error("An exception has occured while handling React Message ", e); - return null; - } else { - return r; - } - }); LOG.debug("Received ReactMessage: {}", reactMessage); future.complete(reactMessage); } 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 f561bce40..0cf454083 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 @@ -3,7 +3,6 @@ import java.io.IOException; import java.time.Instant; import java.util.Collections; -import java.util.EnumSet; import java.util.HashSet; import java.util.Iterator; import java.util.Map; @@ -23,7 +22,6 @@ import org.slf4j.helpers.MessageFormatter; import eu.knowledge.engine.reasoner.BaseRule; -import eu.knowledge.engine.reasoner.BaseRule.MatchFlag; import eu.knowledge.engine.reasoner.ProactiveRule; import eu.knowledge.engine.reasoner.ReasonerPlan; import eu.knowledge.engine.reasoner.Rule; @@ -111,8 +109,10 @@ public ReasonerProcessor(Set knowledgeInteractions, Me if (kii.getType().equals(Type.ANSWER)) { AnswerKnowledgeInteraction aki = (AnswerKnowledgeInteraction) ki; GraphPattern gp = aki.getPattern(); - store.addRule(new Rule(ruleName, new HashSet<>(translateGraphPatternTo(gp)), - new AnswerBindingSetHandler(kii))); + Rule aRule = new Rule(ruleName, new HashSet<>(translateGraphPatternTo(gp)), + new AnswerBindingSetHandler(kii)); + store.addRule(aRule); + LOG.debug("Adding ANSWER to store: {}", aRule); } else if (kii.getType().equals(Type.REACT)) { ReactKnowledgeInteraction rki = (ReactKnowledgeInteraction) ki; GraphPattern argGp = rki.getArgument(); @@ -129,6 +129,7 @@ public ReasonerProcessor(Set knowledgeInteractions, Me } store.addRule(aRule); + LOG.debug("Adding REACT to store: {}", aRule); } } @@ -149,14 +150,14 @@ public void planAskInteraction(MyKnowledgeInteractionInfo aAKI) { ProactiveRule aRule = new ProactiveRule(ruleName, translateGraphPatternTo(aki.getPattern()), new HashSet<>()); this.store.addRule(aRule); - - EnumSet config; + MatchStrategy aStrategy; if (aAKI.getKnowledgeInteraction().getMatchStrategy() == null) - config = this.matchStrategy.toConfig(true); + aStrategy = this.matchStrategy; else - config = aAKI.getKnowledgeInteraction().getMatchStrategy().toConfig(true); + aStrategy = aki.getMatchStrategy(); - this.reasonerPlan = new ReasonerPlan(this.store, aRule, config); + LOG.debug("Creating reasoner plan with strategy: {}", aStrategy); + 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()); @@ -221,13 +222,14 @@ public void planPostInteraction(MyKnowledgeInteractionInfo aPKI) { ProactiveRule aRule = new ProactiveRule(ruleName, new HashSet<>(), new HashSet<>(translatedGraphPattern)); store.addRule(aRule); - EnumSet config; - if (aPKI.getKnowledgeInteraction().getMatchStrategy() == null) - config = this.matchStrategy.toConfig(false); + MatchStrategy aStrategy; + if (pki.getMatchStrategy() == null) + aStrategy = this.matchStrategy; else - config = aPKI.getKnowledgeInteraction().getMatchStrategy().toConfig(false); + aStrategy = pki.getMatchStrategy(); - this.reasonerPlan = new ReasonerPlan(this.store, aRule, config); + LOG.debug("Creating reasoner plan with strategy: {}", aStrategy); + this.reasonerPlan = new ReasonerPlan(this.store, aRule, aStrategy.toConfig(false)); } else { LOG.warn("Type should be Post, not {}", this.myKnowledgeInteraction.getType()); diff --git a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/runtime/messaging/TestRegisterSmartConnectorWithSameId.java b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/runtime/messaging/TestRegisterSmartConnectorWithSameId.java index 5bac8cbbe..3d5f336a7 100644 --- a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/runtime/messaging/TestRegisterSmartConnectorWithSameId.java +++ b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/runtime/messaging/TestRegisterSmartConnectorWithSameId.java @@ -4,6 +4,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import java.net.URI; +import java.util.concurrent.Phaser; import org.junit.jupiter.api.Test; import org.slf4j.Logger; @@ -14,10 +15,11 @@ public class TestRegisterSmartConnectorWithSameId { private static final Logger LOG = LoggerFactory.getLogger(TestRegisterSmartConnectorWithSameId.class); - + private Phaser readyPhaser = new Phaser(1); @Test public void testRegisterSmartConnectorWithSameIdInSameRuntimeThrows() { var kb1 = new MockedKnowledgeBase("http://example.org/kb1"); + kb1.setPhaser(this.readyPhaser); kb1.start(); var kb1AsWell = new MockedKnowledgeBase("http://example.org/kb1");