]> git.mxchange.org Git - simgear.git/blob - simgear/hla/HLAPropertyDataElement.cxx
hla: Use HLADataElementIndices for HLAInteractionClass.
[simgear.git] / simgear / hla / HLAPropertyDataElement.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 "HLAPropertyDataElement.hxx"
25
26 #include "HLAArrayDataElement.hxx"
27 #include "HLABasicDataElement.hxx"
28 #include "HLADataElementVisitor.hxx"
29 #include "HLADataTypeVisitor.hxx"
30 #include "HLAFixedRecordDataElement.hxx"
31 #include "HLAVariantRecordDataElement.hxx"
32
33 namespace simgear {
34
35 class HLAPropertyDataElement::ScalarDecodeVisitor : public HLADataTypeDecodeVisitor {
36 public:
37     ScalarDecodeVisitor(HLADecodeStream& stream, SGPropertyNode& propertyNode) :
38         HLADataTypeDecodeVisitor(stream),
39         _propertyNode(propertyNode)
40     { }
41     virtual ~ScalarDecodeVisitor()
42     { }
43
44     virtual void apply(const HLAInt8DataType& dataType)
45     {
46         int8_t value = 0;
47         dataType.decode(_stream, value);
48         _propertyNode.setIntValue(value);
49     }
50     virtual void apply(const HLAUInt8DataType& dataType)
51     {
52         uint8_t value = 0;
53         dataType.decode(_stream, value);
54         _propertyNode.setIntValue(value);
55     }
56     virtual void apply(const HLAInt16DataType& dataType)
57     {
58         int16_t value = 0;
59         dataType.decode(_stream, value);
60         _propertyNode.setIntValue(value);
61     }
62     virtual void apply(const HLAUInt16DataType& dataType)
63     {
64         uint16_t value = 0;
65         dataType.decode(_stream, value);
66         _propertyNode.setIntValue(value);
67     }
68     virtual void apply(const HLAInt32DataType& dataType)
69     {
70         int32_t value = 0;
71         dataType.decode(_stream, value);
72         _propertyNode.setIntValue(value);
73     }
74     virtual void apply(const HLAUInt32DataType& dataType)
75     {
76         uint32_t value = 0;
77         dataType.decode(_stream, value);
78         _propertyNode.setIntValue(value);
79     }
80     virtual void apply(const HLAInt64DataType& dataType)
81     {
82         int64_t value = 0;
83         dataType.decode(_stream, value);
84         _propertyNode.setLongValue(value);
85     }
86     virtual void apply(const HLAUInt64DataType& dataType)
87     {
88         uint64_t value = 0;
89         dataType.decode(_stream, value);
90         _propertyNode.setLongValue(value);
91     }
92     virtual void apply(const HLAFloat32DataType& dataType)
93     {
94         float value = 0;
95         dataType.decode(_stream, value);
96         _propertyNode.setFloatValue(value);
97     }
98     virtual void apply(const HLAFloat64DataType& dataType)
99     {
100         double value = 0;
101         dataType.decode(_stream, value);
102         _propertyNode.setDoubleValue(value);
103     }
104
105 protected:
106     SGPropertyNode& _propertyNode;
107 };
108
109 class HLAPropertyDataElement::ScalarEncodeVisitor : public HLADataTypeEncodeVisitor {
110 public:
111     ScalarEncodeVisitor(HLAEncodeStream& stream, const SGPropertyNode& propertyNode) :
112         HLADataTypeEncodeVisitor(stream),
113         _propertyNode(propertyNode)
114     { }
115     virtual ~ScalarEncodeVisitor()
116     { }
117
118     virtual void apply(const HLAInt8DataType& dataType)
119     {
120         dataType.encode(_stream, _propertyNode.getIntValue());
121     }
122     virtual void apply(const HLAUInt8DataType& dataType)
123     {
124         dataType.encode(_stream, _propertyNode.getIntValue());
125     }
126     virtual void apply(const HLAInt16DataType& dataType)
127     {
128         dataType.encode(_stream, _propertyNode.getIntValue());
129     }
130     virtual void apply(const HLAUInt16DataType& dataType)
131     {
132         dataType.encode(_stream, _propertyNode.getIntValue());
133     }
134     virtual void apply(const HLAInt32DataType& dataType)
135     {
136         dataType.encode(_stream, _propertyNode.getIntValue());
137     }
138     virtual void apply(const HLAUInt32DataType& dataType)
139     {
140         dataType.encode(_stream, _propertyNode.getIntValue());
141     }
142     virtual void apply(const HLAInt64DataType& dataType)
143     {
144         dataType.encode(_stream, _propertyNode.getLongValue());
145     }
146     virtual void apply(const HLAUInt64DataType& dataType)
147     {
148         dataType.encode(_stream, _propertyNode.getLongValue());
149     }
150     virtual void apply(const HLAFloat32DataType& dataType)
151     {
152         dataType.encode(_stream, _propertyNode.getFloatValue());
153     }
154     virtual void apply(const HLAFloat64DataType& dataType)
155     {
156         dataType.encode(_stream, _propertyNode.getDoubleValue());
157     }
158
159 protected:
160     const SGPropertyNode& _propertyNode;
161 };
162
163 class HLAPropertyDataElement::ScalarDataElement : public HLABasicDataElement {
164 public:
165     ScalarDataElement(const HLABasicDataType* dataType, SGPropertyNode* propertyNode);
166     virtual ~ScalarDataElement();
167
168     virtual bool encode(HLAEncodeStream& stream) const;
169     virtual bool decode(HLADecodeStream& stream);
170
171 private:
172     SGSharedPtr<SGPropertyNode> _propertyNode;
173 };
174
175 HLAPropertyDataElement::ScalarDataElement::ScalarDataElement(const HLABasicDataType* dataType, SGPropertyNode* propertyNode) :
176     HLABasicDataElement(dataType),
177     _propertyNode(propertyNode)
178 {
179 }
180
181 HLAPropertyDataElement::ScalarDataElement::~ScalarDataElement()
182 {
183 }
184
185 bool
186 HLAPropertyDataElement::ScalarDataElement::encode(HLAEncodeStream& stream) const
187 {
188     ScalarEncodeVisitor visitor(stream, *_propertyNode);
189     _dataType->accept(visitor);
190     return true;
191 }
192
193 bool
194 HLAPropertyDataElement::ScalarDataElement::decode(HLADecodeStream& stream)
195 {
196     ScalarDecodeVisitor visitor(stream, *_propertyNode);
197     _dataType->accept(visitor);
198     return true;
199 }
200
201 class HLAPropertyDataElement::StringDataElement : public HLAStringDataElement {
202 public:
203     StringDataElement(const HLAArrayDataType* dataType, SGPropertyNode* propertyNode);
204     virtual ~StringDataElement();
205
206     virtual bool decodeElement(HLADecodeStream& stream, unsigned i);
207
208     class Listener : public SGPropertyChangeListener {
209     public:
210         Listener(StringDataElement* stringDataElement);
211         virtual ~Listener();
212         virtual void valueChanged (SGPropertyNode * node);
213     private:
214         StringDataElement* _stringDataElement;
215     };
216
217 private:
218     SGSharedPtr<SGPropertyNode> _propertyNode;
219     Listener* _listener;
220 };
221
222 HLAPropertyDataElement::StringDataElement::Listener::Listener(StringDataElement* stringDataElement) :
223             _stringDataElement(stringDataElement)
224 {
225 }
226
227 HLAPropertyDataElement::StringDataElement::Listener::~Listener()
228 {
229 }
230
231 void
232 HLAPropertyDataElement::StringDataElement::Listener::valueChanged (SGPropertyNode * node)
233 {
234     _stringDataElement->setValue(node->getStringValue());
235 }
236
237 HLAPropertyDataElement::StringDataElement::StringDataElement(const HLAArrayDataType* dataType, SGPropertyNode* propertyNode) :
238     HLAStringDataElement(dataType),
239     _propertyNode(propertyNode),
240     _listener(new Listener(this))
241 {
242     _propertyNode->addChangeListener(_listener, true);
243 }
244
245 HLAPropertyDataElement::StringDataElement::~StringDataElement()
246 {
247     _propertyNode->removeChangeListener(_listener);
248     delete _listener;
249     _listener = 0;
250 }
251
252 bool
253 HLAPropertyDataElement::StringDataElement::decodeElement(HLADecodeStream& stream, unsigned i)
254 {
255     if (!HLAStringDataElement::decodeElement(stream, i))
256         return false;
257     if (i + 1 == getValue().size())
258         _propertyNode->setStringValue(getValue());
259     return true;
260 }
261
262 class HLAPropertyDataElement::DataElementFactoryVisitor : public HLADataTypeVisitor {
263 public:
264     DataElementFactoryVisitor(SGPropertyNode* propertyNode) :
265         _propertyNode(propertyNode)
266     { }
267     virtual ~DataElementFactoryVisitor()
268     { }
269
270     virtual void apply(const HLADataType& dataType)
271     {
272         SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Can not find a suitable data element for data type \""
273                << dataType.getName() << "\"");
274     }
275
276     virtual void apply(const HLAInt8DataType& dataType)
277     {
278         _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
279     }
280     virtual void apply(const HLAUInt8DataType& dataType)
281     {
282         _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
283     }
284     virtual void apply(const HLAInt16DataType& dataType)
285     {
286         _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
287     }
288     virtual void apply(const HLAUInt16DataType& dataType)
289     {
290         _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
291     }
292     virtual void apply(const HLAInt32DataType& dataType)
293     {
294         _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
295     }
296     virtual void apply(const HLAUInt32DataType& dataType)
297     {
298         _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
299     }
300     virtual void apply(const HLAInt64DataType& dataType)
301     {
302         _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
303     }
304     virtual void apply(const HLAUInt64DataType& dataType)
305     {
306         _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
307     }
308     virtual void apply(const HLAFloat32DataType& dataType)
309     {
310         _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
311     }
312     virtual void apply(const HLAFloat64DataType& dataType)
313     {
314         _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
315     }
316
317     class ArrayDataElementFactory : public HLAArrayDataElement::DataElementFactory {
318     public:
319         ArrayDataElementFactory(SGPropertyNode* propertyNode) :
320             _propertyNode(propertyNode)
321         { }
322         virtual HLADataElement* createElement(const HLAArrayDataElement& element, unsigned index)
323         {
324             const HLADataType* dataType = element.getElementDataType();
325             if (!dataType)
326                 return 0;
327
328             SGPropertyNode* parent = _propertyNode->getParent();
329             DataElementFactoryVisitor visitor(parent->getChild(_propertyNode->getNameString(), index, true));
330             dataType->accept(visitor);
331             return visitor.getDataElement();
332         }
333     private:
334         SGSharedPtr<SGPropertyNode> _propertyNode;
335     };
336
337     virtual void apply(const HLAFixedArrayDataType& dataType)
338     {
339         if (dataType.getIsString()) {
340             _dataElement = new StringDataElement(&dataType, _propertyNode.get());
341         } else {
342             SGSharedPtr<HLAArrayDataElement> arrayDataElement;
343             arrayDataElement = new HLAArrayDataElement(&dataType);
344             arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_propertyNode.get()));
345             arrayDataElement->setNumElements(dataType.getNumElements());
346             _dataElement = arrayDataElement;
347         }
348     }
349
350     virtual void apply(const HLAVariableArrayDataType& dataType)
351     {
352         if (dataType.getIsString()) {
353             _dataElement = new StringDataElement(&dataType, _propertyNode.get());
354         } else {
355             SGSharedPtr<HLAArrayDataElement> arrayDataElement;
356             arrayDataElement = new HLAArrayDataElement(&dataType);
357             arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_propertyNode.get()));
358             _dataElement = arrayDataElement;
359         }
360     }
361
362     virtual void apply(const HLAEnumeratedDataType& dataType)
363     {
364         _dataElement = new ScalarDataElement(dataType.getRepresentation(), _propertyNode.get());
365     }
366
367     virtual void apply(const HLAFixedRecordDataType& dataType)
368     {
369         SGSharedPtr<HLAFixedRecordDataElement> recordDataElement;
370         recordDataElement = new HLAFixedRecordDataElement(&dataType);
371
372         unsigned numFields = dataType.getNumFields();
373         for (unsigned i = 0; i < numFields; ++i) {
374             DataElementFactoryVisitor visitor(_propertyNode->getChild(dataType.getFieldName(i), 0, true));
375             dataType.getFieldDataType(i)->accept(visitor);
376             recordDataElement->setField(i, visitor._dataElement.get());
377         }
378
379         _dataElement = recordDataElement;
380     }
381
382     class VariantRecordDataElementFactory : public HLAVariantRecordDataElement::DataElementFactory {
383     public:
384         VariantRecordDataElementFactory(SGPropertyNode* propertyNode) :
385             _propertyNode(propertyNode)
386         { }
387         virtual HLADataElement* createElement(const HLAVariantRecordDataElement& element, unsigned index)
388         {
389             const HLAVariantRecordDataType* dataType = element.getDataType();
390             if (!dataType)
391                 return 0;
392             const HLADataType* alternativeDataType = element.getAlternativeDataType();
393             if (!alternativeDataType)
394                 return 0;
395             DataElementFactoryVisitor visitor(_propertyNode->getChild(dataType->getAlternativeName(index), 0, true));
396             alternativeDataType->accept(visitor);
397             return visitor.getDataElement();
398         }
399     private:
400         SGSharedPtr<SGPropertyNode> _propertyNode;
401     };
402
403     virtual void apply(const HLAVariantRecordDataType& dataType)
404     {
405         SGSharedPtr<HLAVariantRecordDataElement> variantRecordDataElement;
406         variantRecordDataElement = new HLAVariantRecordDataElement(&dataType);
407         variantRecordDataElement->setDataElementFactory(new VariantRecordDataElementFactory(_propertyNode.get()));
408         _dataElement = variantRecordDataElement;
409     }
410
411     HLADataElement* getDataElement()
412     { return _dataElement.release(); }
413
414 private:
415     SGSharedPtr<SGPropertyNode> _propertyNode;
416     SGSharedPtr<HLADataElement> _dataElement;
417 };
418
419 HLAPropertyDataElement::HLAPropertyDataElement()
420 {
421 }
422
423 HLAPropertyDataElement::HLAPropertyDataElement(SGPropertyNode* propertyNode)
424 {
425     setPropertyNode(propertyNode);
426 }
427
428 HLAPropertyDataElement::HLAPropertyDataElement(const HLADataType* dataType, SGPropertyNode* propertyNode) :
429     _dataType(dataType)
430 {
431     setPropertyNode(propertyNode);
432 }
433
434 HLAPropertyDataElement::HLAPropertyDataElement(const HLADataType* dataType) :
435     _dataType(dataType)
436 {
437 }
438
439 HLAPropertyDataElement::~HLAPropertyDataElement()
440 {
441 }
442
443 void
444 HLAPropertyDataElement::accept(HLADataElementVisitor& visitor)
445 {
446     if (_dataElement.valid()) {
447         visitor.apply(*_dataElement);
448     } else {
449         // We cant do anything if the data type is not valid
450         if (_dataType.valid()) {
451             HLADataElementFactoryVisitor factoryVisitor;
452             _dataType->accept(factoryVisitor);
453             _dataElement = factoryVisitor.getDataElement();
454             if (_dataElement.valid()) {
455                 visitor.apply(*_dataElement);
456             } else {
457                 HLADataElement::accept(visitor);
458             }
459         } else {
460             HLADataElement::accept(visitor);
461         }
462     }
463 }
464
465 void
466 HLAPropertyDataElement::accept(HLAConstDataElementVisitor& visitor) const
467 {
468     if (_dataElement.valid()) {
469         visitor.apply(*_dataElement);
470     } else {
471         HLADataElement::accept(visitor);
472     }
473 }
474
475 bool
476 HLAPropertyDataElement::encode(HLAEncodeStream& stream) const
477 {
478     if (_dataElement.valid()) {
479         return _dataElement->encode(stream);
480     } else {
481         if (!_dataType.valid())
482             return false;
483         HLADataTypeEncodeVisitor visitor(stream);
484         _dataType->accept(visitor);
485         return true;
486     }
487 }
488
489 bool
490 HLAPropertyDataElement::decode(HLADecodeStream& stream)
491 {
492     if (_dataElement.valid()) {
493         return _dataElement->decode(stream);
494     } else if (!_dataType.valid()) {
495         // We cant do anything if the data type is not valid
496         return false;
497     } else {
498         HLADataElementFactoryVisitor visitor;
499         _dataType->accept(visitor);
500         _dataElement = visitor.getDataElement();
501         if (_dataElement.valid()) {
502             return _dataElement->decode(stream);
503         } else {
504             HLADataTypeDecodeVisitor visitor(stream);
505             _dataType->accept(visitor);
506             return true;
507         }
508     }
509 }
510
511 const HLADataType*
512 HLAPropertyDataElement::getDataType() const
513 {
514     return _dataType.get();
515 }
516
517 bool
518 HLAPropertyDataElement::setDataType(const HLADataType* dataType)
519 {
520     _dataType = dataType;
521     if (_dataType.valid() && _propertyNode.valid())
522         _dataElement = createDataElement(_dataType, _propertyNode);
523     return true;
524 }
525
526 void
527 HLAPropertyDataElement::setPropertyNode(SGPropertyNode* propertyNode)
528 {
529     _propertyNode = propertyNode;
530     if (_dataType.valid() && _propertyNode.valid())
531         _dataElement = createDataElement(_dataType, _propertyNode);
532 }
533
534 SGPropertyNode*
535 HLAPropertyDataElement::getPropertyNode()
536 {
537     return _propertyNode.get();
538 }
539
540 const SGPropertyNode*
541 HLAPropertyDataElement::getPropertyNode() const
542 {
543     return _propertyNode.get();
544 }
545
546 HLADataElement*
547 HLAPropertyDataElement::createDataElement(const SGSharedPtr<const HLADataType>& dataType,
548                                           const SGSharedPtr<SGPropertyNode>& propertyNode)
549 {
550     DataElementFactoryVisitor visitor(propertyNode);
551     dataType->accept(visitor);
552     SGSharedPtr<HLADataElement> dataElement = visitor.getDataElement();
553
554     // Copy over the content of the previous data element if there is any.
555     if (_dataElement.valid()) {
556         // FIXME is encode/decode the right tool here??
557         RTIData data;
558         HLAEncodeStream encodeStream(data);
559         if (_dataElement->encode(encodeStream)) {
560             HLADecodeStream decodeStream(data);
561             dataElement->decode(decodeStream);
562         }
563     }
564
565     return dataElement.release();
566 }
567
568 } // namespace simgear