Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make AdminUI in distributive setup more useful. #553

Merged
merged 1 commit into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 49 additions & 25 deletions admin-ui/src/main/java/eu/knowledge/engine/admin/AdminUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ public class AdminUI implements KnowledgeBase {

private static final String META_GRAPH_PATTERN_STR = "?kb rdf:type ke:KnowledgeBase . ?kb ke:hasName ?name . ?kb ke:hasDescription ?description . ?kb ke:hasKnowledgeInteraction ?ki . ?ki rdf:type ?kiType . ?ki ke:isMeta ?isMeta . ?ki ke:hasCommunicativeAct ?act . ?act rdf:type ke:CommunicativeAct . ?act ke:hasRequirement ?req . ?act ke:hasSatisfaction ?sat . ?req rdf:type ?reqType . ?sat rdf:type ?satType . ?ki ke:hasGraphPattern ?gp . ?gp rdf:type ?patternType . ?gp ke:hasPattern ?pattern .";

private static final String CONF_KEY_INITIAL_ADMIN_UI_DELAY = "INITIAL_ADMIN_UI_DELAY";

private SmartConnector sc;
private final PrefixMapping prefixes;

Expand Down Expand Up @@ -119,34 +121,41 @@ public void smartConnectorReady(SmartConnector aSC) {
// create the correct Knowledge Interactions
this.aKI = new AskKnowledgeInteraction(new CommunicativeAct(), this.metaGraphPattern, true);
this.rKINew = new ReactKnowledgeInteraction(
new CommunicativeAct(new HashSet<Resource>(Arrays.asList(Vocab.NEW_KNOWLEDGE_PURPOSE)), new HashSet<Resource>(Arrays.asList(Vocab.INFORM_PURPOSE))),
this.metaGraphPattern, null
);
new CommunicativeAct(new HashSet<Resource>(Arrays.asList(Vocab.NEW_KNOWLEDGE_PURPOSE)),
new HashSet<Resource>(Arrays.asList(Vocab.INFORM_PURPOSE))),
this.metaGraphPattern, null);
this.rKIChanged = new ReactKnowledgeInteraction(
new CommunicativeAct(new HashSet<Resource>(Arrays.asList(Vocab.CHANGED_KNOWLEDGE_PURPOSE)), new HashSet<Resource>(Arrays.asList(Vocab.INFORM_PURPOSE))),
this.metaGraphPattern, null
);
new CommunicativeAct(new HashSet<Resource>(Arrays.asList(Vocab.CHANGED_KNOWLEDGE_PURPOSE)),
new HashSet<Resource>(Arrays.asList(Vocab.INFORM_PURPOSE))),
this.metaGraphPattern, null);
this.rKIRemoved = new ReactKnowledgeInteraction(
new CommunicativeAct(new HashSet<Resource>(Arrays.asList(Vocab.REMOVED_KNOWLEDGE_PURPOSE)), new HashSet<Resource>(Arrays.asList(Vocab.INFORM_PURPOSE))),
this.metaGraphPattern, null
);
new CommunicativeAct(new HashSet<Resource>(Arrays.asList(Vocab.REMOVED_KNOWLEDGE_PURPOSE)),
new HashSet<Resource>(Arrays.asList(Vocab.INFORM_PURPOSE))),
this.metaGraphPattern, null);

// register the knowledge interactions with the smart connector.
this.sc.register(this.aKI);
this.sc.register(this.rKINew, (rki, ei) -> this.handleNewKnowledgeBaseKnowledge(ei));
this.sc.register(this.rKIChanged, (rki, ei) -> this.handleChangedKnowledgeBaseKnowledge(ei));
this.sc.register(this.rKIRemoved, (rki, ei) -> this.handleRemovedKnowledgeBaseKnowledge(ei));

// to receive the initial state, we do a single Ask
// to receive the initial state, we do a single Ask (after sleeping for a
// specific amount of time)
try {
Thread.sleep(Integer.parseInt(AdminUI.getConfigProperty(CONF_KEY_INITIAL_ADMIN_UI_DELAY, "5000")));
} catch (InterruptedException e) {
LOG.info("{}", e);
}
this.fetchInitialData();
}

