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(CEntity::TMultiMap::iterator 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(CEntity::TMultiMap::iterator 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(CEntity::TMultiMap::iterator 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  CEntity::TMultiMap::iterator 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  CEntity::TMultiMap::iterator 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  CComposableEntity* pcComposableEntity = dynamic_cast<CComposableEntity*>(itComponent->second);
126  if(pcComposableEntity != NULL) {
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  CEntity::TMultiMap::iterator 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  CComposableEntity* pcComposableEntity = dynamic_cast<CComposableEntity*>(itComponent->second);
166  if(pcComposableEntity != NULL) {
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 }
virtual void SetEnabled(bool b_enabled)
Enables or disables an entity.
Definition: entity.cpp:139
#define THROW_ARGOSEXCEPTION(message)
This macro throws an ARGoS exception with the passed message.
virtual void SetEnabled(bool b_enabled)
Enables or disables an entity.
The basic entity type.
Definition: entity.h:89
#define THROW_ARGOSEXCEPTION_NESTED(message, nested)
This macro throws an ARGoS exception with the passed message and nesting the passed exception...
virtual std::string GetTypeDescription() const
Returns a string label for this class.
Definition: entity.h:213
Basic class for an entity that contains other entities.
void AddComponent(CEntity &c_component)
Adds a component to this composable entity.
CComposableEntity(CComposableEntity *pc_parent)
Class constructor.
The exception that wraps all errors in ARGoS.
bool HasComponent(const std::string &str_component)
Returns true if this composable entity has a component with the given string label.
const std::string & GetId() const
Returns the id of this entity.
Definition: entity.h:157
REGISTER_STANDARD_SPACE_OPERATIONS_ON_COMPOSABLE(CComposableEntity)
The namespace containing all the ARGoS related code.
Definition: ci_actuator.h:12
std::string GetContext() const
Returns the context of this entity.
Definition: entity.cpp:79
CEntity::TMultiMap::iterator FindComponent(const std::string &str_component)
Searches for a component with the given string label.
virtual void UpdateComponents()
Calls the Update() method on all the components.
virtual void Update()
Updates the status of this entity.
virtual void Reset()
Resets the state of the entity to whatever it was after Init() or the standalone constructor was call...
CEntity & GetComponent(const std::string &str_component)
Returns the component with the passed string label.
CEntity & RemoveComponent(const std::string &str_component)
Removes a component from this composable entity.