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