1 // Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de
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.
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.
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.
19 # include <simgear_config.h>
22 #include <simgear/compiler.h>
24 #include "HLAObjectClass.hxx"
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"
37 HLAObjectClass::InstanceCallback::~InstanceCallback()
42 HLAObjectClass::InstanceCallback::discoverInstance(const HLAObjectClass&, HLAObjectInstance& objectInstance, const RTIData& tag)
47 HLAObjectClass::InstanceCallback::removeInstance(const HLAObjectClass&, HLAObjectInstance& objectInstance, const RTIData& tag)
52 HLAObjectClass::InstanceCallback::registerInstance(const HLAObjectClass&, HLAObjectInstance& objectInstance)
57 HLAObjectClass::InstanceCallback::deleteInstance(const HLAObjectClass&, HLAObjectInstance& objectInstance)
61 HLAObjectClass::RegistrationCallback::~RegistrationCallback()
65 HLAObjectClass::HLAObjectClass(const std::string& name, HLAFederate* federate) :
70 SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass::HLAObjectClass(): "
71 "No parent federate given for object class \"" << getName() << "\"!");
74 federate->_insertObjectClass(this);
77 HLAObjectClass::~HLAObjectClass()
79 // HLAObjectClass objects only get deleted when the parent federate
80 // dies. So we do not need to deregister there.
82 _clearRTIObjectClass();
86 HLAObjectClass::getName() const
91 const SGWeakPtr<HLAFederate>&
92 HLAObjectClass::getFederate() const
98 HLAObjectClass::getNumAttributes() const
100 return _attributeVector.size();
104 HLAObjectClass::addAttribute(const std::string& name)
106 unsigned index = _attributeVector.size();
107 _nameIndexMap[name] = index;
108 _attributeVector.push_back(Attribute(name));
109 _resolveAttributeIndex(name, index);
114 HLAObjectClass::getAttributeIndex(const std::string& name) const
116 NameIndexMap::const_iterator i = _nameIndexMap.find(name);
117 if (i == _nameIndexMap.end())
123 HLAObjectClass::getAttributeName(unsigned index) const
125 if (_attributeVector.size() <= index)
126 return std::string();
127 return _attributeVector[index]._name;
131 HLAObjectClass::getAttributeDataType(unsigned index) const
133 if (_attributeVector.size() <= index)
135 return _attributeVector[index]._dataType.get();
139 HLAObjectClass::setAttributeDataType(unsigned index, const HLADataType* dataType)
141 if (_attributeVector.size() <= index)
143 _attributeVector[index]._dataType = dataType;
147 HLAObjectClass::getAttributeUpdateType(unsigned index) const
149 if (_attributeVector.size() <= index)
150 return HLAUndefinedUpdate;
151 return _attributeVector[index]._updateType;
155 HLAObjectClass::setAttributeUpdateType(unsigned index, HLAUpdateType updateType)
157 if (_attributeVector.size() <= index)
159 _attributeVector[index]._updateType = updateType;
163 HLAObjectClass::getAttributeSubscriptionType(unsigned index) const
165 if (_attributeVector.size() <= index)
166 return HLAUnsubscribed;
167 return _attributeVector[index]._subscriptionType;
171 HLAObjectClass::setAttributeSubscriptionType(unsigned index, HLASubscriptionType subscriptionType)
173 if (_attributeVector.size() <= index)
175 _attributeVector[index]._subscriptionType = subscriptionType;
179 HLAObjectClass::getAttributePublicationType(unsigned index) const
181 if (_attributeVector.size() <= index)
182 return HLAUnpublished;
183 return _attributeVector[index]._publicationType;
187 HLAObjectClass::setAttributePublicationType(unsigned index, HLAPublicationType publicationType)
189 if (_attributeVector.size() <= index)
191 _attributeVector[index]._publicationType = publicationType;
194 HLADataElement::IndexPathPair
195 HLAObjectClass::getIndexPathPair(const HLADataElement::StringPathPair& stringPathPair) const
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() << "\"!");
204 return HLADataElement::IndexPathPair(index, stringPathPair.second);
207 HLADataElement::IndexPathPair
208 HLAObjectClass::getIndexPathPair(const std::string& path) const
210 return getIndexPathPair(HLADataElement::toStringPathPair(path));
214 HLAObjectClass::getDataElementIndex(HLADataElementIndex& dataElementIndex, const std::string& path) const
217 SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: failed to parse empty element path!");
220 std::string::size_type len = std::min(path.find_first_of("[."), path.size());
222 while (index < getNumAttributes()) {
223 if (path.compare(0, len, getAttributeName(index)) == 0)
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() << "\"!");
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) << "\"!");
239 dataElementIndex.push_back(index);
240 return getAttributeDataType(index)->getDataElementIndex(dataElementIndex, path, len);
244 HLAObjectClass::getDataElementIndex(const std::string& path) const
246 HLADataElementIndex dataElementIndex;
247 getDataElementIndex(dataElementIndex, path);
248 return dataElementIndex;
252 HLAObjectClass::subscribe()
254 if (!_rtiObjectClass.valid()) {
255 SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::subscribe(): "
256 "No RTIObject class for object class \"" << getName() << "\"!");
260 HLAIndexList indexList;
261 for (unsigned i = 1; i < getNumAttributes(); ++i) {
262 if (_attributeVector[i]._subscriptionType != HLASubscribedActive)
264 indexList.push_back(i);
266 if (!indexList.empty()) {
267 if (!_rtiObjectClass->subscribe(indexList, true))
272 for (unsigned i = 1; i < getNumAttributes(); ++i) {
273 if (_attributeVector[i]._subscriptionType != HLASubscribedPassive)
275 indexList.push_back(i);
277 if (!indexList.empty()) {
278 if (!_rtiObjectClass->subscribe(indexList, false))
285 HLAObjectClass::unsubscribe()
287 if (!_rtiObjectClass.valid()) {
288 SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::unsubscribe(): "
289 "No RTIObject class for object class \"" << getName() << "\"!");
292 return _rtiObjectClass->unsubscribe();
296 HLAObjectClass::publish()
298 if (!_rtiObjectClass.valid()) {
299 SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::publish(): "
300 "No RTIObject class for object class \"" << getName() << "\"!");
304 HLAIndexList indexList;
305 for (unsigned i = 1; i < getNumAttributes(); ++i) {
306 if (_attributeVector[i]._publicationType == HLAUnpublished)
308 indexList.push_back(i);
310 if (indexList.empty())
312 if (!_rtiObjectClass->publish(indexList))
318 HLAObjectClass::unpublish()
320 if (!_rtiObjectClass.valid()) {
321 SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::unpublish(): "
322 "No RTIObject class for object class \"" << getName() << "\"!");
325 return _rtiObjectClass->unpublish();
329 HLAObjectClass::discoverInstance(HLAObjectInstance& objectInstance, const RTIData& tag)
331 if (_instanceCallback.valid())
332 _instanceCallback->discoverInstance(*this, objectInstance, tag);
336 HLAObjectClass::removeInstance(HLAObjectInstance& objectInstance, const RTIData& tag)
338 if (_instanceCallback.valid())
339 _instanceCallback->removeInstance(*this, objectInstance, tag);
343 HLAObjectClass::registerInstance(HLAObjectInstance& objectInstance)
345 if (_instanceCallback.valid())
346 _instanceCallback->registerInstance(*this, objectInstance);
350 HLAObjectClass::deleteInstance(HLAObjectInstance& objectInstance)
352 if (_instanceCallback.valid())
353 _instanceCallback->deleteInstance(*this, objectInstance);
357 HLAObjectClass::startRegistration() const
362 HLAObjectClass::stopRegistration() const
367 HLAObjectClass::createObjectInstance(const std::string& name)
369 SGSharedPtr<HLAFederate> federate = _federate.lock();
370 if (!federate.valid())
372 return federate->createObjectInstance(this, name);
376 HLAObjectClass::createAttributeDataElements(HLAObjectInstance& objectInstance)
378 unsigned numAttributes = getNumAttributes();
379 for (unsigned i = 0; i < numAttributes; ++i)
380 objectInstance.createAndSetAttributeDataElement(i);
384 HLAObjectClass::createAttributeDataElement(HLAObjectInstance& objectInstance, unsigned index)
386 // FIXME here we want to have a vector of factories and if this fails do the following
387 const HLADataType* dataType = getAttributeDataType(index);
390 HLADataElementFactoryVisitor dataElementFactoryVisitor;
391 dataType->accept(dataElementFactoryVisitor);
392 return dataElementFactoryVisitor.getDataElement();
396 HLAObjectClass::_setRTIObjectClass(RTIObjectClass* objectClass)
398 if (_rtiObjectClass) {
399 SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: Setting RTIObjectClass twice for object class \"" << getName() << "\"!");
402 _rtiObjectClass = objectClass;
403 if (_rtiObjectClass->_objectClass != this) {
404 SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: backward reference does not match!");
407 for (unsigned i = 0; i < _attributeVector.size(); ++i)
408 _resolveAttributeIndex(_attributeVector[i]._name, i);
412 HLAObjectClass::_resolveAttributeIndex(const std::string& name, unsigned index)
414 if (!_rtiObjectClass)
416 if (!_rtiObjectClass->resolveAttributeIndex(name, index))
417 SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: Could not resolve attribute \""
418 << name << "\" for object class \"" << getName() << "\"!");
422 HLAObjectClass::_clearRTIObjectClass()
424 if (!_rtiObjectClass.valid())
426 _rtiObjectClass->_objectClass = 0;
431 HLAObjectClass::_discoverInstance(RTIObjectInstance* rtiObjectInstance, const RTIData& tag)
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");
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");
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");
453 objectInstance->discoverInstance(tag);
454 objectInstance->createAttributeDataElements();
458 HLAObjectClass::_removeInstance(HLAObjectInstance& objectInstance, const RTIData& tag)
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");
465 SG_LOG(SG_NETWORK, SG_INFO, "RTI: remove object instance \"" << objectInstance.getName() << "\"");
466 objectInstance.removeInstance(tag);
467 federate->_eraseObjectInstance(objectInstance.getName());
471 HLAObjectClass::_registerInstance(HLAObjectInstance* objectInstance)
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");
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");
487 registerInstance(*objectInstance);
488 objectInstance->createAttributeDataElements();
492 HLAObjectClass::_deleteInstance(HLAObjectInstance& objectInstance)
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");
499 deleteInstance(objectInstance);
500 federate->_eraseObjectInstance(objectInstance.getName());
504 HLAObjectClass::_startRegistration()
506 if (_registrationCallback.valid())
507 _registrationCallback->startRegistration(*this);
513 HLAObjectClass::_stopRegistration()
515 if (_registrationCallback.valid())
516 _registrationCallback->stopRegistration(*this);
521 } // namespace simgear