diff --git a/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/AskResult.java b/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/AskResult.java index 28e4d196..1c476659 100644 --- a/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/AskResult.java +++ b/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/AskResult.java @@ -27,10 +27,14 @@ public class AskResult { * Can be null, if the matcher is used instead of the reasoner. */ private ReasonerPlan reasonerPlan; - + private Set knowledgeGaps; - private final Set exchangeInfos; + /** + * Can contain both Post and Ask ExchangeInfo objects, because the reasoner can + * activate Post KIs while answering. + */ + private final Set exchangeInfos; /** * Create a {@link AskResult}. @@ -41,14 +45,15 @@ public class AskResult { * value for every available variable in the * {@link GraphPattern}. */ - public AskResult(BindingSet someBindings, Set askExchangeInfos, ReasonerPlan aRootNode, Set kGaps) { + public AskResult(BindingSet someBindings, Set askExchangeInfos, ReasonerPlan aRootNode, + Set kGaps) { this.bindings = someBindings; this.exchangeInfos = askExchangeInfos; this.reasonerPlan = aRootNode; this.knowledgeGaps = kGaps; } - public AskResult(BindingSet someBindings, Set askExchangeInfos) { + public AskResult(BindingSet someBindings, Set askExchangeInfos) { this(someBindings, askExchangeInfos, null, null); } @@ -60,20 +65,20 @@ public BindingSet getBindings() { return this.bindings; } - public Set getExchangeInfoPerKnowledgeBase() { + public Set getExchangeInfoPerKnowledgeBase() { return Collections.unmodifiableSet(exchangeInfos); } public Duration getTotalExchangeTime() { - Set infos = this.getExchangeInfoPerKnowledgeBase(); + Set infos = this.getExchangeInfoPerKnowledgeBase(); if (!infos.isEmpty()) { Instant start = Instant.MAX; Instant end = Instant.MIN; // find the earliest and latest instant among the exchange infos. - for (AskExchangeInfo info : infos) { + for (ExchangeInfo info : infos) { if (info.getExchangeStart().isBefore(start)) { start = info.getExchangeStart(); @@ -109,6 +114,7 @@ public Set getKnowledgeGaps() { @Override public String toString() { - return "AskResult [bindings=" + bindings + ", exchangeInfoPerKnowledgeBase=" + exchangeInfos + ", knowledgeGaps=" + knowledgeGaps + "]"; + return "AskResult [bindings=" + bindings + ", exchangeInfoPerKnowledgeBase=" + exchangeInfos + + ", knowledgeGaps=" + knowledgeGaps + "]"; } } diff --git a/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/PostResult.java b/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/PostResult.java index 00c14e63..b0d3367e 100644 --- a/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/PostResult.java +++ b/smart-connector-api/src/main/java/eu/knowledge/engine/smartconnector/api/PostResult.java @@ -21,7 +21,12 @@ public class PostResult { private static final Logger LOG = LoggerFactory.getLogger(PostResult.class); private final BindingSet bindings; - private final Set exchangeInfos; + + /** + * The exchange infos can contain Post and Ask Exchange infos, because the + * reasoner can activate Ask KIs while reacting. + */ + private final Set exchangeInfos; /** * Can be null if the matcher is used instead of the reasoner. */ @@ -36,11 +41,11 @@ public class PostResult { * value for every available variable in the * {@link GraphPattern}. */ - public PostResult(BindingSet someBindings, Set postExchangeInfos) { + public PostResult(BindingSet someBindings, Set postExchangeInfos) { this(someBindings, postExchangeInfos, null); } - public PostResult(BindingSet someBindings, Set postExchangeInfos, ReasonerPlan aNode) { + public PostResult(BindingSet someBindings, Set postExchangeInfos, ReasonerPlan aNode) { this.bindings = someBindings; this.exchangeInfos = postExchangeInfos; this.rootNode = aNode; @@ -54,20 +59,20 @@ public BindingSet getBindings() { return this.bindings; } - public Set getExchangeInfoPerKnowledgeBase() { + public Set getExchangeInfoPerKnowledgeBase() { return Collections.unmodifiableSet(exchangeInfos); } public Duration getTotalExchangeTime() { - Set infos = this.getExchangeInfoPerKnowledgeBase(); + Set infos = this.getExchangeInfoPerKnowledgeBase(); if (!infos.isEmpty()) { Instant start = Instant.MAX; Instant end = Instant.MIN; // find the earliest and latest instant among the exchange infos. - for (PostExchangeInfo info : infos) { + for (ExchangeInfo info : infos) { if (info.getExchangeStart().isBefore(start)) { start = info.getExchangeStart(); diff --git a/smart-connector-rest-dist/src/test/java/eu/knowledge/engine/rest/api/TestAskAnswerReact.java b/smart-connector-rest-dist/src/test/java/eu/knowledge/engine/rest/api/TestAskAnswerReact.java new file mode 100644 index 00000000..4e785bf1 --- /dev/null +++ b/smart-connector-rest-dist/src/test/java/eu/knowledge/engine/rest/api/TestAskAnswerReact.java @@ -0,0 +1,293 @@ +package eu.knowledge.engine.rest.api; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + +import java.io.IOException; +import java.io.StringReader; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CountDownLatch; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import eu.knowledge.engine.rest.RestServerHelper; +import eu.knowledge.engine.test_utils.AsyncTester; +import eu.knowledge.engine.test_utils.HttpTester; +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; +import jakarta.json.JsonObjectBuilder; +import jakarta.json.JsonReader; +import jakarta.json.JsonString; +import jakarta.json.JsonValue; + +/** + * In this test there will be an Ask KB with an AskKI with 2 triplepatterns, an + * AnswerKB with a single AnswerKI that answers only the first triplepattern of + * the Ask pattern, and a ReactKB that can answer the other triplepattern of the + * Ask, but needs another pattern to be satisfied. This is done by another KB + * that provides that triple. + */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public class TestAskAnswerReact { + private final RestServerHelper rsh = new RestServerHelper(); + private static int PORT = 8280; + + private static final Logger LOG = LoggerFactory.getLogger(TestAskAnswerReact.class); + + @BeforeAll + public void setUpServer() { + rsh.start(PORT); + } + + @Test + public void testAskAnswerReact() throws IOException, InterruptedException { + URL url = new URL("http://localhost:" + PORT + "/rest"); + + // sync between threads to make sure the ask is not activated before the others + // are ready. + CountDownLatch KBReady = new CountDownLatch(3); + + // activate the answer SC, KB, KI in a separate thread + var answeringSc = new AsyncTester(new Runnable() { + @Override + public void run() { + String answerKBId = "https://www.example.org/example/relationProvider"; + String answerKIId = answerKBId + "/interaction/answerRelations"; + try { + // register the AnswerKB + HttpTester registerAnswerKb = new HttpTester(new URL(url + "/sc"), "POST", + "{\"knowledgeBaseId\": \"" + answerKBId + + "\", \"knowledgeBaseName\": \"RelationProvider\", \"knowledgeBaseDescription\": \"A KB that provides relations between people\", \"reasonerLevel\" : 2}", + Map.of("Content-Type", "application/json", "Accept", "*/*")); + registerAnswerKb.expectStatus(200); + + // register the AnswerKI + HttpTester registerAnswerKi = new HttpTester(new URL(url + "/sc/ki"), "POST", """ + { + "knowledgeInteractionType": "AnswerKnowledgeInteraction", + "knowledgeInteractionName": "answerRelations", + "graphPattern": "?a ?b ." + } + """, Map.of("Knowledge-Base-Id", answerKBId, "Content-Type", "application/json", "Accept", + "*/*")); + registerAnswerKi.expectStatus(200); + + KBReady.countDown(); + + // get the handle for the answerKB to see if there are requests to be handled + var test = new HttpTester(new URL(url.toString() + "/sc/handle"), "GET", null, Map + .of("Knowledge-Base-Id", answerKBId, "Content-Type", "application/json", "Accept", "*/*")); + test.expectStatus(200); + + // build the body to answer the request: add handle request ID and dummy data + // bindingset + JsonObjectBuilder builder = Json.createObjectBuilder(); + JsonReader jp = Json.createReader(new StringReader(test.getBody())); + JsonObject jo = jp.readObject(); + int handleRequestId = jo.getInt("handleRequestId"); + builder.add("handleRequestId", handleRequestId); + JsonReader jr = Json.createReader(new StringReader( + "[{\"a\": \"\",\"b\": \"\"}]")); + JsonArray bs = jr.readArray(); + builder.add("bindingSet", bs); + JsonObject jo2 = builder.build(); + String body = jo2.toString(); + LOG.info("Handle an answer to a request with body: {}", body); + + // fire the POST handle to execute the answer + var test2 = new HttpTester(new URL(url.toString() + "/sc/handle"), "POST", body, + Map.of("Knowledge-Base-Id", answerKBId, "Knowledge-Interaction-Id", answerKIId, + "Content-Type", "application/json", "Accept", "*/*")); + test2.expectStatus(200); + + } catch (MalformedURLException e) { + fail(); + } + } + }); + answeringSc.start(); + + // activate the react SC, KB, KI in a separate thread + var reactingSc = new AsyncTester(new Runnable() { + @Override + public void run() { + String reactKBId = "https://www.example.org/example/relationReactor"; + String reactKIId = reactKBId + "/interaction/reactRelations"; + try { + // register the ReactKB + HttpTester registerReactKb = new HttpTester(new URL(url + "/sc"), "POST", + "{\"knowledgeBaseId\": \"https://www.example.org/example/relationReactor\", \"knowledgeBaseName\": \"RelationReactor\", \"knowledgeBaseDescription\": \"A KB that reacts to supply related people\", \"reasonerLevel\" : 2}", + Map.of("Content-Type", "application/json", "Accept", "*/*")); + registerReactKb.expectStatus(200); + + // register the ReactKI + HttpTester registerReactKi = new HttpTester(new URL(url + "/sc/ki"), "POST", """ + { + "knowledgeInteractionType": "ReactKnowledgeInteraction", + "knowledgeInteractionName": "reactRelations", + "argumentGraphPattern": "?a ?b .", + "resultGraphPattern": "?a ?b ." + } + """, Map.of("Knowledge-Base-Id", "https://www.example.org/example/relationReactor", + "Content-Type", "application/json", "Accept", "*/*")); + registerReactKi.expectStatus(200); + + KBReady.countDown(); + + LOG.info("Getting the handle for the reactKBId"); + // get the handle for the reactKB to see if there are requests to be handled => + // NOTE: it should never exit/return this handle for this test + var test = new HttpTester(new URL(url.toString() + "/sc/handle"), "GET", null, Map + .of("Knowledge-Base-Id", reactKBId, "Content-Type", "application/json", "Accept", "*/*")); + test.expectStatus(200); + + JsonObject jsonObject = Json.createReader(new StringReader(test.getBody())).readObject(); + JsonArray incomingBindingSet = jsonObject.getJsonArray("bindingSet"); + + // build the body to react to the request: add handle request ID and dummy data + // bindingset + JsonObjectBuilder builder = Json.createObjectBuilder(); + JsonReader jp = Json.createReader(new StringReader(test.getBody())); + JsonObject jo = jp.readObject(); + int handleRequestId = jo.getInt("handleRequestId"); + builder.add("handleRequestId", handleRequestId); + // for now simply add an empty bindingset as a result + builder.add("bindingSet", incomingBindingSet); + JsonObject jo2 = builder.build(); + String body = jo2.toString(); + LOG.info("Handle a react to a request with body: {}", body); + + // fire the POST handle to execute the react + var test2 = new HttpTester(new URL(url.toString() + "/sc/handle"), "POST", body, + Map.of("Knowledge-Base-Id", reactKBId, "Knowledge-Interaction-Id", reactKIId, + "Content-Type", "application/json", "Accept", "*/*")); + test2.expectStatus(200); + + } catch (MalformedURLException e) { + fail(); + } + } + }); + reactingSc.start(); + + // activate the answer SC, KB, KI in a separate thread + var answeringSc2 = new AsyncTester(new Runnable() { + @Override + public void run() { + String answerKBId = "https://www.example.org/example/sameHouseProvider"; + String answerKIId = answerKBId + "/interaction/sameHouse"; + try { + // register the AnswerKB + HttpTester registerAnswerKb = new HttpTester(new URL(url + "/sc"), "POST", + "{\"knowledgeBaseId\": \"" + answerKBId + + "\", \"knowledgeBaseName\": \"SomeHouseProvider\", \"knowledgeBaseDescription\": \"A KB that provides whether people live in the same house\", \"reasonerLevel\" : 2}", + Map.of("Content-Type", "application/json", "Accept", "*/*")); + registerAnswerKb.expectStatus(200); + + // register the AnswerKI + HttpTester registerAnswerKi = new HttpTester(new URL(url + "/sc/ki"), "POST", """ + { + "knowledgeInteractionType": "AnswerKnowledgeInteraction", + "knowledgeInteractionName": "sameHouse", + "graphPattern": "?a ?b ." + } + """, Map.of("Knowledge-Base-Id", answerKBId, "Content-Type", "application/json", "Accept", + "*/*")); + registerAnswerKi.expectStatus(200); + + KBReady.countDown(); + + // get the handle for the answerKB to see if there are requests to be handled + var test = new HttpTester(new URL(url.toString() + "/sc/handle"), "GET", null, Map + .of("Knowledge-Base-Id", answerKBId, "Content-Type", "application/json", "Accept", "*/*")); + test.expectStatus(200); + + // build the body to answer the request: add handle request ID and dummy data + // bindingset + JsonObjectBuilder builder = Json.createObjectBuilder(); + JsonReader jp = Json.createReader(new StringReader(test.getBody())); + JsonObject jo = jp.readObject(); + int handleRequestId = jo.getInt("handleRequestId"); + builder.add("handleRequestId", handleRequestId); + JsonReader jr = Json.createReader(new StringReader( + "[{\"a\": \"\",\"b\": \"\"}]")); + JsonArray bs = jr.readArray(); + builder.add("bindingSet", bs); + JsonObject jo2 = builder.build(); + String body = jo2.toString(); + LOG.info("Handle an answer to a request with body: {}", body); + + // fire the POST handle to execute the answer + var test2 = new HttpTester(new URL(url.toString() + "/sc/handle"), "POST", body, + Map.of("Knowledge-Base-Id", answerKBId, "Knowledge-Interaction-Id", answerKIId, + "Content-Type", "application/json", "Accept", "*/*")); + test2.expectStatus(200); + + } catch (MalformedURLException e) { + fail(); + } + } + }); + answeringSc2.start(); + + KBReady.await(); + + // register the AskKB + HttpTester registerKb = new HttpTester(new URL(url + "/sc"), "POST", + "{\"knowledgeBaseId\": \"https://www.example.org/example/relationAsker\", \"knowledgeBaseName\": \"RelationAsker\", \"knowledgeBaseDescription\": \"A KB that asks for relations between people\", \"reasonerLevel\" : 2}", + Map.of("Content-Type", "application/json", "Accept", "*/*")); + registerKb.expectStatus(200); + + // register the AskKI + HttpTester registerKi = new HttpTester(new URL(url + "/sc/ki"), "POST", """ + { + "knowledgeInteractionType": "AskKnowledgeInteraction", + "knowledgeInteractionName": "askRelations", + "graphPattern": "?a ?b . ?a ?b .", + "knowledgeGapsEnabled": false + } + """, Map.of("Knowledge-Base-Id", "https://www.example.org/example/relationAsker", "Content-Type", + "application/json", "Accept", "*/*")); + registerKi.expectStatus(200); + + // fire the ask KI + HttpTester askKiWithoutGapsEnabled = new HttpTester(new URL(url + "/sc/ask"), "POST", + "{\"recipientSelector\": {\"knowledgeBases\": []}, \"bindingSet\": []}", + Map.of("Knowledge-Base-Id", "https://www.example.org/example/relationAsker", "Knowledge-Interaction-Id", + "https://www.example.org/example/relationAsker/interaction/askRelations", "Content-Type", + "application/json", "Accept", "*/*")); + var result = askKiWithoutGapsEnabled.getBody(); + LOG.info("Result is: {}", result); + + JsonObject jsonObject = Json.createReader(new StringReader(result)).readObject(); + JsonArray exchangeInfoArray = jsonObject.getJsonArray("exchangeInfo"); + + assertEquals(exchangeInfoArray.size(), 3); + + JsonArray actualBindingSet = jsonObject.getJsonArray("bindingSet"); + var expectedBindingSet = Json.createArrayBuilder() + .add(Json.createObjectBuilder().add("a", "") + .add("b", "").build()) + .build(); + assertEquals(expectedBindingSet, actualBindingSet); + } + + @AfterAll + public void cleanUp() throws IOException { + + TestUtil.unregisterAllKBs("http://localhost:" + PORT + "/rest"); + + rsh.cleanUp(); + } + +} diff --git a/smart-connector-rest-dist/src/test/java/eu/knowledge/engine/rest/api/TestAskAnswerReactWithGapsEnabled.java b/smart-connector-rest-dist/src/test/java/eu/knowledge/engine/rest/api/TestAskAnswerReactWithGapsEnabled.java index 15fb0fd9..d6d7de8e 100644 --- a/smart-connector-rest-dist/src/test/java/eu/knowledge/engine/rest/api/TestAskAnswerReactWithGapsEnabled.java +++ b/smart-connector-rest-dist/src/test/java/eu/knowledge/engine/rest/api/TestAskAnswerReactWithGapsEnabled.java @@ -118,7 +118,7 @@ public void run() { }); answeringSc.start(); - // activate the answer SC, KB, KI in a separate thread + // activate the react SC, KB, KI in a separate thread var reactingSc = new AsyncTester(new Runnable() { @Override public void run() { @@ -230,7 +230,6 @@ public void run() { var actualBindingSet = Set.of(bindingArray.toArray()); var expectedBindingSet = Set.>of( /* empty */ ); assertEquals(expectedBindingSet, actualBindingSet); - } @AfterAll diff --git a/smart-connector-rest-server/src/main/java/eu/knowledge/engine/rest/api/impl/ProactiveApiServiceImpl.java b/smart-connector-rest-server/src/main/java/eu/knowledge/engine/rest/api/impl/ProactiveApiServiceImpl.java index 3b7ea138..44c1404b 100644 --- a/smart-connector-rest-server/src/main/java/eu/knowledge/engine/rest/api/impl/ProactiveApiServiceImpl.java +++ b/smart-connector-rest-server/src/main/java/eu/knowledge/engine/rest/api/impl/ProactiveApiServiceImpl.java @@ -20,6 +20,7 @@ import eu.knowledge.engine.rest.model.AskExchangeInfo; import eu.knowledge.engine.rest.model.AskResult; +import eu.knowledge.engine.rest.model.ExchangeInfo; import eu.knowledge.engine.rest.model.KnowledgeInteractionWithId; import eu.knowledge.engine.rest.model.PostExchangeInfo; import eu.knowledge.engine.rest.model.PostResult; @@ -127,16 +128,7 @@ public void scAskPost( askFuture.thenAccept(askResult -> { LOG.trace("AskResult received, resuming async response: {}", askResult); - List infos = askResult.getExchangeInfoPerKnowledgeBase().stream() - .map(aei -> new AskExchangeInfo().bindingSet(this.bindingSetToList(aei.getBindings())) - .knowledgeBaseId(aei.getKnowledgeBaseId().toString()) - .knowledgeInteractionId(aei.getKnowledgeInteractionId().toString()) - .exchangeStart(Date.from(aei.getExchangeStart())) - .exchangeStart(Date.from(aei.getExchangeStart())) - .initiator(toInitiatorEnumAsk(aei.getInitiator())) - .exchangeEnd(Date.from(aei.getExchangeEnd())).status(aei.getStatus().toString()) - .failedMessage(aei.getFailedMessage())) - .collect(Collectors.toList()); + List infos = convertToExchangeInfos(askResult.getExchangeInfoPerKnowledgeBase()); LOG.trace("KnowledgeGapsEnabled is {}", ki.getKnowledgeGapsEnabled()); @@ -173,6 +165,42 @@ public void scAskPost( } } + private List convertToExchangeInfos( + Set exchangeInfos) { + + List someExchangeInfos = new ArrayList(); + + for (eu.knowledge.engine.smartconnector.api.ExchangeInfo ei : exchangeInfos) { + switch (ei) { + case eu.knowledge.engine.smartconnector.api.AskExchangeInfo aei: + someExchangeInfos.add(new AskExchangeInfo().bindingSet(this.bindingSetToList(aei.getBindings())) + .knowledgeBaseId(aei.getKnowledgeBaseId().toString()) + .knowledgeInteractionId(aei.getKnowledgeInteractionId().toString()) + .exchangeStart(Date.from(aei.getExchangeStart())) + .exchangeStart(Date.from(aei.getExchangeStart())) + .initiator(toInitiatorEnumAsk(aei.getInitiator())).exchangeEnd(Date.from(aei.getExchangeEnd())) + .status(aei.getStatus().toString()).failedMessage(aei.getFailedMessage())); + break; + case eu.knowledge.engine.smartconnector.api.PostExchangeInfo pei: + someExchangeInfos.add(new PostExchangeInfo() + .argumentBindingSet(this.bindingSetToList(pei.getArgument())) + .resultBindingSet(this.bindingSetToList(pei.getResult())) + .knowledgeBaseId(pei.getKnowledgeBaseId().toString()) + .knowledgeInteractionId(pei.getKnowledgeInteractionId().toString()) + .initiator(toInitiatorEnumPost(pei.getInitiator())) + .exchangeStart(Date.from(pei.getExchangeStart())).exchangeEnd(Date.from(pei.getExchangeEnd())) + .status(pei.getStatus().toString()).failedMessage(pei.getFailedMessage())); + + break; + default: + LOG.error("ExchangeInfos should either be of type AskExchangeInfo or PostExchangeInfo and not {}", + ei.getClass().getSimpleName()); + } + } + + return someExchangeInfos; + } + private List> bindingSetToList(BindingSet bindings) { var listBindings = new ArrayList>(bindings.size()); bindings.forEach((binding) -> { @@ -289,17 +317,7 @@ public void scPostPost( LOG.trace("PostResult received, resuming async response: {}", postResult); - List infos = postResult.getExchangeInfoPerKnowledgeBase().stream() - .map(pei -> new PostExchangeInfo() - .argumentBindingSet(this.bindingSetToList(pei.getArgument())) - .resultBindingSet(this.bindingSetToList(pei.getResult())) - .knowledgeBaseId(pei.getKnowledgeBaseId().toString()) - .knowledgeInteractionId(pei.getKnowledgeInteractionId().toString()) - .initiator(toInitiatorEnumPost(pei.getInitiator())) - .exchangeStart(Date.from(pei.getExchangeStart())) - .exchangeEnd(Date.from(pei.getExchangeEnd())).status(pei.getStatus().toString()) - .failedMessage(pei.getFailedMessage())) - .collect(Collectors.toList()); + List infos = convertToExchangeInfos(postResult.getExchangeInfoPerKnowledgeBase()); PostResult pr = new PostResult().resultBindingSet(this.bindingSetToList(postResult.getBindings())) .exchangeInfo(infos); diff --git a/smart-connector-rest-server/src/main/resources/openapi-sc.yaml b/smart-connector-rest-server/src/main/resources/openapi-sc.yaml index f2b0cbf7..7f602a43 100644 --- a/smart-connector-rest-server/src/main/resources/openapi-sc.yaml +++ b/smart-connector-rest-server/src/main/resources/openapi-sc.yaml @@ -771,7 +771,7 @@ components: exchangeInfo: type: array items: - $ref: '#/components/schemas/AskExchangeInfo' + $ref: '#/components/schemas/ExchangeInfo' knowledgeGaps: type: array items: @@ -786,10 +786,15 @@ components: exchangeInfo: type: array items: - $ref: '#/components/schemas/PostExchangeInfo' + $ref: '#/components/schemas/ExchangeInfo' ExchangeInfo: type: object - required: [initiator, knowledgeBaseId, knowledgeInteractionId, exchangeStart, exchangeEnd, status] + discriminator: + propertyName: knowledgeInteractionType + mapping: + ReactKnowledgeInteraction: '#/components/schemas/PostExchangeInfo' + AnswerKnowledgeInteraction: '#/components/schemas/AskExchangeInfo' + required: [knowledgeInteractionType, initiator, knowledgeBaseId, knowledgeInteractionId, exchangeStart, exchangeEnd, status] properties: initiator: type: string 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 7ef113d7..77a747c8 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 @@ -36,6 +36,7 @@ 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.ExchangeInfo; import eu.knowledge.engine.smartconnector.api.ExchangeInfo.Initiator; import eu.knowledge.engine.smartconnector.api.ExchangeInfo.Status; import eu.knowledge.engine.smartconnector.api.GraphPattern; @@ -69,8 +70,7 @@ public class ReasonerProcessor extends SingleInteractionProcessor { private RuleStore store; private MyKnowledgeInteractionInfo myKnowledgeInteraction; - private final Set askExchangeInfos; - private final Set postExchangeInfos; + private final Set exchangeInfos; private Set additionalDomainKnowledge; private ReasonerPlan reasonerPlan; private Set knowledgeGaps; @@ -101,8 +101,7 @@ public ReasonerProcessor(Set knowledgeInteractions, Me store.addRule(r); } - this.askExchangeInfos = Collections.newSetFromMap(new ConcurrentHashMap()); - this.postExchangeInfos = Collections.newSetFromMap(new ConcurrentHashMap()); + this.exchangeInfos = Collections.newSetFromMap(new ConcurrentHashMap()); for (KnowledgeInteractionInfo kii : knowledgeInteractions) { String ruleName = kii.getKnowledgeInteraction().getName() != null ? kii.getKnowledgeInteraction().getName() @@ -185,12 +184,12 @@ public CompletableFuture executeAskInteraction(BindingSet someBinding this.finalBindingSetFuture = new CompletableFuture(); // this.reasonerPlan.optimize(); - + if (this.myKnowledgeInteraction.isMeta()) LOG.trace("Ask: {}", this.reasonerPlan); else LOG.debug("Ask: {}", this.reasonerPlan); - + continueReasoningBackward(someBindings); return this.finalBindingSetFuture.thenApply((bs) -> { @@ -201,7 +200,7 @@ public CompletableFuture executeAskInteraction(BindingSet someBinding // extract succeeded nr of exchange infos and nr of failed exchange infos List succeededKIs = new ArrayList(), failedKIs = new ArrayList(); - for (AskExchangeInfo aei : this.askExchangeInfos) { + for (ExchangeInfo aei : this.exchangeInfos) { if (aei.getStatus().equals(Status.SUCCEEDED)) { succeededKIs.add(aei.getKnowledgeInteractionId().toString()); } else if (aei.getStatus().equals(Status.FAILED)) { @@ -217,7 +216,7 @@ public CompletableFuture executeAskInteraction(BindingSet someBinding LOG.info(logStatement, this.myKnowledgeInteraction.getId(), bs.size(), succeededKIs.size() + failedKIs.size(), failedKIs.size(), failedKIs); - return new AskResult(Util.translateToApiBindingSet(bs), this.askExchangeInfos, this.reasonerPlan, + return new AskResult(Util.translateToApiBindingSet(bs), this.exchangeInfos, this.reasonerPlan, this.knowledgeGaps); }); } @@ -287,19 +286,19 @@ public CompletableFuture executePostInteraction(BindingSet someBindi this.finalBindingSetFuture = new CompletableFuture(); // this.reasonerPlan.optimize(); - + if (this.myKnowledgeInteraction.isMeta()) LOG.trace("Post: {}", this.reasonerPlan); else LOG.debug("Post: {}", this.reasonerPlan); - + continueReasoningForward(someBindings, this.captureResultBindingSetHandler); return this.finalBindingSetFuture.thenApply((bs) -> { // extract succeeded nr of exchange infos and nr of failed exchange infos List succeededKIs = new ArrayList<>(), failedKIs = new ArrayList<>(); - for (PostExchangeInfo aei : this.postExchangeInfos) { + for (ExchangeInfo aei : this.exchangeInfos) { if (aei.getStatus().equals(Status.SUCCEEDED)) { succeededKIs.add(aei.getKnowledgeInteractionId().toString()); } else if (aei.getStatus().equals(Status.FAILED)) { @@ -315,7 +314,7 @@ public CompletableFuture executePostInteraction(BindingSet someBindi LOG.info(logMessage, this.myKnowledgeInteraction.getId(), bs.size(), succeededKIs.size() + failedKIs.size(), failedKIs.size(), failedKIs); - return new PostResult(Util.translateToApiBindingSet(bs), this.postExchangeInfos, this.reasonerPlan); + return new PostResult(Util.translateToApiBindingSet(bs), this.exchangeInfos, this.reasonerPlan); }); } @@ -460,7 +459,7 @@ public CompletableFuture handle(BindingSet bs) { LOG.trace("Received ANSWER message from KI '{}'", answerMessage.getFromKnowledgeInteraction()); BindingSet resultBindingSet = answerMessage.getBindings(); - ReasonerProcessor.this.askExchangeInfos + ReasonerProcessor.this.exchangeInfos .add(convertMessageToExchangeInfo(resultBindingSet, answerMessage, aPreviousSend)); return resultBindingSet; @@ -555,7 +554,7 @@ public CompletableFuture handle(BindingSet bs) { assert reactMessage != null; BindingSet resultBindingSet = reactMessage.getResult(); - ReasonerProcessor.this.postExchangeInfos + ReasonerProcessor.this.exchangeInfos .add(convertMessageToExchangeInfo(bs, resultBindingSet, reactMessage, aPreviousSend)); return resultBindingSet; @@ -628,7 +627,7 @@ public CompletableFuture handle(BindingSet bs) { failedMessage); }).thenApply((reactMessage) -> { assert reactMessage != null; - ReasonerProcessor.this.postExchangeInfos.add( + ReasonerProcessor.this.exchangeInfos.add( convertMessageToExchangeInfo(bs, reactMessage.getResult(), reactMessage, aPreviousSend)); return (Void) null; diff --git a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestAskAnswer3.java b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestAskAnswer3.java index 22a4ef2b..88e663e1 100644 --- a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestAskAnswer3.java +++ b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestAskAnswer3.java @@ -123,7 +123,7 @@ public void testAskAnswer() throws InterruptedException { bindings = result.getBindings(); LOG.trace("After ask."); - Set kbIds = result.getExchangeInfoPerKnowledgeBase().stream().map(AskExchangeInfo::getKnowledgeBaseId) + Set kbIds = result.getExchangeInfoPerKnowledgeBase().stream().map(ExchangeInfo::getKnowledgeBaseId) .collect(Collectors.toSet()); assertEquals( diff --git a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestAskAnswer4.java b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestAskAnswer4.java index ac11d495..2ae0b5df 100644 --- a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestAskAnswer4.java +++ b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestAskAnswer4.java @@ -77,7 +77,6 @@ public void testAskAnswer() throws InterruptedException { bindings = result.getBindings(); LOG.info("Bindings: {}", bindings); - LOG.info("Bindings2: {}", result.getExchangeInfoPerKnowledgeBase().iterator().next().getBindings()); LOG.trace("After ask."); } catch (InterruptedException | ExecutionException e) { diff --git a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestAskAnswer5.java b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestAskAnswer5.java index 0d8f3618..7ca71472 100644 --- a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestAskAnswer5.java +++ b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestAskAnswer5.java @@ -141,7 +141,7 @@ public void testAskAnswer() throws InterruptedException { bindings = result.getBindings(); LOG.trace("After ask."); - Set kbIds = result.getExchangeInfoPerKnowledgeBase().stream().map(AskExchangeInfo::getKnowledgeBaseId) + Set kbIds = result.getExchangeInfoPerKnowledgeBase().stream().map(ExchangeInfo::getKnowledgeBaseId) .collect(Collectors.toSet()); assertEquals( diff --git a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestAskAnswerLargeBindingSets.java b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestAskAnswerLargeBindingSets.java index 491aa330..b563a5a0 100644 --- a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestAskAnswerLargeBindingSets.java +++ b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestAskAnswerLargeBindingSets.java @@ -130,7 +130,7 @@ public void testAskAnswer() throws InterruptedException { bindings = result.getBindings(); LOG.trace("After ask."); - Set kbIds = result.getExchangeInfoPerKnowledgeBase().stream().map(AskExchangeInfo::getKnowledgeBaseId) + Set kbIds = result.getExchangeInfoPerKnowledgeBase().stream().map(ExchangeInfo::getKnowledgeBaseId) .collect(Collectors.toSet()); assertEquals(new HashSet(Arrays.asList(kb1.getKnowledgeBaseId(), kb3.getKnowledgeBaseId())), kbIds, diff --git a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestAskAnswerRealistic.java b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestAskAnswerRealistic.java index a3c689aa..413bf902 100644 --- a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestAskAnswerRealistic.java +++ b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestAskAnswerRealistic.java @@ -513,7 +513,7 @@ public void testAskAnswer() throws InterruptedException { bindings = result.getBindings(); LOG.trace("After ask"); - Set kbIds = result.getExchangeInfoPerKnowledgeBase().stream().map(AskExchangeInfo::getKnowledgeBaseId) + Set kbIds = result.getExchangeInfoPerKnowledgeBase().stream().map(ExchangeInfo::getKnowledgeBaseId) .collect(Collectors.toSet()); assertEquals(new HashSet( diff --git a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestAskAnswerSingleKBMultipleMatchingKIs.java b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestAskAnswerSingleKBMultipleMatchingKIs.java index 010ab126..a2d67806 100644 --- a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestAskAnswerSingleKBMultipleMatchingKIs.java +++ b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestAskAnswerSingleKBMultipleMatchingKIs.java @@ -97,7 +97,7 @@ public void testAskAnswer() throws InterruptedException { bindings = result.getBindings(); LOG.trace("After ask."); - List kbIds = result.getExchangeInfoPerKnowledgeBase().stream().map(AskExchangeInfo::getKnowledgeBaseId) + List kbIds = result.getExchangeInfoPerKnowledgeBase().stream().map(ExchangeInfo::getKnowledgeBaseId) .collect(Collectors.toList()); // with the reasoner there used to be more matching gp (i.e. the meta diff --git a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestAskRecipientSelector.java b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestAskRecipientSelector.java index 66ab2d00..a16f9951 100644 --- a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestAskRecipientSelector.java +++ b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestAskRecipientSelector.java @@ -128,7 +128,7 @@ public void testAskAnswer() throws InterruptedException { // Recipient Selector is single KB (kb1). result = kb2.ask(askKI, new RecipientSelector(kb1.getKnowledgeBaseId()), new BindingSet()).get(); bindings = result.getBindings(); - Set kbIds = result.getExchangeInfoPerKnowledgeBase().stream().map(AskExchangeInfo::getKnowledgeBaseId) + Set kbIds = result.getExchangeInfoPerKnowledgeBase().stream().map(ExchangeInfo::getKnowledgeBaseId) .collect(Collectors.toSet()); assertEquals(new HashSet(Arrays.asList(kb1.getKnowledgeBaseId())), kbIds, @@ -149,7 +149,7 @@ public void testAskAnswer() throws InterruptedException { new RecipientSelector(Arrays.asList(kb1.getKnowledgeBaseId(), kb3.getKnowledgeBaseId())), new BindingSet()).get(); bindings = result.getBindings(); - kbIds = result.getExchangeInfoPerKnowledgeBase().stream().map(AskExchangeInfo::getKnowledgeBaseId) + kbIds = result.getExchangeInfoPerKnowledgeBase().stream().map(ExchangeInfo::getKnowledgeBaseId) .collect(Collectors.toSet()); assertEquals(new HashSet(Arrays.asList(kb1.getKnowledgeBaseId(), kb3.getKnowledgeBaseId())), kbIds, @@ -173,7 +173,7 @@ public void testAskAnswer() throws InterruptedException { bindings = result.getBindings(); LOG.trace("After ask."); - kbIds = result.getExchangeInfoPerKnowledgeBase().stream().map(AskExchangeInfo::getKnowledgeBaseId) + kbIds = result.getExchangeInfoPerKnowledgeBase().stream().map(ExchangeInfo::getKnowledgeBaseId) .collect(Collectors.toSet()); assertEquals( 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 4938722e..f77d7c35 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 @@ -81,8 +81,8 @@ public void testComplexGraphPattern() throws InterruptedException { bindings = askResult.getBindings(); LOG.trace("After ask."); - Set kbIds = askResult.getExchangeInfoPerKnowledgeBase().stream() - .map(AskExchangeInfo::getKnowledgeBaseId).collect(Collectors.toSet()); + Set kbIds = askResult.getExchangeInfoPerKnowledgeBase().stream().map(ExchangeInfo::getKnowledgeBaseId) + .collect(Collectors.toSet()); assertEquals( new HashSet( diff --git a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestDuplicateBindings.java b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestDuplicateBindings.java index 2de681c1..b5cd3723 100644 --- a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestDuplicateBindings.java +++ b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestDuplicateBindings.java @@ -141,7 +141,7 @@ public void testAskAnswer() throws InterruptedException { LOG.trace("After ask."); LOG.info("Bindings: {}", bindings); - Set kbIds = result.getExchangeInfoPerKnowledgeBase().stream().map(AskExchangeInfo::getKnowledgeBaseId) + Set kbIds = result.getExchangeInfoPerKnowledgeBase().stream().map(ExchangeInfo::getKnowledgeBaseId) .collect(Collectors.toSet()); assertEquals(new HashSet(Arrays.asList(kb1.getKnowledgeBaseId(), kb3.getKnowledgeBaseId())), kbIds, @@ -181,7 +181,7 @@ public void testPostReact() throws InterruptedException { LOG.trace("After post."); LOG.info("Bindings: {}", bindings); - Set kbIds = result.getExchangeInfoPerKnowledgeBase().stream().map(PostExchangeInfo::getKnowledgeBaseId) + Set kbIds = result.getExchangeInfoPerKnowledgeBase().stream().map(ExchangeInfo::getKnowledgeBaseId) .collect(Collectors.toSet()); assertEquals(new HashSet(Arrays.asList(kb1.getKnowledgeBaseId(), kb3.getKnowledgeBaseId())), kbIds, diff --git a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestDynamicSemanticComposition.java b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestDynamicSemanticComposition.java index 988039c0..15888b68 100644 --- a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestDynamicSemanticComposition.java +++ b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestDynamicSemanticComposition.java @@ -70,7 +70,8 @@ public void setup() throws InterruptedException, BrokenBarrierException, Timeout HashSet antecedent1 = new HashSet(); antecedent1.add(new TriplePattern( "?id ")); - antecedent1.add(new TriplePattern("?id \"Prussia\"")); + antecedent1 + .add(new TriplePattern("?id \"Prussia\"")); HashSet consequent2 = new HashSet(); consequent2.add(new TriplePattern( @@ -78,7 +79,8 @@ public void setup() throws InterruptedException, BrokenBarrierException, Timeout HashSet antecedent2 = new HashSet(); antecedent2.add(new TriplePattern( "?id ")); - antecedent2.add(new TriplePattern("?id \"Prussian\"")); + antecedent2.add( + new TriplePattern("?id \"Prussian\"")); HashSet consequent3 = new HashSet(); consequent3.add(new TriplePattern( @@ -86,8 +88,10 @@ public void setup() throws InterruptedException, BrokenBarrierException, Timeout HashSet antecedent3 = new HashSet(); antecedent3.add(new TriplePattern( "?id ")); - antecedent3.add(new TriplePattern("?id \"Prussian\"")); - antecedent3.add(new TriplePattern("?id \"Prussia\"")); + antecedent3.add( + new TriplePattern("?id \"Prussian\"")); + antecedent3 + .add(new TriplePattern("?id \"Prussia\"")); ruleSet = new HashSet<>(); ruleSet.add(new Rule(antecedent1, consequent1)); @@ -119,6 +123,7 @@ public void testAskAnswer() throws InterruptedException, URISyntaxException { BindingSet bindings = null; try { AskResult result = kbHVTSearcher.ask(askKI, new BindingSet()).get(); + assertTrue(result.getExchangeInfoPerKnowledgeBase().size() == 2); bindings = result.getBindings(); // try to generate JSON tree. TestUtils.printSequenceDiagram(kbHVTSearcher.getKnowledgeBaseId().toString(), "ask", postKI.getArgument(), @@ -149,6 +154,7 @@ public void testAskAnswer() throws InterruptedException, URISyntaxException { LOG.info("Before post!"); PostPlan aPlan = kbTargetObserver.planPost(postKI, new RecipientSelector()); PostResult result = aPlan.execute(bindingSet).get(); + assertEquals(2, result.getExchangeInfoPerKnowledgeBase().size()); bindings = result.getBindings(); iter = bindings.iterator(); assertFalse(iter.hasNext(), "there should be no bindings"); diff --git a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestPostReactWithAnswer.java b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestPostReactWithAnswer.java new file mode 100644 index 00000000..b37469d5 --- /dev/null +++ b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/TestPostReactWithAnswer.java @@ -0,0 +1,115 @@ +package eu.knowledge.engine.smartconnector.api; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +import java.util.Iterator; +import java.util.concurrent.ExecutionException; + +import org.apache.jena.shared.PrefixMapping; +import org.apache.jena.sparql.graph.PrefixMappingMem; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import eu.knowledge.engine.smartconnector.util.KnowledgeNetwork; +import eu.knowledge.engine.smartconnector.util.KnowledgeBaseImpl; + +/** + * We test a KB that posts knowledge that is received by another KB, but only if + * it is supplemented with data from another KB. We check whether the exchange + * info is correct and includes both the post and ask exchange infos. + */ +public class TestPostReactWithAnswer { + private static KnowledgeBaseImpl kb1; + private static KnowledgeBaseImpl kb2; + private static KnowledgeBaseImpl kb3; + + public boolean kb2Received = false; + + private static final Logger LOG = LoggerFactory.getLogger(TestPostReactWithAnswer.class); + private static KnowledgeNetwork kn; + + @Test + public void testPostReact() throws InterruptedException { + PrefixMappingMem prefixes = new PrefixMappingMem(); + prefixes.setNsPrefixes(PrefixMapping.Standard); + prefixes.setNsPrefix("ex", "https://www.example.org/example/"); + + kn = new KnowledgeNetwork(); + kb1 = new KnowledgeBaseImpl("kb1"); + kn.addKB(kb1); + kb2 = new KnowledgeBaseImpl("kb2"); + kn.addKB(kb2); + kb3 = new KnowledgeBaseImpl("kb3"); + kn.addKB(kb3); + + GraphPattern gp1 = new GraphPattern(prefixes, "?a ?c."); + PostKnowledgeInteraction pKI = new PostKnowledgeInteraction(new CommunicativeAct(), gp1, null); + kb1.register(pKI); + + GraphPattern gp2 = new GraphPattern(prefixes, + "?d ?e. ?d ?g ."); + ReactKnowledgeInteraction rKI = new ReactKnowledgeInteraction(new CommunicativeAct(), gp2, null); + kb2.register(rKI, ((anRKI, aReactExchangeInfo) -> { + LOG.trace("KB2 reacting..."); + TestPostReactWithAnswer.this.kb2Received = true; + var argument = aReactExchangeInfo.getArgumentBindings(); + Iterator iter = argument.iterator(); + assertTrue(iter.hasNext(), "There should be at least a single binding."); + Binding b = iter.next(); + + assertEquals("", b.get("d"), "Binding of 'd' is incorrect."); + assertEquals("", b.get("e"), "Binding of 'e' is incorrect."); + + assertFalse(iter.hasNext(), "This BindingSet should only have a single binding."); + + return new BindingSet(); + })); + + GraphPattern gp3 = new GraphPattern(prefixes, "?a ?b ."); + AnswerKnowledgeInteraction aKI = new AnswerKnowledgeInteraction(new CommunicativeAct(), gp3); + kb3.register(aKI, (_, _) -> { + BindingSet bs = new BindingSet(); + Binding b = new Binding(); + b.put("a", ""); + b.put("b", ""); + bs.add(b); + + return bs; + }); + + kn.sync(); + LOG.info("Everyone is up-to-date!"); + + BindingSet bindingSet = new BindingSet(); + Binding binding = new Binding(); + binding.put("a", ""); + binding.put("c", ""); + bindingSet.add(binding); + + try { + PostResult result = kb1.post(pKI, bindingSet).get(); + assertTrue(this.kb2Received, "KB2 should have received the posted data."); + assertEquals(2, result.getExchangeInfoPerKnowledgeBase().size()); + + BindingSet bs = result.getBindings(); + assertTrue(bs.isEmpty()); + + LOG.info("After post!"); + } catch (ExecutionException e) { + LOG.error("Error", e); + fail(); + } + } + + @AfterAll + public static void cleanup() throws InterruptedException, ExecutionException { + LOG.info("Clean up: {}", TestPostReactWithAnswer.class.getSimpleName()); + kn.stop().get(); + } + +} diff --git a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/VariableBindingNameTest.java b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/VariableBindingNameTest.java index 6bde742c..2772c478 100644 --- a/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/VariableBindingNameTest.java +++ b/smart-connector/src/test/java/eu/knowledge/engine/smartconnector/api/VariableBindingNameTest.java @@ -16,8 +16,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import eu.knowledge.engine.smartconnector.util.KnowledgeNetwork; import eu.knowledge.engine.smartconnector.util.KnowledgeBaseImpl; +import eu.knowledge.engine.smartconnector.util.KnowledgeNetwork; class VariableBindingNameTest { @@ -106,9 +106,9 @@ public BindingSet react(ReactKnowledgeInteraction anRKI, ReactExchangeInfo aReac try { PostResult postResult = sensor.post(sensorPostKI, bs).get(); - Set infos = postResult.getExchangeInfoPerKnowledgeBase(); + Set infos = postResult.getExchangeInfoPerKnowledgeBase(); - PostExchangeInfo info = infos.stream() + PostExchangeInfo info = (PostExchangeInfo) infos.stream() .filter(ei -> ei.getKnowledgeBaseId().equals(thermostat.getKnowledgeBaseId())).findFirst().get(); BindingSet bindingSet = info.getArgument();