Entity.cpp
Go to the documentation of this file.
1 /*
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * @package MemoryX::WorkingMemory
17 * @author ALexey Kozlov ( kozlov at kit dot edu)
18 * @date 2012
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22 
23 #include "Entity.h"
24 #include "ProbabilityMeasures.h"
25 
27 
30 
31 namespace memoryx
32 {
33 
35  IceUtil::Shared(source),
36  ::armarx::Serializable(source),
37  EntityBase()
38  {
39  deepCopy(source);
40  }
41 
43  {
44  return EntityPtr(new Entity());
45  }
46 
47  void Entity::deepCopy(const Entity& source)
48  {
49  {
50  // boost::shared_lock<boost::shared_mutex> lock(source.entityMutex);
51  std::shared_lock lock2(entityMutex);
52  id = source.id;
53  name = source.name;
54  }
55  // ARMARX_INFO_S << "Entity copy const - " << VAROUT(source.wrappers.size());
56  // clone attributes
57  {
58  // armarx::ScopedLock lock(source.attributesMutex);
59  std::scoped_lock lock2(attributesMutex);
60  attributes.clear();
61 
62  for (AttributeMap::const_iterator iter = source.attributes.begin() ; iter != source.attributes.end() ; iter++)
63  {
64  EntityAttributeBasePtr attrBase = iter->second;
65  EntityAttributeBasePtr attr = EntityAttributeBasePtr::dynamicCast(attrBase->ice_clone());
66  attributes[iter->first] = attr;
67  }
68  }
69  // clone wrappers
70  {
71  // RecursiveMutex::scoped_lock lock(source.wrappersMutex);
72  std::scoped_lock lock2(wrappersMutex);
73  wrappers.clear();
74 
75  for (AbstractEntityWrapperBaseList::const_iterator iter = source.wrappers.begin() ; iter != source.wrappers.end() ; iter++)
76  {
77  if ((*iter))
78  {
79  EntityWrappers::AbstractEntityWrapperPtr wrapper = EntityWrappers::AbstractEntityWrapperPtr::dynamicCast((*iter)->ice_clone());
80 
81  if (wrapper)
82  {
83  wrapper->setEntity(this);
84  wrappers.push_back(wrapper);
85  }
86  }
87  }
88  }
89  }
90 
92  {
93  int wrapperCount;
94  {
95  std::scoped_lock lock(wrappersMutex);
96  wrapperCount = wrappers.size();
97  }
98  int remainingRefs = __getRef() - 1;
99  if (
100  remainingRefs <= wrapperCount &&
101  remainingRefs > 0 &&
102  wrapperCount > 0 &&
103 
104 #if ICE_INT_VERSION >= 30603
105  !__hasFlag(NoDelete)
106 #else
107  !_noDelete
108 #endif
109  )
110  {
111  std::scoped_lock lock(wrappersMutex);
112  int counter = 0;
113  for (const AbstractEntityWrapperBasePtr& wrapper : wrappers)
114  {
115  EntityWrappers::AbstractEntityWrapperPtr p = EntityWrappers::AbstractEntityWrapperPtr::dynamicCast(wrapper);
116  if (p)
117  {
118  if (p->getEntity().get() == this)
119  {
120  counter++;
121  }
122  }
123 
124  }
125  if (counter == remainingRefs)
126  {
127  // only the wrappers point on this object
128  // first make a temporal copy of the wrapper list, then delete the wrappers list
129  // so that when the temp wrapper list is deleted and the ref count of the entity decreased, the wrappers.size() check is zero and this part is not run again
130  auto tmpWrappers = wrappers;
131  wrappers.clear();
132  for (const AbstractEntityWrapperBasePtr& wrapper : tmpWrappers)
133  {
134  EntityWrappers::AbstractEntityWrapperPtr p = EntityWrappers::AbstractEntityWrapperPtr::dynamicCast(wrapper);
135  p->setEntity(NULL);
136  }
137  }
138  }
139  Shared::__decRef();
140  }
141 
143  {
144  // ARMARX_INFO_S << "Deleting entity with id " << id;
145  __setNoDelete(true);
146  // ARMARX_INFO_S << "~Entity() " << getName();
147  // Remove entity ptr in wrapper, because it becomes invalid
148  // it is not a shared ptr because it would introduce a cycle of shared ptrs
149  // auto tmpWrapper = wrappers;
150  // wrappers.clear();
151  // for (const AbstractEntityWrapperBasePtr& wrapper : tmpWrapper)
152  // {
153  // auto p = EntityWrappers::AbstractEntityWrapperPtr::dynamicCast(wrapper);
154  // if (p)
155  // {
156  // p->setEntity(NULL);
157  // }
158  // }
159  }
160 
161  ::std::string Entity::getId(const ::Ice::Current&) const
162  {
163  std::shared_lock lock(entityMutex);
164  return id;
165  }
166 
167  void Entity::setId(const ::std::string& id, const ::Ice::Current&)
168  {
169  std::unique_lock lock(entityMutex);
170  this->id = id;
171  }
172 
173  ::std::string Entity::getName(const ::Ice::Current&) const
174  {
175  std::shared_lock lock(entityMutex);
176  return name;
177  }
178 
179  void Entity::setName(const ::std::string& name, const ::Ice::Current&)
180  {
181  std::unique_lock lock(entityMutex);
182  this->name = name;
183  }
184 
185  bool Entity::isMetaEntity(const Ice::Current&) const
186  {
187  if (hasAttribute("isMetaEntity"))
188  {
189  auto attr = getAttribute("isMetaEntity");
190  return attr->getValue()->getBool();
191  }
192 
193  return false;
194  }
195 
196  void Entity::setMetaEntity(bool isMetaEntity, const Ice::Current&)
197  {
198  if (hasAttribute("isMetaEntity"))
199  {
200  removeAttribute("isMetaEntity");
201  }
202 
203  EntityAttributePtr attr = new EntityAttribute("isMetaEntity");
204  attr->addValue(armarx::VariantPtr(new armarx::Variant(isMetaEntity)));
205  putAttribute(attr);
206  }
207 
208  EntityRefBaseList Entity::getDirectParentRefs() const
209  {
210  EntityRefBaseList result;
211 
212  if (!hasAttribute("parentEntityRefs"))
213  {
214  return result;
215  }
216 
217  auto attr = getAttribute("parentEntityRefs");
218 
219  for (int i = 0; i < attr->size(); i++)
220  {
221  result.push_back(armarx::VariantPtr::dynamicCast(attr->getValueAt(i))->get<EntityRefBase>());
222  }
223 
224  return result;
225  }
226 
227  EntityRefBaseList Entity::getAllParentRefs(bool includeMetaEntities) const
228  {
229  EntityRefBaseList result;
230  EntityRefBaseList explored;
231  EntityRefBaseList unexplored = getDirectParentRefs();
232 
233  while (!unexplored.empty())
234  {
235  EntityRefBasePtr entityRef = unexplored.back();
236  EntityPtr next = EntityPtr::dynamicCast(entityRef->getEntity());
237  unexplored.pop_back();
238 
239  bool isExplored = std::find_if(explored.cbegin(), explored.cend(), [&](const EntityRefBasePtr & entityRef)
240  {
241  return entityRef->entityId == next->getId();
242  }) != explored.cend();
243 
244  if (isExplored)
245  {
246  continue;
247  }
248 
249  EntityRefBaseList newParents = next->getDirectParentRefs();
250  explored.push_back(entityRef);
251  unexplored.insert(unexplored.end(), newParents.begin(), newParents.end());
252 
253  if (next->isMetaEntity() && !includeMetaEntities)
254  {
255  continue;
256  }
257 
258  result.push_back(entityRef);
259  }
260 
261  return result;
262  }
263 
264  std::vector<std::string> Entity::getAllParentsAsStringList() const
265  {
266  Ice::StringSeq result;
267  const auto& parents = getAllParentRefs();
268  std::transform(parents.cbegin(), parents.cend(), std::back_inserter(result), [](const EntityRefBasePtr & e)
269  {
270  return e->entityName;
271  });
272 
273  return result;
274  }
275 
276  void Entity::setDirectParentRefs(const EntityRefBaseList& entityRefs)
277  {
278  if (hasAttribute("parentEntityRefs"))
279  {
280  removeAttribute("parentEntityRefs");
281  }
282 
283  EntityAttributePtr attr = new EntityAttribute("parentEntityRefs");
284 
285  for (const auto& entity : entityRefs)
286  {
287  attr->addValue(new armarx::Variant(entity));
288  }
289 
290  putAttribute(attr);
291  }
292 
293  EntityAttributeBasePtr Entity::getAttribute(const ::std::string& attrName, const ::Ice::Current&) const
294  {
295  std::scoped_lock lock(attributesMutex);
296  AttributeMap::const_iterator it = attributes.find(attrName);
297 
298  if (it != attributes.end())
299  {
300  return it->second;
301  }
302  else
303  {
304  return EntityAttributeBasePtr();
305  }
306  }
307 
308  armarx::VariantPtr Entity::getAttributeValue(const ::std::string& attrName) const
309  {
310  EntityAttributeBasePtr attr = getAttribute(attrName);
311 
312  // check if attribute exists
313  if (!attr)
314  {
315  return armarx::VariantPtr();
316  }
317 
318  // check if attr has exactly one value (ie not empty and not multimodal)
319  if (attr->size() != 1)
320  {
321  return armarx::VariantPtr();
322  }
323 
324  return armarx::VariantPtr::dynamicCast(attr->getValue());
325  }
326 
327  void Entity::putAttribute(const ::memoryx::EntityAttributeBasePtr& attr, const ::Ice::Current&)
328  {
329  std::scoped_lock lock(attributesMutex);
330  attributes[attr->getName()] = attr;
331  }
332 
333  void Entity::removeAttribute(const ::std::string& attrName, const ::Ice::Current&)
334  {
335  std::scoped_lock lock(attributesMutex);
336  attributes.erase(attrName);
337  }
338 
339  bool Entity::hasAttribute(const std::string& attrName, const Ice::Current& c) const
340  {
341  ARMARX_TRACE;
342  std::scoped_lock lock(attributesMutex);
343  return attributes.find(attrName) != attributes.end();
344  }
345 
346  memoryx::NameList Entity::getAttributeNames(const Ice::Current&) const
347  {
348  memoryx::NameList result;
349  std::scoped_lock lock(attributesMutex);
350 
351  for (AttributeMap::const_iterator it = attributes.begin(); it != attributes.end(); ++it)
352  {
353  result.push_back(it->first);
354  }
355 
356  return result;
357  }
358 
359 
360  bool Entity::equals(const EntityBasePtr& otherEntity, const Ice::Current&) const
361  {
362  if (getId() != otherEntity->getId())
363  {
364  return false;
365  }
366  return equalsAttributes(otherEntity);
367  }
368 
369  bool Entity::equalsAttributes(const EntityBasePtr& otherEntity, const Ice::Current&) const
370  {
371  if (getName() != otherEntity->getName())
372  {
373  return false;
374  }
375  NameList attributeNames = getAttributeNames();
376  if (otherEntity->getAttributeNames().size() != attributeNames.size())
377  {
378  return false;
379  }
380 
381  for (std::string& attributeName : attributeNames)
382  {
383  // check if attribute values are equal
384  armarx::JSONObjectPtr thisSerializer = new armarx::JSONObject();
385  armarx::JSONObjectPtr otherSerializer = new armarx::JSONObject();
386  getAttribute(attributeName)->serialize(thisSerializer);
387  otherEntity->getAttribute(attributeName)->serialize(otherSerializer);
388  if (otherSerializer->toString() != thisSerializer->toString())
389  {
390  return false;
391  }
392  }
393 
394  return true;
395  }
396 
398  {
399  return this->clone();
400  }
401 
402  EntityPtr Entity::clone(const Ice::Current& c) const
403  {
404  EntityPtr ret = new Entity();
405  ret->deepCopy(*this);
406  return ret;
407  }
408 
409  void Entity::output(std::ostream& stream) const
410  {
411  std::scoped_lock lock(attributesMutex);
412  stream << "[" << id << "] " << name << std::endl;
413  stream << "Attributes: (" << attributes.size() << ")" << std::endl;
414 
415  for (AttributeMap::const_iterator it = attributes.begin(); it != attributes.end(); ++it)
416  {
417  stream << it->first << ": " << EntityAttributePtr::dynamicCast(it->second) << std::endl;
418  }
419  }
420 
422  {
423  // wrappers are only locally available -> clear them before sending (they would be broken on the other side)
424  // armarx::RecursiveMutex::scoped_lock lock(wrappersMutex);
425  // wrappers.clear();
426  // for(auto& elem : wrappers)
427  // {
428  // elem = NULL;
429  // }
430  // ARMARX_INFO_S << getName() << " size: " << wrappers.size();
431  }
432 
434  {
435  // ARMARX_INFO_S << getName() << " size: " << wrappers.size();
436  std::scoped_lock lock(wrappersMutex);
437  wrappers.clear();
438  }
439 
440 
441  void Entity::serialize(const armarx::ObjectSerializerBasePtr& serializer, const ::Ice::Current& c) const
442  {
443  armarx::AbstractObjectSerializerPtr obj = armarx::AbstractObjectSerializerPtr::dynamicCast(serializer);
444  {
445  std::shared_lock lock(entityMutex);
446 
447  // empty ids shouldn't be added to allow them to be auto-generated
448  if (!id.empty())
449  {
450  obj->setId(id);
451  }
452 
453  obj->setString("name", name);
454  }
455 
456  armarx::AbstractObjectSerializerPtr objAttrs = obj->createElement();
457  {
458  std::scoped_lock lock(attributesMutex);
459 
460  for (AttributeMap::const_iterator it = attributes.begin(); it != attributes.end(); ++it)
461  {
462  armarx::AbstractObjectSerializerPtr attr = obj->createElement();
463  it->second->serialize(attr, c);
464  objAttrs->setElement(it->first, attr);
465  }
466  }
467  obj->setElement("attrs", objAttrs);
468  }
469 
470  void Entity::deserialize(const armarx::ObjectSerializerBasePtr& serializer, const ::Ice::Current& c)
471  {
472  armarx::AbstractObjectSerializerPtr obj = armarx::AbstractObjectSerializerPtr::dynamicCast(serializer);
473  {
474  std::unique_lock lock(entityMutex);
475 
476  if (!obj->getIdField().empty() && obj->hasElement(obj->getIdField()))
477  {
478  id = obj->getStringId();
479  }
480 
481  name = obj->getString("name");
482  }
483 
484  const armarx::AbstractObjectSerializerPtr objAttrs = obj->getElement("attrs");
485  const std::vector<std::string> attrNames = objAttrs->getElementNames();
486  {
487  // putAttribute() also locks the datastructure!
488  std::scoped_lock lock(attributesMutex);
489  attributes.clear();
490  }
491 
492  for (std::vector<std::string>::const_iterator it = attrNames.begin(); it != attrNames.end(); ++it)
493  {
494  EntityAttributePtr attr = new EntityAttribute(*it);
495  attr->deserialize(objAttrs->getElement(*it));
496  putAttribute(attr);
497  }
498  }
499 
500 }
memoryx::Entity::ice_preMarshal
void ice_preMarshal() override
Definition: Entity.cpp:421
memoryx::Entity::setMetaEntity
void setMetaEntity(bool isMetaEntity, const ::Ice::Current &=Ice::emptyCurrent) override
Mark this entity as meta (i.e.
Definition: Entity.cpp:196
armarx::Variant
The Variant class is described here: Variants.
Definition: Variant.h:224
armarx::aron::ret
ReaderT::InputType T & ret
Definition: rw.h:21
memoryx::Entity::putAttribute
void putAttribute(const ::memoryx::EntityAttributeBasePtr &attr, const ::Ice::Current &=Ice::emptyCurrent) override
Store attribute in entity.
Definition: Entity.cpp:327
JSONObject.h
memoryx::Entity::getName
::std::string getName(const ::Ice::Current &=Ice::emptyCurrent) const override
Retrieve name of this entity.
Definition: Entity.cpp:173
memoryx::Entity::getId
::std::string getId(const ::Ice::Current &=Ice::emptyCurrent) const override
Retrieve id of this entity which is an integer in string representation.
Definition: Entity.cpp:161
memoryx::Entity::deserialize
void deserialize(const armarx::ObjectSerializerBasePtr &serializer, const ::Ice::Current &=Ice::emptyCurrent) override
Subclasses should use serializable attributes and consider these methods final.
Definition: Entity.cpp:470
memoryx::Entity::getAttribute
EntityAttributeBasePtr getAttribute(const ::std::string &attrName, const ::Ice::Current &=Ice::emptyCurrent) const override
Retrieve attribute from entity.
Definition: Entity.cpp:293
memoryx::Entity::Entity
Entity()
Definition: Entity.h:498
memoryx::Entity::removeAttribute
void removeAttribute(const ::std::string &attrName, const ::Ice::Current &=Ice::emptyCurrent) override
Remove attribute with given name from entity.
Definition: Entity.cpp:333
memoryx::Entity::~Entity
~Entity() override
Definition: Entity.cpp:142
armarx::JSONObject
The JSONObject class is used to represent and (de)serialize JSON objects.
Definition: JSONObject.h:43
memoryx::Entity::clone
EntityPtr clone(const Ice::Current &c=Ice::emptyCurrent) const
Definition: Entity.cpp:402
trace.h
AbstractObjectSerializer.h
memoryx::Entity::serialize
void serialize(const armarx::ObjectSerializerBasePtr &serializer, const ::Ice::Current &=Ice::emptyCurrent) const override
Subclasses should use serializable attributes and consider these methods final.
Definition: Entity.cpp:441
memoryx
VirtualRobot headers.
Definition: CommonPlacesTester.cpp:48
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:43
memoryx::Entity::getAttributeNames
memoryx::NameList getAttributeNames(const ::Ice::Current &=Ice::emptyCurrent) const override
Retrieve list of all attribute names.
Definition: Entity.cpp:346
IceUtil
Definition: Instance.h:21
memoryx::Entity::CreateGenericEntity
static EntityPtr CreateGenericEntity()
Creates an entity without any convenience getter/setter functions.
Definition: Entity.cpp:42
memoryx::Entity::ice_postUnmarshal
void ice_postUnmarshal() override
Definition: Entity.cpp:433
memoryx::Entity::output
void output(std::ostream &stream) const
Definition: Entity.cpp:409
memoryx::Entity::getAttributeValue
virtual armarx::VariantPtr getAttributeValue(const ::std::string &attrName) const
Retrieve value of an attribute from entity.
Definition: Entity.cpp:308
cxxopts::empty
bool empty(const std::string &s)
Definition: cxxopts.hpp:255
IceInternal::Handle
Definition: forward_declarations.h:8
memoryx::Entity::setDirectParentRefs
virtual void setDirectParentRefs(const EntityRefBaseList &entityRefs)
Replace parent entity references.
Definition: Entity.cpp:276
ARMARX_TRACE
#define ARMARX_TRACE
Definition: trace.h:69
armarx::VariantPtr
IceInternal::Handle< Variant > VariantPtr
Definition: Variant.h:42
memoryx::Entity::ice_clone
Ice::ObjectPtr ice_clone() const override
Definition: Entity.cpp:397
memoryx::Entity::getDirectParentRefs
virtual EntityRefBaseList getDirectParentRefs() const
Retrieve parent entity references.
Definition: Entity.cpp:208
memoryx::Entity::attributesMutex
std::mutex attributesMutex
Definition: Entity.h:504
memoryx::Entity::__decRef
void __decRef() override
Definition: Entity.cpp:91
memoryx::Entity::getAllParentsAsStringList
virtual std::vector< std::string > getAllParentsAsStringList() const
Definition: Entity.cpp:264
memoryx::Entity::getAllParentRefs
virtual EntityRefBaseList getAllParentRefs(bool includeMetaEntities=true) const
Retrieve all parents by traversing the whole hierarchy.
Definition: Entity.cpp:227
memoryx::EntityWrappers::AbstractEntityWrapperPtr
IceInternal::Handle< AbstractEntityWrapper > AbstractEntityWrapperPtr
Typedef of AbstractEntityWrapperPtr as IceUtil::Handle<AbstractEntityWrapper> for convenience.
Definition: AbstractEntityWrapper.h:112
boost::source
Vertex source(const detail::edge_base< Directed, Vertex > &e, const PCG &)
Definition: point_cloud_graph.h:681
memoryx::Entity::setId
void setId(const ::std::string &id, const ::Ice::Current &=Ice::emptyCurrent) override
Set id of this entity.
Definition: Entity.cpp:167
memoryx::Entity::wrappers
AbstractEntityWrapperBaseList wrappers
Definition: Entity.h:502
memoryx::EntityPtr
IceInternal::Handle< Entity > EntityPtr
Typedef of EntityPtr as IceInternal::Handle<Entity> for convenience.
Definition: Entity.h:46
memoryx::Entity::equalsAttributes
bool equalsAttributes(const EntityBasePtr &otherEntity, const ::Ice::Current &=Ice::emptyCurrent) const override
equalsAttributes computes if two Entity instances are equal.
Definition: Entity.cpp:369
ProbabilityMeasures.h
memoryx::Entity::entityMutex
std::shared_mutex entityMutex
Definition: Entity.h:505
memoryx::Entity::hasAttribute
bool hasAttribute(const ::std::string &attrName, const ::Ice::Current &=Ice::emptyCurrent) const override
Check whether this entity has an attribute with the given name.
Definition: Entity.cpp:339
Entity.h
armarx::transform
auto transform(const Container< InputT, Alloc > &in, OutputT(*func)(InputT const &)) -> Container< OutputT, typename std::allocator_traits< Alloc >::template rebind_alloc< OutputT > >
Convenience function (with less typing) to transform a container of type InputT into the same contain...
Definition: algorithm.h:315
memoryx::EntityAttribute
Attribute of MemoryX entities.
Definition: EntityAttribute.h:48
armarx::aron::type::ObjectPtr
std::shared_ptr< Object > ObjectPtr
Definition: Object.h:36
memoryx::Entity
Definition: Entity.h:246
memoryx::Entity::equals
bool equals(const EntityBasePtr &otherEntity, const ::Ice::Current &=Ice::emptyCurrent) const override
equals computes if two Entity instances are equal.
Definition: Entity.cpp:360
endif
endif() find_package(Simox QUIET) armarx_build_if(Simox_FOUND "Simox not available") find_package(PythonLibs 3.6 QUIET) armarx_build_if(PYTHONLIBS_FOUND "Python libs not available") if(PYTHONLIBS_FOUND) include_directories($
Definition: CMakeLists.txt:10
memoryx::Entity::setName
void setName(const ::std::string &name, const ::Ice::Current &=Ice::emptyCurrent) override
Set name of this entity.
Definition: Entity.cpp:179
memoryx::Entity::wrappersMutex
std::recursive_mutex wrappersMutex
Definition: Entity.h:506
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28
memoryx::Entity::isMetaEntity
bool isMetaEntity(const ::Ice::Current &=Ice::emptyCurrent) const override
Indicates whether this entity only contains meta information.
Definition: Entity.cpp:185