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 _attributeVector[index]._dataElement = dataElement;
120 if (getAttributeOwned(index))
121 encodeAttributeValue(index);
124 class HLAObjectInstance::DataElementFactoryVisitor : public HLADataElementFactoryVisitor {
126 DataElementFactoryVisitor(const HLAPathElementMap& pathElementMap) :
127 _pathElementMap(pathElementMap)
129 DataElementFactoryVisitor(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) :
130 _pathElementMap(pathElementMap),
133 virtual ~DataElementFactoryVisitor() {}
135 virtual void apply(const HLADataType& dataType)
137 _dataElement = createDataElement(_path, dataType);
138 if (_dataElement.valid())
141 SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Can not find a suitable data element for data type \""
142 << dataType.getName() << "\"");
145 virtual void apply(const HLAInt8DataType& dataType)
147 _dataElement = createDataElement(_path, dataType);
148 if (_dataElement.valid())
151 HLADataElementFactoryVisitor::apply(dataType);
153 virtual void apply(const HLAUInt8DataType& dataType)
155 _dataElement = createDataElement(_path, dataType);
156 if (_dataElement.valid())
159 HLADataElementFactoryVisitor::apply(dataType);
161 virtual void apply(const HLAInt16DataType& dataType)
163 _dataElement = createDataElement(_path, dataType);
164 if (_dataElement.valid())
167 HLADataElementFactoryVisitor::apply(dataType);
169 virtual void apply(const HLAUInt16DataType& dataType)
171 _dataElement = createDataElement(_path, dataType);
172 if (_dataElement.valid())
175 HLADataElementFactoryVisitor::apply(dataType);
177 virtual void apply(const HLAInt32DataType& dataType)
179 _dataElement = createDataElement(_path, dataType);
180 if (_dataElement.valid())
183 HLADataElementFactoryVisitor::apply(dataType);
185 virtual void apply(const HLAUInt32DataType& dataType)
187 _dataElement = createDataElement(_path, dataType);
188 if (_dataElement.valid())
191 HLADataElementFactoryVisitor::apply(dataType);
193 virtual void apply(const HLAInt64DataType& dataType)
195 _dataElement = createDataElement(_path, dataType);
196 if (_dataElement.valid())
199 HLADataElementFactoryVisitor::apply(dataType);
201 virtual void apply(const HLAUInt64DataType& dataType)
203 _dataElement = createDataElement(_path, dataType);
204 if (_dataElement.valid())
207 HLADataElementFactoryVisitor::apply(dataType);
209 virtual void apply(const HLAFloat32DataType& dataType)
211 _dataElement = createDataElement(_path, dataType);
212 if (_dataElement.valid())
215 HLADataElementFactoryVisitor::apply(dataType);
217 virtual void apply(const HLAFloat64DataType& dataType)
219 _dataElement = createDataElement(_path, dataType);
220 if (_dataElement.valid())
223 HLADataElementFactoryVisitor::apply(dataType);
226 class ArrayDataElementFactory : public HLAArrayDataElement::DataElementFactory {
228 ArrayDataElementFactory(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) :
231 for (HLAPathElementMap::const_iterator i = pathElementMap.lower_bound(path);
232 i != pathElementMap.end(); ++i) {
233 if (i->first.begin() != std::search(i->first.begin(), i->first.end(),
234 path.begin(), path.end()))
236 _pathElementMap.insert(*i);
239 virtual HLADataElement* createElement(const HLAArrayDataElement& element, unsigned index)
241 const HLADataType* dataType = element.getElementDataType();
244 HLADataElement::Path path = _path;
245 path.push_back(HLADataElement::PathElement(index));
246 DataElementFactoryVisitor visitor(path, _pathElementMap);
247 dataType->accept(visitor);
248 return visitor._dataElement.release();
251 HLADataElement::Path _path;
252 HLAPathElementMap _pathElementMap;
255 virtual void apply(const HLAFixedArrayDataType& dataType)
257 _dataElement = createDataElement(_path, dataType);
258 if (_dataElement.valid())
261 SGSharedPtr<HLAArrayDataElement> arrayDataElement;
262 arrayDataElement = new HLAArrayDataElement(&dataType);
263 arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_path, _pathElementMap));
264 arrayDataElement->setNumElements(dataType.getNumElements());
266 _dataElement = arrayDataElement;
269 virtual void apply(const HLAVariableArrayDataType& dataType)
271 _dataElement = createDataElement(_path, dataType);
272 if (_dataElement.valid())
275 SGSharedPtr<HLAArrayDataElement> arrayDataElement;
276 arrayDataElement = new HLAArrayDataElement(&dataType);
277 arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_path, _pathElementMap));
279 _dataElement = arrayDataElement;
282 virtual void apply(const HLAEnumeratedDataType& dataType)
284 _dataElement = createDataElement(_path, dataType);
285 if (_dataElement.valid())
288 HLADataElementFactoryVisitor::apply(dataType);
291 virtual void apply(const HLAFixedRecordDataType& dataType)
293 _dataElement = createDataElement(_path, dataType);
294 if (_dataElement.valid())
297 SGSharedPtr<HLAFixedRecordDataElement> recordDataElement;
298 recordDataElement = new HLAFixedRecordDataElement(&dataType);
300 unsigned numFields = dataType.getNumFields();
301 for (unsigned i = 0; i < numFields; ++i) {
303 _path.push_back(HLADataElement::PathElement(dataType.getFieldName(i)));
305 dataType.getFieldDataType(i)->accept(*this);
306 recordDataElement->setField(i, _dataElement.release());
310 _dataElement = recordDataElement;
313 class VariantRecordDataElementFactory : public HLAVariantRecordDataElement::DataElementFactory {
315 VariantRecordDataElementFactory(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) :
318 for (HLAPathElementMap::const_iterator i = pathElementMap.lower_bound(path);
319 i != pathElementMap.end(); ++i) {
320 if (i->first.begin() != std::search(i->first.begin(), i->first.end(),
321 path.begin(), path.end()))
323 _pathElementMap.insert(*i);
326 virtual HLADataElement* createElement(const HLAVariantRecordDataElement& element, unsigned index)
328 const HLAVariantRecordDataType* dataType = element.getDataType();
331 const HLADataType* alternativeDataType = element.getAlternativeDataType();
332 if (!alternativeDataType)
334 HLADataElement::Path path = _path;
335 path.push_back(HLADataElement::PathElement(dataType->getAlternativeName(index)));
336 DataElementFactoryVisitor visitor(path, _pathElementMap);
337 alternativeDataType->accept(visitor);
338 return visitor._dataElement.release();
341 HLADataElement::Path _path;
342 HLAPathElementMap _pathElementMap;
345 virtual void apply(const HLAVariantRecordDataType& dataType)
347 _dataElement = createDataElement(_path, dataType);
348 if (_dataElement.valid())
351 SGSharedPtr<HLAVariantRecordDataElement> variantRecordDataElement;
352 variantRecordDataElement = new HLAVariantRecordDataElement(&dataType);
353 variantRecordDataElement->setDataElementFactory(new VariantRecordDataElementFactory(_path, _pathElementMap));
355 _dataElement = variantRecordDataElement;
359 SGSharedPtr<HLADataElement> createDataElement(const HLADataElement::Path& path, const HLADataType& dataType)
361 HLAPathElementMap::const_iterator i = _pathElementMap.find(path);
362 if (i == _pathElementMap.end()) {
363 SG_LOG(SG_IO, SG_WARN, "No dataElement provided for \""
364 << HLADataElement::toString(path) << "\".");
368 SGSharedPtr<HLADataElement> dataElement = i->second.getDataElement(path);
369 if (!dataElement->setDataType(&dataType)) {
370 SG_LOG(SG_IO, SG_ALERT, "Cannot set data type for data element at \""
371 << HLADataElement::toString(path) << "\"!");
374 SG_LOG(SG_IO, SG_DEBUG, "Using provided dataElement for \""
375 << HLADataElement::toString(path) << "\".");
379 const HLAPathElementMap& _pathElementMap;
380 HLADataElement::Path _path;
384 HLAObjectInstance::setAttribute(unsigned index, const HLAPathElementMap& pathElementMap)
386 const HLADataType* dataType = getAttributeDataType(index);
388 SG_LOG(SG_IO, SG_ALERT, "Cannot get attribute data type for setting attribute \""
389 << getAttributeName(index) << "\" at index " << index << "!");
393 SG_LOG(SG_IO, SG_DEBUG, "Setting DataElement for attribute \""
394 << getAttributeName(index) << "\".");
396 DataElementFactoryVisitor visitor(pathElementMap);
397 dataType->accept(visitor);
398 setAttributeDataElement(index, visitor.getDataElement());
402 HLAObjectInstance::setAttributes(const HLAAttributePathElementMap& attributePathElementMap)
404 for (HLAAttributePathElementMap::const_iterator i = attributePathElementMap.begin();
405 i != attributePathElementMap.end(); ++i) {
406 setAttribute(i->first, i->second);
411 HLAObjectInstance::registerInstance()
413 if (_rtiObjectInstance.valid()) {
414 SG_LOG(SG_IO, SG_ALERT, "Trying to register object " << getName() << " already known to the RTI!");
417 if (!_objectClass.valid()) {
418 SG_LOG(SG_IO, SG_ALERT, "Could not register object with unknown object class!");
421 // This error must have been flagged before
422 if (!_objectClass->_rtiObjectClass.valid())
424 _setRTIObjectInstance(_objectClass->_rtiObjectClass->registerObjectInstance(this));
425 if (!_rtiObjectInstance.valid()) {
426 SG_LOG(SG_IO, SG_ALERT, "Could not register object at the RTI!");
429 _objectClass->_registerInstance(this);
433 HLAObjectInstance::deleteInstance(const RTIData& tag)
435 if (!_rtiObjectInstance.valid()) {
436 SG_LOG(SG_IO, SG_ALERT, "Trying to delete inactive object!");
439 if (!_objectClass.valid())
441 _objectClass->_deleteInstance(*this);
442 _rtiObjectInstance->deleteObjectInstance(tag);
446 HLAObjectInstance::updateAttributeValues(const RTIData& tag)
448 if (_attributeCallback.valid())
449 _attributeCallback->updateAttributeValues(*this, tag);
450 if (_updateCallback.valid()) {
451 _updateCallback->updateAttributeValues(*this, tag);
453 encodeAttributeValues();
454 sendAttributeValues(tag);
459 HLAObjectInstance::updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag)
461 if (_attributeCallback.valid())
462 _attributeCallback->updateAttributeValues(*this, tag);
463 if (_updateCallback.valid()) {
464 _updateCallback->updateAttributeValues(*this, timeStamp, tag);
466 encodeAttributeValues();
467 sendAttributeValues(timeStamp, tag);
472 HLAObjectInstance::encodeAttributeValues()
474 unsigned numAttributes = _attributeVector.size();
475 for (unsigned i = 0; i < numAttributes;++i) {
476 if (!_attributeVector[i]._unconditionalUpdate)
478 encodeAttributeValue(i);
483 HLAObjectInstance::encodeAttributeValue(unsigned index)
485 if (!_rtiObjectInstance.valid()) {
486 SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
489 const HLADataElement* dataElement = getAttributeDataElement(index);
492 _rtiObjectInstance->encodeAttributeData(index, *dataElement);
496 HLAObjectInstance::sendAttributeValues(const RTIData& tag)
498 if (!_rtiObjectInstance.valid()) {
499 SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
502 _rtiObjectInstance->updateAttributeValues(tag);
506 HLAObjectInstance::sendAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag)
508 if (!_rtiObjectInstance.valid()) {
509 SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
512 _rtiObjectInstance->updateAttributeValues(timeStamp, tag);
516 HLAObjectInstance::reflectAttributeValues(const HLAIndexList& indexList, const RTIData& tag)
518 for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i)
519 reflectAttributeValue(*i, tag);
523 HLAObjectInstance::reflectAttributeValues(const HLAIndexList& indexList,
524 const SGTimeStamp& timeStamp, const RTIData& tag)
526 for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i)
527 reflectAttributeValue(*i, timeStamp, tag);
531 HLAObjectInstance::reflectAttributeValue(unsigned index, const RTIData& tag)
533 HLADataElement* dataElement = getAttributeDataElement(index);
536 _rtiObjectInstance->decodeAttributeData(index, *dataElement);
540 HLAObjectInstance::reflectAttributeValue(unsigned index, const SGTimeStamp& timeStamp, const RTIData& tag)
542 HLADataElement* dataElement = getAttributeDataElement(index);
545 // dataElement->setTimeStamp(timeStamp);
546 _rtiObjectInstance->decodeAttributeData(index, *dataElement);
550 HLAObjectInstance::_setRTIObjectInstance(RTIObjectInstance* rtiObjectInstance)
552 _rtiObjectInstance = rtiObjectInstance;
553 _rtiObjectInstance->setObjectInstance(this);
554 _name = _rtiObjectInstance->getName();
556 unsigned numAttributes = getNumAttributes();
557 _attributeVector.resize(numAttributes);
558 for (unsigned i = 0; i < numAttributes; ++i) {
559 HLAUpdateType updateType = getObjectClass()->getAttributeUpdateType(i);
560 if (getAttributeOwned(i) && updateType != HLAUndefinedUpdate) {
561 _attributeVector[i]._enabledUpdate = true;
562 _attributeVector[i]._unconditionalUpdate = (updateType == HLAPeriodicUpdate);
563 // In case of an owned attribute, now encode its value
564 encodeAttributeValue(i);
566 _attributeVector[i]._enabledUpdate = false;
567 _attributeVector[i]._unconditionalUpdate = false;
571 // This makes sense with any new object. Even if we registered one, there might be unpublished attributes.
572 HLAIndexList indexList;
573 for (unsigned i = 0; i < numAttributes; ++i) {
574 HLAUpdateType updateType = getObjectClass()->getAttributeUpdateType(i);
575 if (getAttributeOwned(i))
577 if (updateType == HLAUndefinedUpdate)
579 if (updateType == HLAPeriodicUpdate)
581 indexList.push_back(i);
583 _rtiObjectInstance->requestObjectAttributeValueUpdate(indexList);
587 HLAObjectInstance::_clearRTIObjectInstance()
589 if (!_rtiObjectInstance.valid())
592 for (unsigned i = 0; i < _attributeVector.size(); ++i) {
593 _attributeVector[i]._enabledUpdate = false;
594 _attributeVector[i]._unconditionalUpdate = false;
597 _rtiObjectInstance->setObjectInstance(0);
598 _rtiObjectInstance = 0;
602 HLAObjectInstance::_removeInstance(const RTIData& tag)
604 if (!_objectClass.valid())
606 _objectClass->_removeInstance(*this, tag);
610 HLAObjectInstance::_reflectAttributeValues(const HLAIndexList& indexList, const RTIData& tag)
612 if (_reflectCallback.valid()) {
613 _reflectCallback->reflectAttributeValues(*this, indexList, tag);
614 } else if (_attributeCallback.valid()) {
615 reflectAttributeValues(indexList, tag);
617 RTIIndexDataPairList dataPairList;
618 for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i) {
619 dataPairList.push_back(RTIIndexDataPair());
620 dataPairList.back().first = *i;
621 getAttributeData(*i, dataPairList.back().second);
623 _attributeCallback->reflectAttributeValues(*this, dataPairList, tag);
625 reflectAttributeValues(indexList, tag);
630 HLAObjectInstance::_reflectAttributeValues(const HLAIndexList& indexList, const SGTimeStamp& timeStamp, const RTIData& tag)
632 if (_reflectCallback.valid()) {
633 _reflectCallback->reflectAttributeValues(*this, indexList, timeStamp, tag);
634 } else if (_attributeCallback.valid()) {
635 reflectAttributeValues(indexList, timeStamp, tag);
637 RTIIndexDataPairList dataPairList;
638 for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i) {
639 dataPairList.push_back(RTIIndexDataPair());
640 dataPairList.back().first = *i;
641 getAttributeData(*i, dataPairList.back().second);
643 _attributeCallback->reflectAttributeValues(*this, dataPairList, timeStamp, tag);
645 reflectAttributeValues(indexList, timeStamp, tag);
649 } // namespace simgear