// Copyright (C) 2009 - 2012 Mathias Froehlich // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #ifndef HLAObjectReferenceData_hxx #define HLAObjectReferenceData_hxx #include #include #include #include "HLAProxyDataElement.hxx" namespace simgear { /// Data element that references an other object instance by its name, or object instance handle? /// Abstract variant that is object type independent and could be registered at the federate /// if the object is not found immediately and might arrive later. class HLAAbstractObjectReferenceDataElement : public HLAProxyDataElement { public: // FIXME drop the federate once we have a decode/encode visitor?! HLAAbstractObjectReferenceDataElement(const SGWeakPtr& federate) : _federate(federate) { } virtual bool decode(HLADecodeStream& stream) { if (!HLAProxyDataElement::decode(stream)) return false; // No change? if (!_name.getDataElement()->getDirty()) return true; _name.getDataElement()->setDirty(false); return recheckObject(); } /// Returns true if the object is correctly set bool getComplete() const { if (HLAObjectInstance* objectInstance = _getObjectInstance()) { return _name.getValue() == objectInstance->getName(); } else { return _name.getValue().empty(); } } bool recheckObject() { HLAObjectInstance* objectInstance = _getObjectInstance(); if (objectInstance && _name.getValue() == objectInstance->getName()) return true; if (_name.getValue().empty()) { return _setObjectInstance(0); } else { // Get the object by its name from the federate SGSharedPtr federate = _federate.lock(); if (!federate.valid()) return false; SGSharedPtr objectInstance; objectInstance = federate->getObjectInstance(_name.getValue()); return _setObjectInstance(objectInstance.get()); } } protected: virtual HLAStringDataElement* _getDataElement() { return _name.getDataElement(); } virtual const HLAStringDataElement* _getDataElement() const { return _name.getDataElement(); } virtual HLAObjectInstance* _getObjectInstance() const = 0; virtual bool _setObjectInstance(HLAObjectInstance*) = 0; void _setName(const HLAObjectInstance* objectInstance) { if (objectInstance) _name.setValue(objectInstance->getName()); else _name.setValue(std::string()); _name.getDataElement()->setDirty(true); } private: HLAStringData _name; SGWeakPtr _federate; }; template class HLAObjectReferenceDataElement : public HLAAbstractObjectReferenceDataElement { public: // FIXME drop the federate once we have a decode/encode visitor?! HLAObjectReferenceDataElement(const SGWeakPtr& federate) : HLAAbstractObjectReferenceDataElement(federate) { } const SGSharedPtr& getObject() const { return _object; } void setObject(const SGSharedPtr& object) { if (_object == object) return; _setName(object.get()); _object = object; } protected: virtual HLAObjectInstance* _getObjectInstance() const { return _object.get(); } virtual bool _setObjectInstance(HLAObjectInstance* objectInstance) { if (!objectInstance) { _object.clear(); return true; } else { if (!dynamic_cast(objectInstance)) return false; _object = static_cast(objectInstance); return true; } } private: SGSharedPtr _object; }; template class HLAObjectReferenceData { public: typedef HLAObjectReferenceDataElement DataElement; HLAObjectReferenceData(const SGWeakPtr& federate) : _dataElement(new DataElement(federate)) { } const HLADataElement* getDataElement() const { return _dataElement.get(); } HLADataElement* getDataElement() { return _dataElement.get(); } const SGSharedPtr& getObject() const { return _dataElement->getObject(); } void setObject(const SGSharedPtr& object) { _dataElement->setObject(object); } bool getComplete() const { return _dataElement->getComplete(); } /// FIXME this must happen in the federate by registering object references /// that still want to be resolved bool recheckObject() const { return _dataElement->recheckObject(); } private: SGSharedPtr _dataElement; }; } #endif