ObjectClassMemorySegment.h
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 Kai Welke ( welke 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#pragma once
24
27
28#include <MemoryX/interface/components/PriorKnowledgeInterface.h>
29#include <MemoryX/interface/core/EntityBase.h>
30#include <MemoryX/interface/memorytypes/MemoryEntities.h>
31#include <MemoryX/interface/memorytypes/MemorySegments.h>
34
35namespace memoryx
36{
37 /**
38 * The object class segment is a specialized segment of the SegmentedMemory.
39 * It keeps object classes which are usually held in short term memory.
40 * This segment is usually part of the working memory.
41 */
43 virtual public WorkingMemoryEntitySegment<ObjectClass>,
44 virtual public ObjectClassMemorySegmentBase
45 {
46 public:
47 /**
48 * Creates a new object class segment.
49 * Object classes are usually fetched from prior knowledge. Use the method addPriorClassWithSubclasses() in order to fetch
50 * parts of the class ontology into the object classes segment.
51 * Object classes in this segment use reference counting so use the methods provided in this class to add, update and remove
52 * classes.
53 * The ObjectClass MongoDB-collections that are accessed can be configured via PriorKnowledge config files (e.g. Prior_Objects)
54 *
55 * @param priorKnowledgePrx proxy to prior knowledge
56 *
57 */
58 ObjectClassMemorySegment(const PriorKnowledgeInterfacePrx& priorKnowledgePrx) :
60 ObjectClassMemorySegmentBase::ObjectClassMemorySegmentBase()
61 {
62 this->priorKnowledgePrx = priorKnowledgePrx;
63
64 // get classes from prior knowledge
65 classesSegmentPrx = priorKnowledgePrx->getObjectClassesSegment();
66 }
67
68 /**
69 * Fetches a class and its ontological subclasses from prior knowledge and inserts the complete
70 * subtree in this segment.
71 * If a class with the same name already exists in this segment, its reference count is increased.
72 *
73 * @param className name of the class in prior knowledge
74 */
75 ObjectClassList
76 addPriorClassWithSubclasses(const std::string& className,
77 const ::Ice::Current& = Ice::emptyCurrent) override
78 {
79 ObjectClassList touchedClasses;
80
81 // iterate through unique classes and add them to classes segment
82 ObjectClassList objectClasses = classesSegmentPrx->getClassWithSubclasses(className);
83
84 ObjectClassList::iterator iter = objectClasses.begin();
85
86 while (iter != objectClasses.end())
87 {
88 ObjectClassBasePtr priorObjectClass = *iter;
89
90 ObjectClassBasePtr wmObjectClass = addClass(priorObjectClass);
91 touchedClasses.push_back(wmObjectClass);
92
93 iter++;
94 }
95
96 return touchedClasses;
97 }
98
99 /**
100 * Retrieves complete ontological tree from this segment
101 *
102 * @param rootClassName name of the root class
103 */
104 ObjectClassList
105 getClassWithSubclasses(const std::string& rootClassName,
106 const ::Ice::Current& = Ice::emptyCurrent) override
107 {
108 // iterate through classes
109 ObjectClassList relevantClasses;
110 ObjectClassPtr root = ObjectClassPtr::dynamicCast(getEntityByName(rootClassName));
111
112 if (!root)
113 {
114 return ObjectClassList();
115 }
116
117 relevantClasses.push_back(root);
118
119 int index = 0;
120
121 while (index != int(relevantClasses.size()))
122 {
123 ObjectClassBasePtr current = relevantClasses.at(index);
124
125 // add children of this class
126 ObjectClassList childs = getChildClasses(current->getName());
127
128 if (childs.size() != 0)
129 {
130 std::copy(childs.begin(), childs.end(), std::back_inserter(relevantClasses));
131 }
132
133 index++;
134 }
135
136 return relevantClasses;
137 }
138
139 /**
140 * Update a class with the given entity. Copys reference counter to updated entity.
141 *
142 * @param className name of the class in prior knowledge
143 * @param update entity replacing the old one
144 */
145 ObjectClassBasePtr
146 updateClass(const std::string& className,
147 const ObjectClassBasePtr& update,
148 const ::Ice::Current& = Ice::emptyCurrent) override
149 {
150 ARMARX_DEBUG_S << "updateClass(): " << className;
151
152 if (update->getName() != className)
153 {
154 return NULL;
155 }
156
157 // check whether entity already present in segment
158 EntityBasePtr storedObjectClass = getEntityByName(className);
159
160 if (!storedObjectClass)
161 {
162 return NULL;
163 }
164
165 // copy reference counting
166 std::string refCountAttrName = "referenceCounter";
167
168 if (storedObjectClass->hasAttribute(refCountAttrName))
169 {
170
171 int counter =
172 storedObjectClass->getAttribute(refCountAttrName)->getValue()->getInt();
173 update->putAttribute(
174 new EntityAttribute(refCountAttrName, new armarx::Variant(counter)));
175 }
176
177 // update the entity
178 updateEntity(storedObjectClass->getId(), update);
179
180 return ObjectClassBasePtr::dynamicCast(getEntityById(storedObjectClass->getId()));
181 }
182
183 /**
184 * Removes a class and its ontological subclasses. The ontology is fetched from prior knowledge.
185 *
186 * Reference counting is used, so classes are only removed, if they are not referenced anymore.
187 *
188 * @param className name of the class in prior knowledge
189 */
190 void
191 removePriorClassWithSubclasses(const std::string& className,
192 const ::Ice::Current& = Ice::emptyCurrent) override
193 {
194 // iterate through unique classes and add them to classes segment
195 ObjectClassList objectClasses = classesSegmentPrx->getClassWithSubclasses(className);
196
197 ObjectClassList::iterator iter = objectClasses.begin();
198
199
200 while (iter != objectClasses.end())
201 {
202 removeClass((*iter)->getName());
203 iter++;
204 }
205 }
206
207 static std::string
208 ObjectsToString(const ObjectClassList& objects)
209 {
210 std::string result;
211
212 for (ObjectClassList::const_iterator it = objects.begin(); it != objects.end(); it++)
213 {
214 if (!result.empty())
215 {
216 result += ", ";
217 }
218
219 if (*it)
220 {
221 result += (*it)->getName();
222 }
223 else
224 {
225 result += "NULL";
226 }
227 }
228
229 return result;
230 }
231
232 static Ice::StringSeq
233 ObjectsToStringList(const ObjectClassList& objects)
234 {
235 Ice::StringSeq result;
236
237 for (ObjectClassList::const_iterator it = objects.begin(); it != objects.end(); it++)
238 {
239 if (*it)
240 {
241 result.push_back((*it)->getName());
242 }
243 else
244 {
245 result.push_back("NULL");
246 }
247 }
248
249 return result;
250 }
251
252 static bool
253 ListContainsObject(const ObjectClassList& objects, ObjectClassBasePtr object)
254 {
255 for (ObjectClassList::const_iterator it = objects.begin(); it != objects.end(); it++)
256 {
257 if ((*it)->getName() == object->getName())
258 {
259 return true;
260 }
261 }
262
263 return false;
264 }
265
266 private:
267 ObjectClassBasePtr
268 addClass(const ObjectClassBasePtr& objectClass)
269 {
270 std::string refCountAttrName = "referenceCounter";
271
272 // check whether entity already present in segment
273 EntityBasePtr storedObjectClass = getEntityByName(objectClass->getName());
274
275 if (storedObjectClass)
276 {
277 // increase reference counter
278 if (storedObjectClass->hasAttribute(refCountAttrName))
279 {
280 int counter =
281 storedObjectClass->getAttribute(refCountAttrName)->getValue()->getInt();
282 counter++;
283 storedObjectClass->putAttribute(
284 new EntityAttribute(refCountAttrName, new armarx::Variant(counter)));
285 }
286 else
287 {
288 storedObjectClass->putAttribute(
289 new EntityAttribute(refCountAttrName, new armarx::Variant(2)));
290 }
291 }
292 else
293 {
294 // add entity
295 objectClass->putAttribute(
296 new EntityAttribute(refCountAttrName, new armarx::Variant(1)));
297 std::string id = addEntity(objectClass);
298 storedObjectClass = getEntityById(id);
299 }
300
301 return ObjectClassBasePtr::dynamicCast(storedObjectClass);
302 }
303
304 void
305 removeClass(const std::string& className)
306 {
307 std::string refCountAttrName = "referenceCounter";
308
309 // check whether entity already present in segment
310 EntityBasePtr storedObjectClass = getEntityByName(className);
311
312 if (storedObjectClass)
313 {
314 // storedObjectClass reference counter
315 if (storedObjectClass->hasAttribute(refCountAttrName))
316 {
317
318 int counter =
319 storedObjectClass->getAttribute(refCountAttrName)->getValue()->getInt();
320 counter--;
321
322 if (counter != 0)
323 {
324 storedObjectClass->putAttribute(
325 new EntityAttribute(refCountAttrName, new armarx::Variant(counter)));
326 }
327 else
328 {
329 // remove entity
330 ARMARX_INFO_S << "Removing object class " << storedObjectClass->getName();
331 removeEntity(storedObjectClass->getId());
332 }
333 }
334 }
335 }
336
337 ObjectClassList
338 getChildClasses(const std::string& parentClassName)
339 {
340 ObjectClassList result;
341 EntityBaseList children = getEntitiesByAttrValue("parentClasses", parentClassName);
342
343 for (EntityBaseList::const_iterator it = children.begin(); it != children.end(); ++it)
344 {
345 result.push_back(ObjectClassBasePtr::dynamicCast(*it));
346 }
347
348 return result;
349 }
350
351 PriorKnowledgeInterfacePrx priorKnowledgePrx;
352 memoryx::PersistentObjectClassSegmentBasePrx classesSegmentPrx;
353 };
354
356
357
358} // namespace memoryx
uint8_t index
#define ARMARXCOMPONENT_IMPORT_EXPORT
The Variant class is described here: Variants.
Definition Variant.h:224
Attribute of MemoryX entities.
static bool ListContainsObject(const ObjectClassList &objects, ObjectClassBasePtr object)
static std::string ObjectsToString(const ObjectClassList &objects)
ObjectClassMemorySegment(const PriorKnowledgeInterfacePrx &priorKnowledgePrx)
Creates a new object class segment.
ObjectClassList getClassWithSubclasses(const std::string &rootClassName, const ::Ice::Current &=Ice::emptyCurrent) override
Retrieves complete ontological tree from this segment.
void removePriorClassWithSubclasses(const std::string &className, const ::Ice::Current &=Ice::emptyCurrent) override
Removes a class and its ontological subclasses.
ObjectClassList addPriorClassWithSubclasses(const std::string &className, const ::Ice::Current &=Ice::emptyCurrent) override
Fetches a class and its ontological subclasses from prior knowledge and inserts the complete subtree ...
static Ice::StringSeq ObjectsToStringList(const ObjectClassList &objects)
ObjectClassBasePtr updateClass(const std::string &className, const ObjectClassBasePtr &update, const ::Ice::Current &=Ice::emptyCurrent) override
Update a class with the given entity.
void updateEntity(const std::string &entityId, const EntityBasePtr &update, const ::Ice::Current &c=Ice::emptyCurrent) override
EntityBasePtr getEntityByName(const ::std::string &name) const
EntityBasePtr getEntityById(const ::std::string &id) const
#define ARMARX_DEBUG_S
The logging level for output that is only interesting while debugging.
Definition Logging.h:205
#define ARMARX_INFO_S
Definition Logging.h:202
VirtualRobot headers.
IceInternal::Handle< ObjectClassMemorySegment > ObjectClassMemorySegmentPtr
IceInternal::Handle< ObjectClass > ObjectClassPtr
Definition ObjectClass.h:35