6 #include "knowrob/storage/ObserverJob.h"
13 : manager_(manager), query_(query), callback_(callback) {
18 for (
const auto &node:
nodes_) {
34 auto node = std::make_shared<Node>();
42 switch (
term->termType()) {
44 auto node =
createNode(std::static_pointer_cast<GraphPattern>(
term));
45 for (
const auto &parent: parents) {
46 node->parents.push_back(parent.get());
47 parent->children.push_back(node);
52 if (!parents.empty()) {
53 for (
const auto &parent: parents) {
54 auto builtin = std::static_pointer_cast<GraphBuiltin>(
term);
55 parent->builtins.push_back(builtin);
58 KB_WARN(
"Builtins are not allowed at the top level of an observed query.");
63 auto sequence = std::static_pointer_cast<GraphSequence>(
term);
65 for (
const auto &subTerm: sequence->terms()) {
71 auto unionTerm = std::static_pointer_cast<GraphUnion>(
term);
73 for (
const auto &subTerm: unionTerm->terms()) {
75 nextParents.insert(nextParents.end(), subParents.begin(), subParents.end());
84 std::vector<std::shared_ptr<GraphTerm>> terms;
85 for (
auto it = reverseSequence.rbegin(); it != reverseSequence.rend(); ++it) {
86 terms.push_back((*it)->pattern);
87 for (
const auto &builtin: (*it)->builtins) {
88 terms.push_back(builtin);
91 if (terms.size() == 1) {
92 return std::make_shared<GraphQuery>(terms[0]);
94 return std::make_shared<GraphQuery>(std::make_shared<GraphSequence>(terms));
99 std::vector<std::shared_ptr<GraphTerm>> terms;
101 for (
const auto &builtin: node->builtins) {
102 std::shared_ptr<GraphTerm> builtinTerm = builtin;
105 if (terms.size() == 1) {
106 return std::make_shared<GraphQuery>(terms[0]);
108 return std::make_shared<GraphQuery>(std::make_shared<GraphSequence>(terms));
113 std::vector<GraphQueryPtr> queries;
114 std::queue<std::pair<Node *, std::vector<Node *>>> queryQueue;
115 queryQueue.push({nodeToInit.get(), { nodeToInit.get() }});
118 while (!queryQueue.empty()) {
119 auto [node, seq] = queryQueue.front();
122 if (node->parents.empty()) {
125 for (
const auto &parent: node->parents) {
126 std::vector<Node *> newSeq = seq;
127 newSeq.push_back(parent);
128 queryQueue.push({parent, newSeq});
134 for (
const auto &nodeQuery: queries) {
142 auto answerHash = answer->hash();
143 auto it = node->solutions.find(answerHash);
144 if (it == node->solutions.end()) {
146 node->solutions[answerHash] = answer;
148 if (node->children.empty()) {
156 auto &pat = node.
pattern->value();
158 auto &s_pat = pat->subjectTerm();
159 if (s_pat->isAtomic()) {
160 auto s_pat_atom = std::static_pointer_cast<Atomic>(s_pat);
161 if (s_pat_atom->stringForm() != triple.
subject())
return false;
162 }
else if (!s_pat->isVariable()) {
166 auto &p_pat = pat->propertyTerm();
167 if (p_pat->isAtomic()) {
168 auto p_pat_atom = std::static_pointer_cast<Atomic>(p_pat);
169 if (p_pat_atom->stringForm() != triple.
predicate())
return false;
170 }
else if (!p_pat->isVariable()) {
174 auto &o_pat = pat->objectTerm();
175 if (o_pat->isAtomic()) {
176 auto o_pat_atom = std::static_pointer_cast<Atomic>(o_pat);
180 if (o_pat_atom->stringForm() != o_triple)
return false;
183 if (*o_pat_atom != *o_triple)
return false;
185 }
else if (!o_pat->isVariable()) {
193 for (
auto &triplePtr: *triples) {
194 auto &triple = *triplePtr;
195 for (
auto &node:
nodes_) {
204 for (
auto &triplePtr: *triples) {
205 auto &triple = *triplePtr;
206 for (
auto &node:
nodes_) {
215 if (node->builtins.empty()) {
218 auto bindings_rw = std::make_shared<Bindings>(*bindings);
219 for (
const auto &builtin: node->builtins) {
220 builtin->apply(bindings_rw);
227 auto nodePattern = node->pattern->value();
230 auto tripleBindings = std::make_shared<Bindings>();
231 if (nodePattern->subjectTerm()->isVariable()) {
232 auto var = std::static_pointer_cast<Variable>(nodePattern->subjectTerm());
233 tripleBindings->set(
var, std::make_shared<IRIAtom>(triple.
subject()));
235 if (nodePattern->propertyTerm()->isVariable()) {
236 auto var = std::static_pointer_cast<Variable>(nodePattern->propertyTerm());
237 tripleBindings->set(
var, std::make_shared<IRIAtom>(triple.
predicate()));
239 if (nodePattern->objectTerm()->isVariable()) {
240 auto var = std::static_pointer_cast<Variable>(nodePattern->objectTerm());
242 tripleBindings->set(
var, o_triple);
247 std::queue<Node*> nodeQueue;
248 nodeQueue.push(node.get());
249 while (!nodeQueue.empty()) {
250 auto nextNode = nodeQueue.front();
252 for (
auto &solPair: nextNode->solutions) {
253 auto &solution = solPair.second;
254 if (solution->isConsistentWith(*tripleBindings)) {
255 nextNode->solutions.erase(solPair.first);
258 for (
auto &childNode: nextNode->children) {
259 nodeQueue.push(childNode.get());
265 auto nodePattern = node->pattern->value();
268 auto tripleBindings = std::make_shared<Bindings>();
269 if (nodePattern->subjectTerm()->isVariable()) {
270 auto var = std::static_pointer_cast<Variable>(nodePattern->subjectTerm());
271 tripleBindings->set(
var, std::make_shared<IRIAtom>(triple.
subject()));
273 if (nodePattern->propertyTerm()->isVariable()) {
274 auto var = std::static_pointer_cast<Variable>(nodePattern->propertyTerm());
275 tripleBindings->set(
var, std::make_shared<IRIAtom>(triple.
predicate()));
277 if (nodePattern->objectTerm()->isVariable()) {
278 auto var = std::static_pointer_cast<Variable>(nodePattern->objectTerm());
280 tripleBindings->set(
var, o_triple);
284 if (node->parents.empty()) {
289 for (
auto &parentNode: node->parents) {
290 for (
auto &parentSolPair: parentNode->solutions) {
291 auto &parentSolution = parentSolPair.second;
292 if (parentSolution->isConsistentWith(*tripleBindings)) {
293 doInsert(node, parentSolution, tripleBindings);
303 auto newBindings_rw = std::make_shared<Bindings>(*parentBindings);
304 newBindings_rw->operator+=(*nodeBindings);
310 auto solHash = newBindings->hash();
312 if(node->solutions.find(solHash) != node->solutions.end()) {
316 node->solutions[solHash] = newBindings;
318 if (node->children.empty()) {
326 for (
auto &childNode: node->children) {
329 doInsert(childNode, newBindings, bindings);
static std::shared_ptr< Atomic > makeTripleValue(const Triple &triple)
ObserverJob(const std::shared_ptr< ObserverManager > &manager, const GraphQueryPtr &query, const BindingsHandler &callback)
BindingsPtr applyBuiltins(const std::shared_ptr< Node > &node, const BindingsPtr &bindings)
void initializeNode(const std::shared_ptr< Node > &node)
std::vector< std::shared_ptr< Node > > nodes_
void remove(const std::shared_ptr< Node > &node, const Triple &triple)
void processRemoval(const TripleContainerPtr &triples)
std::shared_ptr< ObserverJob::Node > createNode(const std::shared_ptr< GraphPattern > &pattern)
NodeParents createGraph(const std::shared_ptr< GraphTerm > &term, const NodeParents &parents)
bool matches(const Node &node, const Triple &triple)
BindingsHandler callback_
void doInsert(const std::shared_ptr< Node > &node, const BindingsPtr &newBindings)
std::vector< std::shared_ptr< Node > > NodeParents
void insert(const std::shared_ptr< Node > &node, const Triple &triple)
std::shared_ptr< ObserverManager > manager_
void processInsertion(const TripleContainerPtr &triples)
GraphQueryPtr makeQuery(const std::vector< Node * > &reverseSequence)
NodeParents terminalNodes_
GraphQueryPtr makeAtomicQuery(const std::shared_ptr< Node > &node, const BindingsPtr &bindings)
virtual std::string_view valueAsString() const =0
virtual std::string_view subject() const =0
virtual std::string_view predicate() const =0
bool isObjectBlank() const
GraphTermRule & pattern()
std::shared_ptr< TripleContainer > TripleContainerPtr
std::shared_ptr< const Bindings > BindingsPtr
std::function< void(const BindingsPtr &)> BindingsHandler
std::shared_ptr< GraphQuery > GraphQueryPtr
FirstOrderLiteralPtr applyBindings(const FirstOrderLiteralPtr &lit, const Bindings &bindings)
std::shared_ptr< GraphPattern > pattern