EntitySnapshotBase.h
Go to the documentation of this file.
1#pragma once
2
3#include <vector>
4
7
12
14{
15 void throwIfNotEqual(const Time& ownTime, const Time& updateTime);
16}
17
18namespace armarx::armem::base
19{
20 /**
21 * @brief Data of an entity at one point in time.
22 */
23 template <class _EntityInstanceT, class _Derived>
25 public detail::MemoryContainerBase<std::vector<_EntityInstanceT>, _Derived>
26 {
28
29 public:
30 using typename Base::ContainerT;
31 using typename Base::DerivedT;
32
33 using EntityInstanceT = _EntityInstanceT;
34
35
36 public:
38 {
39 }
40
41 explicit EntitySnapshotBase(Time time, const MemoryID& parentID = {}) :
42 EntitySnapshotBase(parentID.withTimestamp(time))
43 {
44 }
45
46 explicit EntitySnapshotBase(const MemoryID& id) : Base(id)
47 {
48 }
49
50 EntitySnapshotBase(const EntitySnapshotBase& other) = default;
54
55 // READING
56
57 // Get key
58 inline Time&
60 {
61 return this->id().timestamp;
62 }
63
64 inline const Time&
65 time() const
66 {
67 return this->id().timestamp;
68 }
69
70 /// Indicate whether this snapshot has any instances.
71 bool
73 {
74 return not this->empty();
75 }
76
77 // Has child by key
78 bool
79 hasInstance(int index) const
80 {
81 return this->findInstance(index) != nullptr;
82 }
83
84 // Has child by ID
85 bool
86 hasInstance(const MemoryID& instanceID) const
87 {
88 return this->findInstance(instanceID) != nullptr;
89 }
90
91 // Find child by key
94 {
95 return const_cast<EntityInstanceT*>(
96 const_cast<const EntitySnapshotBase*>(this)->findInstance(index));
97 }
98
99 const EntityInstanceT*
101 {
102 const size_t si = static_cast<size_t>(index);
103 return (index >= 0 && si < this->_container.size()) ? &this->_container[si] : nullptr;
104 }
105
106 // Get child by key
107 /**
108 * @brief Get the given instance.
109 * @param index The instance's index.
110 * @return The instance.
111 * @throw `armem::error::MissingEntry` If the given index is invalid.
112 */
115 {
116 return const_cast<EntityInstanceT&>(
117 const_cast<const EntitySnapshotBase*>(this)->getInstance(index));
118 }
119
120 const EntityInstanceT&
122 {
123 if (const EntityInstanceT* instance = findInstance(index))
124 {
125 return *instance;
126 }
127 else
128 {
130 *this);
131 }
132 }
133
134 // Find child by MemoryID
136 findInstance(const MemoryID& instanceID)
137 {
139 return this->findInstance(instanceID.instanceIndex);
140 }
141
142 const EntityInstanceT*
143 findInstance(const MemoryID& instanceID) const
144 {
146 return this->findInstance(instanceID.instanceIndex);
147 }
148
149 // Get child by MemoryID
150 /**
151 * @brief Get the given instance.
152 * @param index The instance's index.
153 * @return The instance.
154 * @throw `armem::error::MissingEntry` If the given index is invalid.
155 * @throw `armem::error::InvalidMemoryID` If memory ID does not have an instance index.
156 */
158 getInstance(const MemoryID& instanceID)
159 {
161 return this->getInstance(instanceID.instanceIndex);
162 }
163
164 const EntityInstanceT&
165 getInstance(const MemoryID& instanceID) const
166 {
168 return this->getInstance(instanceID.instanceIndex);
169 }
170
171 // ITERATION
172
173 /**
174 * @param func Function like void process(EntityInstanceT& instance)>
175 */
176 template <class InstanceFunctionT>
177 bool
178 forEachInstance(InstanceFunctionT&& func)
179 {
180 return this->forEachChild(func);
181 }
182
183 /**
184 * @param func Function like void process (const EntityInstanceT& instance)
185 */
186 template <class InstanceFunctionT>
187 bool
188 forEachInstance(InstanceFunctionT&& func) const
189 {
190 return this->forEachChild(func);
191 }
192
193 /**
194 * @param func Function like void process(EntityInstanceT& instance)>
195 */
196 template <class InstanceFunctionT>
197 bool
198 forEachInstanceIn(const MemoryID& id, InstanceFunctionT&& func)
199 {
200 if (id.hasInstanceIndex())
201 {
202 EntityInstanceT* child = findInstance(id.instanceIndex);
203 return child ? base::detail::call(func, *child) : true;
204 }
205 else
206 {
207 return this->forEachInstance(func);
208 }
209 }
210
211 /**
212 * @param func Function like void process (const EntityInstanceT& instance)
213 */
214 template <class InstanceFunctionT>
215 bool
216 forEachInstanceIn(const MemoryID& id, InstanceFunctionT&& func) const
217 {
218 if (id.hasInstanceIndex())
219 {
220 const EntityInstanceT* child = findInstance(id.instanceIndex);
221 return child ? base::detail::call(func, *child) : true;
222 }
223 else
224 {
225 return this->forEachInstance(func);
226 }
227 }
228
229 // Get child keys
230 std::vector<int>
232 {
233 std::vector<int> indices;
234 indices.reserve(this->size());
235 for (size_t i = 0; i < this->size(); ++i)
236 {
237 indices.push_back(static_cast<int>(i));
238 }
239 return indices;
240 }
241
242 // MODIFICATION
243
244 void
246 {
247 detail::throwIfNotEqual(time(), update.referencedTime);
248
249 this->_container.clear();
250 for (int index = 0; index < int(update.instancesData.size()); ++index)
251 {
252 EntityInstanceT& data = this->_container.emplace_back(index, this->id());
253 data.update(update);
254 }
255 }
256
257 /**
258 * @brief Add a single instance with data.
259 * @param instance The instance.
260 * @return The stored instance.
261 * @throw `armem::error::InvalidArgument` If the given index is invalid. Must be equal to container.size() or -1 (meaning push_back)
262 */
265 {
266 return addInstance(EntityInstanceT(instance));
267 }
268
271 {
272 if (instance.index() > 0 &&
273 static_cast<size_t>(instance.index()) > this->_container.size())
274 {
276 std::to_string(instance.index()),
277 "EntitySnapshot::addInstance",
278 "Cannot add an EntityInstance because its index is too big.");
279 }
280
281 int index = instance.index();
282 EntityInstanceT& added = this->_container.emplace_back(std::move(instance));
283
284 added.id() = this->id().withInstanceIndex(index);
285 return added;
286 }
287
290 {
291 //ARMARX_INFO << "Trying to add an instance without instance yet generated";
292 int index = static_cast<int>(
293 this->size()); //this is the problem, because instances have names 0 and 11 (I do not know why)
294 EntityInstanceT& added = this->_container.emplace_back(EntityInstanceT());
295 added.id() = this->id().withInstanceIndex(index);
296 return added;
297 }
298
299 // MISC
300
301 bool
302 equalsDeep(const DerivedT& other) const
303 {
304 //std::cout << "EntitySnapshot::equalsDeep" << std::endl;
305 if (this->size() != other.size())
306 {
307 return false;
308 }
309 int i = 0;
310 for (const auto& instance : this->_container)
311 {
312 if (not instance.equalsDeep(other.getInstance(i)))
313 {
314 return false;
315 }
316 i++;
317 }
318 return true;
319 }
320
321 std::string
323 {
324 return toDateTimeMilliSeconds(this->time());
325 }
326
327 static std::string
329 {
330 return "entity snapshot";
331 }
332 };
333
334} // namespace armarx::armem::base
MemoryID withInstanceIndex(int index) const
Definition MemoryID.cpp:441
Data of an entity at one point in time.
bool hasInstance(const MemoryID &instanceID) const
bool forEachInstanceIn(const MemoryID &id, InstanceFunctionT &&func)
EntityInstanceT & addInstance(EntityInstanceT &&instance)
bool equalsDeep(const DerivedT &other) const
EntityInstanceT & addInstance(const EntityInstanceT &instance)
Add a single instance with data.
EntityInstanceT * findInstance(int index)
const EntityInstanceT * findInstance(const MemoryID &instanceID) const
EntitySnapshotBase(const EntitySnapshotBase &other)=default
bool forEachInstanceIn(const MemoryID &id, InstanceFunctionT &&func) const
bool forEachInstance(InstanceFunctionT &&func)
EntityInstanceT & getInstance(int index)
Get the given instance.
const EntityInstanceT * findInstance(int index) const
EntityInstanceT * findInstance(const MemoryID &instanceID)
EntitySnapshotBase & operator=(EntitySnapshotBase &&other)=default
EntityInstanceT & getInstance(const MemoryID &instanceID)
Get the given instance.
const EntityInstanceT & getInstance(const MemoryID &instanceID) const
bool hasInstances() const
Indicate whether this snapshot has any instances.
EntitySnapshotBase(Time time, const MemoryID &parentID={})
void update(const EntityUpdate &update)
EntitySnapshotBase(EntitySnapshotBase &&other)=default
bool forEachInstance(InstanceFunctionT &&func) const
const EntityInstanceT & getInstance(int index) const
EntitySnapshotBase & operator=(const EntitySnapshotBase &other)=default
std::vector< int > getInstanceIndices() const
Provides default implmentations of MemoryContainer, as well as iterators (which requires a template).
Indicates that an argument was invalid.
Definition ArMemError.h:28
static MissingEntry create(const std::string &missingKey, const ContainerT &container)
Definition ArMemError.h:79
void checkHasInstanceIndex(const MemoryID &instanceID)
Throw armem::error::InvalidMemoryID if the given ID has no instance index.
void throwIfNotEqual(const Time &ownTime, const Time &updateTime)
bool call(FunctionT &&func, ChildT &&child)
std::string toDateTimeMilliSeconds(const Time &time, int decimals=6)
Returns timeas e.g.
Definition Time.cpp:35
armarx::core::time::DateTime Time
An update of an entity for a specific point in time.
Definition Commit.h:26