CoreSegmentBase.h
Go to the documentation of this file.
1#pragma once
2
3#include <map>
4#include <string>
5
7
9#include "detail/AronTyped.h"
11#include "detail/Predictive.h"
14
16{
17
18 /**
19 * @brief Data of a core segment containing multiple provider segments.
20 */
21 template <class _ProviderSegmentT, class _Derived>
23 public detail::MemoryContainerBase<std::map<std::string, _ProviderSegmentT>, _Derived>,
24 public detail::AronTyped,
25 public detail::PredictiveContainer<_Derived>,
28 public detail::ForEachEntityMixin<_Derived>,
29 public detail::GetFindInstanceMixin<_Derived>,
30 public detail::GetFindSnapshotMixin<_Derived>,
31 public detail::GetFindEntityMixin<_Derived>
32 {
33 using Base =
35
36 public:
37 using typename Base::ContainerT;
38 using typename Base::DerivedT;
39
40 using ProviderSegmentT = _ProviderSegmentT;
41 using EntityT = typename ProviderSegmentT::EntityT;
42 using EntitySnapshotT = typename EntityT::EntitySnapshotT;
43 using EntityInstanceT = typename EntitySnapshotT::EntityInstanceT;
44
46
67
68
69 public:
71 {
72 }
73
74 explicit CoreSegmentBase(const std::string& name,
76 const std::vector<PredictionEngine>& predictionEngines = {}) :
78 {
79 }
80
81 explicit CoreSegmentBase(const std::string& name,
82 const MemoryID& parentID,
84 const std::vector<PredictionEngine>& predictionEngines = {}) :
85 CoreSegmentBase(parentID.withCoreSegmentName(name), aronType, predictionEngines)
86 {
87 }
88
89 explicit CoreSegmentBase(const MemoryID& id,
91 const std::vector<PredictionEngine>& predictionEngines = {}) :
92 Base(id), AronTyped(aronType), detail::PredictiveContainer<_Derived>(predictionEngines)
93 {
94 }
95
96 CoreSegmentBase(const CoreSegmentBase& other) = default;
97 CoreSegmentBase(CoreSegmentBase&& other) = default;
98 CoreSegmentBase& operator=(const CoreSegmentBase& other) = default;
100
101 // READ ACCESS
102
103 // Get key
104 inline std::string&
106 {
107 return this->id().coreSegmentName;
108 }
109
110 inline const std::string&
111 name() const
112 {
113 return this->id().coreSegmentName;
114 }
115
116 // Has child by key
117 bool
118 hasProviderSegment(const std::string& name) const
119 {
120 return this->findProviderSegment(name) != nullptr;
121 }
122
123 // Has child by memory ID
124 bool
125 hasProviderSegment(const MemoryID& providerSegmentID) const
126 {
127 return this->findProviderSegment(providerSegmentID) != nullptr;
128 }
129
130 // Find child by key
132 findProviderSegment(const std::string& name)
133 {
135 }
136
137 const ProviderSegmentT*
138 findProviderSegment(const std::string& name) const
139 {
141 }
142
143 // Get child by key
145 getProviderSegment(const std::string& name)
146 {
147 return detail::getChildByKey(name, this->_container, *this);
148 }
149
150 const ProviderSegmentT&
151 getProviderSegment(const std::string& name) const
152 {
153 return detail::getChildByKey(name, this->_container, *this);
154 }
155
156 // Find child by MemoryID
158 findProviderSegment(const MemoryID& providerSegmentID)
159 {
160 detail::checkHasProviderSegmentName(providerSegmentID);
161 return this->findProviderSegment(providerSegmentID.providerSegmentName);
162 }
163
164 const ProviderSegmentT*
165 findProviderSegment(const MemoryID& providerSegmentID) const
166 {
167 detail::checkHasProviderSegmentName(providerSegmentID);
168 return this->findProviderSegment(providerSegmentID.providerSegmentName);
169 }
170
171 // Get child by MemoryID
173 getProviderSegment(const MemoryID& providerSegmentID)
174 {
175 detail::checkHasProviderSegmentName(providerSegmentID);
176 return this->getProviderSegment(providerSegmentID.providerSegmentName);
177 }
178
179 const ProviderSegmentT&
180 getProviderSegment(const MemoryID& providerSegmentID) const
181 {
182 detail::checkHasProviderSegmentName(providerSegmentID);
183 return this->getProviderSegment(providerSegmentID.providerSegmentName);
184 }
185
186 // get/findInstance are provided by GetFindInstanceMixin
187 // get/findSnapshot are provided by GetFindSnapshotMixin
188 // get/findEntity are provided by GetFindEntityMixin
191
192 // Search all provider segments for the first matching entity.
193
194 bool
195 hasEntity(const std::string& entityName) const
196 {
197 return this->findEntity(entityName) != nullptr;
198 }
199
200 EntityT*
201 findEntity(const std::string& entityName)
202 {
203 return _findEntity(*this, entityName);
204 }
205
206 const EntityT*
207 findEntity(const std::string& entityName) const
208 {
209 return _findEntity(*this, entityName);
210 }
211
212 // ITERATION
213
214 /**
215 * @param func Function like: bool process(ProviderSegmentT& provSeg)
216 */
217 template <class ProviderSegmentFunctionT>
218 bool
219 forEachProviderSegment(ProviderSegmentFunctionT&& func)
220 {
221 return this->forEachChild(func);
222 }
223
224 /**
225 * @param func Function like: bool process(const ProviderSegmentT& provSeg)
226 */
227 template <class ProviderSegmentFunctionT>
228 bool
229 forEachProviderSegment(ProviderSegmentFunctionT&& func) const
230 {
231 return this->forEachChild(func);
232 }
233
234 // forEachEntity() is provided by ForEachEntityMixin.
235 // forEachSnapshot() is provided by ForEachEntitySnapshotMixin.
236 // forEachInstance() is provided by ForEachEntityInstanceMixin.
237
238
239 /**
240 * @param func Function like void process(EntityInstanceT& instance)>
241 */
242 template <class InstanceFunctionT>
243 bool
244 forEachInstanceIn(const MemoryID& id, InstanceFunctionT&& func)
245 {
247 func,
248 *this,
249 id.hasProviderSegmentName(),
250 id.hasProviderSegmentName()
251 ? this->findProviderSegment(id.providerSegmentName)
252 : nullptr);
253 }
254
255 /**
256 * @param func Function like void process(EntityInstanceT& instance)>
257 */
258 template <class InstanceFunctionT>
259 bool
260 forEachInstanceIn(const MemoryID& id, InstanceFunctionT&& func) const
261 {
263 func,
264 *this,
265 id.hasProviderSegmentName(),
266 id.hasProviderSegmentName()
267 ? this->findProviderSegment(id.providerSegmentName)
268 : nullptr);
269 }
270
271 // Get child keys
272 std::vector<std::string>
274 {
275 return simox::alg::get_keys(this->_container);
276 }
277
278 // MODIFICATION
279
280 /**
281 * @brief Updates an entity's history.
282 *
283 * Missing entity entries are added before updating.
284 */
285 UpdateResult
287 {
288 this->_checkContainerName(update.entityID.coreSegmentName, this->name());
289
290 auto [inserted, provSeg] =
291 _addProviderSegmentIfMissing(update.entityID.providerSegmentName);
292
293
294 // Update entry.
295 UpdateResult ret(provSeg->update(update));
296 if (inserted)
297 {
298 ret.coreSegmentUpdateType = UpdateType::InsertedNew;
299 }
300 else
301 {
302 ret.coreSegmentUpdateType = UpdateType::UpdatedExisting;
303 }
304 return ret;
305 }
306
307 template <class OtherDerivedT>
308 void
309 append(const OtherDerivedT& other)
310 {
311 other.forEachProviderSegment(
312 [this](const auto& provSeg)
313 {
314 auto it = this->_container.find(provSeg.name());
315 if (it == this->_container.end())
316 {
317 it = this->_container
318 .emplace(provSeg.name(),
319 this->id().withProviderSegmentName(provSeg.name()))
320 .first;
321 it->second.aronType() = provSeg.aronType();
322 }
323
324 /*TODO: if (it->second.aronType() != provSeg.aronType())
325 {
326 ARMARX_WARNING
327 << "When appending a coreseg to another coreseg type conflicts have "
328 "been found. Setting the type to NULL...";
329 it->second.aronType() = nullptr;
330 }*/
331
332 it->second.append(provSeg);
333 return true;
334 });
335 }
336
337 /**
338 * @brief Add an empty provider segment with the given name,
339 * optional provider segment type and prediction engines.
340 * @param name The segment name.
341 * @param providerSegmentType The provider type. If nullptr, the core segment type is used.
342 * @param predictionEngines The prediction engines supported by the provider segment (optional).
343 * @return The added provider segment.
344 */
346 addProviderSegment(const std::string& name,
347 aron::type::ObjectPtr providerSegmentType = nullptr,
348 const std::vector<PredictionEngine>& predictionEngines = {})
349 {
351 providerSegmentType ? providerSegmentType : this->aronType();
352 return this->_derived().addProviderSegment(name, name, type, predictionEngines);
353 }
354
355 /// Copy and insert a provider segment.
357 addProviderSegment(const ProviderSegmentT& providerSegment)
358 {
359 return this->_derived().addProviderSegment(providerSegment.name(),
360 ProviderSegmentT(providerSegment));
361 }
362
363 /// Move and insert a provider segment.
366 {
367 const std::string name = providerSegment.name(); // Copy before move.
368 return this->_derived().addProviderSegment(name, std::move(providerSegment));
369 }
370
371 /// Insert a provider segment in-place.
372 template <class... Args>
374 addProviderSegment(const std::string& name, Args... args)
375 {
376 ChildT& child = this->template _addChild<ChildT>(name, args...);
377 child.id() = this->id().withProviderSegmentName(name);
378 return child;
379 }
380
381 // MISC
382
383 bool
384 equalsDeep(const DerivedT& other) const
385 {
386 //std::cout << "CoreSegment::equalsDeep" << std::endl;
387 if (this->size() != other.size())
388 {
389 return false;
390 }
391 for (const auto& [key, provider] : this->_container)
392 {
393 if (not other.hasProviderSegment(key))
394 {
395 return false;
396 }
397 if (not provider.equalsDeep(other.getProviderSegment(key)))
398 {
399 return false;
400 }
401 }
402 return true;
403 }
404
405 static std::string
407 {
408 return "core segment";
409 }
410
411 std::string
413 {
414 return this->name();
415 }
416
417
418 protected:
419 template <class ParentT>
420 static auto*
421 _findEntity(ParentT&& parent, const std::string& entityName)
422 {
423 decltype(parent.findEntity(entityName)) result = nullptr;
424 parent.forEachProviderSegment(
425 [&result, &entityName](auto& provSeg)
426 {
427 result = provSeg.findEntity(entityName);
428 return result == nullptr; // Keep going if null, break if not null.
429 });
430 return result;
431 }
432
433 std::pair<bool, ProviderSegmentT*>
434 _addProviderSegmentIfMissing(const std::string& providerSegmentName)
435 {
436 ProviderSegmentT* provSeg;
437
438 auto it = this->_container.find(providerSegmentName);
439 if (it == this->_container.end())
440 {
441 if (_addMissingProviderSegmentDuringUpdate)
442 {
443 // Insert into map.
444 provSeg = &addProviderSegment(providerSegmentName);
445 return {true, provSeg};
446 }
447 else
448 {
449 throw error::MissingEntry::create<ProviderSegmentT>(providerSegmentName, *this);
450 }
451 }
452 else
453 {
454 provSeg = &it->second;
455 return {false, provSeg};
456 }
457 }
458
459
460 private:
461 bool _addMissingProviderSegmentDuringUpdate = true;
462 };
463
464} // namespace armarx::armem::base
constexpr T c
std::string coreSegmentName
Definition MemoryID.h:51
MemoryID withProviderSegmentName(const std::string &name) const
Definition MemoryID.cpp:417
std::string providerSegmentName
Definition MemoryID.h:52
Data of a core segment containing multiple provider segments.
CoreSegmentBase(const MemoryID &id, aron::type::ObjectPtr aronType=nullptr, const std::vector< PredictionEngine > &predictionEngines={})
typename ProviderSegmentT::EntityT EntityT
typename EntityT::EntitySnapshotT EntitySnapshotT
CoreSegmentBase(const std::string &name, aron::type::ObjectPtr aronType=nullptr, const std::vector< PredictionEngine > &predictionEngines={})
bool forEachInstanceIn(const MemoryID &id, InstanceFunctionT &&func)
EntityT * findEntity(const std::string &entityName)
bool hasProviderSegment(const MemoryID &providerSegmentID) const
ProviderSegmentT & addProviderSegment(const std::string &name, aron::type::ObjectPtr providerSegmentType=nullptr, const std::vector< PredictionEngine > &predictionEngines={})
Add an empty provider segment with the given name, optional provider segment type and prediction engi...
static auto * _findEntity(ParentT &&parent, const std::string &entityName)
const std::string & name() const
CoreSegmentBase & operator=(const CoreSegmentBase &other)=default
CoreSegmentBase(const std::string &name, const MemoryID &parentID, aron::type::ObjectPtr aronType=nullptr, const std::vector< PredictionEngine > &predictionEngines={})
bool equalsDeep(const DerivedT &other) const
bool hasProviderSegment(const std::string &name) const
bool forEachProviderSegment(ProviderSegmentFunctionT &&func)
ProviderSegmentT & addProviderSegment(ProviderSegmentT &&providerSegment)
Move and insert a provider segment.
const ProviderSegmentT & getProviderSegment(const MemoryID &providerSegmentID) const
bool hasEntity(const std::string &entityName) const
const ProviderSegmentT * findProviderSegment(const std::string &name) const
bool forEachInstanceIn(const MemoryID &id, InstanceFunctionT &&func) const
const EntityT * findEntity(const std::string &entityName) const
ProviderSegmentT * findProviderSegment(const MemoryID &providerSegmentID)
const ProviderSegmentT & getProviderSegment(const std::string &name) const
void append(const OtherDerivedT &other)
typename EntitySnapshotT::EntityInstanceT EntityInstanceT
std::vector< std::string > getProviderSegmentNames() const
ProviderSegmentT & getProviderSegment(const std::string &name)
std::pair< bool, ProviderSegmentT * > _addProviderSegmentIfMissing(const std::string &providerSegmentName)
CoreSegmentBase & operator=(CoreSegmentBase &&other)=default
ProviderSegmentT & addProviderSegment(const std::string &name, Args... args)
Insert a provider segment in-place.
ProviderSegmentT & addProviderSegment(const ProviderSegmentT &providerSegment)
Copy and insert a provider segment.
ProviderSegmentT & getProviderSegment(const MemoryID &providerSegmentID)
CoreSegmentBase(CoreSegmentBase &&other)=default
UpdateResult update(const EntityUpdate &update)
Updates an entity's history.
ProviderSegmentT * findProviderSegment(const std::string &name)
const ProviderSegmentT * findProviderSegment(const MemoryID &providerSegmentID) const
CoreSegmentBase(const CoreSegmentBase &other)=default
bool forEachProviderSegment(ProviderSegmentFunctionT &&func) const
Something with a specific ARON type.
Definition AronTyped.h:12
aron::type::ObjectPtr & aronType()
Definition AronTyped.cpp:19
AronTyped(aron::type::ObjectPtr aronType=nullptr)
Definition AronTyped.cpp:8
Provides default implmentations of MemoryContainer, as well as iterators (which requires a template).
void _checkContainerName(const std::string &gottenName, const std::string &actualName, bool emptyOk=true) const
Something that supports a set of prediction engines.
Definition Predictive.h:89
const std::vector< PredictionEngine > & predictionEngines() const
Definition Predictive.h:46
static MissingEntry create(const std::string &missingKey, const ContainerT &container)
Definition ArMemError.h:79
void checkHasProviderSegmentName(const MemoryID &providerSegmentID)
Throw armem::error::InvalidMemoryID if the given ID has provider segment name.
auto & getChildByKey(const KeyT &key, ContainerT &&container, const ParentT &owner, KeyStringFn &&keyStringFn)
Retrieve a child in a container by its key.
bool forEachInstanceIn(const MemoryID &id, FunctionT &&func, ParentT &parent, bool single, ChildT *child)
auto * findChildByKey(const KeyT &key, ContainerT &&container)
Find a child in a container by its key.
UpdateType
The type of an update.
Definition Commit.h:17
std::shared_ptr< Object > ObjectPtr
Definition Object.h:36
An update of an entity for a specific point in time.
Definition Commit.h:26
MemoryID entityID
The entity's ID.
Definition Commit.h:28
UpdateResult(const typename ProviderSegmentT::UpdateResult &c)