1 // Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de
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.
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.
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.
19 # include <simgear_config.h>
22 #include <simgear/compiler.h>
24 #include "HLAPropertyDataElement.hxx"
26 #include "HLAArrayDataElement.hxx"
27 #include "HLABasicDataElement.hxx"
28 #include "HLADataElementVisitor.hxx"
29 #include "HLADataTypeVisitor.hxx"
30 #include "HLAFixedRecordDataElement.hxx"
31 #include "HLAVariantRecordDataElement.hxx"
35 class HLAPropertyDataElement::ScalarDecodeVisitor : public HLADataTypeDecodeVisitor {
37 ScalarDecodeVisitor(HLADecodeStream& stream, SGPropertyNode& propertyNode) :
38 HLADataTypeDecodeVisitor(stream),
39 _propertyNode(propertyNode)
41 virtual ~ScalarDecodeVisitor()
44 virtual void apply(const HLAInt8DataType& dataType)
47 dataType.decode(_stream, value);
48 _propertyNode.setIntValue(value);
50 virtual void apply(const HLAUInt8DataType& dataType)
53 dataType.decode(_stream, value);
54 _propertyNode.setIntValue(value);
56 virtual void apply(const HLAInt16DataType& dataType)
59 dataType.decode(_stream, value);
60 _propertyNode.setIntValue(value);
62 virtual void apply(const HLAUInt16DataType& dataType)
65 dataType.decode(_stream, value);
66 _propertyNode.setIntValue(value);
68 virtual void apply(const HLAInt32DataType& dataType)
71 dataType.decode(_stream, value);
72 _propertyNode.setIntValue(value);
74 virtual void apply(const HLAUInt32DataType& dataType)
77 dataType.decode(_stream, value);
78 _propertyNode.setIntValue(value);
80 virtual void apply(const HLAInt64DataType& dataType)
83 dataType.decode(_stream, value);
84 _propertyNode.setLongValue(value);
86 virtual void apply(const HLAUInt64DataType& dataType)
89 dataType.decode(_stream, value);
90 _propertyNode.setLongValue(value);
92 virtual void apply(const HLAFloat32DataType& dataType)
95 dataType.decode(_stream, value);
96 _propertyNode.setFloatValue(value);
98 virtual void apply(const HLAFloat64DataType& dataType)
101 dataType.decode(_stream, value);
102 _propertyNode.setDoubleValue(value);
106 SGPropertyNode& _propertyNode;
109 class HLAPropertyDataElement::ScalarEncodeVisitor : public HLADataTypeEncodeVisitor {
111 ScalarEncodeVisitor(HLAEncodeStream& stream, const SGPropertyNode& propertyNode) :
112 HLADataTypeEncodeVisitor(stream),
113 _propertyNode(propertyNode)
115 virtual ~ScalarEncodeVisitor()
118 virtual void apply(const HLAInt8DataType& dataType)
120 dataType.encode(_stream, _propertyNode.getIntValue());
122 virtual void apply(const HLAUInt8DataType& dataType)
124 dataType.encode(_stream, _propertyNode.getIntValue());
126 virtual void apply(const HLAInt16DataType& dataType)
128 dataType.encode(_stream, _propertyNode.getIntValue());
130 virtual void apply(const HLAUInt16DataType& dataType)
132 dataType.encode(_stream, _propertyNode.getIntValue());
134 virtual void apply(const HLAInt32DataType& dataType)
136 dataType.encode(_stream, _propertyNode.getIntValue());
138 virtual void apply(const HLAUInt32DataType& dataType)
140 dataType.encode(_stream, _propertyNode.getIntValue());
142 virtual void apply(const HLAInt64DataType& dataType)
144 dataType.encode(_stream, _propertyNode.getLongValue());
146 virtual void apply(const HLAUInt64DataType& dataType)
148 dataType.encode(_stream, _propertyNode.getLongValue());
150 virtual void apply(const HLAFloat32DataType& dataType)
152 dataType.encode(_stream, _propertyNode.getFloatValue());
154 virtual void apply(const HLAFloat64DataType& dataType)
156 dataType.encode(_stream, _propertyNode.getDoubleValue());
160 const SGPropertyNode& _propertyNode;
163 class HLAPropertyDataElement::ScalarDataElement : public HLABasicDataElement {
165 ScalarDataElement(const HLABasicDataType* dataType, SGPropertyNode* propertyNode);
166 virtual ~ScalarDataElement();
168 virtual bool encode(HLAEncodeStream& stream) const;
169 virtual bool decode(HLADecodeStream& stream);
172 SGSharedPtr<SGPropertyNode> _propertyNode;
175 HLAPropertyDataElement::ScalarDataElement::ScalarDataElement(const HLABasicDataType* dataType, SGPropertyNode* propertyNode) :
176 HLABasicDataElement(dataType),
177 _propertyNode(propertyNode)
181 HLAPropertyDataElement::ScalarDataElement::~ScalarDataElement()
186 HLAPropertyDataElement::ScalarDataElement::encode(HLAEncodeStream& stream) const
188 ScalarEncodeVisitor visitor(stream, *_propertyNode);
189 _dataType->accept(visitor);
194 HLAPropertyDataElement::ScalarDataElement::decode(HLADecodeStream& stream)
196 ScalarDecodeVisitor visitor(stream, *_propertyNode);
197 _dataType->accept(visitor);
201 class HLAPropertyDataElement::StringDataElement : public HLAStringDataElement {
203 StringDataElement(const HLAArrayDataType* dataType, SGPropertyNode* propertyNode);
204 virtual ~StringDataElement();
206 virtual bool decodeElement(HLADecodeStream& stream, unsigned i);
208 class Listener : public SGPropertyChangeListener {
210 Listener(StringDataElement* stringDataElement);
212 virtual void valueChanged (SGPropertyNode * node);
214 StringDataElement* _stringDataElement;
218 SGSharedPtr<SGPropertyNode> _propertyNode;
222 HLAPropertyDataElement::StringDataElement::Listener::Listener(StringDataElement* stringDataElement) :
223 _stringDataElement(stringDataElement)
227 HLAPropertyDataElement::StringDataElement::Listener::~Listener()
232 HLAPropertyDataElement::StringDataElement::Listener::valueChanged (SGPropertyNode * node)
234 _stringDataElement->setValue(node->getStringValue());
237 HLAPropertyDataElement::StringDataElement::StringDataElement(const HLAArrayDataType* dataType, SGPropertyNode* propertyNode) :
238 HLAStringDataElement(dataType),
239 _propertyNode(propertyNode),
240 _listener(new Listener(this))
242 _propertyNode->addChangeListener(_listener, true);
245 HLAPropertyDataElement::StringDataElement::~StringDataElement()
247 _propertyNode->removeChangeListener(_listener);
253 HLAPropertyDataElement::StringDataElement::decodeElement(HLADecodeStream& stream, unsigned i)
255 if (!HLAStringDataElement::decodeElement(stream, i))
257 if (i + 1 == getValue().size())
258 _propertyNode->setStringValue(getValue());
262 class HLAPropertyDataElement::DataElementFactoryVisitor : public HLADataTypeVisitor {
264 DataElementFactoryVisitor(SGPropertyNode* propertyNode) :
265 _propertyNode(propertyNode)
267 virtual ~DataElementFactoryVisitor()
270 virtual void apply(const HLADataType& dataType)
272 SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Can not find a suitable data element for data type \""
273 << dataType.getName() << "\"");
276 virtual void apply(const HLAInt8DataType& dataType)
278 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
280 virtual void apply(const HLAUInt8DataType& dataType)
282 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
284 virtual void apply(const HLAInt16DataType& dataType)
286 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
288 virtual void apply(const HLAUInt16DataType& dataType)
290 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
292 virtual void apply(const HLAInt32DataType& dataType)
294 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
296 virtual void apply(const HLAUInt32DataType& dataType)
298 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
300 virtual void apply(const HLAInt64DataType& dataType)
302 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
304 virtual void apply(const HLAUInt64DataType& dataType)
306 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
308 virtual void apply(const HLAFloat32DataType& dataType)
310 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
312 virtual void apply(const HLAFloat64DataType& dataType)
314 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
317 class ArrayDataElementFactory : public HLAArrayDataElement::DataElementFactory {
319 ArrayDataElementFactory(SGPropertyNode* propertyNode) :
320 _propertyNode(propertyNode)
322 virtual HLADataElement* createElement(const HLAArrayDataElement& element, unsigned index)
324 const HLADataType* dataType = element.getElementDataType();
328 SGPropertyNode* parent = _propertyNode->getParent();
329 DataElementFactoryVisitor visitor(parent->getChild(_propertyNode->getNameString(), index, true));
330 dataType->accept(visitor);
331 return visitor.getDataElement();
334 SGSharedPtr<SGPropertyNode> _propertyNode;
337 virtual void apply(const HLAFixedArrayDataType& dataType)
339 if (dataType.getIsString()) {
340 _dataElement = new StringDataElement(&dataType, _propertyNode.get());
342 SGSharedPtr<HLAArrayDataElement> arrayDataElement;
343 arrayDataElement = new HLAArrayDataElement(&dataType);
344 arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_propertyNode.get()));
345 arrayDataElement->setNumElements(dataType.getNumElements());
346 _dataElement = arrayDataElement;
350 virtual void apply(const HLAVariableArrayDataType& dataType)
352 if (dataType.getIsString()) {
353 _dataElement = new StringDataElement(&dataType, _propertyNode.get());
355 SGSharedPtr<HLAArrayDataElement> arrayDataElement;
356 arrayDataElement = new HLAArrayDataElement(&dataType);
357 arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_propertyNode.get()));
358 _dataElement = arrayDataElement;
362 virtual void apply(const HLAEnumeratedDataType& dataType)
364 _dataElement = new ScalarDataElement(dataType.getRepresentation(), _propertyNode.get());
367 virtual void apply(const HLAFixedRecordDataType& dataType)
369 SGSharedPtr<HLAFixedRecordDataElement> recordDataElement;
370 recordDataElement = new HLAFixedRecordDataElement(&dataType);
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());
379 _dataElement = recordDataElement;
382 class VariantRecordDataElementFactory : public HLAVariantRecordDataElement::DataElementFactory {
384 VariantRecordDataElementFactory(SGPropertyNode* propertyNode) :
385 _propertyNode(propertyNode)
387 virtual HLADataElement* createElement(const HLAVariantRecordDataElement& element, unsigned index)
389 const HLAVariantRecordDataType* dataType = element.getDataType();
392 const HLADataType* alternativeDataType = element.getAlternativeDataType();
393 if (!alternativeDataType)
395 DataElementFactoryVisitor visitor(_propertyNode->getChild(dataType->getAlternativeName(index), 0, true));
396 alternativeDataType->accept(visitor);
397 return visitor.getDataElement();
400 SGSharedPtr<SGPropertyNode> _propertyNode;
403 virtual void apply(const HLAVariantRecordDataType& dataType)
405 SGSharedPtr<HLAVariantRecordDataElement> variantRecordDataElement;
406 variantRecordDataElement = new HLAVariantRecordDataElement(&dataType);
407 variantRecordDataElement->setDataElementFactory(new VariantRecordDataElementFactory(_propertyNode.get()));
408 _dataElement = variantRecordDataElement;
411 HLADataElement* getDataElement()
412 { return _dataElement.release(); }
415 SGSharedPtr<SGPropertyNode> _propertyNode;
416 SGSharedPtr<HLADataElement> _dataElement;
419 HLAPropertyDataElement::HLAPropertyDataElement()
423 HLAPropertyDataElement::HLAPropertyDataElement(SGPropertyNode* propertyNode)
425 setPropertyNode(propertyNode);
428 HLAPropertyDataElement::HLAPropertyDataElement(const HLADataType* dataType, SGPropertyNode* propertyNode) :
431 setPropertyNode(propertyNode);
434 HLAPropertyDataElement::HLAPropertyDataElement(const HLADataType* dataType) :
439 HLAPropertyDataElement::~HLAPropertyDataElement()
444 HLAPropertyDataElement::accept(HLADataElementVisitor& visitor)
446 if (_dataElement.valid()) {
447 visitor.apply(*_dataElement);
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);
457 HLADataElement::accept(visitor);
460 HLADataElement::accept(visitor);
466 HLAPropertyDataElement::accept(HLAConstDataElementVisitor& visitor) const
468 if (_dataElement.valid()) {
469 visitor.apply(*_dataElement);
471 HLADataElement::accept(visitor);
476 HLAPropertyDataElement::encode(HLAEncodeStream& stream) const
478 if (_dataElement.valid()) {
479 return _dataElement->encode(stream);
481 if (!_dataType.valid())
483 HLADataTypeEncodeVisitor visitor(stream);
484 _dataType->accept(visitor);
490 HLAPropertyDataElement::decode(HLADecodeStream& stream)
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
498 HLADataElementFactoryVisitor visitor;
499 _dataType->accept(visitor);
500 _dataElement = visitor.getDataElement();
501 if (_dataElement.valid()) {
502 return _dataElement->decode(stream);
504 HLADataTypeDecodeVisitor visitor(stream);
505 _dataType->accept(visitor);
512 HLAPropertyDataElement::getDataType() const
514 return _dataType.get();
518 HLAPropertyDataElement::setDataType(const HLADataType* dataType)
520 _dataType = dataType;
521 if (_dataType.valid() && _propertyNode.valid())
522 _dataElement = createDataElement(_dataType, _propertyNode);
527 HLAPropertyDataElement::setPropertyNode(SGPropertyNode* propertyNode)
529 _propertyNode = propertyNode;
530 if (_dataType.valid() && _propertyNode.valid())
531 _dataElement = createDataElement(_dataType, _propertyNode);
535 HLAPropertyDataElement::getPropertyNode()
537 return _propertyNode.get();
540 const SGPropertyNode*
541 HLAPropertyDataElement::getPropertyNode() const
543 return _propertyNode.get();
547 HLAPropertyDataElement::createDataElement(const SGSharedPtr<const HLADataType>& dataType,
548 const SGSharedPtr<SGPropertyNode>& propertyNode)
550 DataElementFactoryVisitor visitor(propertyNode);
551 dataType->accept(visitor);
552 SGSharedPtr<HLADataElement> dataElement = visitor.getDataElement();
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??
558 HLAEncodeStream encodeStream(data);
559 if (_dataElement->encode(encodeStream)) {
560 HLADecodeStream decodeStream(data);
561 dataElement->decode(decodeStream);
565 return dataElement.release();
568 } // namespace simgear