]> git.mxchange.org Git - simgear.git/blobdiff - simgear/hla/HLAObjectClass.cxx
hla: Make use of SGLocation.
[simgear.git] / simgear / hla / HLAObjectClass.cxx
index 4b8265621be009bf81be8a7f227ffbfeceea080a..2740eb029d461ad6e573cf90331d9d3dbcb0e8a8 100644 (file)
@@ -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
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 //
 
+#ifdef HAVE_CONFIG_H
+#  include <simgear_config.h>
+#endif
+
+#include <simgear/compiler.h>
+
 #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<HLAFederate>&
+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<unsigned>& 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<unsigned>& 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<HLAFederate> federate = _federate.lock();
+    if (!federate.valid())
+        return 0;
+    return federate->createObjectInstance(this, name);
 }
 
 void
-HLAObjectClass::discoverInstance(RTIObjectInstance* objectInstance, const RTIData& tag)
-{
-    SGSharedPtr<HLAObjectInstance> 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<HLAFederate> federate = _federate.lock();
+    if (!federate.valid()) {
+        SG_LOG(SG_NETWORK, SG_ALERT, "RTI: could not find parent federate while discovering object instance");
+        return;
+    }
+
+    SGSharedPtr<HLAObjectInstance> 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<HLAFederate> 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<HLAFederate> 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<HLAFederate> 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);