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::getName() const
60 const SGWeakPtr<HLAFederate>&
61 HLAObjectInstance::getFederate() const
66 const SGSharedPtr<HLAObjectClass>&
67 HLAObjectInstance::getObjectClass() const
73 HLAObjectInstance::getNumAttributes() const
75 return _objectClass->getNumAttributes();
79 HLAObjectInstance::getAttributeIndex(const std::string& name) const
81 return _objectClass->getAttributeIndex(name);
85 HLAObjectInstance::getAttributeName(unsigned index) const
87 return _objectClass->getAttributeName(index);
91 HLAObjectInstance::getAttributeOwned(unsigned index) const
93 if (!_rtiObjectInstance.valid())
95 return _rtiObjectInstance->getAttributeOwned(index);
99 HLAObjectInstance::getAttributeDataType(unsigned index) const
101 return _objectClass->getAttributeDataType(index);
105 HLAObjectInstance::getAttributeDataElement(unsigned index)
107 if (_attributeVector.size() <= index)
109 return _attributeVector[index]._dataElement.get();
112 const HLADataElement*
113 HLAObjectInstance::getAttributeDataElement(unsigned index) const
115 if (_attributeVector.size() <= index)
117 return _attributeVector[index]._dataElement.get();
121 HLAObjectInstance::getAttributeData(unsigned index, RTIData& data) const
123 if (!_rtiObjectInstance.valid()) {
124 SG_LOG(SG_IO, SG_ALERT, "Trying to get raw attribute data without rti object instance for \"" << getName() << "\"!");
127 return _rtiObjectInstance->getAttributeData(index, data);
131 HLAObjectInstance::setAttributeDataElement(unsigned index, const SGSharedPtr<HLADataElement>& dataElement)
133 unsigned numAttributes = getNumAttributes();
134 if (numAttributes <= index)
136 _attributeVector.resize(numAttributes);
137 if (_attributeVector[index]._dataElement.valid())
138 _attributeVector[index]._dataElement->clearStamp();
139 _attributeVector[index]._dataElement = dataElement;
140 if (_attributeVector[index]._dataElement.valid())
141 _attributeVector[index]._dataElement->createStamp();
144 class HLAObjectInstance::DataElementFactoryVisitor : public HLADataElementFactoryVisitor {
146 DataElementFactoryVisitor(const HLAPathElementMap& pathElementMap) :
147 _pathElementMap(pathElementMap)
149 DataElementFactoryVisitor(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) :
150 _pathElementMap(pathElementMap),
153 virtual ~DataElementFactoryVisitor() {}
155 virtual void apply(const HLADataType& dataType)
157 _dataElement = createDataElement(_path, dataType);
158 if (_dataElement.valid())
161 SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Can not find a suitable data element for data type \""
162 << dataType.getName() << "\"");
165 virtual void apply(const HLAInt8DataType& dataType)
167 _dataElement = createDataElement(_path, dataType);
168 if (_dataElement.valid())
171 HLADataElementFactoryVisitor::apply(dataType);
173 virtual void apply(const HLAUInt8DataType& dataType)
175 _dataElement = createDataElement(_path, dataType);
176 if (_dataElement.valid())
179 HLADataElementFactoryVisitor::apply(dataType);
181 virtual void apply(const HLAInt16DataType& dataType)
183 _dataElement = createDataElement(_path, dataType);
184 if (_dataElement.valid())
187 HLADataElementFactoryVisitor::apply(dataType);
189 virtual void apply(const HLAUInt16DataType& dataType)
191 _dataElement = createDataElement(_path, dataType);
192 if (_dataElement.valid())
195 HLADataElementFactoryVisitor::apply(dataType);
197 virtual void apply(const HLAInt32DataType& dataType)
199 _dataElement = createDataElement(_path, dataType);
200 if (_dataElement.valid())
203 HLADataElementFactoryVisitor::apply(dataType);
205 virtual void apply(const HLAUInt32DataType& dataType)
207 _dataElement = createDataElement(_path, dataType);
208 if (_dataElement.valid())
211 HLADataElementFactoryVisitor::apply(dataType);
213 virtual void apply(const HLAInt64DataType& dataType)
215 _dataElement = createDataElement(_path, dataType);
216 if (_dataElement.valid())
219 HLADataElementFactoryVisitor::apply(dataType);
221 virtual void apply(const HLAUInt64DataType& dataType)
223 _dataElement = createDataElement(_path, dataType);
224 if (_dataElement.valid())
227 HLADataElementFactoryVisitor::apply(dataType);
229 virtual void apply(const HLAFloat32DataType& dataType)
231 _dataElement = createDataElement(_path, dataType);
232 if (_dataElement.valid())
235 HLADataElementFactoryVisitor::apply(dataType);
237 virtual void apply(const HLAFloat64DataType& dataType)
239 _dataElement = createDataElement(_path, dataType);
240 if (_dataElement.valid())
243 HLADataElementFactoryVisitor::apply(dataType);
246 class ArrayDataElementFactory : public HLAArrayDataElement::DataElementFactory {
248 ArrayDataElementFactory(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) :
251 for (HLAPathElementMap::const_iterator i = pathElementMap.lower_bound(path);
252 i != pathElementMap.end(); ++i) {
253 if (i->first.begin() != std::search(i->first.begin(), i->first.end(),
254 path.begin(), path.end()))
256 _pathElementMap.insert(*i);
259 virtual HLADataElement* createElement(const HLAArrayDataElement& element, unsigned index)
261 const HLADataType* dataType = element.getElementDataType();
264 HLADataElement::Path path = _path;
265 path.push_back(HLADataElement::PathElement(index));
266 DataElementFactoryVisitor visitor(path, _pathElementMap);
267 dataType->accept(visitor);
268 return visitor._dataElement.release();
271 HLADataElement::Path _path;
272 HLAPathElementMap _pathElementMap;
275 virtual void apply(const HLAFixedArrayDataType& dataType)
277 _dataElement = createDataElement(_path, dataType);
278 if (_dataElement.valid())
281 SGSharedPtr<HLAArrayDataElement> arrayDataElement;
282 arrayDataElement = new HLAArrayDataElement(&dataType);
283 arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_path, _pathElementMap));
284 arrayDataElement->setNumElements(dataType.getNumElements());
286 _dataElement = arrayDataElement;
289 virtual void apply(const HLAVariableArrayDataType& dataType)
291 _dataElement = createDataElement(_path, dataType);
292 if (_dataElement.valid())
295 SGSharedPtr<HLAArrayDataElement> arrayDataElement;
296 arrayDataElement = new HLAArrayDataElement(&dataType);
297 arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_path, _pathElementMap));
299 _dataElement = arrayDataElement;
302 virtual void apply(const HLAEnumeratedDataType& dataType)
304 _dataElement = createDataElement(_path, dataType);
305 if (_dataElement.valid())
308 HLADataElementFactoryVisitor::apply(dataType);
311 virtual void apply(const HLAFixedRecordDataType& dataType)
313 _dataElement = createDataElement(_path, dataType);
314 if (_dataElement.valid())
317 SGSharedPtr<HLAFixedRecordDataElement> recordDataElement;
318 recordDataElement = new HLAFixedRecordDataElement(&dataType);
320 unsigned numFields = dataType.getNumFields();
321 for (unsigned i = 0; i < numFields; ++i) {
323 _path.push_back(HLADataElement::PathElement(dataType.getFieldName(i)));
325 dataType.getFieldDataType(i)->accept(*this);
326 recordDataElement->setField(i, _dataElement.release());
330 _dataElement = recordDataElement;
333 class VariantRecordDataElementFactory : public HLAVariantRecordDataElement::DataElementFactory {
335 VariantRecordDataElementFactory(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) :
338 for (HLAPathElementMap::const_iterator i = pathElementMap.lower_bound(path);
339 i != pathElementMap.end(); ++i) {
340 if (i->first.begin() != std::search(i->first.begin(), i->first.end(),
341 path.begin(), path.end()))
343 _pathElementMap.insert(*i);
346 virtual HLADataElement* createElement(const HLAVariantRecordDataElement& element, unsigned index)
348 const HLAVariantRecordDataType* dataType = element.getDataType();
351 const HLADataType* alternativeDataType = element.getAlternativeDataType();
352 if (!alternativeDataType)
354 HLADataElement::Path path = _path;
355 path.push_back(HLADataElement::PathElement(dataType->getAlternativeName(index)));
356 DataElementFactoryVisitor visitor(path, _pathElementMap);
357 alternativeDataType->accept(visitor);
358 return visitor._dataElement.release();
361 HLADataElement::Path _path;
362 HLAPathElementMap _pathElementMap;
365 virtual void apply(const HLAVariantRecordDataType& dataType)
367 _dataElement = createDataElement(_path, dataType);
368 if (_dataElement.valid())
371 SGSharedPtr<HLAVariantRecordDataElement> variantRecordDataElement;
372 variantRecordDataElement = new HLAVariantRecordDataElement(&dataType);
373 variantRecordDataElement->setDataElementFactory(new VariantRecordDataElementFactory(_path, _pathElementMap));
375 _dataElement = variantRecordDataElement;
379 SGSharedPtr<HLADataElement> createDataElement(const HLADataElement::Path& path, const HLADataType& dataType)
381 HLAPathElementMap::const_iterator i = _pathElementMap.find(path);
382 if (i == _pathElementMap.end()) {
383 SG_LOG(SG_IO, SG_WARN, "No dataElement provided for \""
384 << HLADataElement::toString(path) << "\".");
388 SGSharedPtr<HLADataElement> dataElement = i->second.getDataElement(path);
389 if (!dataElement->setDataType(&dataType)) {
390 SG_LOG(SG_IO, SG_ALERT, "Cannot set data type for data element at \""
391 << HLADataElement::toString(path) << "\"!");
394 SG_LOG(SG_IO, SG_DEBUG, "Using provided dataElement for \""
395 << HLADataElement::toString(path) << "\".");
399 const HLAPathElementMap& _pathElementMap;
400 HLADataElement::Path _path;
404 HLAObjectInstance::setAttribute(unsigned index, const HLAPathElementMap& pathElementMap)
406 const HLADataType* dataType = getAttributeDataType(index);
408 SG_LOG(SG_IO, SG_ALERT, "Cannot get attribute data type for setting attribute \""
409 << getAttributeName(index) << "\" at index " << index << "!");
413 SG_LOG(SG_IO, SG_DEBUG, "Setting DataElement for attribute \""
414 << getAttributeName(index) << "\".");
416 DataElementFactoryVisitor visitor(pathElementMap);
417 dataType->accept(visitor);
418 setAttributeDataElement(index, visitor.getDataElement());
422 HLAObjectInstance::setAttributes(const HLAAttributePathElementMap& attributePathElementMap)
424 for (HLAAttributePathElementMap::const_iterator i = attributePathElementMap.begin();
425 i != attributePathElementMap.end(); ++i) {
426 setAttribute(i->first, i->second);
431 HLAObjectInstance::registerInstance()
433 if (_rtiObjectInstance.valid()) {
434 SG_LOG(SG_IO, SG_ALERT, "Trying to register object " << getName() << " already known to the RTI!");
437 if (!_objectClass.valid()) {
438 SG_LOG(SG_IO, SG_ALERT, "Could not register object with unknown object class!");
441 // This error must have been flagged before
442 if (!_objectClass->_rtiObjectClass.valid())
444 _setRTIObjectInstance(_objectClass->_rtiObjectClass->registerObjectInstance(this));
445 if (!_rtiObjectInstance.valid()) {
446 SG_LOG(SG_IO, SG_ALERT, "Could not register object at the RTI!");
449 _objectClass->_registerInstance(this);
453 HLAObjectInstance::deleteInstance(const RTIData& tag)
455 if (!_rtiObjectInstance.valid()) {
456 SG_LOG(SG_IO, SG_ALERT, "Trying to delete inactive object!");
459 if (!_objectClass.valid())
461 _objectClass->_deleteInstance(*this);
462 _rtiObjectInstance->deleteObjectInstance(tag);
466 HLAObjectInstance::updateAttributeValues(const RTIData& tag)
468 if (_attributeCallback.valid())
469 _attributeCallback->updateAttributeValues(*this, tag);
470 if (_updateCallback.valid()) {
471 _updateCallback->updateAttributeValues(*this, tag);
473 encodeAttributeValues();
474 sendAttributeValues(tag);
479 HLAObjectInstance::updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag)
481 if (_attributeCallback.valid())
482 _attributeCallback->updateAttributeValues(*this, tag);
483 if (_updateCallback.valid()) {
484 _updateCallback->updateAttributeValues(*this, timeStamp, tag);
486 encodeAttributeValues();
487 sendAttributeValues(timeStamp, tag);
492 HLAObjectInstance::encodeAttributeValues()
494 unsigned numAttributes = _attributeVector.size();
495 for (unsigned i = 0; i < numAttributes;++i) {
496 if (_attributeVector[i]._unconditionalUpdate) {
497 encodeAttributeValue(i);
498 } else if (_attributeVector[i]._enabledUpdate) {
499 const HLADataElement* dataElement = getAttributeDataElement(i);
500 if (dataElement && dataElement->getDirty())
501 encodeAttributeValue(i);
507 HLAObjectInstance::encodeAttributeValue(unsigned index)
509 if (!_rtiObjectInstance.valid()) {
510 SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
513 HLADataElement* dataElement = getAttributeDataElement(index);
516 _rtiObjectInstance->encodeAttributeData(index, *dataElement);
517 dataElement->setDirty(false);
521 HLAObjectInstance::sendAttributeValues(const RTIData& tag)
523 if (!_rtiObjectInstance.valid()) {
524 SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
527 _rtiObjectInstance->updateAttributeValues(tag);
531 HLAObjectInstance::sendAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag)
533 if (!_rtiObjectInstance.valid()) {
534 SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
537 _rtiObjectInstance->updateAttributeValues(timeStamp, tag);
541 HLAObjectInstance::reflectAttributeValues(const HLAIndexList& indexList, const RTIData& tag)
543 for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i)
544 reflectAttributeValue(*i, tag);
548 HLAObjectInstance::reflectAttributeValues(const HLAIndexList& indexList,
549 const SGTimeStamp& timeStamp, const RTIData& tag)
551 for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i)
552 reflectAttributeValue(*i, timeStamp, tag);
556 HLAObjectInstance::reflectAttributeValue(unsigned index, const RTIData& tag)
558 HLADataElement* dataElement = getAttributeDataElement(index);
561 dataElement->setTimeStampValid(false);
562 _rtiObjectInstance->decodeAttributeData(index, *dataElement);
566 HLAObjectInstance::reflectAttributeValue(unsigned index, const SGTimeStamp& timeStamp, const RTIData& tag)
568 HLADataElement* dataElement = getAttributeDataElement(index);
571 dataElement->setTimeStamp(timeStamp);
572 dataElement->setTimeStampValid(true);
573 _rtiObjectInstance->decodeAttributeData(index, *dataElement);
577 HLAObjectInstance::_setRTIObjectInstance(RTIObjectInstance* rtiObjectInstance)
579 _rtiObjectInstance = rtiObjectInstance;
580 _rtiObjectInstance->setObjectInstance(this);
581 _name = _rtiObjectInstance->getName();
583 unsigned numAttributes = getNumAttributes();
584 _attributeVector.resize(numAttributes);
585 for (unsigned i = 0; i < numAttributes; ++i) {
586 HLAUpdateType updateType = getObjectClass()->getAttributeUpdateType(i);
587 if (getAttributeOwned(i) && updateType != HLAUndefinedUpdate) {
588 _attributeVector[i]._enabledUpdate = true;
589 _attributeVector[i]._unconditionalUpdate = (updateType == HLAPeriodicUpdate);
590 // In case of an owned attribute, now encode its value
591 encodeAttributeValue(i);
593 _attributeVector[i]._enabledUpdate = false;
594 _attributeVector[i]._unconditionalUpdate = false;
598 // This makes sense with any new object. Even if we registered one, there might be unpublished attributes.
599 HLAIndexList indexList;
600 for (unsigned i = 0; i < numAttributes; ++i) {
601 HLAUpdateType updateType = getObjectClass()->getAttributeUpdateType(i);
602 if (getAttributeOwned(i))
604 if (updateType == HLAUndefinedUpdate)
606 if (updateType == HLAPeriodicUpdate)
608 indexList.push_back(i);
610 _rtiObjectInstance->requestObjectAttributeValueUpdate(indexList);
614 HLAObjectInstance::_clearRTIObjectInstance()
616 if (!_rtiObjectInstance.valid())
619 for (unsigned i = 0; i < _attributeVector.size(); ++i) {
620 _attributeVector[i]._enabledUpdate = false;
621 _attributeVector[i]._unconditionalUpdate = false;
624 _rtiObjectInstance->setObjectInstance(0);
625 _rtiObjectInstance = 0;
629 HLAObjectInstance::_removeInstance(const RTIData& tag)
631 if (!_objectClass.valid())
633 _objectClass->_removeInstance(*this, tag);
637 HLAObjectInstance::_reflectAttributeValues(const HLAIndexList& indexList, const RTIData& tag)
639 if (_reflectCallback.valid()) {
640 _reflectCallback->reflectAttributeValues(*this, indexList, tag);
641 } else if (_attributeCallback.valid()) {
642 reflectAttributeValues(indexList, tag);
644 RTIIndexDataPairList dataPairList;
645 for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i) {
646 dataPairList.push_back(RTIIndexDataPair());
647 dataPairList.back().first = *i;
648 getAttributeData(*i, dataPairList.back().second);
650 _attributeCallback->reflectAttributeValues(*this, dataPairList, tag);
652 reflectAttributeValues(indexList, tag);
657 HLAObjectInstance::_reflectAttributeValues(const HLAIndexList& indexList, const SGTimeStamp& timeStamp, const RTIData& tag)
659 if (_reflectCallback.valid()) {
660 _reflectCallback->reflectAttributeValues(*this, indexList, timeStamp, tag);
661 } else if (_attributeCallback.valid()) {
662 reflectAttributeValues(indexList, timeStamp, tag);
664 RTIIndexDataPairList dataPairList;
665 for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i) {
666 dataPairList.push_back(RTIIndexDataPair());
667 dataPairList.back().first = *i;
668 getAttributeData(*i, dataPairList.back().second);
670 _attributeCallback->reflectAttributeValues(*this, dataPairList, timeStamp, tag);
672 reflectAttributeValues(indexList, timeStamp, tag);
676 } // namespace simgear