X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fhla%2FHLAObjectClass.cxx;h=2740eb029d461ad6e573cf90331d9d3dbcb0e8a8;hb=d4310a7f3b27b8403ba1ec030cfd3b4c6c565f24;hp=4b8265621be009bf81be8a7f227ffbfeceea080a;hpb=feab25d0bee2c65a9b5c0a27802fb71c9a1a1190;p=simgear.git diff --git a/simgear/hla/HLAObjectClass.cxx b/simgear/hla/HLAObjectClass.cxx index 4b826562..2740eb02 100644 --- a/simgear/hla/HLAObjectClass.cxx +++ b/simgear/hla/HLAObjectClass.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public @@ -15,12 +15,20 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + #include "HLAObjectClass.hxx" +#include "simgear/debug/logstream.hxx" #include "RTIFederate.hxx" #include "RTIObjectClass.hxx" #include "RTIObjectInstance.hxx" #include "HLADataType.hxx" +#include "HLADataTypeVisitor.hxx" #include "HLAFederate.hxx" #include "HLAObjectInstance.hxx" @@ -54,148 +62,278 @@ HLAObjectClass::RegistrationCallback::~RegistrationCallback() { } -HLAObjectClass::HLAObjectClass(const std::string& name, HLAFederate& federate) : +HLAObjectClass::HLAObjectClass(const std::string& name, HLAFederate* federate) : + _federate(federate), _name(name) { - _rtiObjectClass = federate._rtiFederate->createObjectClass(name, this); - if (!_rtiObjectClass.valid()) - SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::HLAObjectClass(): No RTIObjectClass found for \"" << name << "\"!"); + if (!federate) { + SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass::HLAObjectClass(): " + "No parent federate given for object class \"" << getName() << "\"!"); + return; + } + federate->_insertObjectClass(this); } HLAObjectClass::~HLAObjectClass() { + // HLAObjectClass objects only get deleted when the parent federate + // dies. So we do not need to deregister there. + + _clearRTIObjectClass(); +} + +const std::string& +HLAObjectClass::getName() const +{ + return _name; +} + +const SGWeakPtr& +HLAObjectClass::getFederate() const +{ + return _federate; } unsigned HLAObjectClass::getNumAttributes() const { - if (!_rtiObjectClass.valid()) { - SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::getAttributeIndex(): No RTIObject class for object class \"" << getName() << "\"!"); - return 0; - } - return _rtiObjectClass->getNumAttributes(); + return _attributeVector.size(); +} + +unsigned +HLAObjectClass::addAttribute(const std::string& name) +{ + unsigned index = _attributeVector.size(); + _nameIndexMap[name] = index; + _attributeVector.push_back(Attribute(name)); + _resolveAttributeIndex(name, index); + return index; } unsigned HLAObjectClass::getAttributeIndex(const std::string& name) const { - if (!_rtiObjectClass.valid()) { - SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::getAttributeIndex(): No RTIObject class for object class \"" << getName() << "\"!"); + NameIndexMap::const_iterator i = _nameIndexMap.find(name); + if (i == _nameIndexMap.end()) return ~0u; - } - return _rtiObjectClass->getOrCreateAttributeIndex(name); + return i->second; } std::string HLAObjectClass::getAttributeName(unsigned index) const { - if (!_rtiObjectClass.valid()) { - SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::getAttributeIndex(): No RTIObject class for object class \"" << getName() << "\"!"); - return 0; - } - return _rtiObjectClass->getAttributeName(index); + if (_attributeVector.size() <= index) + return std::string(); + return _attributeVector[index]._name; } const HLADataType* HLAObjectClass::getAttributeDataType(unsigned index) const { - if (!_rtiObjectClass.valid()) { - SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::getAttributeDataType(): No RTIObject class for object class \"" << getName() << "\"!"); + if (_attributeVector.size() <= index) return 0; - } - return _rtiObjectClass->getAttributeDataType(index); + return _attributeVector[index]._dataType.get(); } void HLAObjectClass::setAttributeDataType(unsigned index, const HLADataType* dataType) { - if (!_rtiObjectClass.valid()) { - SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::setAttributeDataType(): No RTIObject class for object class \"" << getName() << "\"!"); + if (_attributeVector.size() <= index) return; - } - _rtiObjectClass->setAttributeDataType(index, dataType); + _attributeVector[index]._dataType = dataType; } HLAUpdateType HLAObjectClass::getAttributeUpdateType(unsigned index) const { - if (!_rtiObjectClass.valid()) { - SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::getAttributeUpdateType(): No RTIObject class for object class \"" << getName() << "\"!"); + if (_attributeVector.size() <= index) return HLAUndefinedUpdate; - } - return _rtiObjectClass->getAttributeUpdateType(index); + return _attributeVector[index]._updateType; } void HLAObjectClass::setAttributeUpdateType(unsigned index, HLAUpdateType updateType) { - if (!_rtiObjectClass.valid()) { - SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::setAttributeUpdateType(): " - "No RTIObject class for object class \"" << getName() << "\"!"); + if (_attributeVector.size() <= index) return; - } - _rtiObjectClass->setAttributeUpdateType(index, updateType); + _attributeVector[index]._updateType = updateType; } -HLADataElement::IndexPathPair -HLAObjectClass::getIndexPathPair(const HLADataElement::AttributePathPair& attributePathPair) const +HLASubscriptionType +HLAObjectClass::getAttributeSubscriptionType(unsigned index) const +{ + if (_attributeVector.size() <= index) + return HLAUnsubscribed; + return _attributeVector[index]._subscriptionType; +} + +void +HLAObjectClass::setAttributeSubscriptionType(unsigned index, HLASubscriptionType subscriptionType) { - unsigned index = getAttributeIndex(attributePathPair.first); + if (_attributeVector.size() <= index) + return; + _attributeVector[index]._subscriptionType = subscriptionType; +} + +HLAPublicationType +HLAObjectClass::getAttributePublicationType(unsigned index) const +{ + if (_attributeVector.size() <= index) + return HLAUnpublished; + return _attributeVector[index]._publicationType; +} + +void +HLAObjectClass::setAttributePublicationType(unsigned index, HLAPublicationType publicationType) +{ + if (_attributeVector.size() <= index) + return; + _attributeVector[index]._publicationType = publicationType; +} + +bool +HLAObjectClass::getDataElementIndex(HLADataElementIndex& dataElementIndex, const std::string& path) const +{ + if (path.empty()) { + SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: failed to parse empty element path!"); + return false; + } + std::string::size_type len = std::min(path.find_first_of("[."), path.size()); + unsigned index = 0; + while (index < getNumAttributes()) { + if (path.compare(0, len, getAttributeName(index)) == 0) + break; + ++index; + } if (getNumAttributes() <= index) { - SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass::getIndexPathPair(\"" - << HLADataElement::toString(attributePathPair) - << "\"): Could not resolve attribute \"" << attributePathPair.first - << "\" for object class \"" << getName() << "\"!"); + SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: faild to parse data element index \"" << path << "\":\n" + << "Attribute \"" << path.substr(0, len) << "\" not found in object class \"" + << getName() << "\"!"); + return false; } - return HLADataElement::IndexPathPair(index, attributePathPair.second); + if (!getAttributeDataType(index)) { + SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: faild to parse data element index \"" << path << "\":\n" + << "Undefined attribute data type in variant record data type \"" + << getAttributeName(index) << "\"!"); + return false; + } + dataElementIndex.push_back(index); + return getAttributeDataType(index)->getDataElementIndex(dataElementIndex, path, len); } -HLADataElement::IndexPathPair -HLAObjectClass::getIndexPathPair(const std::string& path) const +HLADataElementIndex +HLAObjectClass::getDataElementIndex(const std::string& path) const { - return getIndexPathPair(HLADataElement::toAttributePathPair(path)); + HLADataElementIndex dataElementIndex; + getDataElementIndex(dataElementIndex, path); + return dataElementIndex; } bool -HLAObjectClass::subscribe(const std::set& indexSet, bool active) +HLAObjectClass::subscribe() { if (!_rtiObjectClass.valid()) { - SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::subscribe(): No RTIObject class for object class \"" << getName() << "\"!"); + SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::subscribe(): " + "No RTIObject class for object class \"" << getName() << "\"!"); return false; } - return _rtiObjectClass->subscribe(indexSet, active); + + HLAIndexList indexList; + for (unsigned i = 1; i < getNumAttributes(); ++i) { + if (_attributeVector[i]._subscriptionType != HLASubscribedActive) + continue; + indexList.push_back(i); + } + if (!indexList.empty()) { + if (!_rtiObjectClass->subscribe(indexList, true)) + return false; + } + + indexList.clear(); + for (unsigned i = 1; i < getNumAttributes(); ++i) { + if (_attributeVector[i]._subscriptionType != HLASubscribedPassive) + continue; + indexList.push_back(i); + } + if (!indexList.empty()) { + if (!_rtiObjectClass->subscribe(indexList, false)) + return false; + } + return true; } bool HLAObjectClass::unsubscribe() { if (!_rtiObjectClass.valid()) { - SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::unsubscribe(): No RTIObject class for object class \"" << getName() << "\"!"); + SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::unsubscribe(): " + "No RTIObject class for object class \"" << getName() << "\"!"); return false; } return _rtiObjectClass->unsubscribe(); } bool -HLAObjectClass::publish(const std::set& indexSet) +HLAObjectClass::publish() { if (!_rtiObjectClass.valid()) { - SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::publish(): No RTIObject class for object class \"" << getName() << "\"!"); + SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::publish(): " + "No RTIObject class for object class \"" << getName() << "\"!"); return false; } - return _rtiObjectClass->publish(indexSet); + + HLAIndexList indexList; + for (unsigned i = 1; i < getNumAttributes(); ++i) { + if (_attributeVector[i]._publicationType == HLAUnpublished) + continue; + indexList.push_back(i); + } + if (indexList.empty()) + return true; + if (!_rtiObjectClass->publish(indexList)) + return false; + return true; } bool HLAObjectClass::unpublish() { if (!_rtiObjectClass.valid()) { - SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::unpublish(): No RTIObject class for object class \"" << getName() << "\"!"); + SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::unpublish(): " + "No RTIObject class for object class \"" << getName() << "\"!"); return false; } return _rtiObjectClass->unpublish(); } +void +HLAObjectClass::discoverInstance(HLAObjectInstance& objectInstance, const RTIData& tag) +{ + if (_instanceCallback.valid()) + _instanceCallback->discoverInstance(*this, objectInstance, tag); +} + +void +HLAObjectClass::removeInstance(HLAObjectInstance& objectInstance, const RTIData& tag) +{ + if (_instanceCallback.valid()) + _instanceCallback->removeInstance(*this, objectInstance, tag); +} + +void +HLAObjectClass::registerInstance(HLAObjectInstance& objectInstance) +{ + if (_instanceCallback.valid()) + _instanceCallback->registerInstance(*this, objectInstance); +} + +void +HLAObjectClass::deleteInstance(HLAObjectInstance& objectInstance) +{ + if (_instanceCallback.valid()) + _instanceCallback->deleteInstance(*this, objectInstance); +} + void HLAObjectClass::startRegistration() const { @@ -207,82 +345,144 @@ HLAObjectClass::stopRegistration() const } HLAObjectInstance* -HLAObjectClass::createObjectInstance(RTIObjectInstance* rtiObjectInstance) +HLAObjectClass::createObjectInstance(const std::string& name) { - return new HLAObjectInstance(this, rtiObjectInstance); + SGSharedPtr federate = _federate.lock(); + if (!federate.valid()) + return 0; + return federate->createObjectInstance(this, name); } void -HLAObjectClass::discoverInstance(RTIObjectInstance* objectInstance, const RTIData& tag) -{ - SGSharedPtr hlaObjectInstance = createObjectInstance(objectInstance); - if (hlaObjectInstance.valid()) { - SG_LOG(SG_NETWORK, SG_INFO, "RTI: create new object instance for discovered \"" - << hlaObjectInstance->getName() << "\" object"); - _objectInstanceSet.insert(hlaObjectInstance); - discoverInstanceCallback(*hlaObjectInstance, tag); - } else { - SG_LOG(SG_NETWORK, SG_INFO, "RTI: local delete of \"" << objectInstance->getName() << "\""); - objectInstance->localDeleteObjectInstance(); - } +HLAObjectClass::createAttributeDataElements(HLAObjectInstance& objectInstance) +{ + unsigned numAttributes = getNumAttributes(); + for (unsigned i = 0; i < numAttributes; ++i) + objectInstance.createAndSetAttributeDataElement(i); +} + +HLADataElement* +HLAObjectClass::createAttributeDataElement(HLAObjectInstance& objectInstance, unsigned index) +{ + // FIXME here we want to have a vector of factories and if this fails do the following + const HLADataType* dataType = getAttributeDataType(index); + if (!dataType) + return 0; + HLADataElementFactoryVisitor dataElementFactoryVisitor; + dataType->accept(dataElementFactoryVisitor); + return dataElementFactoryVisitor.getDataElement(); } void -HLAObjectClass::removeInstance(HLAObjectInstance& hlaObjectInstance, const RTIData& tag) +HLAObjectClass::_setRTIObjectClass(RTIObjectClass* objectClass) { - SG_LOG(SG_NETWORK, SG_INFO, "RTI: remove object instance \"" << hlaObjectInstance.getName() << "\""); - removeInstanceCallback(hlaObjectInstance, tag); - _objectInstanceSet.erase(&hlaObjectInstance); + if (_rtiObjectClass) { + SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: Setting RTIObjectClass twice for object class \"" << getName() << "\"!"); + return; + } + _rtiObjectClass = objectClass; + if (_rtiObjectClass->_objectClass != this) { + SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: backward reference does not match!"); + return; + } + for (unsigned i = 0; i < _attributeVector.size(); ++i) + _resolveAttributeIndex(_attributeVector[i]._name, i); } void -HLAObjectClass::registerInstance(HLAObjectInstance& objectInstance) +HLAObjectClass::_resolveAttributeIndex(const std::string& name, unsigned index) { - _objectInstanceSet.insert(&objectInstance); - registerInstanceCallback(objectInstance); + if (!_rtiObjectClass) + return; + if (!_rtiObjectClass->resolveAttributeIndex(name, index)) + SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: Could not resolve attribute \"" + << name << "\" for object class \"" << getName() << "\"!"); } void -HLAObjectClass::deleteInstance(HLAObjectInstance& objectInstance) +HLAObjectClass::_clearRTIObjectClass() { - deleteInstanceCallback(objectInstance); - _objectInstanceSet.erase(&objectInstance); + if (!_rtiObjectClass.valid()) + return; + _rtiObjectClass->_objectClass = 0; + _rtiObjectClass = 0; } void -HLAObjectClass::discoverInstanceCallback(HLAObjectInstance& objectInstance, const RTIData& tag) const +HLAObjectClass::_discoverInstance(RTIObjectInstance* rtiObjectInstance, const RTIData& tag) { - if (!_instanceCallback.valid()) + SGSharedPtr federate = _federate.lock(); + if (!federate.valid()) { + SG_LOG(SG_NETWORK, SG_ALERT, "RTI: could not find parent federate while discovering object instance"); + return; + } + + SGSharedPtr objectInstance = createObjectInstance(rtiObjectInstance->getName()); + if (!objectInstance.valid()) { + SG_LOG(SG_NETWORK, SG_INFO, "RTI: could not create new object instance for discovered \"" + << rtiObjectInstance->getName() << "\" object"); + return; + } + SG_LOG(SG_NETWORK, SG_INFO, "RTI: create new object instance for discovered \"" + << rtiObjectInstance->getName() << "\" object"); + objectInstance->_setRTIObjectInstance(rtiObjectInstance); + if (!federate->_insertObjectInstance(objectInstance)) { + SG_LOG(SG_NETWORK, SG_ALERT, "RTI: could not insert new object instance for discovered \"" + << rtiObjectInstance->getName() << "\" object"); return; - _instanceCallback->discoverInstance(*this, objectInstance, tag); + } + objectInstance->discoverInstance(tag); + objectInstance->createAttributeDataElements(); } void -HLAObjectClass::removeInstanceCallback(HLAObjectInstance& objectInstance, const RTIData& tag) const +HLAObjectClass::_removeInstance(HLAObjectInstance& objectInstance, const RTIData& tag) { - if (!_instanceCallback.valid()) + SGSharedPtr federate = _federate.lock(); + if (!federate.valid()) { + SG_LOG(SG_NETWORK, SG_ALERT, "RTI: could not find parent federate while removing object instance"); return; - _instanceCallback->removeInstance(*this, objectInstance, tag); + } + SG_LOG(SG_NETWORK, SG_INFO, "RTI: remove object instance \"" << objectInstance.getName() << "\""); + objectInstance.removeInstance(tag); + federate->_eraseObjectInstance(objectInstance.getName()); } void -HLAObjectClass::registerInstanceCallback(HLAObjectInstance& objectInstance) const +HLAObjectClass::_registerInstance(HLAObjectInstance* objectInstance) { - if (!_instanceCallback.valid()) + SGSharedPtr federate = _federate.lock(); + if (!federate.valid()) { + SG_LOG(SG_NETWORK, SG_ALERT, "RTI: could not find parent federate while registering object instance"); + return; + } + if (!objectInstance) return; - _instanceCallback->registerInstance(*this, objectInstance); + // We can only register object instances with a valid name at the rti. + // So, we cannot do that at HLAObjectInstance creation time. + if (!federate->_insertObjectInstance(objectInstance)) { + SG_LOG(SG_NETWORK, SG_ALERT, "RTI: could not insert new object instance \"" + << objectInstance->getName() << "\" object"); + return; + } + registerInstance(*objectInstance); + objectInstance->createAttributeDataElements(); } void -HLAObjectClass::deleteInstanceCallback(HLAObjectInstance& objectInstance) const +HLAObjectClass::_deleteInstance(HLAObjectInstance& objectInstance) { - if (!_instanceCallback.valid()) + SGSharedPtr federate = _federate.lock(); + if (!federate.valid()) { + SG_LOG(SG_NETWORK, SG_ALERT, "RTI: could not find parent federate while deleting object instance"); return; - _instanceCallback->deleteInstance(*this, objectInstance); + } + deleteInstance(objectInstance); + federate->_eraseObjectInstance(objectInstance.getName()); } void -HLAObjectClass::startRegistrationCallback() +HLAObjectClass::_startRegistration() { if (_registrationCallback.valid()) _registrationCallback->startRegistration(*this); @@ -291,7 +491,7 @@ HLAObjectClass::startRegistrationCallback() } void -HLAObjectClass::stopRegistrationCallback() +HLAObjectClass::_stopRegistration() { if (_registrationCallback.valid()) _registrationCallback->stopRegistration(*this);