]> git.mxchange.org Git - simgear.git/blob - simgear/hla/HLAObjectClass.cxx
hla: Use HLADataElementIndices for HLAInteractionClass.
[simgear.git] / simgear / hla / HLAObjectClass.cxx
1 // Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Library General Public
5 // License as published by the Free Software Foundation; either
6 // version 2 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Library 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, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
16 //
17
18 #ifdef HAVE_CONFIG_H
19 #  include <simgear_config.h>
20 #endif
21
22 #include <simgear/compiler.h>
23
24 #include "HLAObjectClass.hxx"
25
26 #include "simgear/debug/logstream.hxx"
27 #include "RTIFederate.hxx"
28 #include "RTIObjectClass.hxx"
29 #include "RTIObjectInstance.hxx"
30 #include "HLADataType.hxx"
31 #include "HLADataTypeVisitor.hxx"
32 #include "HLAFederate.hxx"
33 #include "HLAObjectInstance.hxx"
34
35 namespace simgear {
36
37 HLAObjectClass::InstanceCallback::~InstanceCallback()
38 {
39 }
40
41 void
42 HLAObjectClass::InstanceCallback::discoverInstance(const HLAObjectClass&, HLAObjectInstance& objectInstance, const RTIData& tag)
43 {
44 }
45
46 void
47 HLAObjectClass::InstanceCallback::removeInstance(const HLAObjectClass&, HLAObjectInstance& objectInstance, const RTIData& tag)
48 {
49 }
50
51 void
52 HLAObjectClass::InstanceCallback::registerInstance(const HLAObjectClass&, HLAObjectInstance& objectInstance)
53 {
54 }
55
56 void
57 HLAObjectClass::InstanceCallback::deleteInstance(const HLAObjectClass&, HLAObjectInstance& objectInstance)
58 {
59 }
60
61 HLAObjectClass::RegistrationCallback::~RegistrationCallback()
62 {
63 }
64
65 HLAObjectClass::HLAObjectClass(const std::string& name, HLAFederate* federate) :
66     _federate(federate),
67     _name(name)
68 {
69     if (!federate) {
70         SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass::HLAObjectClass(): "
71                "No parent federate given for object class \"" << getName() << "\"!");
72         return;
73     }
74     federate->_insertObjectClass(this);
75 }
76
77 HLAObjectClass::~HLAObjectClass()
78 {
79     // HLAObjectClass objects only get deleted when the parent federate
80     // dies. So we do not need to deregister there.
81
82     _clearRTIObjectClass();
83 }
84
85 const std::string&
86 HLAObjectClass::getName() const
87 {
88     return _name;
89 }
90
91 const SGWeakPtr<HLAFederate>&
92 HLAObjectClass::getFederate() const
93 {
94     return _federate;
95 }
96
97 unsigned
98 HLAObjectClass::getNumAttributes() const
99 {
100     return _attributeVector.size();
101 }
102
103 unsigned
104 HLAObjectClass::addAttribute(const std::string& name)
105 {
106     unsigned index = _attributeVector.size();
107     _nameIndexMap[name] = index;
108     _attributeVector.push_back(Attribute(name));
109     _resolveAttributeIndex(name, index);
110     return index;
111 }
112
113 unsigned
114 HLAObjectClass::getAttributeIndex(const std::string& name) const
115 {
116     NameIndexMap::const_iterator i = _nameIndexMap.find(name);
117     if (i == _nameIndexMap.end())
118         return ~0u;
119     return i->second;
120 }
121
122 std::string
123 HLAObjectClass::getAttributeName(unsigned index) const
124 {
125     if (_attributeVector.size() <= index)
126         return std::string();
127     return _attributeVector[index]._name;
128 }
129
130 const HLADataType*
131 HLAObjectClass::getAttributeDataType(unsigned index) const
132 {
133     if (_attributeVector.size() <= index)
134         return 0;
135     return _attributeVector[index]._dataType.get();
136 }
137
138 void
139 HLAObjectClass::setAttributeDataType(unsigned index, const HLADataType* dataType)
140 {
141     if (_attributeVector.size() <= index)
142         return;
143     _attributeVector[index]._dataType = dataType;
144 }
145
146 HLAUpdateType
147 HLAObjectClass::getAttributeUpdateType(unsigned index) const
148 {
149     if (_attributeVector.size() <= index)
150         return HLAUndefinedUpdate;
151     return _attributeVector[index]._updateType;
152 }
153
154 void
155 HLAObjectClass::setAttributeUpdateType(unsigned index, HLAUpdateType updateType)
156 {
157     if (_attributeVector.size() <= index)
158         return;
159     _attributeVector[index]._updateType = updateType;
160 }
161
162 HLASubscriptionType
163 HLAObjectClass::getAttributeSubscriptionType(unsigned index) const
164 {
165     if (_attributeVector.size() <= index)
166         return HLAUnsubscribed;
167     return _attributeVector[index]._subscriptionType;
168 }
169
170 void
171 HLAObjectClass::setAttributeSubscriptionType(unsigned index, HLASubscriptionType subscriptionType)
172 {
173     if (_attributeVector.size() <= index)
174         return;
175     _attributeVector[index]._subscriptionType = subscriptionType;
176 }
177
178 HLAPublicationType
179 HLAObjectClass::getAttributePublicationType(unsigned index) const
180 {
181     if (_attributeVector.size() <= index)
182         return HLAUnpublished;
183     return _attributeVector[index]._publicationType;
184 }
185
186 void
187 HLAObjectClass::setAttributePublicationType(unsigned index, HLAPublicationType publicationType)
188 {
189     if (_attributeVector.size() <= index)
190         return;
191     _attributeVector[index]._publicationType = publicationType;
192 }
193
194 HLADataElement::IndexPathPair
195 HLAObjectClass::getIndexPathPair(const HLADataElement::StringPathPair& stringPathPair) const
196 {
197     unsigned index = getAttributeIndex(stringPathPair.first);
198     if (getNumAttributes() <= index) {
199         SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass::getIndexPathPair(\""
200                << HLADataElement::toString(stringPathPair)
201                << "\"): Could not resolve attribute \"" << stringPathPair.first
202                << "\" for object class \"" << getName() << "\"!");
203     }
204     return HLADataElement::IndexPathPair(index, stringPathPair.second);
205 }
206
207 HLADataElement::IndexPathPair
208 HLAObjectClass::getIndexPathPair(const std::string& path) const
209 {
210     return getIndexPathPair(HLADataElement::toStringPathPair(path));
211 }
212
213 bool
214 HLAObjectClass::getDataElementIndex(HLADataElementIndex& dataElementIndex, const std::string& path) const
215 {
216     if (path.empty()) {
217         SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: failed to parse empty element path!");
218         return false;
219     }
220     std::string::size_type len = std::min(path.find_first_of("[."), path.size());
221     unsigned index = 0;
222     while (index < getNumAttributes()) {
223         if (path.compare(0, len, getAttributeName(index)) == 0)
224             break;
225         ++index;
226     }
227     if (getNumAttributes() <= index) {
228         SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: faild to parse data element index \"" << path << "\":\n"
229                << "Attribute \"" << path.substr(0, len) << "\" not found in object class \""
230                << getName() << "\"!");
231         return false;
232     }
233     if (!getAttributeDataType(index)) {
234         SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: faild to parse data element index \"" << path << "\":\n"
235                << "Undefined attribute data type in variant record data type \""
236                << getAttributeName(index) << "\"!");
237         return false;
238     }
239     dataElementIndex.push_back(index);
240     return getAttributeDataType(index)->getDataElementIndex(dataElementIndex, path, len);
241 }
242
243 HLADataElementIndex
244 HLAObjectClass::getDataElementIndex(const std::string& path) const
245 {
246     HLADataElementIndex dataElementIndex;
247     getDataElementIndex(dataElementIndex, path);
248     return dataElementIndex;
249 }
250
251 bool
252 HLAObjectClass::subscribe()
253 {
254     if (!_rtiObjectClass.valid()) {
255         SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::subscribe(): "
256                "No RTIObject class for object class \"" << getName() << "\"!");
257         return false;
258     }
259
260     HLAIndexList indexList;
261     for (unsigned i = 1; i < getNumAttributes(); ++i) {
262         if (_attributeVector[i]._subscriptionType != HLASubscribedActive)
263             continue;
264         indexList.push_back(i);
265     }
266     if (!indexList.empty()) {
267         if (!_rtiObjectClass->subscribe(indexList, true))
268             return false;
269     }
270
271     indexList.clear();
272     for (unsigned i = 1; i < getNumAttributes(); ++i) {
273         if (_attributeVector[i]._subscriptionType != HLASubscribedPassive)
274             continue;
275         indexList.push_back(i);
276     }
277     if (!indexList.empty()) {
278         if (!_rtiObjectClass->subscribe(indexList, false))
279             return false;
280     }
281     return true;
282 }
283
284 bool
285 HLAObjectClass::unsubscribe()
286 {
287     if (!_rtiObjectClass.valid()) {
288         SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::unsubscribe(): "
289                "No RTIObject class for object class \"" << getName() << "\"!");
290         return false;
291     }
292     return _rtiObjectClass->unsubscribe();
293 }
294
295 bool
296 HLAObjectClass::publish()
297 {
298     if (!_rtiObjectClass.valid()) {
299         SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::publish(): "
300                "No RTIObject class for object class \"" << getName() << "\"!");
301         return false;
302     }
303
304     HLAIndexList indexList;
305     for (unsigned i = 1; i < getNumAttributes(); ++i) {
306         if (_attributeVector[i]._publicationType == HLAUnpublished)
307             continue;
308         indexList.push_back(i);
309     }
310     if (indexList.empty())
311         return true;
312     if (!_rtiObjectClass->publish(indexList))
313         return false;
314     return true;
315 }
316
317 bool
318 HLAObjectClass::unpublish()
319 {
320     if (!_rtiObjectClass.valid()) {
321         SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::unpublish(): "
322                "No RTIObject class for object class \"" << getName() << "\"!");
323         return false;
324     }
325     return _rtiObjectClass->unpublish();
326 }
327
328 void
329 HLAObjectClass::discoverInstance(HLAObjectInstance& objectInstance, const RTIData& tag)
330 {
331     if (_instanceCallback.valid())
332         _instanceCallback->discoverInstance(*this, objectInstance, tag);
333 }
334
335 void
336 HLAObjectClass::removeInstance(HLAObjectInstance& objectInstance, const RTIData& tag)
337 {
338     if (_instanceCallback.valid())
339         _instanceCallback->removeInstance(*this, objectInstance, tag);
340 }
341
342 void
343 HLAObjectClass::registerInstance(HLAObjectInstance& objectInstance)
344 {
345     if (_instanceCallback.valid())
346         _instanceCallback->registerInstance(*this, objectInstance);
347 }
348
349 void
350 HLAObjectClass::deleteInstance(HLAObjectInstance& objectInstance)
351 {
352     if (_instanceCallback.valid())
353         _instanceCallback->deleteInstance(*this, objectInstance);
354 }
355
356 void
357 HLAObjectClass::startRegistration() const
358 {
359 }
360
361 void
362 HLAObjectClass::stopRegistration() const
363 {
364 }
365
366 HLAObjectInstance*
367 HLAObjectClass::createObjectInstance(const std::string& name)
368 {
369     SGSharedPtr<HLAFederate> federate = _federate.lock();
370     if (!federate.valid())
371         return 0;
372     return federate->createObjectInstance(this, name);
373 }
374
375 void
376 HLAObjectClass::createAttributeDataElements(HLAObjectInstance& objectInstance)
377 {
378     unsigned numAttributes = getNumAttributes();
379     for (unsigned i = 0; i < numAttributes; ++i)
380         objectInstance.createAndSetAttributeDataElement(i);
381 }
382
383 HLADataElement*
384 HLAObjectClass::createAttributeDataElement(HLAObjectInstance& objectInstance, unsigned index)
385 {
386     // FIXME here we want to have a vector of factories and if this fails do the following
387     const HLADataType* dataType = getAttributeDataType(index);
388     if (!dataType)
389         return 0;
390     HLADataElementFactoryVisitor dataElementFactoryVisitor;
391     dataType->accept(dataElementFactoryVisitor);
392     return dataElementFactoryVisitor.getDataElement();
393 }
394
395 void
396 HLAObjectClass::_setRTIObjectClass(RTIObjectClass* objectClass)
397 {
398     if (_rtiObjectClass) {
399         SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: Setting RTIObjectClass twice for object class \"" << getName() << "\"!");
400         return;
401     }
402     _rtiObjectClass = objectClass;
403     if (_rtiObjectClass->_objectClass != this) {
404         SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: backward reference does not match!");
405         return;
406     }
407     for (unsigned i = 0; i < _attributeVector.size(); ++i)
408         _resolveAttributeIndex(_attributeVector[i]._name, i);
409 }
410
411 void
412 HLAObjectClass::_resolveAttributeIndex(const std::string& name, unsigned index)
413 {
414     if (!_rtiObjectClass)
415         return;
416     if (!_rtiObjectClass->resolveAttributeIndex(name, index))
417         SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: Could not resolve attribute \""
418                << name << "\" for object class \"" << getName() << "\"!");
419 }
420
421 void
422 HLAObjectClass::_clearRTIObjectClass()
423 {
424     if (!_rtiObjectClass.valid())
425         return;
426     _rtiObjectClass->_objectClass = 0;
427     _rtiObjectClass = 0;
428 }
429
430 void
431 HLAObjectClass::_discoverInstance(RTIObjectInstance* rtiObjectInstance, const RTIData& tag)
432 {
433     SGSharedPtr<HLAFederate> federate = _federate.lock();
434     if (!federate.valid()) {
435         SG_LOG(SG_NETWORK, SG_ALERT, "RTI: could not find parent federate while discovering object instance");
436         return;
437     }
438
439     SGSharedPtr<HLAObjectInstance> objectInstance = createObjectInstance(rtiObjectInstance->getName());
440     if (!objectInstance.valid()) {
441         SG_LOG(SG_NETWORK, SG_INFO, "RTI: could not create new object instance for discovered \""
442                << rtiObjectInstance->getName() << "\" object");
443         return;
444     }
445     SG_LOG(SG_NETWORK, SG_INFO, "RTI: create new object instance for discovered \""
446            << rtiObjectInstance->getName() << "\" object");
447     objectInstance->_setRTIObjectInstance(rtiObjectInstance);
448     if (!federate->_insertObjectInstance(objectInstance)) {
449         SG_LOG(SG_NETWORK, SG_ALERT, "RTI: could not insert new object instance for discovered \""
450                << rtiObjectInstance->getName() << "\" object");
451         return;
452     }
453     objectInstance->discoverInstance(tag);
454     objectInstance->createAttributeDataElements();
455 }
456
457 void
458 HLAObjectClass::_removeInstance(HLAObjectInstance& objectInstance, const RTIData& tag)
459 {
460     SGSharedPtr<HLAFederate> federate = _federate.lock();
461     if (!federate.valid()) {
462         SG_LOG(SG_NETWORK, SG_ALERT, "RTI: could not find parent federate while removing object instance");
463         return;
464     }
465     SG_LOG(SG_NETWORK, SG_INFO, "RTI: remove object instance \"" << objectInstance.getName() << "\"");
466     objectInstance.removeInstance(tag);
467     federate->_eraseObjectInstance(objectInstance.getName());
468 }
469
470 void
471 HLAObjectClass::_registerInstance(HLAObjectInstance* objectInstance)
472 {
473     SGSharedPtr<HLAFederate> federate = _federate.lock();
474     if (!federate.valid()) {
475         SG_LOG(SG_NETWORK, SG_ALERT, "RTI: could not find parent federate while registering object instance");
476         return;
477     }
478     if (!objectInstance)
479         return;
480     // We can only register object instances with a valid name at the rti.
481     // So, we cannot do that at HLAObjectInstance creation time.
482     if (!federate->_insertObjectInstance(objectInstance)) {
483         SG_LOG(SG_NETWORK, SG_ALERT, "RTI: could not insert new object instance \""
484                << objectInstance->getName() << "\" object");
485         return;
486     }
487     registerInstance(*objectInstance);
488     objectInstance->createAttributeDataElements();
489 }
490
491 void
492 HLAObjectClass::_deleteInstance(HLAObjectInstance& objectInstance)
493 {
494     SGSharedPtr<HLAFederate> federate = _federate.lock();
495     if (!federate.valid()) {
496         SG_LOG(SG_NETWORK, SG_ALERT, "RTI: could not find parent federate while deleting object instance");
497         return;
498     }
499     deleteInstance(objectInstance);
500     federate->_eraseObjectInstance(objectInstance.getName());
501 }
502
503 void
504 HLAObjectClass::_startRegistration()
505 {
506     if (_registrationCallback.valid())
507         _registrationCallback->startRegistration(*this);
508     else
509         startRegistration();
510 }
511
512 void
513 HLAObjectClass::_stopRegistration()
514 {
515     if (_registrationCallback.valid())
516         _registrationCallback->stopRegistration(*this);
517     else
518         stopRegistration();
519 }
520
521 } // namespace simgear