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 "HLAObjectInstance.hxx"
27 #include "simgear/debug/logstream.hxx"
28 #include "HLAArrayDataElement.hxx"
29 #include "HLABasicDataElement.hxx"
30 #include "HLADataElement.hxx"
31 #include "HLAEnumeratedDataElement.hxx"
32 #include "HLAFederate.hxx"
33 #include "HLAFixedRecordDataElement.hxx"
34 #include "HLAObjectClass.hxx"
35 #include "HLAVariantRecordDataElement.hxx"
36 #include "RTIObjectClass.hxx"
37 #include "RTIObjectInstance.hxx"
41 HLAObjectInstance::UpdateCallback::~UpdateCallback()
45 HLAObjectInstance::ReflectCallback::~ReflectCallback()
49 HLAObjectInstance::HLAObjectInstance(HLAObjectClass* objectClass) :
50 _objectClass(objectClass)
53 _federate = objectClass->_federate;
56 HLAObjectInstance::~HLAObjectInstance()
58 _clearRTIObjectInstance();
62 HLAObjectInstance::getName() const
67 const SGWeakPtr<HLAFederate>&
68 HLAObjectInstance::getFederate() const
73 const SGSharedPtr<HLAObjectClass>&
74 HLAObjectInstance::getObjectClass() const
80 HLAObjectInstance::getNumAttributes() const
82 if (!_objectClass.valid())
84 return _objectClass->getNumAttributes();
88 HLAObjectInstance::getAttributeIndex(const std::string& name) const
90 if (!_objectClass.valid())
92 return _objectClass->getAttributeIndex(name);
96 HLAObjectInstance::getAttributeName(unsigned index) const
98 if (!_objectClass.valid())
100 return _objectClass->getAttributeName(index);
104 HLAObjectInstance::getAttributeOwned(unsigned index) const
106 if (!_rtiObjectInstance.valid())
108 return _rtiObjectInstance->getAttributeOwned(index);
112 HLAObjectInstance::getAttributeDataType(unsigned index) const
114 if (!_objectClass.valid())
116 return _objectClass->getAttributeDataType(index);
120 HLAObjectInstance::getAttributeDataElement(unsigned index)
122 if (_attributeVector.size() <= index)
124 return _attributeVector[index]._dataElement.get();
127 const HLADataElement*
128 HLAObjectInstance::getAttributeDataElement(unsigned index) const
130 if (_attributeVector.size() <= index)
132 return _attributeVector[index]._dataElement.get();
136 HLAObjectInstance::getAttributeData(unsigned index, RTIData& data) const
138 if (!_rtiObjectInstance.valid()) {
139 SG_LOG(SG_IO, SG_ALERT, "Trying to get raw attribute data without rti object instance for \"" << getName() << "\"!");
142 return _rtiObjectInstance->getAttributeData(index, data);
146 HLAObjectInstance::setAttributeDataElement(unsigned index, const SGSharedPtr<HLADataElement>& dataElement)
148 unsigned numAttributes = getNumAttributes();
149 if (numAttributes <= index)
151 _attributeVector.resize(numAttributes);
152 if (_attributeVector[index]._dataElement.valid())
153 _attributeVector[index]._dataElement->clearStamp();
154 _attributeVector[index]._dataElement = dataElement;
155 if (_attributeVector[index]._dataElement.valid())
156 _attributeVector[index]._dataElement->createStamp();
159 class HLAObjectInstance::DataElementFactoryVisitor : public HLADataElementFactoryVisitor {
161 DataElementFactoryVisitor(const HLAPathElementMap& pathElementMap) :
162 _pathElementMap(pathElementMap)
164 DataElementFactoryVisitor(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) :
165 _pathElementMap(pathElementMap),
168 virtual ~DataElementFactoryVisitor() {}
170 virtual void apply(const HLADataType& dataType)
172 _dataElement = createDataElement(_path, dataType);
173 if (_dataElement.valid())
176 SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Can not find a suitable data element for data type \""
177 << dataType.getName() << "\"");
180 virtual void apply(const HLAInt8DataType& dataType)
182 _dataElement = createDataElement(_path, dataType);
183 if (_dataElement.valid())
186 HLADataElementFactoryVisitor::apply(dataType);
188 virtual void apply(const HLAUInt8DataType& dataType)
190 _dataElement = createDataElement(_path, dataType);
191 if (_dataElement.valid())
194 HLADataElementFactoryVisitor::apply(dataType);
196 virtual void apply(const HLAInt16DataType& dataType)
198 _dataElement = createDataElement(_path, dataType);
199 if (_dataElement.valid())
202 HLADataElementFactoryVisitor::apply(dataType);
204 virtual void apply(const HLAUInt16DataType& dataType)
206 _dataElement = createDataElement(_path, dataType);
207 if (_dataElement.valid())
210 HLADataElementFactoryVisitor::apply(dataType);
212 virtual void apply(const HLAInt32DataType& dataType)
214 _dataElement = createDataElement(_path, dataType);
215 if (_dataElement.valid())
218 HLADataElementFactoryVisitor::apply(dataType);
220 virtual void apply(const HLAUInt32DataType& dataType)
222 _dataElement = createDataElement(_path, dataType);
223 if (_dataElement.valid())
226 HLADataElementFactoryVisitor::apply(dataType);
228 virtual void apply(const HLAInt64DataType& dataType)
230 _dataElement = createDataElement(_path, dataType);
231 if (_dataElement.valid())
234 HLADataElementFactoryVisitor::apply(dataType);
236 virtual void apply(const HLAUInt64DataType& dataType)
238 _dataElement = createDataElement(_path, dataType);
239 if (_dataElement.valid())
242 HLADataElementFactoryVisitor::apply(dataType);
244 virtual void apply(const HLAFloat32DataType& dataType)
246 _dataElement = createDataElement(_path, dataType);
247 if (_dataElement.valid())
250 HLADataElementFactoryVisitor::apply(dataType);
252 virtual void apply(const HLAFloat64DataType& dataType)
254 _dataElement = createDataElement(_path, dataType);
255 if (_dataElement.valid())
258 HLADataElementFactoryVisitor::apply(dataType);
261 class ArrayDataElementFactory : public HLAArrayDataElement::DataElementFactory {
263 ArrayDataElementFactory(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) :
266 for (HLAPathElementMap::const_iterator i = pathElementMap.lower_bound(path);
267 i != pathElementMap.end(); ++i) {
268 if (i->first.begin() != std::search(i->first.begin(), i->first.end(),
269 path.begin(), path.end()))
271 _pathElementMap.insert(*i);
274 virtual HLADataElement* createElement(const HLAArrayDataElement& element, unsigned index)
276 const HLADataType* dataType = element.getElementDataType();
279 HLADataElement::Path path = _path;
280 path.push_back(HLADataElement::PathElement(index));
281 DataElementFactoryVisitor visitor(path, _pathElementMap);
282 dataType->accept(visitor);
283 return visitor._dataElement.release();
286 HLADataElement::Path _path;
287 HLAPathElementMap _pathElementMap;
290 virtual void apply(const HLAFixedArrayDataType& dataType)
292 _dataElement = createDataElement(_path, dataType);
293 if (_dataElement.valid())
296 SGSharedPtr<HLAArrayDataElement> arrayDataElement;
297 arrayDataElement = new HLAArrayDataElement(&dataType);
298 arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_path, _pathElementMap));
299 arrayDataElement->setNumElements(dataType.getNumElements());
301 _dataElement = arrayDataElement;
304 virtual void apply(const HLAVariableArrayDataType& dataType)
306 _dataElement = createDataElement(_path, dataType);
307 if (_dataElement.valid())
310 SGSharedPtr<HLAArrayDataElement> arrayDataElement;
311 arrayDataElement = new HLAArrayDataElement(&dataType);
312 arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_path, _pathElementMap));
314 _dataElement = arrayDataElement;
317 virtual void apply(const HLAEnumeratedDataType& dataType)
319 _dataElement = createDataElement(_path, dataType);
320 if (_dataElement.valid())
323 HLADataElementFactoryVisitor::apply(dataType);
326 virtual void apply(const HLAFixedRecordDataType& dataType)
328 _dataElement = createDataElement(_path, dataType);
329 if (_dataElement.valid())
332 SGSharedPtr<HLAFixedRecordDataElement> recordDataElement;
333 recordDataElement = new HLAFixedRecordDataElement(&dataType);
335 unsigned numFields = dataType.getNumFields();
336 for (unsigned i = 0; i < numFields; ++i) {
338 _path.push_back(HLADataElement::PathElement(dataType.getFieldName(i)));
340 dataType.getFieldDataType(i)->accept(*this);
341 recordDataElement->setField(i, _dataElement.release());
345 _dataElement = recordDataElement;
348 class VariantRecordDataElementFactory : public HLAVariantRecordDataElement::DataElementFactory {
350 VariantRecordDataElementFactory(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) :
353 for (HLAPathElementMap::const_iterator i = pathElementMap.lower_bound(path);
354 i != pathElementMap.end(); ++i) {
355 if (i->first.begin() != std::search(i->first.begin(), i->first.end(),
356 path.begin(), path.end()))
358 _pathElementMap.insert(*i);
361 virtual HLADataElement* createElement(const HLAVariantRecordDataElement& element, unsigned index)
363 const HLAVariantRecordDataType* dataType = element.getDataType();
366 const HLADataType* alternativeDataType = element.getAlternativeDataType();
367 if (!alternativeDataType)
369 HLADataElement::Path path = _path;
370 path.push_back(HLADataElement::PathElement(dataType->getAlternativeName(index)));
371 DataElementFactoryVisitor visitor(path, _pathElementMap);
372 alternativeDataType->accept(visitor);
373 return visitor._dataElement.release();
376 HLADataElement::Path _path;
377 HLAPathElementMap _pathElementMap;
380 virtual void apply(const HLAVariantRecordDataType& dataType)
382 _dataElement = createDataElement(_path, dataType);
383 if (_dataElement.valid())
386 SGSharedPtr<HLAVariantRecordDataElement> variantRecordDataElement;
387 variantRecordDataElement = new HLAVariantRecordDataElement(&dataType);
388 variantRecordDataElement->setDataElementFactory(new VariantRecordDataElementFactory(_path, _pathElementMap));
390 _dataElement = variantRecordDataElement;
394 SGSharedPtr<HLADataElement> createDataElement(const HLADataElement::Path& path, const HLADataType& dataType)
396 HLAPathElementMap::const_iterator i = _pathElementMap.find(path);
397 if (i == _pathElementMap.end()) {
398 SG_LOG(SG_IO, SG_WARN, "No dataElement provided for \""
399 << HLADataElement::toString(path) << "\".");
403 SGSharedPtr<HLADataElement> dataElement = i->second.getDataElement(path);
404 if (!dataElement->setDataType(&dataType)) {
405 SG_LOG(SG_IO, SG_ALERT, "Cannot set data type for data element at \""
406 << HLADataElement::toString(path) << "\"!");
409 SG_LOG(SG_IO, SG_DEBUG, "Using provided dataElement for \""
410 << HLADataElement::toString(path) << "\".");
414 const HLAPathElementMap& _pathElementMap;
415 HLADataElement::Path _path;
419 HLAObjectInstance::setAttribute(unsigned index, const HLAPathElementMap& pathElementMap)
421 const HLADataType* dataType = getAttributeDataType(index);
423 SG_LOG(SG_IO, SG_ALERT, "Cannot get attribute data type for setting attribute \""
424 << getAttributeName(index) << "\" at index " << index << "!");
428 SG_LOG(SG_IO, SG_DEBUG, "Setting DataElement for attribute \""
429 << getAttributeName(index) << "\".");
431 DataElementFactoryVisitor visitor(pathElementMap);
432 dataType->accept(visitor);
433 setAttributeDataElement(index, visitor.getDataElement());
437 HLAObjectInstance::setAttributes(const HLAAttributePathElementMap& attributePathElementMap)
439 for (HLAAttributePathElementMap::const_iterator i = attributePathElementMap.begin();
440 i != attributePathElementMap.end(); ++i) {
441 setAttribute(i->first, i->second);
446 HLAObjectInstance::getDataElementIndex(HLADataElementIndex& index, const std::string& path) const
448 HLAObjectClass* objectClass = getObjectClass().get();
450 SG_LOG(SG_IO, SG_ALERT, "Could not get the data element index of an object instance with unknown class!");
453 return objectClass->getDataElementIndex(index, path);
457 HLAObjectInstance::getDataElementIndex(const std::string& path) const
459 HLADataElementIndex dataElementIndex;
460 getDataElementIndex(dataElementIndex, path);
461 return dataElementIndex;
465 HLAObjectInstance::getAttributeDataElement(const HLADataElementIndex& index)
469 HLADataElement* dataElement = getAttributeDataElement(index[0]);
472 return dataElement->getDataElement(index.begin() + 1, index.end());
475 const HLADataElement*
476 HLAObjectInstance::getAttributeDataElement(const HLADataElementIndex& index) const
480 const HLADataElement* dataElement = getAttributeDataElement(index[0]);
483 return dataElement->getDataElement(index.begin() + 1, index.end());
487 HLAObjectInstance::setAttributeDataElement(const HLADataElementIndex& index, const SGSharedPtr<HLADataElement>& dataElement)
491 if (index.size() == 1) {
492 if (!getAttributeDataType(index[0]))
494 if (dataElement.valid() && !dataElement->setDataType(getAttributeDataType(index[0])))
496 setAttributeDataElement(index[0], dataElement);
498 SGSharedPtr<HLADataElement> attributeDataElement = getAttributeDataElement(index[0]);
499 if (!attributeDataElement.valid()) {
500 createAndSetAttributeDataElement(index[0]);
501 attributeDataElement = getAttributeDataElement(index[0]);
503 if (!attributeDataElement.valid())
505 attributeDataElement->setDataElement(index.begin() + 1, index.end(), dataElement.get());
510 HLAObjectInstance::getAttributeDataElement(const std::string& path)
512 HLADataElementIndex index;
513 if (!getDataElementIndex(index, path))
515 return getAttributeDataElement(index);
518 const HLADataElement*
519 HLAObjectInstance::getAttributeDataElement(const std::string& path) const
521 HLADataElementIndex index;
522 if (!getDataElementIndex(index, path))
524 return getAttributeDataElement(index);
528 HLAObjectInstance::setAttributeDataElement(const std::string& path, const SGSharedPtr<HLADataElement>& dataElement)
530 HLADataElementIndex index;
531 if (!getDataElementIndex(index, path))
533 setAttributeDataElement(index, dataElement);
537 HLAObjectInstance::discoverInstance(const RTIData& tag)
539 HLAObjectClass* objectClass = getObjectClass().get();
541 SG_LOG(SG_IO, SG_ALERT, "Could not discover instance of unknown object class!");
544 objectClass->discoverInstance(*this, tag);
548 HLAObjectInstance::removeInstance(const RTIData& tag)
550 HLAObjectClass* objectClass = getObjectClass().get();
552 SG_LOG(SG_IO, SG_ALERT, "Could not remove instance of unknown object class!");
555 objectClass->removeInstance(*this, tag);
559 HLAObjectInstance::registerInstance()
561 registerInstance(_objectClass.get());
565 HLAObjectInstance::registerInstance(HLAObjectClass* objectClass)
567 if (_rtiObjectInstance.valid()) {
568 SG_LOG(SG_IO, SG_ALERT, "Trying to register object " << getName() << " already known to the RTI!");
572 SG_LOG(SG_IO, SG_ALERT, "Could not register object with unknown object class!");
575 if (_objectClass.valid() && objectClass != _objectClass.get()) {
576 SG_LOG(SG_IO, SG_ALERT, "Could not change object class while registering!");
579 _objectClass = objectClass;
580 _federate = _objectClass->_federate;
581 // This error must have been flagged before
582 if (!_objectClass->_rtiObjectClass.valid())
584 _setRTIObjectInstance(_objectClass->_rtiObjectClass->registerObjectInstance(this));
585 if (!_rtiObjectInstance.valid()) {
586 SG_LOG(SG_IO, SG_ALERT, "Could not register object at the RTI!");
589 _objectClass->_registerInstance(this);
593 HLAObjectInstance::deleteInstance(const RTIData& tag)
595 if (!_rtiObjectInstance.valid()) {
596 SG_LOG(SG_IO, SG_ALERT, "Trying to delete inactive object!");
599 if (!_objectClass.valid())
601 _objectClass->_deleteInstance(*this);
602 _rtiObjectInstance->deleteObjectInstance(tag);
606 HLAObjectInstance::createAttributeDataElements()
608 HLAObjectClass* objectClass = getObjectClass().get();
610 SG_LOG(SG_IO, SG_ALERT, "Could not create data elements for instance of unknown object class!");
613 objectClass->createAttributeDataElements(*this);
617 HLAObjectInstance::createAndSetAttributeDataElement(unsigned index)
619 if (getAttributeDataElement(index)) {
620 SG_LOG(SG_IO, SG_DEBUG, "Attribute data element for attribute \""
621 << getAttributeName(index) << "\" is already set.");
624 SGSharedPtr<HLADataElement> dataElement = createAttributeDataElement(index);
625 setAttributeDataElement(index, dataElement);
629 HLAObjectInstance::createAttributeDataElement(unsigned index)
631 HLAObjectClass* objectClass = getObjectClass().get();
633 SG_LOG(SG_IO, SG_ALERT, "Could not create data element for instance of unknown object class!");
636 return objectClass->createAttributeDataElement(*this, index);
640 HLAObjectInstance::updateAttributeValues(const RTIData& tag)
642 if (_updateCallback.valid()) {
643 _updateCallback->updateAttributeValues(*this, tag);
645 encodeAttributeValues();
646 sendAttributeValues(tag);
651 HLAObjectInstance::updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag)
653 if (_updateCallback.valid()) {
654 _updateCallback->updateAttributeValues(*this, timeStamp, tag);
656 encodeAttributeValues();
657 sendAttributeValues(timeStamp, tag);
662 HLAObjectInstance::encodeAttributeValues()
664 unsigned numAttributes = _attributeVector.size();
665 for (unsigned i = 0; i < numAttributes;++i) {
666 if (_attributeVector[i]._unconditionalUpdate) {
667 encodeAttributeValue(i);
668 } else if (_attributeVector[i]._enabledUpdate) {
669 const HLADataElement* dataElement = getAttributeDataElement(i);
670 if (dataElement && dataElement->getDirty())
671 encodeAttributeValue(i);
677 HLAObjectInstance::encodeAttributeValue(unsigned index)
679 if (!_rtiObjectInstance.valid()) {
680 SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
683 HLADataElement* dataElement = getAttributeDataElement(index);
686 _rtiObjectInstance->encodeAttributeData(index, *dataElement);
687 dataElement->setDirty(false);
691 HLAObjectInstance::sendAttributeValues(const RTIData& tag)
693 if (!_rtiObjectInstance.valid()) {
694 SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
697 _rtiObjectInstance->updateAttributeValues(tag);
701 HLAObjectInstance::sendAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag)
703 if (!_rtiObjectInstance.valid()) {
704 SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
707 _rtiObjectInstance->updateAttributeValues(timeStamp, tag);
711 HLAObjectInstance::reflectAttributeValues(const HLAIndexList& indexList, const RTIData& tag)
713 for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i)
714 reflectAttributeValue(*i, tag);
718 HLAObjectInstance::reflectAttributeValues(const HLAIndexList& indexList,
719 const SGTimeStamp& timeStamp, const RTIData& tag)
721 for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i)
722 reflectAttributeValue(*i, timeStamp, tag);
726 HLAObjectInstance::reflectAttributeValue(unsigned index, const RTIData& tag)
728 HLADataElement* dataElement = getAttributeDataElement(index);
731 dataElement->setTimeStampValid(false);
732 _rtiObjectInstance->decodeAttributeData(index, *dataElement);
736 HLAObjectInstance::reflectAttributeValue(unsigned index, const SGTimeStamp& timeStamp, const RTIData& tag)
738 HLADataElement* dataElement = getAttributeDataElement(index);
741 dataElement->setTimeStamp(timeStamp);
742 dataElement->setTimeStampValid(true);
743 _rtiObjectInstance->decodeAttributeData(index, *dataElement);
747 HLAObjectInstance::_setRTIObjectInstance(RTIObjectInstance* rtiObjectInstance)
749 if (!_objectClass.valid())
752 _rtiObjectInstance = rtiObjectInstance;
753 _rtiObjectInstance->setObjectInstance(this);
754 _name = _rtiObjectInstance->getName();
756 unsigned numAttributes = getNumAttributes();
757 _attributeVector.resize(numAttributes);
758 for (unsigned i = 0; i < numAttributes; ++i) {
759 HLAUpdateType updateType = _objectClass->getAttributeUpdateType(i);
760 if (getAttributeOwned(i) && updateType != HLAUndefinedUpdate) {
761 _attributeVector[i]._enabledUpdate = true;
762 _attributeVector[i]._unconditionalUpdate = (updateType == HLAPeriodicUpdate);
763 // In case of an owned attribute, now encode its value
764 encodeAttributeValue(i);
766 _attributeVector[i]._enabledUpdate = false;
767 _attributeVector[i]._unconditionalUpdate = false;
771 // This makes sense with any new object. Even if we registered one, there might be unpublished attributes.
772 HLAIndexList indexList;
773 for (unsigned i = 0; i < numAttributes; ++i) {
774 HLAUpdateType updateType = _objectClass->getAttributeUpdateType(i);
775 if (getAttributeOwned(i))
777 if (updateType == HLAUndefinedUpdate)
779 if (updateType == HLAPeriodicUpdate)
781 indexList.push_back(i);
783 _rtiObjectInstance->requestObjectAttributeValueUpdate(indexList);
787 HLAObjectInstance::_clearRTIObjectInstance()
789 if (!_rtiObjectInstance.valid())
792 for (unsigned i = 0; i < _attributeVector.size(); ++i) {
793 _attributeVector[i]._enabledUpdate = false;
794 _attributeVector[i]._unconditionalUpdate = false;
797 _rtiObjectInstance->setObjectInstance(0);
798 _rtiObjectInstance = 0;
802 HLAObjectInstance::_removeInstance(const RTIData& tag)
804 if (!_objectClass.valid())
806 _objectClass->_removeInstance(*this, tag);
810 HLAObjectInstance::_reflectAttributeValues(const HLAIndexList& indexList, const RTIData& tag)
812 if (_reflectCallback.valid()) {
813 _reflectCallback->reflectAttributeValues(*this, indexList, tag);
815 reflectAttributeValues(indexList, tag);
820 HLAObjectInstance::_reflectAttributeValues(const HLAIndexList& indexList, const SGTimeStamp& timeStamp, const RTIData& tag)
822 if (_reflectCallback.valid()) {
823 _reflectCallback->reflectAttributeValues(*this, indexList, timeStamp, tag);
825 reflectAttributeValues(indexList, timeStamp, tag);
829 } // namespace simgear