]> git.mxchange.org Git - simgear.git/blob - simgear/hla/HLAObjectInstance.cxx
Add an initial implementation of a rti/hla dispatcher.
[simgear.git] / simgear / hla / HLAObjectInstance.cxx
1 // Copyright (C) 2009 - 2010  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 #include "HLAObjectInstance.hxx"
19
20 #include <algorithm>
21 #include "HLAArrayDataElement.hxx"
22 #include "HLABasicDataElement.hxx"
23 #include "HLADataElement.hxx"
24 #include "HLAEnumeratedDataElement.hxx"
25 #include "HLAFixedRecordDataElement.hxx"
26 #include "HLAObjectClass.hxx"
27 #include "HLAVariantDataElement.hxx"
28 #include "RTIObjectClass.hxx"
29 #include "RTIObjectInstance.hxx"
30
31 namespace simgear {
32
33 HLAObjectInstance::HLAObjectInstance(HLAObjectClass* objectClass) :
34     _objectClass(objectClass)
35 {
36 }
37
38 HLAObjectInstance::HLAObjectInstance(HLAObjectClass* objectClass, RTIObjectInstance* rtiObjectInstance) :
39     _objectClass(objectClass),
40     _rtiObjectInstance(rtiObjectInstance)
41 {
42     _rtiObjectInstance->_hlaObjectInstance = this;
43     _name = _rtiObjectInstance->getName();
44 }
45
46 HLAObjectInstance::~HLAObjectInstance()
47 {
48 }
49
50 SGSharedPtr<HLAObjectClass>
51 HLAObjectInstance::getObjectClass() const
52 {
53     return _objectClass.lock();
54 }
55
56 unsigned
57 HLAObjectInstance::getNumAttributes() const
58 {
59     if (!_rtiObjectInstance.valid()) {
60         SG_LOG(SG_IO, SG_ALERT, "Trying to get number of attributes for inactive object!");
61         return 0;
62     }
63     return _rtiObjectInstance->getNumAttributes();
64 }
65
66 unsigned
67 HLAObjectInstance::getAttributeIndex(const std::string& name) const
68 {
69     if (!_rtiObjectInstance.valid()) {
70         SG_LOG(SG_IO, SG_ALERT, "Trying to get attribute index for inactive object!");
71         return 0;
72     }
73     return _rtiObjectInstance->getAttributeIndex(name);
74 }
75
76 std::string
77 HLAObjectInstance::getAttributeName(unsigned index) const
78 {
79     if (!_rtiObjectInstance.valid()) {
80         SG_LOG(SG_IO, SG_ALERT, "Trying to get attribute name for inactive object!");
81         return std::string();
82     }
83     return _rtiObjectInstance->getAttributeName(index);
84 }
85
86 const HLADataType*
87 HLAObjectInstance::getAttributeDataType(unsigned index) const
88 {
89     if (!_rtiObjectInstance.valid()) {
90         SG_LOG(SG_IO, SG_ALERT, "Trying to get attribute index for inactive object!");
91         return 0;
92     }
93     return _rtiObjectInstance->getAttributeDataType(index);
94 }
95
96 void
97 HLAObjectInstance::setAttributeDataElement(unsigned index, SGSharedPtr<HLADataElement> dataElement)
98 {
99     if (!_rtiObjectInstance.valid()) {
100         SG_LOG(SG_IO, SG_ALERT, "Trying to set data element for inactive object!");
101         return;
102     }
103     _rtiObjectInstance->setDataElement(index, dataElement);
104 }
105
106 HLADataElement*
107 HLAObjectInstance::getAttributeDataElement(unsigned index)
108 {
109     if (!_rtiObjectInstance.valid()) {
110         SG_LOG(SG_IO, SG_ALERT, "Trying to set data element for inactive object!");
111         return 0;
112     }
113     return _rtiObjectInstance->getDataElement(index);
114 }
115
116 const HLADataElement*
117 HLAObjectInstance::getAttributeDataElement(unsigned index) const
118 {
119     if (!_rtiObjectInstance.valid()) {
120         SG_LOG(SG_IO, SG_ALERT, "Trying to set data element for inactive object!");
121         return 0;
122     }
123     return _rtiObjectInstance->getDataElement(index);
124 }
125
126 class HLAObjectInstance::DataElementFactoryVisitor : public HLADataTypeVisitor {
127 public:
128     DataElementFactoryVisitor(const HLAPathElementMap& pathElementMap) :
129         _pathElementMap(pathElementMap)
130     { }
131     DataElementFactoryVisitor(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) :
132         _pathElementMap(pathElementMap),
133         _path(path)
134     { }
135     virtual ~DataElementFactoryVisitor() {}
136
137     virtual void apply(const HLADataType& dataType)
138     {
139         _dataElement = createDataElement(_path, dataType);
140         if (_dataElement.valid())
141             return;
142
143         SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Can not find a suitable data element for data type \""
144                << dataType.getName() << "\"");
145     }
146
147     virtual void apply(const HLAInt8DataType& dataType)
148     {
149         _dataElement = createDataElement(_path, dataType);
150         if (_dataElement.valid())
151             return;
152
153         _dataElement = new HLASCharDataElement(&dataType);
154     }
155     virtual void apply(const HLAUInt8DataType& dataType)
156     {
157         _dataElement = createDataElement(_path, dataType);
158         if (_dataElement.valid())
159             return;
160
161         _dataElement = new HLAUCharDataElement(&dataType);
162     }
163     virtual void apply(const HLAInt16DataType& dataType)
164     {
165         _dataElement = createDataElement(_path, dataType);
166         if (_dataElement.valid())
167             return;
168
169         _dataElement = new HLAShortDataElement(&dataType);
170     }
171     virtual void apply(const HLAUInt16DataType& dataType)
172     {
173         _dataElement = createDataElement(_path, dataType);
174         if (_dataElement.valid())
175             return;
176
177         _dataElement = new HLAUShortDataElement(&dataType);
178     }
179     virtual void apply(const HLAInt32DataType& dataType)
180     {
181         _dataElement = createDataElement(_path, dataType);
182         if (_dataElement.valid())
183             return;
184
185         _dataElement = new HLAIntDataElement(&dataType);
186     }
187     virtual void apply(const HLAUInt32DataType& dataType)
188     {
189         _dataElement = createDataElement(_path, dataType);
190         if (_dataElement.valid())
191             return;
192
193         _dataElement = new HLAUIntDataElement(&dataType);
194     }
195     virtual void apply(const HLAInt64DataType& dataType)
196     {
197         _dataElement = createDataElement(_path, dataType);
198         if (_dataElement.valid())
199             return;
200
201         _dataElement = new HLALongDataElement(&dataType);
202     }
203     virtual void apply(const HLAUInt64DataType& dataType)
204     {
205         _dataElement = createDataElement(_path, dataType);
206         if (_dataElement.valid())
207             return;
208
209         _dataElement = new HLAULongDataElement(&dataType);
210     }
211     virtual void apply(const HLAFloat32DataType& dataType)
212     {
213         _dataElement = createDataElement(_path, dataType);
214         if (_dataElement.valid())
215             return;
216
217         _dataElement = new HLAFloatDataElement(&dataType);
218     }
219     virtual void apply(const HLAFloat64DataType& dataType)
220     {
221         _dataElement = createDataElement(_path, dataType);
222         if (_dataElement.valid())
223             return;
224
225         _dataElement = new HLADoubleDataElement(&dataType);
226     }
227
228     class ArrayDataElementFactory : public HLAArrayDataElement::DataElementFactory {
229     public:
230         ArrayDataElementFactory(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) :
231             _path(path)
232         {
233             for (HLAPathElementMap::const_iterator i = pathElementMap.lower_bound(path);
234                  i != pathElementMap.end(); ++i) {
235                 if (i->first.begin() != std::search(i->first.begin(), i->first.end(),
236                                                     path.begin(), path.end()))
237                     break;
238                 _pathElementMap.insert(*i);
239             }
240         }
241         virtual HLADataElement* createElement(const HLAArrayDataElement& element, unsigned index)
242         {
243             const HLADataType* dataType = element.getElementDataType();
244             if (!dataType)
245                 return 0;
246             HLADataElement::Path path = _path;
247             path.push_back(HLADataElement::PathElement(index));
248             DataElementFactoryVisitor visitor(path, _pathElementMap);
249             dataType->accept(visitor);
250             return visitor._dataElement.release();
251         }
252     private:
253         HLADataElement::Path _path;
254         HLAPathElementMap _pathElementMap;
255     };
256
257     virtual void apply(const HLAFixedArrayDataType& dataType)
258     {
259         _dataElement = createDataElement(_path, dataType);
260         if (_dataElement.valid())
261             return;
262
263         SGSharedPtr<HLAArrayDataElement> arrayDataElement;
264         arrayDataElement = new HLAArrayDataElement(&dataType);
265         arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_path, _pathElementMap));
266         arrayDataElement->setNumElements(dataType.getNumElements());
267
268         _dataElement = arrayDataElement;
269     }
270
271     virtual void apply(const HLAVariableArrayDataType& dataType)
272     {
273         _dataElement = createDataElement(_path, dataType);
274         if (_dataElement.valid())
275             return;
276
277         SGSharedPtr<HLAArrayDataElement> arrayDataElement;
278         arrayDataElement = new HLAArrayDataElement(&dataType);
279         arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_path, _pathElementMap));
280
281         _dataElement = arrayDataElement;
282     }
283
284     virtual void apply(const HLAEnumeratedDataType& dataType)
285     {
286         _dataElement = createDataElement(_path, dataType);
287         if (_dataElement.valid())
288             return;
289
290         _dataElement = new HLAEnumeratedDataElement(&dataType);
291     }
292
293     virtual void apply(const HLAFixedRecordDataType& dataType)
294     {
295         _dataElement = createDataElement(_path, dataType);
296         if (_dataElement.valid())
297             return;
298
299         SGSharedPtr<HLAFixedRecordDataElement> recordDataElement;
300         recordDataElement = new HLAFixedRecordDataElement(&dataType);
301
302         unsigned numFields = dataType.getNumFields();
303         for (unsigned i = 0; i < numFields; ++i) {
304
305             _path.push_back(HLADataElement::PathElement(dataType.getFieldName(i)));
306
307             dataType.getFieldDataType(i)->accept(*this);
308             recordDataElement->setField(i, _dataElement.release());
309
310             _path.pop_back();
311         }
312         _dataElement = recordDataElement;
313     }
314
315     class VariantDataElementFactory : public HLAVariantDataElement::DataElementFactory {
316     public:
317         VariantDataElementFactory(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) :
318             _path(path)
319         {
320             for (HLAPathElementMap::const_iterator i = pathElementMap.lower_bound(path);
321                  i != pathElementMap.end(); ++i) {
322                 if (i->first.begin() != std::search(i->first.begin(), i->first.end(),
323                                                     path.begin(), path.end()))
324                     break;
325                 _pathElementMap.insert(*i);
326             }
327         }
328         virtual HLADataElement* createElement(const HLAVariantDataElement& element, unsigned index)
329         {
330             const HLAVariantDataType* dataType = element.getDataType();
331             if (!dataType)
332                 return 0;
333             const HLADataType* alternativeDataType = element.getAlternativeDataType();
334             if (!alternativeDataType)
335                 return 0;
336             HLADataElement::Path path = _path;
337             path.push_back(HLADataElement::PathElement(dataType->getAlternativeName(index)));
338             DataElementFactoryVisitor visitor(path, _pathElementMap);
339             alternativeDataType->accept(visitor);
340             return visitor._dataElement.release();
341         }
342     private:
343         HLADataElement::Path _path;
344         HLAPathElementMap _pathElementMap;
345     };
346
347     virtual void apply(const HLAVariantDataType& dataType)
348     {
349         _dataElement = createDataElement(_path, dataType);
350         if (_dataElement.valid())
351             return;
352
353         SGSharedPtr<HLAVariantDataElement> variantDataElement;
354         variantDataElement = new HLAVariantDataElement(&dataType);
355         variantDataElement->setDataElementFactory(new VariantDataElementFactory(_path, _pathElementMap));
356
357         _dataElement = variantDataElement;
358     }
359
360     const SGSharedPtr<HLADataElement>& getDataElement() const
361     { return _dataElement; }
362
363 private:
364     SGSharedPtr<HLADataElement> createDataElement(const HLADataElement::Path& path, const HLADataType& dataType)
365     {
366         HLAPathElementMap::const_iterator i = _pathElementMap.find(path);
367         if (i == _pathElementMap.end()) {
368             SG_LOG(SG_IO, SG_WARN, "No dataElement provided for \""
369                    << HLADataElement::toString(path) << "\".");
370
371             return 0;
372         }
373         SGSharedPtr<HLADataElement> dataElement = i->second.getDataElement(path);
374         if (!dataElement->setDataType(&dataType)) {
375             SG_LOG(SG_IO, SG_ALERT, "Cannot set data type for data element at \""
376                    << HLADataElement::toString(path) <<  "\"!");
377             return 0;
378         }
379         SG_LOG(SG_IO, SG_DEBUG, "Using provided dataElement for \""
380                << HLADataElement::toString(path) << "\".");
381         return dataElement;
382     }
383
384     SGSharedPtr<HLADataElement> _dataElement;
385     const HLAPathElementMap& _pathElementMap;
386     HLADataElement::Path _path;
387 };
388
389 void
390 HLAObjectInstance::setAttribute(unsigned index, const HLAPathElementMap& pathElementMap)
391 {
392     const HLADataType* dataType = getAttributeDataType(index);
393     if (!dataType) {
394         SG_LOG(SG_IO, SG_ALERT, "Cannot get attribute data type for setting attribute at index "
395                << index << "!");
396         return;
397     }
398
399     SG_LOG(SG_IO, SG_DEBUG, "Setting DataElement for attribute \""
400            << getAttributeName(index) << "\".");
401
402     DataElementFactoryVisitor visitor(pathElementMap);
403     dataType->accept(visitor);
404     setAttributeDataElement(index, visitor.getDataElement());
405 }
406
407 void
408 HLAObjectInstance::setAttributes(const HLAAttributePathElementMap& attributePathElementMap)
409 {
410     for (HLAAttributePathElementMap::const_iterator i = attributePathElementMap.begin();
411          i != attributePathElementMap.end(); ++i) {
412         setAttribute(i->first, i->second);
413     }
414 }
415
416 void
417 HLAObjectInstance::requestAttributeUpdate(unsigned index)
418 {
419     if (!_rtiObjectInstance.valid()) {
420         SG_LOG(SG_IO, SG_ALERT, "Trying to request attribute update for inactive object!");
421         return;
422     }
423     _rtiObjectInstance->setRequestAttributeUpdate(index, true);
424 }
425
426 void
427 HLAObjectInstance::requestAttributeUpdate()
428 {
429     if (!_rtiObjectInstance.valid()) {
430         SG_LOG(SG_IO, SG_ALERT, "Trying to request attribute update for inactive object!");
431         return;
432     }
433     _rtiObjectInstance->setRequestAttributeUpdate(true);
434 }
435
436 void
437 HLAObjectInstance::registerInstance()
438 {
439     if (_rtiObjectInstance.valid()) {
440         SG_LOG(SG_IO, SG_ALERT, "Trying to register object " << getName() << " already known to the RTI!");
441         return;
442     }
443     SGSharedPtr<HLAObjectClass> objectClass = _objectClass.lock();
444     if (!objectClass.valid()) {
445         SG_LOG(SG_IO, SG_ALERT, "Could not register object with unknown object class!");
446         return;
447     }
448     // This error must have been flagged before
449     if (!objectClass->_rtiObjectClass.valid())
450         return;
451     _rtiObjectInstance = objectClass->_rtiObjectClass->registerObjectInstance(this);
452     if (!_rtiObjectInstance.valid()) {
453         SG_LOG(SG_IO, SG_ALERT, "Could not register object at the RTI!");
454         return;
455     }
456     _name = _rtiObjectInstance->getName();
457     objectClass->registerInstance(*this);
458 }
459
460 void
461 HLAObjectInstance::deleteInstance(const RTIData& tag)
462 {
463     if (!_rtiObjectInstance.valid()) {
464         SG_LOG(SG_IO, SG_ALERT, "Trying to delete inactive object!");
465         return;
466     }
467     SGSharedPtr<HLAObjectClass> objectClass = _objectClass.lock();
468     if (!objectClass.valid())
469         return;
470     objectClass->deleteInstance(*this);
471     _rtiObjectInstance->deleteObjectInstance(tag);
472 }
473
474 void
475 HLAObjectInstance::localDeleteInstance()
476 {
477     if (!_rtiObjectInstance.valid()) {
478         SG_LOG(SG_IO, SG_ALERT, "Trying to delete inactive object!");
479         return;
480     }
481    _rtiObjectInstance->localDeleteObjectInstance();
482 }
483
484 void
485 HLAObjectInstance::updateAttributeValues(const RTIData& tag)
486 {
487     if (!_rtiObjectInstance.valid()) {
488         SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
489         return;
490     }
491     if (_attributeCallback.valid())
492         _attributeCallback->updateAttributeValues(*this, tag);
493     _rtiObjectInstance->updateAttributeValues(tag);
494 }
495
496 void
497 HLAObjectInstance::updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag)
498 {
499     if (!_rtiObjectInstance.valid()) {
500         SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
501         return;
502     }
503     if (_attributeCallback.valid())
504         _attributeCallback->updateAttributeValues(*this, tag);
505     _rtiObjectInstance->updateAttributeValues(timeStamp, tag);
506 }
507
508 void
509 HLAObjectInstance::reflectQueuedAttributeValues(const SGTimeStamp& timeStamp)
510 {
511     if (!_rtiObjectInstance.valid()) {
512         SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
513         return;
514     }
515     _rtiObjectInstance->reflectQueuedAttributeValues(timeStamp);
516 }
517
518 void
519 HLAObjectInstance::removeInstance(const RTIData& tag)
520 {
521     SGSharedPtr<HLAObjectClass> objectClass = _objectClass.lock();
522     if (!objectClass.valid())
523         return;
524     objectClass->removeInstanceCallback(*this, tag);
525 }
526
527 void
528 HLAObjectInstance::reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const RTIData& tag)
529 {
530     if (!_attributeCallback.valid())
531         return;
532     _attributeCallback->reflectAttributeValues(*this, dataPairList, tag);
533 }
534
535 void
536 HLAObjectInstance::reflectAttributeValues(const RTIIndexDataPairList& dataPairList,
537                                           const SGTimeStamp& timeStamp, const RTIData& tag)
538 {
539     if (!_attributeCallback.valid())
540         return;
541     _attributeCallback->reflectAttributeValues(*this, dataPairList, timeStamp, tag);
542 }
543
544 } // namespace simgear