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.
18 #include "HLAObjectInstance.hxx"
21 #include "simgear/debug/logstream.hxx"
22 #include "HLAArrayDataElement.hxx"
23 #include "HLABasicDataElement.hxx"
24 #include "HLADataElement.hxx"
25 #include "HLAEnumeratedDataElement.hxx"
26 #include "HLAFederate.hxx"
27 #include "HLAFixedRecordDataElement.hxx"
28 #include "HLAObjectClass.hxx"
29 #include "HLAVariantRecordDataElement.hxx"
30 #include "RTIObjectClass.hxx"
31 #include "RTIObjectInstance.hxx"
35 HLAObjectInstance::UpdateCallback::~UpdateCallback()
39 HLAObjectInstance::ReflectCallback::~ReflectCallback()
43 HLAObjectInstance::HLAObjectInstance(HLAObjectClass* objectClass) :
44 _federate(objectClass->_federate),
45 _objectClass(objectClass)
49 HLAObjectInstance::~HLAObjectInstance()
51 _clearRTIObjectInstance();
55 HLAObjectInstance::getNumAttributes() const
57 return _objectClass->getNumAttributes();
61 HLAObjectInstance::getAttributeIndex(const std::string& name) const
63 return _objectClass->getAttributeIndex(name);
67 HLAObjectInstance::getAttributeName(unsigned index) const
69 return _objectClass->getAttributeName(index);
73 HLAObjectInstance::getAttributeOwned(unsigned index) const
75 if (!_rtiObjectInstance.valid())
77 return _rtiObjectInstance->getAttributeOwned(index);
81 HLAObjectInstance::getAttributeDataType(unsigned index) const
83 return _objectClass->getAttributeDataType(index);
87 HLAObjectInstance::getAttributeDataElement(unsigned index)
89 if (_attributeVector.size() <= index)
91 return _attributeVector[index]._dataElement.get();
95 HLAObjectInstance::getAttributeDataElement(unsigned index) const
97 if (_attributeVector.size() <= index)
99 return _attributeVector[index]._dataElement.get();
103 HLAObjectInstance::getAttributeData(unsigned index, RTIData& data) const
105 if (!_rtiObjectInstance.valid()) {
106 SG_LOG(SG_IO, SG_ALERT, "Trying to get raw attribute data without rti object instance for \"" << getName() << "\"!");
109 return _rtiObjectInstance->getAttributeData(index, data);
113 HLAObjectInstance::setAttributeDataElement(unsigned index, const SGSharedPtr<HLADataElement>& dataElement)
115 unsigned numAttributes = getNumAttributes();
116 if (numAttributes <= index)
118 _attributeVector.resize(numAttributes);
119 if (_attributeVector[index]._dataElement.valid())
120 _attributeVector[index]._dataElement->clearStamp();
121 _attributeVector[index]._dataElement = dataElement;
122 if (_attributeVector[index]._dataElement.valid())
123 _attributeVector[index]._dataElement->createStamp();
126 class HLAObjectInstance::DataElementFactoryVisitor : public HLADataElementFactoryVisitor {
128 DataElementFactoryVisitor(const HLAPathElementMap& pathElementMap) :
129 _pathElementMap(pathElementMap)
131 DataElementFactoryVisitor(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) :
132 _pathElementMap(pathElementMap),
135 virtual ~DataElementFactoryVisitor() {}
137 virtual void apply(const HLADataType& dataType)
139 _dataElement = createDataElement(_path, dataType);
140 if (_dataElement.valid())
143 SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Can not find a suitable data element for data type \""
144 << dataType.getName() << "\"");
147 virtual void apply(const HLAInt8DataType& dataType)
149 _dataElement = createDataElement(_path, dataType);
150 if (_dataElement.valid())
153 HLADataElementFactoryVisitor::apply(dataType);
155 virtual void apply(const HLAUInt8DataType& dataType)
157 _dataElement = createDataElement(_path, dataType);
158 if (_dataElement.valid())
161 HLADataElementFactoryVisitor::apply(dataType);
163 virtual void apply(const HLAInt16DataType& dataType)
165 _dataElement = createDataElement(_path, dataType);
166 if (_dataElement.valid())
169 HLADataElementFactoryVisitor::apply(dataType);
171 virtual void apply(const HLAUInt16DataType& dataType)
173 _dataElement = createDataElement(_path, dataType);
174 if (_dataElement.valid())
177 HLADataElementFactoryVisitor::apply(dataType);
179 virtual void apply(const HLAInt32DataType& dataType)
181 _dataElement = createDataElement(_path, dataType);
182 if (_dataElement.valid())
185 HLADataElementFactoryVisitor::apply(dataType);
187 virtual void apply(const HLAUInt32DataType& dataType)
189 _dataElement = createDataElement(_path, dataType);
190 if (_dataElement.valid())
193 HLADataElementFactoryVisitor::apply(dataType);
195 virtual void apply(const HLAInt64DataType& dataType)
197 _dataElement = createDataElement(_path, dataType);
198 if (_dataElement.valid())
201 HLADataElementFactoryVisitor::apply(dataType);
203 virtual void apply(const HLAUInt64DataType& dataType)
205 _dataElement = createDataElement(_path, dataType);
206 if (_dataElement.valid())
209 HLADataElementFactoryVisitor::apply(dataType);
211 virtual void apply(const HLAFloat32DataType& dataType)
213 _dataElement = createDataElement(_path, dataType);
214 if (_dataElement.valid())
217 HLADataElementFactoryVisitor::apply(dataType);
219 virtual void apply(const HLAFloat64DataType& dataType)
221 _dataElement = createDataElement(_path, dataType);
222 if (_dataElement.valid())
225 HLADataElementFactoryVisitor::apply(dataType);
228 class ArrayDataElementFactory : public HLAArrayDataElement::DataElementFactory {
230 ArrayDataElementFactory(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) :
233 for (HLAPathElementMap::const_iterator i = pathElementMap.lower_bound(path);
234 i != pathElementMap.end(); ++i) {
235 if (i->first.begin() != std::search(i->first.begin(), i->first.end(),
236 path.begin(), path.end()))
238 _pathElementMap.insert(*i);
241 virtual HLADataElement* createElement(const HLAArrayDataElement& element, unsigned index)
243 const HLADataType* dataType = element.getElementDataType();
246 HLADataElement::Path path = _path;
247 path.push_back(HLADataElement::PathElement(index));
248 DataElementFactoryVisitor visitor(path, _pathElementMap);
249 dataType->accept(visitor);
250 return visitor._dataElement.release();
253 HLADataElement::Path _path;
254 HLAPathElementMap _pathElementMap;
257 virtual void apply(const HLAFixedArrayDataType& dataType)
259 _dataElement = createDataElement(_path, dataType);
260 if (_dataElement.valid())
263 SGSharedPtr<HLAArrayDataElement> arrayDataElement;
264 arrayDataElement = new HLAArrayDataElement(&dataType);
265 arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_path, _pathElementMap));
266 arrayDataElement->setNumElements(dataType.getNumElements());
268 _dataElement = arrayDataElement;
271 virtual void apply(const HLAVariableArrayDataType& dataType)
273 _dataElement = createDataElement(_path, dataType);
274 if (_dataElement.valid())
277 SGSharedPtr<HLAArrayDataElement> arrayDataElement;
278 arrayDataElement = new HLAArrayDataElement(&dataType);
279 arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_path, _pathElementMap));
281 _dataElement = arrayDataElement;
284 virtual void apply(const HLAEnumeratedDataType& dataType)
286 _dataElement = createDataElement(_path, dataType);
287 if (_dataElement.valid())
290 HLADataElementFactoryVisitor::apply(dataType);
293 virtual void apply(const HLAFixedRecordDataType& dataType)
295 _dataElement = createDataElement(_path, dataType);
296 if (_dataElement.valid())
299 SGSharedPtr<HLAFixedRecordDataElement> recordDataElement;
300 recordDataElement = new HLAFixedRecordDataElement(&dataType);
302 unsigned numFields = dataType.getNumFields();
303 for (unsigned i = 0; i < numFields; ++i) {
305 _path.push_back(HLADataElement::PathElement(dataType.getFieldName(i)));
307 dataType.getFieldDataType(i)->accept(*this);
308 recordDataElement->setField(i, _dataElement.release());
312 _dataElement = recordDataElement;
315 class VariantRecordDataElementFactory : public HLAVariantRecordDataElement::DataElementFactory {
317 VariantRecordDataElementFactory(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) :
320 for (HLAPathElementMap::const_iterator i = pathElementMap.lower_bound(path);
321 i != pathElementMap.end(); ++i) {
322 if (i->first.begin() != std::search(i->first.begin(), i->first.end(),
323 path.begin(), path.end()))
325 _pathElementMap.insert(*i);
328 virtual HLADataElement* createElement(const HLAVariantRecordDataElement& element, unsigned index)
330 const HLAVariantRecordDataType* dataType = element.getDataType();
333 const HLADataType* alternativeDataType = element.getAlternativeDataType();
334 if (!alternativeDataType)
336 HLADataElement::Path path = _path;
337 path.push_back(HLADataElement::PathElement(dataType->getAlternativeName(index)));
338 DataElementFactoryVisitor visitor(path, _pathElementMap);
339 alternativeDataType->accept(visitor);
340 return visitor._dataElement.release();
343 HLADataElement::Path _path;
344 HLAPathElementMap _pathElementMap;
347 virtual void apply(const HLAVariantRecordDataType& dataType)
349 _dataElement = createDataElement(_path, dataType);
350 if (_dataElement.valid())
353 SGSharedPtr<HLAVariantRecordDataElement> variantRecordDataElement;
354 variantRecordDataElement = new HLAVariantRecordDataElement(&dataType);
355 variantRecordDataElement->setDataElementFactory(new VariantRecordDataElementFactory(_path, _pathElementMap));
357 _dataElement = variantRecordDataElement;
361 SGSharedPtr<HLADataElement> createDataElement(const HLADataElement::Path& path, const HLADataType& dataType)
363 HLAPathElementMap::const_iterator i = _pathElementMap.find(path);
364 if (i == _pathElementMap.end()) {
365 SG_LOG(SG_IO, SG_WARN, "No dataElement provided for \""
366 << HLADataElement::toString(path) << "\".");
370 SGSharedPtr<HLADataElement> dataElement = i->second.getDataElement(path);
371 if (!dataElement->setDataType(&dataType)) {
372 SG_LOG(SG_IO, SG_ALERT, "Cannot set data type for data element at \""
373 << HLADataElement::toString(path) << "\"!");
376 SG_LOG(SG_IO, SG_DEBUG, "Using provided dataElement for \""
377 << HLADataElement::toString(path) << "\".");
381 const HLAPathElementMap& _pathElementMap;
382 HLADataElement::Path _path;
386 HLAObjectInstance::setAttribute(unsigned index, const HLAPathElementMap& pathElementMap)
388 const HLADataType* dataType = getAttributeDataType(index);
390 SG_LOG(SG_IO, SG_ALERT, "Cannot get attribute data type for setting attribute \""
391 << getAttributeName(index) << "\" at index " << index << "!");
395 SG_LOG(SG_IO, SG_DEBUG, "Setting DataElement for attribute \""
396 << getAttributeName(index) << "\".");
398 DataElementFactoryVisitor visitor(pathElementMap);
399 dataType->accept(visitor);
400 setAttributeDataElement(index, visitor.getDataElement());
404 HLAObjectInstance::setAttributes(const HLAAttributePathElementMap& attributePathElementMap)
406 for (HLAAttributePathElementMap::const_iterator i = attributePathElementMap.begin();
407 i != attributePathElementMap.end(); ++i) {
408 setAttribute(i->first, i->second);
413 HLAObjectInstance::registerInstance()
415 if (_rtiObjectInstance.valid()) {
416 SG_LOG(SG_IO, SG_ALERT, "Trying to register object " << getName() << " already known to the RTI!");
419 if (!_objectClass.valid()) {
420 SG_LOG(SG_IO, SG_ALERT, "Could not register object with unknown object class!");
423 // This error must have been flagged before
424 if (!_objectClass->_rtiObjectClass.valid())
426 _setRTIObjectInstance(_objectClass->_rtiObjectClass->registerObjectInstance(this));
427 if (!_rtiObjectInstance.valid()) {
428 SG_LOG(SG_IO, SG_ALERT, "Could not register object at the RTI!");
431 _objectClass->_registerInstance(this);
435 HLAObjectInstance::deleteInstance(const RTIData& tag)
437 if (!_rtiObjectInstance.valid()) {
438 SG_LOG(SG_IO, SG_ALERT, "Trying to delete inactive object!");
441 if (!_objectClass.valid())
443 _objectClass->_deleteInstance(*this);
444 _rtiObjectInstance->deleteObjectInstance(tag);
448 HLAObjectInstance::updateAttributeValues(const RTIData& tag)
450 if (_attributeCallback.valid())
451 _attributeCallback->updateAttributeValues(*this, tag);
452 if (_updateCallback.valid()) {
453 _updateCallback->updateAttributeValues(*this, tag);
455 encodeAttributeValues();
456 sendAttributeValues(tag);
461 HLAObjectInstance::updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag)
463 if (_attributeCallback.valid())
464 _attributeCallback->updateAttributeValues(*this, tag);
465 if (_updateCallback.valid()) {
466 _updateCallback->updateAttributeValues(*this, timeStamp, tag);
468 encodeAttributeValues();
469 sendAttributeValues(timeStamp, tag);
474 HLAObjectInstance::encodeAttributeValues()
476 unsigned numAttributes = _attributeVector.size();
477 for (unsigned i = 0; i < numAttributes;++i) {
478 if (_attributeVector[i]._unconditionalUpdate) {
479 encodeAttributeValue(i);
480 } else if (_attributeVector[i]._enabledUpdate) {
481 const HLADataElement* dataElement = getAttributeDataElement(i);
482 if (dataElement && dataElement->getDirty())
483 encodeAttributeValue(i);
489 HLAObjectInstance::encodeAttributeValue(unsigned index)
491 if (!_rtiObjectInstance.valid()) {
492 SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
495 HLADataElement* dataElement = getAttributeDataElement(index);
498 _rtiObjectInstance->encodeAttributeData(index, *dataElement);
499 dataElement->setDirty(false);
503 HLAObjectInstance::sendAttributeValues(const RTIData& tag)
505 if (!_rtiObjectInstance.valid()) {
506 SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
509 _rtiObjectInstance->updateAttributeValues(tag);
513 HLAObjectInstance::sendAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag)
515 if (!_rtiObjectInstance.valid()) {
516 SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
519 _rtiObjectInstance->updateAttributeValues(timeStamp, tag);
523 HLAObjectInstance::reflectAttributeValues(const HLAIndexList& indexList, const RTIData& tag)
525 for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i)
526 reflectAttributeValue(*i, tag);
530 HLAObjectInstance::reflectAttributeValues(const HLAIndexList& indexList,
531 const SGTimeStamp& timeStamp, const RTIData& tag)
533 for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i)
534 reflectAttributeValue(*i, timeStamp, tag);
538 HLAObjectInstance::reflectAttributeValue(unsigned index, const RTIData& tag)
540 HLADataElement* dataElement = getAttributeDataElement(index);
543 dataElement->setTimeStampValid(false);
544 _rtiObjectInstance->decodeAttributeData(index, *dataElement);
548 HLAObjectInstance::reflectAttributeValue(unsigned index, const SGTimeStamp& timeStamp, const RTIData& tag)
550 HLADataElement* dataElement = getAttributeDataElement(index);
553 dataElement->setTimeStamp(timeStamp);
554 dataElement->setTimeStampValid(true);
555 _rtiObjectInstance->decodeAttributeData(index, *dataElement);
559 HLAObjectInstance::_setRTIObjectInstance(RTIObjectInstance* rtiObjectInstance)
561 _rtiObjectInstance = rtiObjectInstance;
562 _rtiObjectInstance->setObjectInstance(this);
563 _name = _rtiObjectInstance->getName();
565 unsigned numAttributes = getNumAttributes();
566 _attributeVector.resize(numAttributes);
567 for (unsigned i = 0; i < numAttributes; ++i) {
568 HLAUpdateType updateType = getObjectClass()->getAttributeUpdateType(i);
569 if (getAttributeOwned(i) && updateType != HLAUndefinedUpdate) {
570 _attributeVector[i]._enabledUpdate = true;
571 _attributeVector[i]._unconditionalUpdate = (updateType == HLAPeriodicUpdate);
572 // In case of an owned attribute, now encode its value
573 encodeAttributeValue(i);
575 _attributeVector[i]._enabledUpdate = false;
576 _attributeVector[i]._unconditionalUpdate = false;
580 // This makes sense with any new object. Even if we registered one, there might be unpublished attributes.
581 HLAIndexList indexList;
582 for (unsigned i = 0; i < numAttributes; ++i) {
583 HLAUpdateType updateType = getObjectClass()->getAttributeUpdateType(i);
584 if (getAttributeOwned(i))
586 if (updateType == HLAUndefinedUpdate)
588 if (updateType == HLAPeriodicUpdate)
590 indexList.push_back(i);
592 _rtiObjectInstance->requestObjectAttributeValueUpdate(indexList);
596 HLAObjectInstance::_clearRTIObjectInstance()
598 if (!_rtiObjectInstance.valid())
601 for (unsigned i = 0; i < _attributeVector.size(); ++i) {
602 _attributeVector[i]._enabledUpdate = false;
603 _attributeVector[i]._unconditionalUpdate = false;
606 _rtiObjectInstance->setObjectInstance(0);
607 _rtiObjectInstance = 0;
611 HLAObjectInstance::_removeInstance(const RTIData& tag)
613 if (!_objectClass.valid())
615 _objectClass->_removeInstance(*this, tag);
619 HLAObjectInstance::_reflectAttributeValues(const HLAIndexList& indexList, const RTIData& tag)
621 if (_reflectCallback.valid()) {
622 _reflectCallback->reflectAttributeValues(*this, indexList, tag);
623 } else if (_attributeCallback.valid()) {
624 reflectAttributeValues(indexList, tag);
626 RTIIndexDataPairList dataPairList;
627 for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i) {
628 dataPairList.push_back(RTIIndexDataPair());
629 dataPairList.back().first = *i;
630 getAttributeData(*i, dataPairList.back().second);
632 _attributeCallback->reflectAttributeValues(*this, dataPairList, tag);
634 reflectAttributeValues(indexList, tag);
639 HLAObjectInstance::_reflectAttributeValues(const HLAIndexList& indexList, const SGTimeStamp& timeStamp, const RTIData& tag)
641 if (_reflectCallback.valid()) {
642 _reflectCallback->reflectAttributeValues(*this, indexList, timeStamp, tag);
643 } else if (_attributeCallback.valid()) {
644 reflectAttributeValues(indexList, timeStamp, tag);
646 RTIIndexDataPairList dataPairList;
647 for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i) {
648 dataPairList.push_back(RTIIndexDataPair());
649 dataPairList.back().first = *i;
650 getAttributeData(*i, dataPairList.back().second);
652 _attributeCallback->reflectAttributeValues(*this, dataPairList, timeStamp, tag);
654 reflectAttributeValues(indexList, timeStamp, tag);
658 } // namespace simgear