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();
160 HLAObjectInstance::getDataElementIndex(HLADataElementIndex& index, const std::string& path) const
162 HLAObjectClass* objectClass = getObjectClass().get();
164 SG_LOG(SG_IO, SG_ALERT, "Could not get the data element index of an object instance with unknown class!");
167 return objectClass->getDataElementIndex(index, path);
171 HLAObjectInstance::getDataElementIndex(const std::string& path) const
173 HLADataElementIndex dataElementIndex;
174 getDataElementIndex(dataElementIndex, path);
175 return dataElementIndex;
179 HLAObjectInstance::getAttributeDataElement(const HLADataElementIndex& index)
183 HLADataElement* dataElement = getAttributeDataElement(index[0]);
186 return dataElement->getDataElement(index.begin() + 1, index.end());
189 const HLADataElement*
190 HLAObjectInstance::getAttributeDataElement(const HLADataElementIndex& index) const
194 const HLADataElement* dataElement = getAttributeDataElement(index[0]);
197 return dataElement->getDataElement(index.begin() + 1, index.end());
201 HLAObjectInstance::setAttributeDataElement(const HLADataElementIndex& index, const SGSharedPtr<HLADataElement>& dataElement)
205 if (index.size() == 1) {
206 if (!getAttributeDataType(index[0]))
208 if (dataElement.valid() && !dataElement->setDataType(getAttributeDataType(index[0])))
210 setAttributeDataElement(index[0], dataElement);
212 SGSharedPtr<HLADataElement> attributeDataElement = getAttributeDataElement(index[0]);
213 if (!attributeDataElement.valid()) {
214 createAndSetAttributeDataElement(index[0]);
215 attributeDataElement = getAttributeDataElement(index[0]);
217 if (!attributeDataElement.valid())
219 attributeDataElement->setDataElement(index.begin() + 1, index.end(), dataElement.get());
224 HLAObjectInstance::getAttributeDataElement(const std::string& path)
226 HLADataElementIndex index;
227 if (!getDataElementIndex(index, path))
229 return getAttributeDataElement(index);
232 const HLADataElement*
233 HLAObjectInstance::getAttributeDataElement(const std::string& path) const
235 HLADataElementIndex index;
236 if (!getDataElementIndex(index, path))
238 return getAttributeDataElement(index);
242 HLAObjectInstance::setAttributeDataElement(const std::string& path, const SGSharedPtr<HLADataElement>& dataElement)
244 HLADataElementIndex index;
245 if (!getDataElementIndex(index, path))
247 setAttributeDataElement(index, dataElement);
251 HLAObjectInstance::discoverInstance(const RTIData& tag)
253 HLAObjectClass* objectClass = getObjectClass().get();
255 SG_LOG(SG_IO, SG_ALERT, "Could not discover instance of unknown object class!");
258 objectClass->discoverInstance(*this, tag);
262 HLAObjectInstance::removeInstance(const RTIData& tag)
264 HLAObjectClass* objectClass = getObjectClass().get();
266 SG_LOG(SG_IO, SG_ALERT, "Could not remove instance of unknown object class!");
269 objectClass->removeInstance(*this, tag);
273 HLAObjectInstance::registerInstance()
275 registerInstance(_objectClass.get());
279 HLAObjectInstance::registerInstance(HLAObjectClass* objectClass)
281 if (_rtiObjectInstance.valid()) {
282 SG_LOG(SG_IO, SG_ALERT, "Trying to register object " << getName() << " already known to the RTI!");
286 SG_LOG(SG_IO, SG_ALERT, "Could not register object with unknown object class!");
289 if (_objectClass.valid() && objectClass != _objectClass.get()) {
290 SG_LOG(SG_IO, SG_ALERT, "Could not change object class while registering!");
293 _objectClass = objectClass;
294 _federate = _objectClass->_federate;
295 // This error must have been flagged before
296 if (!_objectClass->_rtiObjectClass.valid())
298 _setRTIObjectInstance(_objectClass->_rtiObjectClass->registerObjectInstance(this));
299 if (!_rtiObjectInstance.valid()) {
300 SG_LOG(SG_IO, SG_ALERT, "Could not register object at the RTI!");
303 _objectClass->_registerInstance(this);
307 HLAObjectInstance::deleteInstance(const RTIData& tag)
309 if (!_rtiObjectInstance.valid()) {
310 SG_LOG(SG_IO, SG_ALERT, "Trying to delete inactive object!");
313 if (!_objectClass.valid())
315 _objectClass->_deleteInstance(*this);
316 _rtiObjectInstance->deleteObjectInstance(tag);
320 HLAObjectInstance::createAttributeDataElements()
322 HLAObjectClass* objectClass = getObjectClass().get();
324 SG_LOG(SG_IO, SG_ALERT, "Could not create data elements for instance of unknown object class!");
327 objectClass->createAttributeDataElements(*this);
331 HLAObjectInstance::createAndSetAttributeDataElement(unsigned index)
333 if (getAttributeDataElement(index)) {
334 SG_LOG(SG_IO, SG_DEBUG, "Attribute data element for attribute \""
335 << getAttributeName(index) << "\" is already set.");
338 SGSharedPtr<HLADataElement> dataElement = createAttributeDataElement(index);
339 setAttributeDataElement(index, dataElement);
343 HLAObjectInstance::createAttributeDataElement(unsigned index)
345 HLAObjectClass* objectClass = getObjectClass().get();
347 SG_LOG(SG_IO, SG_ALERT, "Could not create data element for instance of unknown object class!");
350 return objectClass->createAttributeDataElement(*this, index);
354 HLAObjectInstance::updateAttributeValues(const RTIData& tag)
356 if (_updateCallback.valid()) {
357 _updateCallback->updateAttributeValues(*this, tag);
359 encodeAttributeValues();
360 sendAttributeValues(tag);
365 HLAObjectInstance::updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag)
367 if (_updateCallback.valid()) {
368 _updateCallback->updateAttributeValues(*this, timeStamp, tag);
370 encodeAttributeValues();
371 sendAttributeValues(timeStamp, tag);
376 HLAObjectInstance::encodeAttributeValues()
378 unsigned numAttributes = _attributeVector.size();
379 for (unsigned i = 0; i < numAttributes;++i) {
380 if (_attributeVector[i]._unconditionalUpdate) {
381 encodeAttributeValue(i);
382 } else if (_attributeVector[i]._enabledUpdate) {
383 const HLADataElement* dataElement = getAttributeDataElement(i);
384 if (dataElement && dataElement->getDirty())
385 encodeAttributeValue(i);
391 HLAObjectInstance::encodeAttributeValue(unsigned index)
393 if (!_rtiObjectInstance.valid()) {
394 SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
397 HLADataElement* dataElement = getAttributeDataElement(index);
400 _rtiObjectInstance->encodeAttributeData(index, *dataElement);
401 dataElement->setDirty(false);
405 HLAObjectInstance::sendAttributeValues(const RTIData& tag)
407 if (!_rtiObjectInstance.valid()) {
408 SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
411 _rtiObjectInstance->updateAttributeValues(tag);
415 HLAObjectInstance::sendAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag)
417 if (!_rtiObjectInstance.valid()) {
418 SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
421 _rtiObjectInstance->updateAttributeValues(timeStamp, tag);
425 HLAObjectInstance::reflectAttributeValues(const HLAIndexList& indexList, const RTIData& tag)
427 for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i)
428 reflectAttributeValue(*i, tag);
432 HLAObjectInstance::reflectAttributeValues(const HLAIndexList& indexList,
433 const SGTimeStamp& timeStamp, const RTIData& tag)
435 for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i)
436 reflectAttributeValue(*i, timeStamp, tag);
440 HLAObjectInstance::reflectAttributeValue(unsigned index, const RTIData& tag)
442 HLADataElement* dataElement = getAttributeDataElement(index);
445 dataElement->setTimeStampValid(false);
446 _rtiObjectInstance->decodeAttributeData(index, *dataElement);
450 HLAObjectInstance::reflectAttributeValue(unsigned index, const SGTimeStamp& timeStamp, const RTIData& tag)
452 HLADataElement* dataElement = getAttributeDataElement(index);
455 dataElement->setTimeStamp(timeStamp);
456 dataElement->setTimeStampValid(true);
457 _rtiObjectInstance->decodeAttributeData(index, *dataElement);
461 HLAObjectInstance::_setRTIObjectInstance(RTIObjectInstance* rtiObjectInstance)
463 if (!_objectClass.valid())
466 _rtiObjectInstance = rtiObjectInstance;
467 _rtiObjectInstance->setObjectInstance(this);
468 _name = _rtiObjectInstance->getName();
470 unsigned numAttributes = getNumAttributes();
471 _attributeVector.resize(numAttributes);
472 for (unsigned i = 0; i < numAttributes; ++i) {
473 HLAUpdateType updateType = _objectClass->getAttributeUpdateType(i);
474 if (getAttributeOwned(i) && updateType != HLAUndefinedUpdate) {
475 _attributeVector[i]._enabledUpdate = true;
476 _attributeVector[i]._unconditionalUpdate = (updateType == HLAPeriodicUpdate);
477 // In case of an owned attribute, now encode its value
478 encodeAttributeValue(i);
480 _attributeVector[i]._enabledUpdate = false;
481 _attributeVector[i]._unconditionalUpdate = false;
485 // This makes sense with any new object. Even if we registered one, there might be unpublished attributes.
486 HLAIndexList indexList;
487 for (unsigned i = 0; i < numAttributes; ++i) {
488 HLAUpdateType updateType = _objectClass->getAttributeUpdateType(i);
489 if (getAttributeOwned(i))
491 if (updateType == HLAUndefinedUpdate)
493 if (updateType == HLAPeriodicUpdate)
495 indexList.push_back(i);
497 _rtiObjectInstance->requestObjectAttributeValueUpdate(indexList);
501 HLAObjectInstance::_clearRTIObjectInstance()
503 if (!_rtiObjectInstance.valid())
506 for (unsigned i = 0; i < _attributeVector.size(); ++i) {
507 _attributeVector[i]._enabledUpdate = false;
508 _attributeVector[i]._unconditionalUpdate = false;
511 _rtiObjectInstance->setObjectInstance(0);
512 _rtiObjectInstance = 0;
516 HLAObjectInstance::_removeInstance(const RTIData& tag)
518 if (!_objectClass.valid())
520 _objectClass->_removeInstance(*this, tag);
524 HLAObjectInstance::_reflectAttributeValues(const HLAIndexList& indexList, const RTIData& tag)
526 if (_reflectCallback.valid()) {
527 _reflectCallback->reflectAttributeValues(*this, indexList, tag);
529 reflectAttributeValues(indexList, tag);
534 HLAObjectInstance::_reflectAttributeValues(const HLAIndexList& indexList, const SGTimeStamp& timeStamp, const RTIData& tag)
536 if (_reflectCallback.valid()) {
537 _reflectCallback->reflectAttributeValues(*this, indexList, timeStamp, tag);
539 reflectAttributeValues(indexList, timeStamp, tag);
543 } // namespace simgear