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:
ScalarDecodeVisitor(HLADecodeStream & stream,SGPropertyNode & propertyNode)37 ScalarDecodeVisitor(HLADecodeStream& stream, SGPropertyNode& propertyNode) :
38 HLADataTypeDecodeVisitor(stream),
39 _propertyNode(propertyNode)
40 { }
~ScalarDecodeVisitor()41 virtual ~ScalarDecodeVisitor()
42 { }
43
apply(const HLAInt8DataType & dataType)44 virtual void apply(const HLAInt8DataType& dataType)
45 {
46 int8_t value = 0;
47 dataType.decode(_stream, value);
48 _propertyNode.setIntValue(value);
49 }
apply(const HLAUInt8DataType & dataType)50 virtual void apply(const HLAUInt8DataType& dataType)
51 {
52 uint8_t value = 0;
53 dataType.decode(_stream, value);
54 _propertyNode.setIntValue(value);
55 }
apply(const HLAInt16DataType & dataType)56 virtual void apply(const HLAInt16DataType& dataType)
57 {
58 int16_t value = 0;
59 dataType.decode(_stream, value);
60 _propertyNode.setIntValue(value);
61 }
apply(const HLAUInt16DataType & dataType)62 virtual void apply(const HLAUInt16DataType& dataType)
63 {
64 uint16_t value = 0;
65 dataType.decode(_stream, value);
66 _propertyNode.setIntValue(value);
67 }
apply(const HLAInt32DataType & dataType)68 virtual void apply(const HLAInt32DataType& dataType)
69 {
70 int32_t value = 0;
71 dataType.decode(_stream, value);
72 _propertyNode.setIntValue(value);
73 }
apply(const HLAUInt32DataType & dataType)74 virtual void apply(const HLAUInt32DataType& dataType)
75 {
76 uint32_t value = 0;
77 dataType.decode(_stream, value);
78 _propertyNode.setIntValue(value);
79 }
apply(const HLAInt64DataType & dataType)80 virtual void apply(const HLAInt64DataType& dataType)
81 {
82 int64_t value = 0;
83 dataType.decode(_stream, value);
84 _propertyNode.setLongValue(value);
85 }
apply(const HLAUInt64DataType & dataType)86 virtual void apply(const HLAUInt64DataType& dataType)
87 {
88 uint64_t value = 0;
89 dataType.decode(_stream, value);
90 _propertyNode.setLongValue(value);
91 }
apply(const HLAFloat32DataType & dataType)92 virtual void apply(const HLAFloat32DataType& dataType)
93 {
94 float value = 0;
95 dataType.decode(_stream, value);
96 _propertyNode.setFloatValue(value);
97 }
apply(const HLAFloat64DataType & dataType)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:
ScalarEncodeVisitor(HLAEncodeStream & stream,const SGPropertyNode & propertyNode)111 ScalarEncodeVisitor(HLAEncodeStream& stream, const SGPropertyNode& propertyNode) :
112 HLADataTypeEncodeVisitor(stream),
113 _propertyNode(propertyNode)
114 { }
~ScalarEncodeVisitor()115 virtual ~ScalarEncodeVisitor()
116 { }
117
apply(const HLAInt8DataType & dataType)118 virtual void apply(const HLAInt8DataType& dataType)
119 {
120 dataType.encode(_stream, _propertyNode.getIntValue());
121 }
apply(const HLAUInt8DataType & dataType)122 virtual void apply(const HLAUInt8DataType& dataType)
123 {
124 dataType.encode(_stream, _propertyNode.getIntValue());
125 }
apply(const HLAInt16DataType & dataType)126 virtual void apply(const HLAInt16DataType& dataType)
127 {
128 dataType.encode(_stream, _propertyNode.getIntValue());
129 }
apply(const HLAUInt16DataType & dataType)130 virtual void apply(const HLAUInt16DataType& dataType)
131 {
132 dataType.encode(_stream, _propertyNode.getIntValue());
133 }
apply(const HLAInt32DataType & dataType)134 virtual void apply(const HLAInt32DataType& dataType)
135 {
136 dataType.encode(_stream, _propertyNode.getIntValue());
137 }
apply(const HLAUInt32DataType & dataType)138 virtual void apply(const HLAUInt32DataType& dataType)
139 {
140 dataType.encode(_stream, _propertyNode.getIntValue());
141 }
apply(const HLAInt64DataType & dataType)142 virtual void apply(const HLAInt64DataType& dataType)
143 {
144 dataType.encode(_stream, _propertyNode.getLongValue());
145 }
apply(const HLAUInt64DataType & dataType)146 virtual void apply(const HLAUInt64DataType& dataType)
147 {
148 dataType.encode(_stream, _propertyNode.getLongValue());
149 }
apply(const HLAFloat32DataType & dataType)150 virtual void apply(const HLAFloat32DataType& dataType)
151 {
152 dataType.encode(_stream, _propertyNode.getFloatValue());
153 }
apply(const HLAFloat64DataType & dataType)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
ScalarDataElement(const HLABasicDataType * dataType,SGPropertyNode * propertyNode)175 HLAPropertyDataElement::ScalarDataElement::ScalarDataElement(const HLABasicDataType* dataType, SGPropertyNode* propertyNode) :
176 HLABasicDataElement(dataType),
177 _propertyNode(propertyNode)
178 {
179 }
180
~ScalarDataElement()181 HLAPropertyDataElement::ScalarDataElement::~ScalarDataElement()
182 {
183 }
184
185 bool
encode(HLAEncodeStream & stream) const186 HLAPropertyDataElement::ScalarDataElement::encode(HLAEncodeStream& stream) const
187 {
188 ScalarEncodeVisitor visitor(stream, *_propertyNode);
189 _dataType->accept(visitor);
190 return true;
191 }
192
193 bool
decode(HLADecodeStream & stream)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
Listener(StringDataElement * stringDataElement)222 HLAPropertyDataElement::StringDataElement::Listener::Listener(StringDataElement* stringDataElement) :
223 _stringDataElement(stringDataElement)
224 {
225 }
226
~Listener()227 HLAPropertyDataElement::StringDataElement::Listener::~Listener()
228 {
229 }
230
231 void
valueChanged(SGPropertyNode * node)232 HLAPropertyDataElement::StringDataElement::Listener::valueChanged (SGPropertyNode * node)
233 {
234 _stringDataElement->setValue(node->getStringValue());
235 }
236
StringDataElement(const HLAArrayDataType * dataType,SGPropertyNode * propertyNode)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
~StringDataElement()245 HLAPropertyDataElement::StringDataElement::~StringDataElement()
246 {
247 _propertyNode->removeChangeListener(_listener);
248 delete _listener;
249 _listener = 0;
250 }
251
252 bool
decodeElement(HLADecodeStream & stream,unsigned i)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:
DataElementFactoryVisitor(SGPropertyNode * propertyNode)264 DataElementFactoryVisitor(SGPropertyNode* propertyNode) :
265 _propertyNode(propertyNode)
266 { }
~DataElementFactoryVisitor()267 virtual ~DataElementFactoryVisitor()
268 { }
269
apply(const HLADataType & dataType)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
apply(const HLAInt8DataType & dataType)276 virtual void apply(const HLAInt8DataType& dataType)
277 {
278 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
279 }
apply(const HLAUInt8DataType & dataType)280 virtual void apply(const HLAUInt8DataType& dataType)
281 {
282 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
283 }
apply(const HLAInt16DataType & dataType)284 virtual void apply(const HLAInt16DataType& dataType)
285 {
286 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
287 }
apply(const HLAUInt16DataType & dataType)288 virtual void apply(const HLAUInt16DataType& dataType)
289 {
290 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
291 }
apply(const HLAInt32DataType & dataType)292 virtual void apply(const HLAInt32DataType& dataType)
293 {
294 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
295 }
apply(const HLAUInt32DataType & dataType)296 virtual void apply(const HLAUInt32DataType& dataType)
297 {
298 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
299 }
apply(const HLAInt64DataType & dataType)300 virtual void apply(const HLAInt64DataType& dataType)
301 {
302 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
303 }
apply(const HLAUInt64DataType & dataType)304 virtual void apply(const HLAUInt64DataType& dataType)
305 {
306 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
307 }
apply(const HLAFloat32DataType & dataType)308 virtual void apply(const HLAFloat32DataType& dataType)
309 {
310 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
311 }
apply(const HLAFloat64DataType & dataType)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:
ArrayDataElementFactory(SGPropertyNode * propertyNode)319 ArrayDataElementFactory(SGPropertyNode* propertyNode) :
320 _propertyNode(propertyNode)
321 { }
createElement(const HLAArrayDataElement & element,unsigned index)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
apply(const HLAFixedArrayDataType & dataType)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
apply(const HLAVariableArrayDataType & dataType)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
apply(const HLAEnumeratedDataType & dataType)362 virtual void apply(const HLAEnumeratedDataType& dataType)
363 {
364 _dataElement = new ScalarDataElement(dataType.getRepresentation(), _propertyNode.get());
365 }
366
apply(const HLAFixedRecordDataType & dataType)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:
VariantRecordDataElementFactory(SGPropertyNode * propertyNode)384 VariantRecordDataElementFactory(SGPropertyNode* propertyNode) :
385 _propertyNode(propertyNode)
386 { }
createElement(const HLAVariantRecordDataElement & element,unsigned index)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
apply(const HLAVariantRecordDataType & dataType)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
getDataElement()411 HLADataElement* getDataElement()
412 { return _dataElement.release(); }
413
414 private:
415 SGSharedPtr<SGPropertyNode> _propertyNode;
416 SGSharedPtr<HLADataElement> _dataElement;
417 };
418
HLAPropertyDataElement()419 HLAPropertyDataElement::HLAPropertyDataElement()
420 {
421 }
422
HLAPropertyDataElement(SGPropertyNode * propertyNode)423 HLAPropertyDataElement::HLAPropertyDataElement(SGPropertyNode* propertyNode)
424 {
425 setPropertyNode(propertyNode);
426 }
427
HLAPropertyDataElement(const HLADataType * dataType,SGPropertyNode * propertyNode)428 HLAPropertyDataElement::HLAPropertyDataElement(const HLADataType* dataType, SGPropertyNode* propertyNode) :
429 _dataType(dataType)
430 {
431 setPropertyNode(propertyNode);
432 }
433
HLAPropertyDataElement(const HLADataType * dataType)434 HLAPropertyDataElement::HLAPropertyDataElement(const HLADataType* dataType) :
435 _dataType(dataType)
436 {
437 }
438
~HLAPropertyDataElement()439 HLAPropertyDataElement::~HLAPropertyDataElement()
440 {
441 }
442
443 void
accept(HLADataElementVisitor & visitor)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
accept(HLAConstDataElementVisitor & visitor) const466 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
encode(HLAEncodeStream & stream) const476 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
decode(HLADecodeStream & stream)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*
getDataType() const512 HLAPropertyDataElement::getDataType() const
513 {
514 return _dataType.get();
515 }
516
517 bool
setDataType(const HLADataType * dataType)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
setPropertyNode(SGPropertyNode * propertyNode)527 HLAPropertyDataElement::setPropertyNode(SGPropertyNode* propertyNode)
528 {
529 _propertyNode = propertyNode;
530 if (_dataType.valid() && _propertyNode.valid())
531 _dataElement = createDataElement(_dataType, _propertyNode);
532 }
533
534 SGPropertyNode*
getPropertyNode()535 HLAPropertyDataElement::getPropertyNode()
536 {
537 return _propertyNode.get();
538 }
539
540 const SGPropertyNode*
getPropertyNode() const541 HLAPropertyDataElement::getPropertyNode() const
542 {
543 return _propertyNode.get();
544 }
545
546 HLADataElement*
createDataElement(const SGSharedPtr<const HLADataType> & dataType,const SGSharedPtr<SGPropertyNode> & propertyNode)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
569