1 // Copyright (C) 2009 - 2011 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.
18 #include "HLAPropertyDataElement.hxx"
20 #include "HLAArrayDataElement.hxx"
21 #include "HLABasicDataElement.hxx"
22 #include "HLADataElementVisitor.hxx"
23 #include "HLADataTypeVisitor.hxx"
24 #include "HLAFixedRecordDataElement.hxx"
25 #include "HLAVariantDataElement.hxx"
29 class HLAPropertyDataElement::ScalarDecodeVisitor : public HLADataTypeDecodeVisitor {
31 ScalarDecodeVisitor(HLADecodeStream& stream, SGPropertyNode& propertyNode) :
32 HLADataTypeDecodeVisitor(stream),
33 _propertyNode(propertyNode)
35 virtual ~ScalarDecodeVisitor()
38 virtual void apply(const HLAInt8DataType& dataType)
41 dataType.decode(_stream, value);
42 _propertyNode.setIntValue(value);
44 virtual void apply(const HLAUInt8DataType& dataType)
47 dataType.decode(_stream, value);
48 _propertyNode.setIntValue(value);
50 virtual void apply(const HLAInt16DataType& dataType)
53 dataType.decode(_stream, value);
54 _propertyNode.setIntValue(value);
56 virtual void apply(const HLAUInt16DataType& dataType)
59 dataType.decode(_stream, value);
60 _propertyNode.setIntValue(value);
62 virtual void apply(const HLAInt32DataType& dataType)
65 dataType.decode(_stream, value);
66 _propertyNode.setIntValue(value);
68 virtual void apply(const HLAUInt32DataType& dataType)
71 dataType.decode(_stream, value);
72 _propertyNode.setIntValue(value);
74 virtual void apply(const HLAInt64DataType& dataType)
77 dataType.decode(_stream, value);
78 _propertyNode.setLongValue(value);
80 virtual void apply(const HLAUInt64DataType& dataType)
83 dataType.decode(_stream, value);
84 _propertyNode.setLongValue(value);
86 virtual void apply(const HLAFloat32DataType& dataType)
89 dataType.decode(_stream, value);
90 _propertyNode.setFloatValue(value);
92 virtual void apply(const HLAFloat64DataType& dataType)
95 dataType.decode(_stream, value);
96 _propertyNode.setDoubleValue(value);
100 SGPropertyNode& _propertyNode;
103 class HLAPropertyDataElement::ScalarEncodeVisitor : public HLADataTypeEncodeVisitor {
105 ScalarEncodeVisitor(HLAEncodeStream& stream, const SGPropertyNode& propertyNode) :
106 HLADataTypeEncodeVisitor(stream),
107 _propertyNode(propertyNode)
109 virtual ~ScalarEncodeVisitor()
112 virtual void apply(const HLAInt8DataType& dataType)
114 dataType.encode(_stream, _propertyNode.getIntValue());
116 virtual void apply(const HLAUInt8DataType& dataType)
118 dataType.encode(_stream, _propertyNode.getIntValue());
120 virtual void apply(const HLAInt16DataType& dataType)
122 dataType.encode(_stream, _propertyNode.getIntValue());
124 virtual void apply(const HLAUInt16DataType& dataType)
126 dataType.encode(_stream, _propertyNode.getIntValue());
128 virtual void apply(const HLAInt32DataType& dataType)
130 dataType.encode(_stream, _propertyNode.getIntValue());
132 virtual void apply(const HLAUInt32DataType& dataType)
134 dataType.encode(_stream, _propertyNode.getIntValue());
136 virtual void apply(const HLAInt64DataType& dataType)
138 dataType.encode(_stream, _propertyNode.getLongValue());
140 virtual void apply(const HLAUInt64DataType& dataType)
142 dataType.encode(_stream, _propertyNode.getLongValue());
144 virtual void apply(const HLAFloat32DataType& dataType)
146 dataType.encode(_stream, _propertyNode.getFloatValue());
148 virtual void apply(const HLAFloat64DataType& dataType)
150 dataType.encode(_stream, _propertyNode.getDoubleValue());
154 const SGPropertyNode& _propertyNode;
157 class HLAPropertyDataElement::ScalarDataElement : public HLABasicDataElement {
159 ScalarDataElement(const HLABasicDataType* dataType, SGPropertyNode* propertyNode);
160 virtual ~ScalarDataElement();
162 virtual bool encode(HLAEncodeStream& stream) const;
163 virtual bool decode(HLADecodeStream& stream);
166 SGSharedPtr<SGPropertyNode> _propertyNode;
169 HLAPropertyDataElement::ScalarDataElement::ScalarDataElement(const HLABasicDataType* dataType, SGPropertyNode* propertyNode) :
170 HLABasicDataElement(dataType),
171 _propertyNode(propertyNode)
175 HLAPropertyDataElement::ScalarDataElement::~ScalarDataElement()
180 HLAPropertyDataElement::ScalarDataElement::encode(HLAEncodeStream& stream) const
182 ScalarEncodeVisitor visitor(stream, *_propertyNode);
183 _dataType->accept(visitor);
188 HLAPropertyDataElement::ScalarDataElement::decode(HLADecodeStream& stream)
190 ScalarDecodeVisitor visitor(stream, *_propertyNode);
191 _dataType->accept(visitor);
195 class HLAPropertyDataElement::StringDataElement : public HLAStringDataElement {
197 StringDataElement(const HLAArrayDataType* dataType, SGPropertyNode* propertyNode);
198 virtual ~StringDataElement();
200 virtual bool decodeElement(HLADecodeStream& stream, unsigned i);
202 class Listener : public SGPropertyChangeListener {
204 Listener(StringDataElement* stringDataElement);
206 virtual void valueChanged (SGPropertyNode * node);
208 StringDataElement* _stringDataElement;
212 SGSharedPtr<SGPropertyNode> _propertyNode;
216 HLAPropertyDataElement::StringDataElement::Listener::Listener(StringDataElement* stringDataElement) :
217 _stringDataElement(stringDataElement)
221 HLAPropertyDataElement::StringDataElement::Listener::~Listener()
226 HLAPropertyDataElement::StringDataElement::Listener::valueChanged (SGPropertyNode * node)
228 _stringDataElement->setValue(node->getStringValue());
231 HLAPropertyDataElement::StringDataElement::StringDataElement(const HLAArrayDataType* dataType, SGPropertyNode* propertyNode) :
232 HLAStringDataElement(dataType),
233 _propertyNode(propertyNode),
234 _listener(new Listener(this))
236 _propertyNode->addChangeListener(_listener, true);
239 HLAPropertyDataElement::StringDataElement::~StringDataElement()
241 _propertyNode->removeChangeListener(_listener);
247 HLAPropertyDataElement::StringDataElement::decodeElement(HLADecodeStream& stream, unsigned i)
249 if (!HLAStringDataElement::decodeElement(stream, i))
251 if (i + 1 == getValue().size())
252 _propertyNode->setStringValue(getValue());
256 class HLAPropertyDataElement::DataElementFactoryVisitor : public HLADataTypeVisitor {
258 DataElementFactoryVisitor(SGPropertyNode* propertyNode) :
259 _propertyNode(propertyNode)
261 virtual ~DataElementFactoryVisitor()
264 virtual void apply(const HLADataType& dataType)
266 SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Can not find a suitable data element for data type \""
267 << dataType.getName() << "\"");
270 virtual void apply(const HLAInt8DataType& dataType)
272 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
274 virtual void apply(const HLAUInt8DataType& dataType)
276 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
278 virtual void apply(const HLAInt16DataType& dataType)
280 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
282 virtual void apply(const HLAUInt16DataType& dataType)
284 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
286 virtual void apply(const HLAInt32DataType& dataType)
288 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
290 virtual void apply(const HLAUInt32DataType& dataType)
292 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
294 virtual void apply(const HLAInt64DataType& dataType)
296 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
298 virtual void apply(const HLAUInt64DataType& dataType)
300 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
302 virtual void apply(const HLAFloat32DataType& dataType)
304 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
306 virtual void apply(const HLAFloat64DataType& dataType)
308 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
311 class ArrayDataElementFactory : public HLAArrayDataElement::DataElementFactory {
313 ArrayDataElementFactory(SGPropertyNode* propertyNode) :
314 _propertyNode(propertyNode)
316 virtual HLADataElement* createElement(const HLAArrayDataElement& element, unsigned index)
318 const HLADataType* dataType = element.getElementDataType();
322 SGPropertyNode* parent = _propertyNode->getParent();
323 DataElementFactoryVisitor visitor(parent->getChild(_propertyNode->getNameString(), index, true));
324 dataType->accept(visitor);
325 return visitor.getDataElement();
328 SGSharedPtr<SGPropertyNode> _propertyNode;
331 virtual void apply(const HLAFixedArrayDataType& dataType)
333 if (dataType.getIsString()) {
334 _dataElement = new StringDataElement(&dataType, _propertyNode.get());
336 SGSharedPtr<HLAArrayDataElement> arrayDataElement;
337 arrayDataElement = new HLAArrayDataElement(&dataType);
338 arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_propertyNode.get()));
339 arrayDataElement->setNumElements(dataType.getNumElements());
340 _dataElement = arrayDataElement;
344 virtual void apply(const HLAVariableArrayDataType& dataType)
346 if (dataType.getIsString()) {
347 _dataElement = new StringDataElement(&dataType, _propertyNode.get());
349 SGSharedPtr<HLAArrayDataElement> arrayDataElement;
350 arrayDataElement = new HLAArrayDataElement(&dataType);
351 arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_propertyNode.get()));
352 _dataElement = arrayDataElement;
356 virtual void apply(const HLAEnumeratedDataType& dataType)
358 _dataElement = new ScalarDataElement(dataType.getRepresentation(), _propertyNode.get());
361 virtual void apply(const HLAFixedRecordDataType& dataType)
363 SGSharedPtr<HLAFixedRecordDataElement> recordDataElement;
364 recordDataElement = new HLAFixedRecordDataElement(&dataType);
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());
373 _dataElement = recordDataElement;
376 class VariantDataElementFactory : public HLAVariantDataElement::DataElementFactory {
378 VariantDataElementFactory(SGPropertyNode* propertyNode) :
379 _propertyNode(propertyNode)
381 virtual HLADataElement* createElement(const HLAVariantDataElement& element, unsigned index)
383 const HLAVariantDataType* dataType = element.getDataType();
386 const HLADataType* alternativeDataType = element.getAlternativeDataType();
387 if (!alternativeDataType)
389 DataElementFactoryVisitor visitor(_propertyNode->getChild(dataType->getAlternativeName(index), 0, true));
390 alternativeDataType->accept(visitor);
391 return visitor.getDataElement();
394 SGSharedPtr<SGPropertyNode> _propertyNode;
397 virtual void apply(const HLAVariantDataType& dataType)
399 SGSharedPtr<HLAVariantDataElement> variantDataElement;
400 variantDataElement = new HLAVariantDataElement(&dataType);
401 variantDataElement->setDataElementFactory(new VariantDataElementFactory(_propertyNode.get()));
402 _dataElement = variantDataElement;
405 HLADataElement* getDataElement()
406 { return _dataElement.release(); }
409 SGSharedPtr<SGPropertyNode> _propertyNode;
410 SGSharedPtr<HLADataElement> _dataElement;
413 HLAPropertyDataElement::HLAPropertyDataElement()
417 HLAPropertyDataElement::HLAPropertyDataElement(SGPropertyNode* propertyNode)
419 setPropertyNode(propertyNode);
422 HLAPropertyDataElement::HLAPropertyDataElement(const HLADataType* dataType, SGPropertyNode* propertyNode) :
425 setPropertyNode(propertyNode);
428 HLAPropertyDataElement::HLAPropertyDataElement(const HLADataType* dataType) :
433 HLAPropertyDataElement::~HLAPropertyDataElement()
438 HLAPropertyDataElement::accept(HLADataElementVisitor& visitor)
440 if (_dataElement.valid()) {
441 visitor.apply(*_dataElement);
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);
451 HLADataElement::accept(visitor);
454 HLADataElement::accept(visitor);
460 HLAPropertyDataElement::accept(HLAConstDataElementVisitor& visitor) const
462 if (_dataElement.valid()) {
463 visitor.apply(*_dataElement);
465 HLADataElement::accept(visitor);
470 HLAPropertyDataElement::encode(HLAEncodeStream& stream) const
472 if (_dataElement.valid()) {
473 return _dataElement->encode(stream);
475 if (!_dataType.valid())
477 HLADataTypeEncodeVisitor visitor(stream);
478 _dataType->accept(visitor);
484 HLAPropertyDataElement::decode(HLADecodeStream& stream)
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
492 HLADataElementFactoryVisitor visitor;
493 _dataType->accept(visitor);
494 _dataElement = visitor.getDataElement();
495 if (_dataElement.valid()) {
496 return _dataElement->decode(stream);
498 HLADataTypeDecodeVisitor visitor(stream);
499 _dataType->accept(visitor);
506 HLAPropertyDataElement::getDataType() const
508 return _dataType.get();
512 HLAPropertyDataElement::setDataType(const HLADataType* dataType)
514 _dataType = dataType;
515 if (_dataType.valid() && _propertyNode.valid())
516 _dataElement = createDataElement(_dataType, _propertyNode);
521 HLAPropertyDataElement::setPropertyNode(SGPropertyNode* propertyNode)
523 _propertyNode = propertyNode;
524 if (_dataType.valid() && _propertyNode.valid())
525 _dataElement = createDataElement(_dataType, _propertyNode);
529 HLAPropertyDataElement::getPropertyNode()
531 return _propertyNode.get();
534 const SGPropertyNode*
535 HLAPropertyDataElement::getPropertyNode() const
537 return _propertyNode.get();
541 HLAPropertyDataElement::createDataElement(const SGSharedPtr<const HLADataType>& dataType,
542 const SGSharedPtr<SGPropertyNode>& propertyNode)
544 DataElementFactoryVisitor visitor(propertyNode);
545 dataType->accept(visitor);
546 SGSharedPtr<HLADataElement> dataElement = visitor.getDataElement();
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??
552 HLAEncodeStream encodeStream(data);
553 if (_dataElement->encode(encodeStream)) {
554 HLADecodeStream decodeStream(data);
555 dataElement->decode(decodeStream);
559 return dataElement.release();
562 } // namespace simgear