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();
124 if (getAttributeOwned(index))
125 encodeAttributeValue(index);
128 class HLAObjectInstance::DataElementFactoryVisitor : public HLADataElementFactoryVisitor {
130 DataElementFactoryVisitor(const HLAPathElementMap& pathElementMap) :
131 _pathElementMap(pathElementMap)
133 DataElementFactoryVisitor(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) :
134 _pathElementMap(pathElementMap),
137 virtual ~DataElementFactoryVisitor() {}
139 virtual void apply(const HLADataType& dataType)
141 _dataElement = createDataElement(_path, dataType);
142 if (_dataElement.valid())
145 SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Can not find a suitable data element for data type \""
146 << dataType.getName() << "\"");
149 virtual void apply(const HLAInt8DataType& dataType)
151 _dataElement = createDataElement(_path, dataType);
152 if (_dataElement.valid())
155 HLADataElementFactoryVisitor::apply(dataType);
157 virtual void apply(const HLAUInt8DataType& dataType)
159 _dataElement = createDataElement(_path, dataType);
160 if (_dataElement.valid())
163 HLADataElementFactoryVisitor::apply(dataType);
165 virtual void apply(const HLAInt16DataType& dataType)
167 _dataElement = createDataElement(_path, dataType);
168 if (_dataElement.valid())
171 HLADataElementFactoryVisitor::apply(dataType);
173 virtual void apply(const HLAUInt16DataType& dataType)
175 _dataElement = createDataElement(_path, dataType);
176 if (_dataElement.valid())
179 HLADataElementFactoryVisitor::apply(dataType);
181 virtual void apply(const HLAInt32DataType& dataType)
183 _dataElement = createDataElement(_path, dataType);
184 if (_dataElement.valid())
187 HLADataElementFactoryVisitor::apply(dataType);
189 virtual void apply(const HLAUInt32DataType& dataType)
191 _dataElement = createDataElement(_path, dataType);
192 if (_dataElement.valid())
195 HLADataElementFactoryVisitor::apply(dataType);
197 virtual void apply(const HLAInt64DataType& dataType)
199 _dataElement = createDataElement(_path, dataType);
200 if (_dataElement.valid())
203 HLADataElementFactoryVisitor::apply(dataType);
205 virtual void apply(const HLAUInt64DataType& dataType)
207 _dataElement = createDataElement(_path, dataType);
208 if (_dataElement.valid())
211 HLADataElementFactoryVisitor::apply(dataType);
213 virtual void apply(const HLAFloat32DataType& dataType)
215 _dataElement = createDataElement(_path, dataType);
216 if (_dataElement.valid())
219 HLADataElementFactoryVisitor::apply(dataType);
221 virtual void apply(const HLAFloat64DataType& dataType)
223 _dataElement = createDataElement(_path, dataType);
224 if (_dataElement.valid())
227 HLADataElementFactoryVisitor::apply(dataType);
230 class ArrayDataElementFactory : public HLAArrayDataElement::DataElementFactory {
232 ArrayDataElementFactory(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) :
235 for (HLAPathElementMap::const_iterator i = pathElementMap.lower_bound(path);
236 i != pathElementMap.end(); ++i) {
237 if (i->first.begin() != std::search(i->first.begin(), i->first.end(),
238 path.begin(), path.end()))
240 _pathElementMap.insert(*i);
243 virtual HLADataElement* createElement(const HLAArrayDataElement& element, unsigned index)
245 const HLADataType* dataType = element.getElementDataType();
248 HLADataElement::Path path = _path;
249 path.push_back(HLADataElement::PathElement(index));
250 DataElementFactoryVisitor visitor(path, _pathElementMap);
251 dataType->accept(visitor);
252 return visitor._dataElement.release();
255 HLADataElement::Path _path;
256 HLAPathElementMap _pathElementMap;
259 virtual void apply(const HLAFixedArrayDataType& dataType)
261 _dataElement = createDataElement(_path, dataType);
262 if (_dataElement.valid())
265 SGSharedPtr<HLAArrayDataElement> arrayDataElement;
266 arrayDataElement = new HLAArrayDataElement(&dataType);
267 arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_path, _pathElementMap));
268 arrayDataElement->setNumElements(dataType.getNumElements());
270 _dataElement = arrayDataElement;
273 virtual void apply(const HLAVariableArrayDataType& dataType)
275 _dataElement = createDataElement(_path, dataType);
276 if (_dataElement.valid())
279 SGSharedPtr<HLAArrayDataElement> arrayDataElement;
280 arrayDataElement = new HLAArrayDataElement(&dataType);
281 arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_path, _pathElementMap));
283 _dataElement = arrayDataElement;
286 virtual void apply(const HLAEnumeratedDataType& dataType)
288 _dataElement = createDataElement(_path, dataType);
289 if (_dataElement.valid())
292 HLADataElementFactoryVisitor::apply(dataType);
295 virtual void apply(const HLAFixedRecordDataType& dataType)
297 _dataElement = createDataElement(_path, dataType);
298 if (_dataElement.valid())
301 SGSharedPtr<HLAFixedRecordDataElement> recordDataElement;
302 recordDataElement = new HLAFixedRecordDataElement(&dataType);
304 unsigned numFields = dataType.getNumFields();
305 for (unsigned i = 0; i < numFields; ++i) {
307 _path.push_back(HLADataElement::PathElement(dataType.getFieldName(i)));
309 dataType.getFieldDataType(i)->accept(*this);
310 recordDataElement->setField(i, _dataElement.release());
314 _dataElement = recordDataElement;
317 class VariantRecordDataElementFactory : public HLAVariantRecordDataElement::DataElementFactory {
319 VariantRecordDataElementFactory(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) :
322 for (HLAPathElementMap::const_iterator i = pathElementMap.lower_bound(path);
323 i != pathElementMap.end(); ++i) {
324 if (i->first.begin() != std::search(i->first.begin(), i->first.end(),
325 path.begin(), path.end()))
327 _pathElementMap.insert(*i);
330 virtual HLADataElement* createElement(const HLAVariantRecordDataElement& element, unsigned index)
332 const HLAVariantRecordDataType* dataType = element.getDataType();
335 const HLADataType* alternativeDataType = element.getAlternativeDataType();
336 if (!alternativeDataType)
338 HLADataElement::Path path = _path;
339 path.push_back(HLADataElement::PathElement(dataType->getAlternativeName(index)));
340 DataElementFactoryVisitor visitor(path, _pathElementMap);
341 alternativeDataType->accept(visitor);
342 return visitor._dataElement.release();
345 HLADataElement::Path _path;
346 HLAPathElementMap _pathElementMap;
349 virtual void apply(const HLAVariantRecordDataType& dataType)
351 _dataElement = createDataElement(_path, dataType);
352 if (_dataElement.valid())
355 SGSharedPtr<HLAVariantRecordDataElement> variantRecordDataElement;
356 variantRecordDataElement = new HLAVariantRecordDataElement(&dataType);
357 variantRecordDataElement->setDataElementFactory(new VariantRecordDataElementFactory(_path, _pathElementMap));
359 _dataElement = variantRecordDataElement;
363 SGSharedPtr<HLADataElement> createDataElement(const HLADataElement::Path& path, const HLADataType& dataType)
365 HLAPathElementMap::const_iterator i = _pathElementMap.find(path);
366 if (i == _pathElementMap.end()) {
367 SG_LOG(SG_IO, SG_WARN, "No dataElement provided for \""
368 << HLADataElement::toString(path) << "\".");
372 SGSharedPtr<HLADataElement> dataElement = i->second.getDataElement(path);
373 if (!dataElement->setDataType(&dataType)) {
374 SG_LOG(SG_IO, SG_ALERT, "Cannot set data type for data element at \""
375 << HLADataElement::toString(path) << "\"!");
378 SG_LOG(SG_IO, SG_DEBUG, "Using provided dataElement for \""
379 << HLADataElement::toString(path) << "\".");
383 const HLAPathElementMap& _pathElementMap;
384 HLADataElement::Path _path;
388 HLAObjectInstance::setAttribute(unsigned index, const HLAPathElementMap& pathElementMap)
390 const HLADataType* dataType = getAttributeDataType(index);
392 SG_LOG(SG_IO, SG_ALERT, "Cannot get attribute data type for setting attribute \""
393 << getAttributeName(index) << "\" at index " << index << "!");
397 SG_LOG(SG_IO, SG_DEBUG, "Setting DataElement for attribute \""
398 << getAttributeName(index) << "\".");
400 DataElementFactoryVisitor visitor(pathElementMap);
401 dataType->accept(visitor);
402 setAttributeDataElement(index, visitor.getDataElement());
406 HLAObjectInstance::setAttributes(const HLAAttributePathElementMap& attributePathElementMap)
408 for (HLAAttributePathElementMap::const_iterator i = attributePathElementMap.begin();
409 i != attributePathElementMap.end(); ++i) {
410 setAttribute(i->first, i->second);
415 HLAObjectInstance::registerInstance()
417 if (_rtiObjectInstance.valid()) {
418 SG_LOG(SG_IO, SG_ALERT, "Trying to register object " << getName() << " already known to the RTI!");
421 if (!_objectClass.valid()) {
422 SG_LOG(SG_IO, SG_ALERT, "Could not register object with unknown object class!");
425 // This error must have been flagged before
426 if (!_objectClass->_rtiObjectClass.valid())
428 _setRTIObjectInstance(_objectClass->_rtiObjectClass->registerObjectInstance(this));
429 if (!_rtiObjectInstance.valid()) {
430 SG_LOG(SG_IO, SG_ALERT, "Could not register object at the RTI!");
433 _objectClass->_registerInstance(this);
437 HLAObjectInstance::deleteInstance(const RTIData& tag)
439 if (!_rtiObjectInstance.valid()) {
440 SG_LOG(SG_IO, SG_ALERT, "Trying to delete inactive object!");
443 if (!_objectClass.valid())
445 _objectClass->_deleteInstance(*this);
446 _rtiObjectInstance->deleteObjectInstance(tag);
450 HLAObjectInstance::updateAttributeValues(const RTIData& tag)
452 if (_attributeCallback.valid())
453 _attributeCallback->updateAttributeValues(*this, tag);
454 if (_updateCallback.valid()) {
455 _updateCallback->updateAttributeValues(*this, tag);
457 encodeAttributeValues();
458 sendAttributeValues(tag);
463 HLAObjectInstance::updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag)
465 if (_attributeCallback.valid())
466 _attributeCallback->updateAttributeValues(*this, tag);
467 if (_updateCallback.valid()) {
468 _updateCallback->updateAttributeValues(*this, timeStamp, tag);
470 encodeAttributeValues();
471 sendAttributeValues(timeStamp, tag);
476 HLAObjectInstance::encodeAttributeValues()
478 unsigned numAttributes = _attributeVector.size();
479 for (unsigned i = 0; i < numAttributes;++i) {
480 if (!_attributeVector[i]._unconditionalUpdate)
482 encodeAttributeValue(i);
487 HLAObjectInstance::encodeAttributeValue(unsigned index)
489 if (!_rtiObjectInstance.valid()) {
490 SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
493 const HLADataElement* dataElement = getAttributeDataElement(index);
496 _rtiObjectInstance->encodeAttributeData(index, *dataElement);
500 HLAObjectInstance::sendAttributeValues(const RTIData& tag)
502 if (!_rtiObjectInstance.valid()) {
503 SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
506 _rtiObjectInstance->updateAttributeValues(tag);
510 HLAObjectInstance::sendAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag)
512 if (!_rtiObjectInstance.valid()) {
513 SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
516 _rtiObjectInstance->updateAttributeValues(timeStamp, tag);
520 HLAObjectInstance::reflectAttributeValues(const HLAIndexList& indexList, const RTIData& tag)
522 for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i)
523 reflectAttributeValue(*i, tag);
527 HLAObjectInstance::reflectAttributeValues(const HLAIndexList& indexList,
528 const SGTimeStamp& timeStamp, const RTIData& tag)
530 for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i)
531 reflectAttributeValue(*i, timeStamp, tag);
535 HLAObjectInstance::reflectAttributeValue(unsigned index, const RTIData& tag)
537 HLADataElement* dataElement = getAttributeDataElement(index);
540 dataElement->setTimeStampValid(false);
541 _rtiObjectInstance->decodeAttributeData(index, *dataElement);
545 HLAObjectInstance::reflectAttributeValue(unsigned index, const SGTimeStamp& timeStamp, const RTIData& tag)
547 HLADataElement* dataElement = getAttributeDataElement(index);
550 dataElement->setTimeStamp(timeStamp);
551 dataElement->setTimeStampValid(true);
552 _rtiObjectInstance->decodeAttributeData(index, *dataElement);
556 HLAObjectInstance::_setRTIObjectInstance(RTIObjectInstance* rtiObjectInstance)
558 _rtiObjectInstance = rtiObjectInstance;
559 _rtiObjectInstance->setObjectInstance(this);
560 _name = _rtiObjectInstance->getName();
562 unsigned numAttributes = getNumAttributes();
563 _attributeVector.resize(numAttributes);
564 for (unsigned i = 0; i < numAttributes; ++i) {
565 HLAUpdateType updateType = getObjectClass()->getAttributeUpdateType(i);
566 if (getAttributeOwned(i) && updateType != HLAUndefinedUpdate) {
567 _attributeVector[i]._enabledUpdate = true;
568 _attributeVector[i]._unconditionalUpdate = (updateType == HLAPeriodicUpdate);
569 // In case of an owned attribute, now encode its value
570 encodeAttributeValue(i);
572 _attributeVector[i]._enabledUpdate = false;
573 _attributeVector[i]._unconditionalUpdate = false;
577 // This makes sense with any new object. Even if we registered one, there might be unpublished attributes.
578 HLAIndexList indexList;
579 for (unsigned i = 0; i < numAttributes; ++i) {
580 HLAUpdateType updateType = getObjectClass()->getAttributeUpdateType(i);
581 if (getAttributeOwned(i))
583 if (updateType == HLAUndefinedUpdate)
585 if (updateType == HLAPeriodicUpdate)
587 indexList.push_back(i);
589 _rtiObjectInstance->requestObjectAttributeValueUpdate(indexList);
593 HLAObjectInstance::_clearRTIObjectInstance()
595 if (!_rtiObjectInstance.valid())
598 for (unsigned i = 0; i < _attributeVector.size(); ++i) {
599 _attributeVector[i]._enabledUpdate = false;
600 _attributeVector[i]._unconditionalUpdate = false;
603 _rtiObjectInstance->setObjectInstance(0);
604 _rtiObjectInstance = 0;
608 HLAObjectInstance::_removeInstance(const RTIData& tag)
610 if (!_objectClass.valid())
612 _objectClass->_removeInstance(*this, tag);
616 HLAObjectInstance::_reflectAttributeValues(const HLAIndexList& indexList, const RTIData& tag)
618 if (_reflectCallback.valid()) {
619 _reflectCallback->reflectAttributeValues(*this, indexList, tag);
620 } else if (_attributeCallback.valid()) {
621 reflectAttributeValues(indexList, tag);
623 RTIIndexDataPairList dataPairList;
624 for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i) {
625 dataPairList.push_back(RTIIndexDataPair());
626 dataPairList.back().first = *i;
627 getAttributeData(*i, dataPairList.back().second);
629 _attributeCallback->reflectAttributeValues(*this, dataPairList, tag);
631 reflectAttributeValues(indexList, tag);
636 HLAObjectInstance::_reflectAttributeValues(const HLAIndexList& indexList, const SGTimeStamp& timeStamp, const RTIData& tag)
638 if (_reflectCallback.valid()) {
639 _reflectCallback->reflectAttributeValues(*this, indexList, timeStamp, tag);
640 } else if (_attributeCallback.valid()) {
641 reflectAttributeValues(indexList, timeStamp, tag);
643 RTIIndexDataPairList dataPairList;
644 for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i) {
645 dataPairList.push_back(RTIIndexDataPair());
646 dataPairList.back().first = *i;
647 getAttributeData(*i, dataPairList.back().second);
649 _attributeCallback->reflectAttributeValues(*this, dataPairList, timeStamp, tag);
651 reflectAttributeValues(indexList, timeStamp, tag);
655 } // namespace simgear