composable_entity.cpp
Go to the documentation of this file.
1 
7 #include "composable_entity.h"
8 
9 #include <argos3/core/utility/string_utilities.h>
10 
11 namespace argos {
12 
13  /****************************************/
14  /****************************************/
15 
17  CEntity(pc_parent) {}
18 
19  /****************************************/
20  /****************************************/
21 
23  const std::string& str_id) :
24  CEntity(pc_parent, str_id) {}
25 
26  /****************************************/
27  /****************************************/
28 
30  for(auto it = m_mapComponents.begin();
31  it != m_mapComponents.end();
32  ++it) {
33  it->second->Reset();
34  }
35  }
36 
37  /****************************************/
38  /****************************************/
39 
42  }
43 
44  /****************************************/
45  /****************************************/
46 
47  void CComposableEntity::SetEnabled(bool b_enabled) {
48  CEntity::SetEnabled(b_enabled);
49  for(auto it = m_mapComponents.begin();
50  it != m_mapComponents.end();
51  ++it) {
52  it->second->SetEnabled(b_enabled);
53  }
54  }
55 
56  /****************************************/
57  /****************************************/
58 
60  for(auto it = m_mapComponents.begin();
61  it != m_mapComponents.end();
62  ++it) {
63  if(it->second->IsEnabled()) {
64  it->second->Update();
65  }
66  }
67  }
68 
69  /****************************************/
70  /****************************************/
71 
73  m_mapComponents.insert(
74  std::pair<std::string, CEntity*>(
75  c_component.GetTypeDescription(),
76  &c_component));
77  m_vecComponents.push_back(&c_component);
78  }
79 
80  /****************************************/
81  /****************************************/
82 
83  CEntity& CComposableEntity::RemoveComponent(const std::string& str_component) {
84  try {
85  auto it = FindComponent(str_component);
86  if(it == m_mapComponents.end()) {
87  THROW_ARGOSEXCEPTION("Element \"" << str_component << "\" not found in the component map.");
88  }
89  CEntity& cRetVal = *(it->second);
90  m_mapComponents.erase(it);
91  size_t i;
92  for(i = 0; i < m_vecComponents.size() && m_vecComponents[i] != &cRetVal; ++i);
93  if(i < m_vecComponents.size()) {
94  m_vecComponents.erase(m_vecComponents.begin() + i);
95  }
96  else {
97  THROW_ARGOSEXCEPTION("Element \"" << str_component << "\" not found in the component vector, but present in the map. BUG!");
98  }
99  return cRetVal;
100  }
101  catch(CARGoSException& ex) {
102  THROW_ARGOSEXCEPTION_NESTED("While removing component \"" << str_component << "\" from the composable entity \"" << GetContext() << GetId() << "\"", ex);
103  }
104  }
105 
106  /****************************************/
107  /****************************************/
108 
109  CEntity& CComposableEntity::GetComponent(const std::string& str_path) {
110  try {
111  /* Search for the path separator character and take the first path segment */
112  size_t unFirstSeparatorIdx = str_path.find(".");
113  std::string strFrontIdentifier;
114  if(unFirstSeparatorIdx == std::string::npos) strFrontIdentifier = str_path;
115  else strFrontIdentifier = str_path.substr(0, unFirstSeparatorIdx);
116  /* Try to find the relevant component in this context */
117  auto itComponent = FindComponent(strFrontIdentifier);
118  if(itComponent != m_mapComponents.end()) {
119  if(unFirstSeparatorIdx == std::string::npos) {
120  /* Path separator not found, found component in the current context is the one we want */
121  return *(itComponent->second);
122  }
123  /* Path separator found, try to cast the found component to a composable entity */
124  else {
125  auto* pcComposableEntity = dynamic_cast<CComposableEntity*>(itComponent->second);
126  if(pcComposableEntity != nullptr) {
127  /* Dynamic cast of component to composable entity was successful, re-execute this function in the new context */
128  return pcComposableEntity->GetComponent(str_path.substr(unFirstSeparatorIdx + 1, std::string::npos));
129  }
130  else {
131  /* Dynamic cast failed, user is requesting an entity from an entity which is not composable -> error */
132  THROW_ARGOSEXCEPTION("Component \"" << strFrontIdentifier << "\" of \"" << GetContext() + GetId()
133  << "\" is not a composable entity");
134  }
135  }
136  }
137  else {
138  THROW_ARGOSEXCEPTION("Component \"" << strFrontIdentifier << "\" does not exist in \""
139  << GetContext() + GetId() << "\"");
140  }
141  }
142  catch(CARGoSException& ex) {
143  THROW_ARGOSEXCEPTION_NESTED("While getting a component from a composable entity", ex);
144  }
145  }
146 
147  /****************************************/
148  /****************************************/
149 
150  bool CComposableEntity::HasComponent(const std::string& str_path) {
151  /* Search for the path separator character and take the first path segement */
152  size_t unFirstSeparatorIdx = str_path.find(".");
153  std::string strFrontIdentifier;
154  if(unFirstSeparatorIdx == std::string::npos) strFrontIdentifier = str_path;
155  else strFrontIdentifier = str_path.substr(0, unFirstSeparatorIdx);
156  /* Try to find the relevant component in this context */
157  auto itComponent = FindComponent(strFrontIdentifier);
158  if(itComponent != m_mapComponents.end()) {
159  if(unFirstSeparatorIdx == std::string::npos) {
160  /* Path separator not found, found component in the current context is the one we want */
161  return true;
162  }
163  else {
164  /* Path separator found, try to cast the found component to a composable entity */
165  auto* pcComposableEntity = dynamic_cast<CComposableEntity*>(itComponent->second);
166  if(pcComposableEntity != nullptr) {
167  /* Dynamic cast of component to composable entity was sucessful, re-execute this function in the new context */
168  return pcComposableEntity->HasComponent(str_path.substr(unFirstSeparatorIdx + 1, std::string::npos));
169  }
170  else {
171  /* Could not cast to a composable entity, the queried component cannot exist in the specified context */
172  return false;
173  }
174  }
175  }
176  else {
177  /* Could not find the queried component in this context */
178  return false;
179  }
180  }
181 
182  /****************************************/
183  /****************************************/
184 
185  CEntity::TMultiMap::iterator CComposableEntity::FindComponent(const std::string& str_component) {
186  /* Check for the presence of [ */
187  std::string::size_type unIdentifierStart = str_component.find('[');
188  if(unIdentifierStart != std::string::npos) {
189  /* Found, now check for the presence of ] after [ */
190  std::string::size_type unIdentifierEnd = str_component.rfind(']');
191  if(unIdentifierEnd != std::string::npos &&
192  unIdentifierEnd > unIdentifierStart) {
193  /* Use the string between [ and ] as an index and whatever comes before as base id */
194  /* Count how many components there are for the base type */
195  std::string strBaseType = str_component.substr(0, unIdentifierStart);
196  if(m_mapComponents.count(strBaseType) == 0) {
197  /* No components of this base type, return an iterator to the end of the collection */
198  return m_mapComponents.end();
199  }
200  else {
201  /* Components of base type found - extract the uid and search for it */
202  std::string strComponentId = str_component.substr(unIdentifierStart + 1, unIdentifierEnd - unIdentifierStart - 1);
203  /* Create a pair of iterators which mark the beginning and the end of the components that match the base type */
204  std::pair<CEntity::TMultiMap::iterator,
205  CEntity::TMultiMap::iterator> cRange = m_mapComponents.equal_range(strBaseType);
206  /* Create an iterator to hold the component we are trying to locate */
207  CEntity::TMultiMap::iterator itComponent;
208  /* Search through components of base type and try find a match for the specified Id */
209  for(itComponent = cRange.first;
210  (itComponent != cRange.second) && (itComponent->second->GetId() != strComponentId);
211  ++itComponent);
212  /* If the iterator itComponent is not equal to cRange.second, then we have found our component */
213  if(itComponent != cRange.second) {
214  return itComponent;
215  }
216  else {
217  /* Identifer not found in the collection of components with the specified base type,
218  * return an iterator to the end of the collect to show this */
219  return m_mapComponents.end();
220  }
221  }
222  }
223  else {
224  THROW_ARGOSEXCEPTION("Syntax error in entity id \"" << str_component << "\"");
225  }
226  }
227  else {
228  /* Identifier syntax not used, return an iterator to the first element or the end of collection if
229  * no elements are found */
230  return m_mapComponents.find(str_component);
231  }
232  }
233 
234  /****************************************/
235  /****************************************/
236 
238 
239  /****************************************/
240  /****************************************/
241 
242 }
#define THROW_ARGOSEXCEPTION_NESTED(message, nested)
This macro throws an ARGoS exception with the passed message and nesting the passed exception.
#define THROW_ARGOSEXCEPTION(message)
This macro throws an ARGoS exception with the passed message.
The namespace containing all the ARGoS related code.
Definition: ci_actuator.h:12
REGISTER_STANDARD_SPACE_OPERATIONS_ON_COMPOSABLE(CComposableEntity)
Basic class for an entity that contains other entities.
CEntity & RemoveComponent(const std::string &str_component)
Removes a component from this composable entity.
virtual void Reset()
Resets the state of the entity to whatever it was after Init() or the standalone constructor was call...
virtual void SetEnabled(bool b_enabled)
Enables or disables an entity.
CComposableEntity(CComposableEntity *pc_parent)
Class constructor.
virtual void UpdateComponents()
Calls the Update() method on all the components.
CEntity & GetComponent(const std::string &str_component)
Returns the component with the passed string label.
virtual void Update()
Updates the status of this entity.
void AddComponent(CEntity &c_component)
Adds a component to this composable entity.
bool HasComponent(const std::string &str_component)
Returns true if this composable entity has a component with the given string label.
CEntity::TMultiMap::iterator FindComponent(const std::string &str_component)
Searches for a component with the given string label.
The basic entity type.
Definition: entity.h:90
const std::string & GetId() const
Returns the id of this entity.
Definition: entity.h:157
std::string GetContext() const
Returns the context of this entity.
Definition: entity.cpp:79
virtual void SetEnabled(bool b_enabled)
Enables or disables an entity.
Definition: entity.cpp:139
virtual std::string GetTypeDescription() const
Returns a string label for this class.
Definition: entity.h:213
The exception that wraps all errors in ARGoS.