Reader.cpp
Go to the documentation of this file.
1#include "Reader.h"
2
3#include <algorithm>
4#include <cstddef>
5#include <map>
6#include <mutex>
7#include <optional>
8#include <set>
9#include <sstream>
10#include <string>
11#include <utility>
12#include <vector>
13
14#include <unistd.h> // For getpid()
15
16#include <Ice/Current.h>
17#include <Ice/Exception.h>
18#include <Ice/LocalException.h>
19
22#include <ArmarXCore/core/ice_conversions/ice_conversions_templates.tpp>
24#include <ArmarXCore/interface/core/time.h>
25
38#include <RobotAPI/interface/armem/prediction.h>
39#include <RobotAPI/interface/armem/query.h>
40#include <RobotAPI/interface/armem/server/PredictingMemoryInterface.h>
41#include <RobotAPI/interface/armem/server/ReadingLongTermMemoryInterface.h>
42#include <RobotAPI/interface/armem/server/ReadingMemoryInterface.h>
43#include <RobotAPI/interface/armem/server/RecordingMemoryInterface.h>
44#include <RobotAPI/libraries/armem/aron/MemoryID.aron.generated.h>
45#include <RobotAPI/libraries/armem/aron/MemoryLink.aron.generated.h>
52
53#include "query/Builder.h"
54#include "query/query_fns.h"
55
57{
58
59 Reader::Reader(server::ReadingMemoryInterfacePrx readingMemory,
60 server::PredictingMemoryInterfacePrx predictingMemory,
61 server::ReadingLongTermMemoryInterfacePrx readingLtmMemory) :
62 readingPrx(readingMemory), predictionPrx(predictingMemory), readingLtmPrx(readingLtmMemory)
63 {
64 // Automatically add PID to Ice context for client tracking
65 Ice::Context ctx;
66 ctx["clientPid"] = std::to_string(getpid());
67
68 if (readingMemory)
69 {
70 this->readingPrx = readingMemory->ice_context(ctx);
71 }
72 if (predictingMemory)
73 {
74 this->predictionPrx = predictingMemory->ice_context(ctx);
75 }
76 if (readingLtmMemory)
77 {
78 this->readingLtmPrx = readingLtmMemory->ice_context(ctx);
79 }
80 }
81
83 Reader::queryLTM(const QueryInput& input, bool storeIntoWM) const
84 {
85 return QueryResult::fromIce(queryLTM(input.toIce(), storeIntoWM));
86 }
87
88 armem::query::data::Result
89 Reader::queryLTM(const armem::query::data::Input& input, bool storeIntoWM) const
90 {
91 armem::query::data::Result result;
92 if (!readingPrx)
93 {
94 throw error::ProxyNotSet("ReadingMemoryInterfacePrx",
95 "Reading interface proxy must be set to perform a query.");
96 }
97
98 try
99 {
100 result = readingLtmPrx->queryLTM(input, storeIntoWM);
101 }
102 catch (const ::Ice::ConnectionRefusedException& e)
103 {
104 // the proxy is invalid. we must perform a reconnect
105 ARMARX_INFO << "Trying to reconnect ...";
106 }
107 catch (const Ice::LocalException& e)
108 {
109 std::stringstream sstream;
110 sstream << "Memory query failed.\nReason: " << e.what();
111 result.errorMessage = sstream.str();
112
113 ARMARX_VERBOSE << result.errorMessage;
114 }
115 return result;
116 }
117
119 Reader::query(const QueryInput& input) const
120 {
121 return QueryResult::fromIce(query(input.toIce()));
122 }
123
124 armem::query::data::Result
125 Reader::query(const armem::query::data::Input& input) const
126 {
127 armem::query::data::Result result;
128 if (!readingPrx)
129 {
130 throw error::ProxyNotSet("ReadingMemoryInterfacePrx",
131 "Reading interface proxy must be set to perform a query.");
132 }
133
134 try
135 {
136 result = readingPrx->query(input);
137 }
138 catch (const ::Ice::ConnectionRefusedException& e)
139 {
140 // the proxy is invalid. we must perform a reconnect
141 ARMARX_INFO << "Proxy is invalid. Must reconnect.";
142 }
143 catch (const Ice::LocalException& e)
144 {
145 std::stringstream sstream;
146 sstream << "Memory query failed.\nReason: " << e.what();
147 result.errorMessage = sstream.str();
148
149 ARMARX_VERBOSE << result.errorMessage;
150 }
151 return result;
152 }
153
155 Reader::query(armem::query::data::MemoryQueryPtr query, armem::query::DataMode dataMode) const
156 {
157 return this->query(armem::query::data::MemoryQuerySeq{query}, dataMode);
158 }
159
161 Reader::query(const armem::query::data::MemoryQuerySeq& queries,
162 armem::query::DataMode dataMode) const
163 {
164 QueryInput input;
165 input.memoryQueries = queries;
166 input.dataMode = dataMode;
167 return this->query(input);
168 }
169
171 Reader::query(const QueryBuilder& queryBuilder) const
172 {
173 return this->query(queryBuilder.buildQueryInput());
174 }
175
179 int recursionDepth) const
180 {
181 return QueryResult::fromIce(query(input.toIce(), mns, recursionDepth));
182 }
183
184 armem::query::data::Result
185 Reader::query(const armem::query::data::Input& input,
187 int recursionDepth) const
188 {
189 if (!readingPrx)
190 {
191 throw error::ProxyNotSet("ReadingMemoryInterfacePrx",
192 "Reading interface proxy must be set to perform a query.");
193 }
194
195 armem::query::data::Result result;
196 try
197 {
198 result = readingPrx->query(input);
199 QueryResult bObj = QueryResult::fromIce(result);
201 [&bObj, &mns, recursionDepth](armem::wm::EntityInstance& instance)
202 { resolveMemoryLinks(instance, bObj.memory, mns, recursionDepth); });
203 result = bObj.toIce();
204 }
205 catch (const Ice::LocalException& e)
206 {
207 std::stringstream sstream;
208 sstream << "Memory query failed.\nReason: " << e.what();
209 result.errorMessage = sstream.str();
210 }
212 {
213 std::stringstream sstream;
214 sstream << "Encountered malformed MemoryLink: " << e.what();
215 result.errorMessage = sstream.str();
216 }
217
218 return result;
219 }
220
222 Reader::query(armem::query::data::MemoryQueryPtr query, // NOLINT
224 int recursionDepth) const
225 {
226 return this->query(armem::query::data::MemoryQuerySeq{query}, mns, recursionDepth);
227 }
228
230 Reader::query(const armem::query::data::MemoryQuerySeq& queries,
232 int recursionDepth) const
233 {
234 QueryInput input;
235 input.memoryQueries = queries;
236 return this->query(input, mns, recursionDepth);
237 }
238
240 Reader::query(const QueryBuilder& queryBuilder,
242 int recursionDepth) const
243 {
244 return this->query(queryBuilder.buildQueryInput(), mns, recursionDepth);
245 }
246
247 /**
248 * Get the MemoryID and data required to fill in the given MemoryLink.
249 *
250 * Returns nothing if the data could not be retrieved or its type does not
251 * match the MemoryLink's template type.
252 *
253 * @param linkData the data object of the MemoryLink
254 * @param linkType the type object of the MemoryLink
255 * @return a pair of memoryID and data to fill in a MemoryLink, or nothing if not available
256 */
257 std::optional<std::pair<MemoryID, aron::data::VariantPtr>>
259 const aron::type::VariantPtr& linkType,
261 {
262 static const aron::Path memoryLinkIDPath{{"memoryID"}};
263 static const aron::Path memoryLinkDataPath{{"data"}};
264 armem::arondto::MemoryID dto;
265 auto memoryIDDict =
266 aron::data::Dict::DynamicCastAndCheck(linkData->navigateAbsolute(memoryLinkIDPath));
267 dto.fromAron(memoryIDDict);
268 auto memoryID = aron::fromAron<armem::MemoryID>(dto);
269 if (!memoryID.isWellDefined() || !memoryID.hasEntityName())
270 {
271 ARMARX_INFO << "Encountered unresolvable MemoryID '" << memoryID.str()
272 << "', ignoring.";
273 return {};
274 }
275
276 auto nextMemory = resolveID(mns, memoryID);
277 if (!nextMemory)
278 {
279 ARMARX_WARNING << "Could not retrieve data for " << memoryID.str() << ", skipping...";
280 return {};
281 }
282 auto nextDataAndType = extractDataAndType(nextMemory.value(), memoryID);
283 if (!nextDataAndType)
284 {
285 ARMARX_WARNING << "Data or type for " << memoryID.str()
286 << " not available in memory containing that MemoryID.";
287 return {};
288 }
289 auto [nextData, nextType] = nextDataAndType.value();
290 auto linkTemplate =
291 aron::type::Object::DynamicCastAndCheck(linkType)->getTemplateInstantiations().at(0);
292 std::string nextObjectName = nextType->getObjectNameWithTemplateInstantiations();
293 if (nextType->getObjectName() != linkTemplate)
294 {
295 ARMARX_WARNING << "Linked object " << memoryID.str() << " is of the type "
296 << nextType->getObjectName() << ", but the link requires the type "
297 << linkTemplate;
298 return {};
299 }
300 return {{memoryID,
301 // This is currently the only method to prefix the path to the data correctly.
303 nextData->toAronDTO(),
304 linkData->getPath().withElement(memoryLinkDataPath.toString()))}};
305 }
306
307 void
308 Reader::resolveMemoryLinks(armem::wm::EntityInstance& instance,
309 armem::wm::Memory& input,
311 int recursionDepth)
312 {
313 static const aron::Path memoryLinkDataPath{{"data"}};
314 // MemoryID is used for the template instantiation as a placeholder -
315 // you could use any type here.
316 static const std::string linkType =
317 arondto::MemoryLink<arondto::MemoryID>::ToAronType()->getFullName();
318
319 std::set<armem::MemoryID> seenIDs{instance.id()};
320 std::vector<aron::Path> currentPaths{{{""}}};
321 std::vector<aron::Path> nextPaths;
322 int depth = 0;
323
324 auto dataAndType = extractDataAndType(input, instance.id());
325 if (!dataAndType)
326 {
327 ARMARX_INFO << "Instance '" << instance.id().str() << "' does not have a defined type.";
328 return;
329 }
330 auto [instanceData, instanceType] = dataAndType.value();
331 while (!currentPaths.empty() && (recursionDepth == -1 || depth < recursionDepth))
332 {
333 for (const auto& path : currentPaths)
334 {
335 aron::SubObjectFinder finder(linkType);
336 if (path.getFirstElement().empty())
337 {
338 armarx::aron::data::visitRecursive(finder, instanceData, instanceType);
339 }
340 else
341 {
343 instanceData->navigateAbsolute(path),
344 instanceType->navigateAbsolute(path));
345 }
346
347 for (auto& [linkPathStr, linkDataAndType] : finder.getFoundObjects()) // NOLINT
348 {
349 auto [linkData, linkType] = linkDataAndType;
350 auto result = findDataForLink(linkData, linkType, mns);
351 if (result)
352 {
353 auto [memoryID, dataToAppend] = result.value();
354 if (seenIDs.find(memoryID) != seenIDs.end())
355 {
356 continue;
357 }
358 seenIDs.insert(memoryID);
359
360 aron::data::Dict::DynamicCastAndCheck(linkData)->setElement(
361 memoryLinkDataPath.toString(), dataToAppend);
362 nextPaths.push_back(
363 linkData->getPath().withElement(memoryLinkDataPath.toString()));
364 }
365 }
366 }
367 currentPaths = std::move(nextPaths);
368 nextPaths.clear();
369 ++depth;
370 }
371 }
372
374 Reader::queryMemoryIDs(const std::vector<MemoryID>& ids, armem::query::DataMode dataMode) const
375 {
376 using namespace client::query_fns;
377
378 query::Builder qb(dataMode);
379 for (const MemoryID& id : ids)
380 {
381 query::EntitySelector& entity =
382 qb.coreSegments(withID(id)).providerSegments(withID(id)).entities(withID(id));
383
384 if (id.hasTimestamp())
385 {
386 entity.snapshots(withID(id));
387 }
388 else
389 {
390 entity.snapshots(latest());
391 }
392 }
393 return query(qb);
394 }
395
396 std::optional<wm::EntitySnapshot>
397 Reader::getLatestSnapshotOf(const std::vector<MemoryID>& _snapshotIDs) const
398 {
399 std::vector<MemoryID> snapshotIDs = _snapshotIDs;
400
401 client::QueryResult result = this->queryMemoryIDs(snapshotIDs);
402 if (result.success)
403 {
404 std::sort(snapshotIDs.begin(), snapshotIDs.end(), compareTimestampDecreasing);
405 for (const MemoryID& snapshotID : snapshotIDs)
406 {
407 try
408 {
409 wm::EntitySnapshot& snapshot = result.memory.getSnapshot(snapshotID);
410 return snapshot;
411 }
412 catch (const armem::error::ArMemError&)
413 {
414 }
415 }
416 return std::nullopt;
417 }
418 else
419 {
420 ARMARX_INFO << "Error querying " << snapshotIDs.size() << " STT snapshots:\n"
421 << result.errorMessage;
422 return std::nullopt;
423 }
424 }
425
428 {
429 using namespace client::query_fns;
430 if (!id.isWellDefined())
431 {
432 throw armem::error::InvalidMemoryID(id, "ID must be well defined, but was not.");
433 }
434
435 query::Builder qb(dataMode);
437 id.hasCoreSegmentName() ? qb.coreSegments(withID(id)) : qb.coreSegments(all());
438 query::ProviderSegmentSelector& prov = id.hasProviderSegmentName()
439 ? core.providerSegments(withID(id))
440 : core.providerSegments(all());
441 query::EntitySelector& entity =
442 id.hasEntityName() ? prov.entities(withID(id)) : prov.entities(all());
443 entity.snapshots(latest());
444
445 return query(qb);
446 }
447
448 std::optional<wm::EntitySnapshot>
450 {
451 client::QueryResult result = getLatestSnapshotsIn(id, dataMode);
452 if (result.success)
453 {
454 std::optional<wm::EntitySnapshot> latest = std::nullopt;
455 result.memory.forEachEntity(
456 [&latest](const wm::Entity& entity)
457 {
458 if (not entity.empty())
459 {
460 const wm::EntitySnapshot& snapshot = entity.getLatestSnapshot();
461 if (not latest.has_value() or latest->time() < snapshot.time())
462 {
463 latest = snapshot;
464 }
465 }
466 return true;
467 });
468 return latest;
469 }
470 else
471 {
472 ARMARX_INFO << "Error querying latest snapshot in " << id;
473 return std::nullopt;
474 }
475 }
476
479 {
480 using namespace client::query_fns;
481
482 query::Builder qb(dataMode);
483 qb.coreSegments(all()).providerSegments(all()).entities(all()).snapshots(latest());
484
485 return this->query(qb);
486 }
487
490 {
491 using namespace client::query_fns;
492
493 query::Builder qb(dataMode);
494 qb.coreSegments(all()).providerSegments(all()).entities(all()).snapshots(all());
495
496 return this->query(qb);
497 }
498
499 server::dto::DirectlyStoreResult
500 Reader::directlyStore(const server::dto::DirectlyStoreInput& input) const
501 {
502 server::RecordingMemoryInterfacePrx storingMemoryPrx =
503 server::RecordingMemoryInterfacePrx::checkedCast(readingPrx);
504 if (storingMemoryPrx)
505 {
506 return storingMemoryPrx->directlyStore(input);
507 }
508 else
509 {
510 ARMARX_WARNING << "Could not store a query into the LTM. It seems like the Memory does "
511 "not implement the StoringMemoryInterface.";
512 return {};
513 }
514 }
515
516 void
518 {
519 server::RecordingMemoryInterfacePrx storingMemoryPrx =
520 server::RecordingMemoryInterfacePrx::checkedCast(readingPrx);
521 if (storingMemoryPrx)
522 {
523 server::dto::StartRecordInput i;
524 i.executionTime = armarx::core::time::dto::DateTime();
525 i.startTime = armarx::core::time::dto::DateTime();
526 i.recordingID = "";
527 i.configuration.clear();
528
529 // Use async call to avoid blocking the GUI thread.
530 // We call begin_startRecord() but don't call end_startRecord() because we don't need
531 // to wait for the result or know if it succeeded - this is a fire-and-forget operation.
532 // The remote server will handle startRecord() asynchronously and we return immediately.
533 storingMemoryPrx->begin_startRecord(i);
534 return;
535 }
536 else
537 {
538 ARMARX_WARNING << "Could not store a query into the LTM. It seems like the Memory does "
539 "not implement the StoringMemoryInterface.";
540 }
541 }
542
543 void
545 {
546 server::RecordingMemoryInterfacePrx storingMemoryPrx =
547 server::RecordingMemoryInterfacePrx::checkedCast(readingPrx);
548 if (storingMemoryPrx)
549 {
550 // Use async call to avoid blocking the GUI thread.
551 // We call begin_stopRecord() but don't call end_stopRecord() because we don't need
552 // to wait for the result or know if it succeeded - this is a fire-and-forget operation.
553 // The remote server will handle stopRecord() asynchronously and we return immediately.
554 storingMemoryPrx->begin_stopRecord();
555 return;
556 }
557 else
558 {
559 ARMARX_WARNING << "Could not store a query into the LTM. It seems like the Memory does "
560 "not implement the StoringMemoryInterface.";
561 }
562 }
563
564 void
565 Reader::setReadingMemory(server::ReadingMemoryInterfacePrx readingMemory)
566 {
567 this->readingPrx = readingMemory;
568 }
569
570 void
571 Reader::setPredictingMemory(server::PredictingMemoryInterfacePrx predictingMemory)
572 {
573 this->predictionPrx = predictingMemory;
574 }
575
576 std::vector<PredictionResult>
577 Reader::predict(const std::vector<PredictionRequest>& requests) const
578 {
579 if (!predictionPrx)
580 {
581 throw error::ProxyNotSet(
582 "PredictingMemoryInterfacePrx",
583 "Prediction interface proxy must be set to request a prediction.");
584 }
585
586 armem::prediction::data::PredictionRequestSeq iceRequests;
587 for (const auto& request : requests)
588 {
589 iceRequests.push_back(request.toIce());
590 }
591
592 armem::prediction::data::PredictionResultSeq results;
593 try
594 {
595 results = predictionPrx->predict(iceRequests);
596 }
597 catch (const Ice::LocalException& e)
598 {
599 armem::prediction::data::PredictionResult failure;
600 failure.success = false;
601 std::stringstream sstream;
602 sstream << "Prediction request failed. Reason: " << e.what();
603 failure.errorMessage = sstream.str();
604
605 for (size_t i = 0; i < requests.size(); ++i)
606 {
607 results.push_back(failure);
608 }
609 }
610
611 std::vector<PredictionResult> boResults;
612 for (const auto& result : results)
613 {
614 boResults.push_back(PredictionResult::fromIce(result));
615 }
616
617 return boResults;
618 }
619
620 std::map<MemoryID, std::vector<PredictionEngine>>
622 {
623 if (!predictionPrx)
624 {
625 throw error::ProxyNotSet(
626 "PredictingMemoryInterfacePrx",
627 "Prediction interface proxy must be set to request a prediction.");
628 }
629
630 armem::prediction::data::EngineSupportMap engines;
631 try
632 {
633 engines = predictionPrx->getAvailableEngines();
634 }
635 catch (const Ice::LocalException& e)
636 {
637 // Just leave engines empty in this case.
638 }
639
640 std::map<MemoryID, std::vector<PredictionEngine>> boMap;
641 armarx::fromIce(engines, boMap);
642
643 return boMap;
644 }
645} // namespace armarx::armem::client
bool isWellDefined() const
Indicate whether this ID is well-defined.
Definition MemoryID.cpp:182
bool hasEntityName() const
Definition MemoryID.h:121
std::string str(bool escapeDelimiters=true) const
Get a string representation of this memory ID.
Definition MemoryID.cpp:102
The memory name system (MNS) client.
std::map< MemoryID, std::vector< PredictionEngine > > getAvailablePredictionEngines() const
Get the list of prediction engines supported by the memory.
Definition Reader.cpp:621
QueryResult query(const QueryInput &input) const
Perform a query on the WM.
Definition Reader.cpp:119
std::optional< wm::EntitySnapshot > getLatestSnapshotIn(const MemoryID &id, armem::query::DataMode dataMode=armem::query::DataMode::WithData) const
Get the latest snapshot under the given memory ID.
Definition Reader.cpp:449
Reader(const Reader &)=default
Construct a memory reader.
server::ReadingMemoryInterfacePrx readingPrx
Definition Reader.h:227
QueryResult getLatestSnapshotsIn(const MemoryID &id, armem::query::DataMode dataMode=armem::query::DataMode::WithData) const
Get the latest snapshots under the given memory ID.
Definition Reader.cpp:427
QueryResult getAll(armem::query::DataMode dataMode=armem::query::DataMode::WithData) const
Get the whole memory content.
Definition Reader.cpp:489
QueryResult queryMemoryIDs(const std::vector< MemoryID > &ids, armem::query::DataMode dataMode=armem::query::DataMode::WithData) const
Query a specific set of memory IDs.
Definition Reader.cpp:374
void setReadingMemory(server::ReadingMemoryInterfacePrx readingMemory)
Definition Reader.cpp:565
void setPredictingMemory(server::PredictingMemoryInterfacePrx predictingMemory)
Definition Reader.cpp:571
server::dto::DirectlyStoreResult directlyStore(const server::dto::DirectlyStoreInput &input) const
Definition Reader.cpp:500
std::vector< PredictionResult > predict(const std::vector< PredictionRequest > &requests) const
Get a prediction for the state of multiple entity instances in the future.
Definition Reader.cpp:577
server::PredictingMemoryInterfacePrx predictionPrx
Definition Reader.h:228
QueryResult getAllLatestSnapshots(armem::query::DataMode dataMode=armem::query::DataMode::WithData) const
Get all latest snapshots in the memory.
Definition Reader.cpp:478
QueryResult queryLTM(const QueryInput &input, bool storeIntoWM=false) const
Queries the linked ltms.
Definition Reader.cpp:83
server::ReadingLongTermMemoryInterfacePrx readingLtmPrx
Definition Reader.h:229
std::optional< wm::EntitySnapshot > getLatestSnapshotOf(const std::vector< MemoryID > &snapshotIDs) const
Query the given snapshot and return the latest existing snapshot.
Definition Reader.cpp:397
The query::Builder class provides a fluent-style specification of hierarchical queries.
Definition Builder.h:22
CoreSegmentSelector & coreSegments()
Start specifying core segments.
Definition Builder.cpp:42
ProviderSegmentSelector & providerSegments()
Start specifying provider segments.
SnapshotSelector & snapshots()
Start specifying entity snapshots.
Definition selectors.cpp:92
EntitySelector & entities()
Start specifying entities.
Base class for all exceptions thrown by the armem library.
Definition ArMemError.h:19
Indicates that a memory ID is invalid, e.g.
Definition ArMemError.h:152
Indicates that a proxy required for an operation wasn't usable.
Definition ArMemError.h:216
Client-side working entity instance.
Client-side working memory.
The Path class.
Definition Path.h:36
static VariantPtr FromAronDTO(const data::dto::GenericDataPtr &, const Path &=Path())
create a variant from a dto object
Definition Variant.cpp:39
This exception is thrown if the macro ARMARX_CHECK_EXPRESSION is used.
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:187
This file is part of ArmarX.
std::optional< std::pair< MemoryID, aron::data::VariantPtr > > findDataForLink(const aron::data::VariantPtr &linkData, const aron::type::VariantPtr &linkType, armem::client::MemoryNameSystem &mns)
Get the MemoryID and data required to fill in the given MemoryLink.
Definition Reader.cpp:258
const MemoryID memoryID
armem::wm::EntitySnapshot EntitySnapshot
bool compareTimestampDecreasing(const MemoryID &lhs, const MemoryID &rhs)
lhs.timestamp > rhs.timstamp
std::optional< std::pair< armarx::aron::data::DictPtr, armarx::aron::type::ObjectPtr > > extractDataAndType(const armarx::armem::wm::Memory &memory, const armarx::armem::MemoryID &memoryID)
get the data and type of the given MemoryID in the given Memory.
Definition util.cpp:34
std::optional< armarx::armem::wm::Memory > resolveID(armarx::armem::client::MemoryNameSystem &mns, const armarx::armem::MemoryID &memoryID)
resolve a single MemoryID with the given MemoryNameSystem.
Definition util.cpp:10
std::shared_ptr< Variant > VariantPtr
void visitRecursive(RecursiveVisitorImplementation &v, typename RecursiveVisitorImplementation::Input &o)
std::shared_ptr< Variant > VariantPtr
void fromAron(const T &dto, T &bo)
void fromIce(const std::map< IceKeyT, IceValueT > &iceMap, boost::container::flat_map< CppKeyT, CppValueT > &cppMap)
static PredictionResult fromIce(const armem::prediction::data::PredictionResult &ice)
auto & getSnapshot(const MemoryID &snapshotID)
Retrieve an entity snapshot.
auto & getLatestSnapshot(int snapshotIndex=0)
Retrieve the latest entity snapshot.
A query for parts of a memory.
Definition Query.h:24
armem::query::data::MemoryQuerySeq memoryQueries
The queries.
Definition Query.h:28
Result of a QueryInput.
Definition Query.h:51
wm::Memory memory
The slice of the memory that matched the query.
Definition Query.h:58
static QueryResult fromIce(const armem::query::data::Result &ice)
Definition Query.cpp:26
armem::query::data::Result toIce() const
Definition Query.cpp:32