]> git.mxchange.org Git - simgear.git/blob - simgear/hla/HLAObjectInstance.cxx
Fix HLAFederate for readXML API change
[simgear.git] / simgear / hla / HLAObjectInstance.cxx
1 // Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
2 //
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.
7 //
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.
12 //
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.
16 //
17
18 #ifdef HAVE_CONFIG_H
19 #  include <simgear_config.h>
20 #endif
21
22 #include <simgear/compiler.h>
23
24 #include "HLAObjectInstance.hxx"
25
26 #include <algorithm>
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"
38
39 namespace simgear {
40
41 HLAObjectInstance::UpdateCallback::~UpdateCallback()
42 {
43 }
44
45 HLAObjectInstance::ReflectCallback::~ReflectCallback()
46 {
47 }
48
49 HLAObjectInstance::HLAObjectInstance(HLAObjectClass* objectClass) :
50     _objectClass(objectClass)
51 {
52     if (objectClass)
53         _federate = objectClass->_federate;
54 }
55
56 HLAObjectInstance::~HLAObjectInstance()
57 {
58     _clearRTIObjectInstance();
59 }
60
61 const std::string&
62 HLAObjectInstance::getName() const
63 {
64     return _name;
65 }
66
67 const SGWeakPtr<HLAFederate>&
68 HLAObjectInstance::getFederate() const
69 {
70     return _federate;
71 }
72
73 const SGSharedPtr<HLAObjectClass>&
74 HLAObjectInstance::getObjectClass() const
75 {
76     return _objectClass;
77 }
78
79 unsigned
80 HLAObjectInstance::getNumAttributes() const
81 {
82     if (!_objectClass.valid())
83         return 0;
84     return _objectClass->getNumAttributes();
85 }
86
87 unsigned
88 HLAObjectInstance::getAttributeIndex(const std::string& name) const
89 {
90     if (!_objectClass.valid())
91         return ~0u;
92     return _objectClass->getAttributeIndex(name);
93 }
94
95 std::string
96 HLAObjectInstance::getAttributeName(unsigned index) const
97 {
98     if (!_objectClass.valid())
99         return std::string();
100     return _objectClass->getAttributeName(index);
101 }
102
103 bool
104 HLAObjectInstance::getAttributeOwned(unsigned index) const
105 {
106     if (!_rtiObjectInstance.valid())
107         return false;
108     return _rtiObjectInstance->getAttributeOwned(index);
109 }
110
111 const HLADataType*
112 HLAObjectInstance::getAttributeDataType(unsigned index) const
113 {
114     if (!_objectClass.valid())
115         return 0;
116     return _objectClass->getAttributeDataType(index);
117 }
118
119 HLADataElement*
120 HLAObjectInstance::getAttributeDataElement(unsigned index)
121 {
122     if (_attributeVector.size() <= index)
123         return 0;
124     return _attributeVector[index]._dataElement.get();
125 }
126
127 const HLADataElement*
128 HLAObjectInstance::getAttributeDataElement(unsigned index) const
129 {
130     if (_attributeVector.size() <= index)
131         return 0;
132     return _attributeVector[index]._dataElement.get();
133 }
134
135 bool
136 HLAObjectInstance::getAttributeData(unsigned index, RTIData& data) const
137 {
138     if (!_rtiObjectInstance.valid()) {
139         SG_LOG(SG_IO, SG_ALERT, "Trying to get raw attribute data without rti object instance for \"" << getName() << "\"!");
140         return false;
141     }
142     return _rtiObjectInstance->getAttributeData(index, data);
143 }
144
145 void
146 HLAObjectInstance::setAttributeDataElement(unsigned index, const SGSharedPtr<HLADataElement>& dataElement)
147 {
148     unsigned numAttributes = getNumAttributes();
149     if (numAttributes <= index)
150         return;
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();
157 }
158
159 bool
160 HLAObjectInstance::getDataElementIndex(HLADataElementIndex& index, const std::string& path) const
161 {
162     HLAObjectClass* objectClass = getObjectClass().get();
163     if (!objectClass) {
164         SG_LOG(SG_IO, SG_ALERT, "Could not get the data element index of an object instance with unknown class!");
165         return false;
166     }
167     return objectClass->getDataElementIndex(index, path);
168 }
169
170 HLADataElementIndex
171 HLAObjectInstance::getDataElementIndex(const std::string& path) const
172 {
173     HLADataElementIndex dataElementIndex;
174     getDataElementIndex(dataElementIndex, path);
175     return dataElementIndex;
176 }
177
178 HLADataElement*
179 HLAObjectInstance::getAttributeDataElement(const HLADataElementIndex& index)
180 {
181     if (index.empty())
182         return 0;
183     HLADataElement* dataElement = getAttributeDataElement(index[0]);
184     if (!dataElement)
185         return 0;
186     return dataElement->getDataElement(index.begin() + 1, index.end());
187 }
188
189 const HLADataElement*
190 HLAObjectInstance::getAttributeDataElement(const HLADataElementIndex& index) const
191 {
192     if (index.empty())
193         return 0;
194     const HLADataElement* dataElement = getAttributeDataElement(index[0]);
195     if (!dataElement)
196         return 0;
197     return dataElement->getDataElement(index.begin() + 1, index.end());
198 }
199
200 void
201 HLAObjectInstance::setAttributeDataElement(const HLADataElementIndex& index, const SGSharedPtr<HLADataElement>& dataElement)
202 {
203     if (index.empty())
204         return;
205     if (index.size() == 1) {
206         if (!getAttributeDataType(index[0]))
207             return;
208         if (dataElement.valid() && !dataElement->setDataType(getAttributeDataType(index[0])))
209             return;
210         setAttributeDataElement(index[0], dataElement);
211     } else {
212         SGSharedPtr<HLADataElement> attributeDataElement = getAttributeDataElement(index[0]);
213         if (!attributeDataElement.valid()) {
214             createAndSetAttributeDataElement(index[0]);
215             attributeDataElement = getAttributeDataElement(index[0]);
216         }
217         if (!attributeDataElement.valid())
218             return;
219         attributeDataElement->setDataElement(index.begin() + 1, index.end(), dataElement.get());
220     }
221 }
222
223 HLADataElement*
224 HLAObjectInstance::getAttributeDataElement(const std::string& path)
225 {
226     HLADataElementIndex index;
227     if (!getDataElementIndex(index, path))
228         return 0;
229     return getAttributeDataElement(index); 
230 }
231
232 const HLADataElement*
233 HLAObjectInstance::getAttributeDataElement(const std::string& path) const
234 {
235     HLADataElementIndex index;
236     if (!getDataElementIndex(index, path))
237         return 0;
238     return getAttributeDataElement(index); 
239 }
240
241 void
242 HLAObjectInstance::setAttributeDataElement(const std::string& path, const SGSharedPtr<HLADataElement>& dataElement)
243 {
244     HLADataElementIndex index;
245     if (!getDataElementIndex(index, path))
246         return;
247     setAttributeDataElement(index, dataElement); 
248 }
249
250 void
251 HLAObjectInstance::discoverInstance(const RTIData& tag)
252 {
253     HLAObjectClass* objectClass = getObjectClass().get();
254     if (!objectClass) {
255         SG_LOG(SG_IO, SG_ALERT, "Could not discover instance of unknown object class!");
256         return;
257     }
258     objectClass->discoverInstance(*this, tag);
259 }
260
261 void
262 HLAObjectInstance::removeInstance(const RTIData& tag)
263 {
264     HLAObjectClass* objectClass = getObjectClass().get();
265     if (!objectClass) {
266         SG_LOG(SG_IO, SG_ALERT, "Could not remove instance of unknown object class!");
267         return;
268     }
269     objectClass->removeInstance(*this, tag);
270 }
271
272 void
273 HLAObjectInstance::registerInstance()
274 {
275     registerInstance(_objectClass.get());
276 }
277
278 void
279 HLAObjectInstance::registerInstance(HLAObjectClass* objectClass)
280 {
281     if (_rtiObjectInstance.valid()) {
282         SG_LOG(SG_IO, SG_ALERT, "Trying to register object " << getName() << " already known to the RTI!");
283         return;
284     }
285     if (!objectClass) {
286         SG_LOG(SG_IO, SG_ALERT, "Could not register object with unknown object class!");
287         return;
288     }
289     if (_objectClass.valid() && objectClass != _objectClass.get()) {
290         SG_LOG(SG_IO, SG_ALERT, "Could not change object class while registering!");
291         return;
292     }
293     _objectClass = objectClass;
294     _federate = _objectClass->_federate;
295     // This error must have been flagged before
296     if (!_objectClass->_rtiObjectClass.valid())
297         return;
298     _setRTIObjectInstance(_objectClass->_rtiObjectClass->registerObjectInstance(this));
299     if (!_rtiObjectInstance.valid()) {
300         SG_LOG(SG_IO, SG_ALERT, "Could not register object at the RTI!");
301         return;
302     }
303     _objectClass->_registerInstance(this);
304 }
305
306 void
307 HLAObjectInstance::deleteInstance(const RTIData& tag)
308 {
309     if (!_rtiObjectInstance.valid()) {
310         SG_LOG(SG_IO, SG_ALERT, "Trying to delete inactive object!");
311         return;
312     }
313     if (!_objectClass.valid())
314         return;
315     _objectClass->_deleteInstance(*this);
316     _rtiObjectInstance->deleteObjectInstance(tag);
317 }
318
319 void
320 HLAObjectInstance::createAttributeDataElements()
321 {
322     HLAObjectClass* objectClass = getObjectClass().get();
323     if (!objectClass) {
324         SG_LOG(SG_IO, SG_ALERT, "Could not create data elements for instance of unknown object class!");
325         return;
326     }
327     objectClass->createAttributeDataElements(*this);
328 }
329
330 void
331 HLAObjectInstance::createAndSetAttributeDataElement(unsigned index)
332 {
333     if (getAttributeDataElement(index)) {
334         SG_LOG(SG_IO, SG_DEBUG, "Attribute data element for attribute \""
335                << getAttributeName(index) << "\" is already set.");
336         return;
337     }
338     SGSharedPtr<HLADataElement> dataElement = createAttributeDataElement(index);
339     setAttributeDataElement(index, dataElement);
340 }
341
342 HLADataElement*
343 HLAObjectInstance::createAttributeDataElement(unsigned index)
344 {
345     HLAObjectClass* objectClass = getObjectClass().get();
346     if (!objectClass) {
347         SG_LOG(SG_IO, SG_ALERT, "Could not create data element for instance of unknown object class!");
348         return 0;
349     }
350     return objectClass->createAttributeDataElement(*this, index);
351 }
352
353 void
354 HLAObjectInstance::updateAttributeValues(const RTIData& tag)
355 {
356     if (_updateCallback.valid()) {
357         _updateCallback->updateAttributeValues(*this, tag);
358     } else {
359         encodeAttributeValues();
360         sendAttributeValues(tag);
361     }
362 }
363
364 void
365 HLAObjectInstance::updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag)
366 {
367     if (_updateCallback.valid()) {
368         _updateCallback->updateAttributeValues(*this, timeStamp, tag);
369     } else {
370         encodeAttributeValues();
371         sendAttributeValues(timeStamp, tag);
372     }
373 }
374
375 void
376 HLAObjectInstance::encodeAttributeValues()
377 {
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);
386         }
387     }
388 }
389
390 void
391 HLAObjectInstance::encodeAttributeValue(unsigned index)
392 {
393     if (!_rtiObjectInstance.valid()) {
394         SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
395         return;
396     }
397     HLADataElement* dataElement = getAttributeDataElement(index);
398     if (!dataElement)
399         return;
400     _rtiObjectInstance->encodeAttributeData(index, *dataElement);
401     dataElement->setDirty(false);
402 }
403
404 void
405 HLAObjectInstance::sendAttributeValues(const RTIData& tag)
406 {
407     if (!_rtiObjectInstance.valid()) {
408         SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
409         return;
410     }
411     _rtiObjectInstance->updateAttributeValues(tag);
412 }
413
414 void
415 HLAObjectInstance::sendAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag)
416 {
417     if (!_rtiObjectInstance.valid()) {
418         SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
419         return;
420     }
421     _rtiObjectInstance->updateAttributeValues(timeStamp, tag);
422 }
423
424 void
425 HLAObjectInstance::reflectAttributeValues(const HLAIndexList& indexList, const RTIData& tag)
426 {
427     for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i)
428         reflectAttributeValue(*i, tag);
429 }
430
431 void
432 HLAObjectInstance::reflectAttributeValues(const HLAIndexList& indexList,
433                                           const SGTimeStamp& timeStamp, const RTIData& tag)
434 {
435     for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i)
436         reflectAttributeValue(*i, timeStamp, tag);
437 }
438
439 void
440 HLAObjectInstance::reflectAttributeValue(unsigned index, const RTIData& tag)
441 {
442     HLADataElement* dataElement = getAttributeDataElement(index);
443     if (!dataElement)
444         return;
445     dataElement->setTimeStampValid(false);
446     _rtiObjectInstance->decodeAttributeData(index, *dataElement);
447 }
448
449 void
450 HLAObjectInstance::reflectAttributeValue(unsigned index, const SGTimeStamp& timeStamp, const RTIData& tag)
451 {
452     HLADataElement* dataElement = getAttributeDataElement(index);
453     if (!dataElement)
454         return;
455     dataElement->setTimeStamp(timeStamp);
456     dataElement->setTimeStampValid(true);
457     _rtiObjectInstance->decodeAttributeData(index, *dataElement);
458 }
459
460 void
461 HLAObjectInstance::_setRTIObjectInstance(RTIObjectInstance* rtiObjectInstance)
462 {
463     if (!_objectClass.valid())
464         return;
465
466     _rtiObjectInstance = rtiObjectInstance;
467     _rtiObjectInstance->setObjectInstance(this);
468     _name = _rtiObjectInstance->getName();
469
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);
479         } else {
480             _attributeVector[i]._enabledUpdate = false;
481             _attributeVector[i]._unconditionalUpdate = false;
482         }
483     }
484
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))
490             continue;
491         if (updateType == HLAUndefinedUpdate)
492             continue;
493         if (updateType == HLAPeriodicUpdate)
494             continue;
495         indexList.push_back(i);
496     }
497     _rtiObjectInstance->requestObjectAttributeValueUpdate(indexList);
498 }
499
500 void
501 HLAObjectInstance::_clearRTIObjectInstance()
502 {
503     if (!_rtiObjectInstance.valid())
504         return;
505
506     for (unsigned i = 0; i < _attributeVector.size(); ++i) {
507         _attributeVector[i]._enabledUpdate = false;
508         _attributeVector[i]._unconditionalUpdate = false;
509     }
510
511     _rtiObjectInstance->setObjectInstance(0);
512     _rtiObjectInstance = 0;
513 }
514
515 void
516 HLAObjectInstance::_removeInstance(const RTIData& tag)
517 {
518     if (!_objectClass.valid())
519         return;
520     _objectClass->_removeInstance(*this, tag);
521 }
522
523 void
524 HLAObjectInstance::_reflectAttributeValues(const HLAIndexList& indexList, const RTIData& tag)
525 {
526     if (_reflectCallback.valid()) {
527         _reflectCallback->reflectAttributeValues(*this, indexList, tag);
528     } else {
529         reflectAttributeValues(indexList, tag);
530     }
531 }
532
533 void
534 HLAObjectInstance::_reflectAttributeValues(const HLAIndexList& indexList, const SGTimeStamp& timeStamp, const RTIData& tag)
535 {
536     if (_reflectCallback.valid()) {
537         _reflectCallback->reflectAttributeValues(*this, indexList, timeStamp, tag);
538     } else {
539         reflectAttributeValues(indexList, timeStamp, tag);
540     }
541 }
542
543 } // namespace simgear