public BindingSet handleNewKnowledgeBaseKnowledge(ReactExchangeInfo ei) {
if (!this.canReceiveUpdates()) return new BindingSet();
if (!this.canReceiveUpdates())
return new BindingSet();

try {
Model model = eu.knowledge.engine.smartconnector.impl.Util
.generateModel(this.aKI.getPattern(), ei.getArgumentBindings());
Model model = eu.knowledge.engine.smartconnector.impl.Util.generateModel(this.aKI.getPattern(),
ei.getArgumentBindings());

// this we can simply add to our model
this.model.add(model);
Expand All @@ -161,21 +170,23 @@ public BindingSet handleNewKnowledgeBaseKnowledge(ReactExchangeInfo ei) {
}
return new BindingSet();
}

public BindingSet handleChangedKnowledgeBaseKnowledge(ReactExchangeInfo ei) {
if (!this.canReceiveUpdates()) return new BindingSet();
if (!this.canReceiveUpdates())
return new BindingSet();

try {
Model model = eu.knowledge.engine.smartconnector.impl.Util
.generateModel(this.aKI.getPattern(), ei.getArgumentBindings());
Model model = eu.knowledge.engine.smartconnector.impl.Util.generateModel(this.aKI.getPattern(),
ei.getArgumentBindings());

// this is a little more complex... we have to:
// - extract the knowledge base that this message is about
// - delete all old data about that knowledge base
// - insert the *new* data about that knowledge base

Resource kb = model.query(new SimpleSelector(null, RDF.type, Vocab.KNOWLEDGE_BASE)).listSubjects().next();
String query = String.format("DELETE { %s } WHERE { %s FILTER (?kb = <%s>) } ", this.metaGraphPattern.getPattern(), this.metaGraphPattern.getPattern(), kb.toString());
String query = String.format("DELETE { %s } WHERE { %s FILTER (?kb = <%s>) } ",
this.metaGraphPattern.getPattern(), this.metaGraphPattern.getPattern(), kb.toString());
UpdateRequest updateRequest = UpdateFactory.create(query);
UpdateAction.execute(updateRequest, this.model);

Expand All @@ -193,18 +204,20 @@ public BindingSet handleChangedKnowledgeBaseKnowledge(ReactExchangeInfo ei) {
}

public BindingSet handleRemovedKnowledgeBaseKnowledge(ReactExchangeInfo ei) {
if (!this.canReceiveUpdates()) return new BindingSet();
if (!this.canReceiveUpdates())
return new BindingSet();

try {
Model model = eu.knowledge.engine.smartconnector.impl.Util
.generateModel(this.aKI.getPattern(), ei.getArgumentBindings());
Model model = eu.knowledge.engine.smartconnector.impl.Util.generateModel(this.aKI.getPattern(),
ei.getArgumentBindings());

// this is also a little complex... we have to:
// - extract the knowledge base that this message is about
// - delete all old data about that knowledge base

Resource kb = model.query(new SimpleSelector(null, RDF.type, Vocab.KNOWLEDGE_BASE)).listSubjects().next();
String query = String.format("DELETE { %s } WHERE { %s FILTER (?kb = <%s>) } ", this.metaGraphPattern.getPattern(), this.metaGraphPattern.getPattern(), kb.toString());
String query = String.format("DELETE { %s } WHERE { %s FILTER (?kb = <%s>) } ",
this.metaGraphPattern.getPattern(), this.metaGraphPattern.getPattern(), kb.toString());
UpdateRequest updateRequest = UpdateFactory.create(query);
UpdateAction.execute(updateRequest, this.model);

Expand All @@ -227,8 +240,8 @@ public void fetchInitialData() {
try {
// using the BindingSet#generateModel() helper method, we can combine the graph
// pattern and the bindings for its variables into a valid RDF Model.
this.model = eu.knowledge.engine.smartconnector.impl.Util
.generateModel(this.aKI.getPattern(), askResult.getBindings());
this.model = eu.knowledge.engine.smartconnector.impl.Util.generateModel(this.aKI.getPattern(),
askResult.getBindings());
this.model.setNsPrefixes(this.prefixes);
// when result available (and the config is enabled), we print the
// knowledge bases to the console.
Expand Down Expand Up @@ -316,4 +329,15 @@ public void close() {
public Model getModel() {
return model;
}

public static String getConfigProperty(String key, String defaultValue) {
// We might replace this with something a bit more fancy in the future...
String value = System.getenv(key);
if (value == null) {
value = defaultValue;
LOG.info("No value for the configuration parameter '" + key + "' was provided, using the default value '"
+ defaultValue + "'");
}
return value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,15 @@ public void getSCOverview(
}
}

@GET
@Path("/reload")
@Operation(summary = "Manually reload the admin-ui's smart connectors within the network. This is sometimes necessary when the initial load did not pick up all SCs correctly.")
@ApiResponses(value = { @ApiResponse(responseCode = "200", description = "If the SC were reloaded."),
@ApiResponse(responseCode = "500", description = "If a problem occurred.") })
public void reloadSCs() {
AdminUI.newInstance(false).fetchInitialData();
}

private eu.knowledge.engine.admin.model.SmartConnector[] findAndAddConnections(SmartConnector[] smartConnectors) {

Set<KnowledgeInteractionInfo> allRelevantKnowledgeInteractions = new HashSet<>();
Expand Down
Loading