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 "HLAOMTXmlVisitor.hxx"
25
26 #include <map>
27 #include <string>
28 #include <sstream>
29
30 #include <simgear/structure/exception.hxx>
31 #include <simgear/xml/easyxml.hxx>
32 #include "HLAArrayDataType.hxx"
33 #include "HLABasicDataType.hxx"
34 #include "HLADataTypeVisitor.hxx"
35 #include "HLAEnumeratedDataType.hxx"
36 #include "HLAFederate.hxx"
37 #include "HLAFixedRecordDataType.hxx"
38 #include "HLAVariantRecordDataType.hxx"
39
40 namespace simgear {
41
ObjectClass(const std::string & name,const std::string & sharing)42 HLAOMTXmlVisitor::ObjectClass::ObjectClass(const std::string& name, const std::string& sharing) :
43 _name(name),
44 _sharing(sharing)
45 {
46 }
47
~ObjectClass()48 HLAOMTXmlVisitor::ObjectClass::~ObjectClass()
49 {
50 }
51
52 const std::string&
getName() const53 HLAOMTXmlVisitor::ObjectClass::getName() const
54 {
55 return _name;
56 }
57
58 const std::string&
getSharing() const59 HLAOMTXmlVisitor::ObjectClass::getSharing() const
60 {
61 return _sharing;
62 }
63
64 unsigned
getNumAttributes() const65 HLAOMTXmlVisitor::ObjectClass::getNumAttributes() const
66 {
67 return _attributes.size();
68 }
69
70 const HLAOMTXmlVisitor::Attribute*
getAttribute(unsigned index) const71 HLAOMTXmlVisitor::ObjectClass::getAttribute(unsigned index) const
72 {
73 if (_attributes.size() <= index)
74 return 0;
75 return _attributes[index];
76 }
77
78 const HLAOMTXmlVisitor::ObjectClass*
getParentObjectClass() const79 HLAOMTXmlVisitor::ObjectClass::getParentObjectClass() const
80 {
81 return _parentObjectClass.get();
82 }
83
InteractionClass(const std::string & name)84 HLAOMTXmlVisitor::InteractionClass::InteractionClass(const std::string& name) :
85 _name(name)
86 {
87 }
88
~InteractionClass()89 HLAOMTXmlVisitor::InteractionClass::~InteractionClass()
90 {
91 }
92
93 const std::string&
getName() const94 HLAOMTXmlVisitor::InteractionClass::getName() const
95 {
96 return _name;
97 }
98
99 const std::string&
getDimensions() const100 HLAOMTXmlVisitor::InteractionClass::getDimensions() const
101 {
102 return _dimensions;
103 }
104
105 const std::string&
getSharing() const106 HLAOMTXmlVisitor::InteractionClass::getSharing() const
107 {
108 return _sharing;
109 }
110
111 const std::string&
getTransportation() const112 HLAOMTXmlVisitor::InteractionClass::getTransportation() const
113 {
114 return _transportation;
115 }
116
117 const std::string&
getOrder() const118 HLAOMTXmlVisitor::InteractionClass::getOrder() const
119 {
120 return _order;
121 }
122
123 unsigned
getNumParameters() const124 HLAOMTXmlVisitor::InteractionClass::getNumParameters() const
125 {
126 return _parameters.size();
127 }
128
129 const HLAOMTXmlVisitor::Parameter*
getParameter(unsigned index) const130 HLAOMTXmlVisitor::InteractionClass::getParameter(unsigned index) const
131 {
132 if (_parameters.size() <= index)
133 return 0;
134 return _parameters[index];
135 }
136
137 const HLAOMTXmlVisitor::InteractionClass*
getParentInteractionClass() const138 HLAOMTXmlVisitor::InteractionClass::getParentInteractionClass() const
139 {
140 return _parentInteractionClass.get();
141 }
142
HLAOMTXmlVisitor()143 HLAOMTXmlVisitor::HLAOMTXmlVisitor()
144 {
145 }
146
~HLAOMTXmlVisitor()147 HLAOMTXmlVisitor::~HLAOMTXmlVisitor()
148 {
149 }
150
151 void
setDataTypesToFederate(HLAFederate & federate)152 HLAOMTXmlVisitor::setDataTypesToFederate(HLAFederate& federate)
153 {
154 // Provide all the data types
155 for (BasicDataMap::iterator i = _basicDataMap.begin(); i != _basicDataMap.end(); ++i)
156 federate.insertDataType(i->first, getDataType(i->first));
157 for (SimpleDataMap::iterator i = _simpleDataMap.begin(); i != _simpleDataMap.end(); ++i)
158 federate.insertDataType(i->first, getDataType(i->first));
159 for (EnumeratedDataMap::iterator i = _enumeratedDataMap.begin(); i != _enumeratedDataMap.end(); ++i)
160 federate.insertDataType(i->first, getDataType(i->first));
161 for (ArrayDataMap::iterator i = _arrayDataMap.begin(); i != _arrayDataMap.end(); ++i)
162 federate.insertDataType(i->first, getDataType(i->first));
163 for (FixedRecordDataMap::iterator i = _fixedRecordDataMap.begin(); i != _fixedRecordDataMap.end(); ++i)
164 federate.insertDataType(i->first, getDataType(i->first));
165 for (VariantRecordDataMap::iterator i = _variantRecordDataMap.begin(); i != _variantRecordDataMap.end(); ++i)
166 federate.insertDataType(i->first, getDataType(i->first));
167
168 // Finish alignment computations
169 federate.recomputeDataTypeAlignment();
170 }
171
172 void
setToFederate(HLAFederate & federate)173 HLAOMTXmlVisitor::setToFederate(HLAFederate& federate)
174 {
175 setDataTypesToFederate(federate);
176
177 // Provide all interaction classes
178 unsigned numInteractionClasses = getNumInteractionClasses();
179 for (unsigned i = 0; i < numInteractionClasses; ++i) {
180 const InteractionClass* interactionClass = getInteractionClass(i);
181 if (federate.getInteractionClass(interactionClass->getName())) {
182 SG_LOG(SG_IO, SG_ALERT, "Not creating Interaction class \"" << interactionClass->getName() << "\" twice!.");
183 continue;
184 }
185
186 SGSharedPtr<HLAInteractionClass> hlaInteractionClass;
187 hlaInteractionClass = federate.createInteractionClass(interactionClass->getName());
188 if (!hlaInteractionClass.valid()) {
189 SG_LOG(SG_IO, SG_INFO, "Ignoring Interaction class \"" << interactionClass->getName() << "\".");
190 continue;
191 }
192
193 hlaInteractionClass->setSubscriptionType(interactionClass->getSubscriptionType());
194 hlaInteractionClass->setPublicationType(interactionClass->getPublicationType());
195
196 // process the parameters
197 for (unsigned j = 0; j < interactionClass->getNumParameters(); ++j) {
198 const Parameter* parameter = interactionClass->getParameter(j);
199 unsigned index = hlaInteractionClass->addParameter(parameter->getName());
200 hlaInteractionClass->setParameterDataType(index, federate.getDataType(parameter->getDataType()));
201 }
202 }
203
204 // Provide all object classes
205 unsigned numObjectClasses = getNumObjectClasses();
206 for (unsigned i = 0; i < numObjectClasses; ++i) {
207 const ObjectClass* objectClass = getObjectClass(i);
208 if (federate.getObjectClass(objectClass->getName())) {
209 SG_LOG(SG_IO, SG_ALERT, "Not creating Object class \"" << objectClass->getName() << "\" twice!.");
210 continue;
211 }
212
213 SGSharedPtr<HLAObjectClass> hlaObjectClass;
214 hlaObjectClass = federate.createObjectClass(objectClass->getName());
215 if (!hlaObjectClass.valid()) {
216 SG_LOG(SG_IO, SG_INFO, "Ignoring Object class \"" << objectClass->getName() << "\".");
217 continue;
218 }
219
220 // process the attributes
221 for (unsigned j = 0; j < objectClass->getNumAttributes(); ++j) {
222 const Attribute* attribute = objectClass->getAttribute(j);
223
224 unsigned index = hlaObjectClass->addAttribute(attribute->getName());
225 hlaObjectClass->setAttributeDataType(index, federate.getDataType(attribute->getDataType()));
226
227 hlaObjectClass->setAttributeSubscriptionType(index, attribute->getSubscriptionType());
228 hlaObjectClass->setAttributePublicationType(index, attribute->getPublicationType());
229 hlaObjectClass->setAttributeUpdateType(index, attribute->getUpdateType());
230 }
231 }
232 }
233
234 unsigned
getNumObjectClasses() const235 HLAOMTXmlVisitor::getNumObjectClasses() const
236 {
237 return _objectClassList.size();
238 }
239
240 const HLAOMTXmlVisitor::ObjectClass*
getObjectClass(unsigned i) const241 HLAOMTXmlVisitor::getObjectClass(unsigned i) const
242 {
243 if (_objectClassList.size() <= i)
244 return 0;
245 return _objectClassList[i];
246 }
247
248 unsigned
getNumInteractionClasses() const249 HLAOMTXmlVisitor::getNumInteractionClasses() const
250 {
251 return _interactionClassList.size();
252 }
253
254 const HLAOMTXmlVisitor::InteractionClass*
getInteractionClass(unsigned i) const255 HLAOMTXmlVisitor::getInteractionClass(unsigned i) const
256 {
257 if (_interactionClassList.size() <= i)
258 return 0;
259 return _interactionClassList[i];
260 }
261
262 SGSharedPtr<HLADataType>
getDataType(const std::string & dataTypeName)263 HLAOMTXmlVisitor::getDataType(const std::string& dataTypeName)
264 {
265 StringDataTypeMap::const_iterator i = _dataTypeMap.find(dataTypeName);
266 if (i != _dataTypeMap.end())
267 return i->second;
268
269 SGSharedPtr<HLADataType> dataType;
270 dataType = getBasicDataType(dataTypeName);
271 if (dataType.valid()) {
272 _dataTypeMap[dataTypeName] = dataType;
273 return dataType;
274 }
275
276 dataType = getSimpleDataType(dataTypeName);
277 if (dataType.valid())
278 return dataType;
279
280 dataType = getEnumeratedDataType(dataTypeName);
281 if (dataType.valid())
282 return dataType;
283
284 dataType = getArrayDataType(dataTypeName);
285 if (dataType.valid())
286 return dataType;
287
288 dataType = getFixedRecordDataType(dataTypeName);
289 if (dataType.valid())
290 return dataType;
291
292 dataType = getVariantRecordDataType(dataTypeName);
293 if (dataType.valid())
294 return dataType;
295
296 SG_LOG(SG_IO, SG_WARN, "Could not resolve dataType \"" << dataTypeName << "\".");
297 return 0;
298 }
299
300 SGSharedPtr<HLABasicDataType>
getBasicDataType(const std::string & dataTypeName)301 HLAOMTXmlVisitor::getBasicDataType(const std::string& dataTypeName)
302 {
303 BasicDataMap::const_iterator i = _basicDataMap.find(dataTypeName);
304 if (i == _basicDataMap.end())
305 return 0;
306 if (i->second._size == "8") {
307 return new HLAUInt8DataType(dataTypeName);
308 } else if (i->second._size == "16") {
309 if (i->first.find("Unsigned") != std::string::npos) {
310 if (i->second._endian == "Little") {
311 return new HLAUInt16LEDataType(dataTypeName);
312 } else {
313 return new HLAUInt16BEDataType(dataTypeName);
314 }
315 } else if (i->first.find("octetPair") != std::string::npos) {
316 if (i->second._endian == "Little") {
317 return new HLAUInt16LEDataType(dataTypeName);
318 } else {
319 return new HLAUInt16BEDataType(dataTypeName);
320 }
321 } else {
322 if (i->second._endian == "Little") {
323 return new HLAInt16LEDataType(dataTypeName);
324 } else {
325 return new HLAInt16BEDataType(dataTypeName);
326 }
327 }
328 } else if (i->second._size == "32") {
329 if (i->first.find("Unsigned") != std::string::npos) {
330 if (i->second._endian == "Little") {
331 return new HLAUInt32LEDataType(dataTypeName);
332 } else {
333 return new HLAUInt32BEDataType(dataTypeName);
334 }
335 } else if (i->first.find("float") != std::string::npos) {
336 if (i->second._endian == "Little") {
337 return new HLAFloat32LEDataType(dataTypeName);
338 } else {
339 return new HLAFloat32BEDataType(dataTypeName);
340 }
341 } else {
342 if (i->second._endian == "Little") {
343 return new HLAInt32LEDataType(dataTypeName);
344 } else {
345 return new HLAInt32BEDataType(dataTypeName);
346 }
347 }
348 } else if (i->second._size == "64") {
349 if (i->first.find("Unsigned") != std::string::npos) {
350 if (i->second._endian == "Little") {
351 return new HLAUInt64LEDataType(dataTypeName);
352 } else {
353 return new HLAUInt64BEDataType(dataTypeName);
354 }
355 } else if (i->first.find("float") != std::string::npos) {
356 if (i->second._endian == "Little") {
357 return new HLAFloat64LEDataType(dataTypeName);
358 } else {
359 return new HLAFloat64BEDataType(dataTypeName);
360 }
361 } else {
362 if (i->second._endian == "Little") {
363 return new HLAInt64LEDataType(dataTypeName);
364 } else {
365 return new HLAInt64BEDataType(dataTypeName);
366 }
367 }
368 }
369
370 return 0;
371 }
372
373 SGSharedPtr<HLADataType>
getSimpleDataType(const std::string & dataTypeName)374 HLAOMTXmlVisitor::getSimpleDataType(const std::string& dataTypeName)
375 {
376 SimpleDataMap::const_iterator i = _simpleDataMap.find(dataTypeName);
377 if (i == _simpleDataMap.end())
378 return 0;
379 return getDataType(i->second._representation);
380 }
381
382 SGSharedPtr<HLAEnumeratedDataType>
getEnumeratedDataType(const std::string & dataTypeName)383 HLAOMTXmlVisitor::getEnumeratedDataType(const std::string& dataTypeName)
384 {
385 EnumeratedDataMap::const_iterator i = _enumeratedDataMap.find(dataTypeName);
386 if (i == _enumeratedDataMap.end())
387 return 0;
388
389 SGSharedPtr<HLAEnumeratedDataType> enumeratedDataType = new HLAEnumeratedDataType(dataTypeName);
390 _dataTypeMap[dataTypeName] = enumeratedDataType;
391 enumeratedDataType->setRepresentation(getBasicDataType(i->second._representation));
392
393 for (EnumeratorList::const_iterator j = i->second._enumeratorList.begin();
394 j != i->second._enumeratorList.end(); ++j) {
395 if (!enumeratedDataType->addEnumerator(j->_name, j->_values)) {
396 SG_LOG(SG_IO, SG_ALERT, "Could not add enumerator \"" << j->_name
397 << "\" to find enumerated data type \"" << dataTypeName << "\".");
398 return 0;
399 }
400 }
401
402 return enumeratedDataType;
403 }
404
405 SGSharedPtr<HLADataType>
getArrayDataType(const std::string & dataTypeName)406 HLAOMTXmlVisitor::getArrayDataType(const std::string& dataTypeName)
407 {
408 ArrayDataMap::const_iterator i = _arrayDataMap.find(dataTypeName);
409 if (i == _arrayDataMap.end())
410 return 0;
411 SGSharedPtr<HLAArrayDataType> arrayDataType;
412 if (i->second._encoding == "HLAvariableArray") {
413 arrayDataType = new HLAVariableArrayDataType(dataTypeName);
414 } else if (i->second._encoding == "HLAfixedArray") {
415 std::stringstream ss(i->second._cardinality);
416 unsigned cardinality;
417 ss >> cardinality;
418 if (ss.fail()) {
419 SG_LOG(SG_IO, SG_ALERT, "Could not interpret cardinality \""
420 << i->second._cardinality << "\" for dataType \""
421 << dataTypeName << "\".");
422 return 0;
423 }
424 SGSharedPtr<HLAFixedArrayDataType> dataType = new HLAFixedArrayDataType(dataTypeName);
425 dataType->setNumElements(cardinality);
426 arrayDataType = dataType;
427 } else {
428 SG_LOG(SG_IO, SG_ALERT, "Can not interpret encoding \""
429 << i->second._encoding << "\" for dataType \""
430 << dataTypeName << "\".");
431 return 0;
432 }
433
434 _dataTypeMap[dataTypeName] = arrayDataType;
435 SGSharedPtr<HLADataType> elementDataType = getDataType(i->second._dataType);
436 if (!elementDataType.valid()) {
437 SG_LOG(SG_IO, SG_ALERT, "Could not interpret dataType \""
438 << i->second._dataType << "\" for array data type \""
439 << dataTypeName << "\".");
440 _dataTypeMap.erase(dataTypeName);
441 return 0;
442 }
443 arrayDataType->setElementDataType(elementDataType.get());
444
445 // Check if this should be a string data type
446 if (elementDataType->toBasicDataType()) {
447 if (dataTypeName == "HLAopaqueData") {
448 arrayDataType->setIsOpaque(true);
449 } else if (dataTypeName.find("String") != std::string::npos || dataTypeName.find("string") != std::string::npos) {
450 arrayDataType->setIsString(true);
451 }
452 }
453
454 return arrayDataType;
455 }
456
457 SGSharedPtr<HLAFixedRecordDataType>
getFixedRecordDataType(const std::string & dataTypeName)458 HLAOMTXmlVisitor::getFixedRecordDataType(const std::string& dataTypeName)
459 {
460 FixedRecordDataMap::const_iterator i = _fixedRecordDataMap.find(dataTypeName);
461 if (i == _fixedRecordDataMap.end())
462 return 0;
463
464 SGSharedPtr<HLAFixedRecordDataType> dataType = new HLAFixedRecordDataType(dataTypeName);
465 _dataTypeMap[dataTypeName] = dataType;
466 for (FieldList::size_type j = 0; j < i->second._fieldList.size(); ++j) {
467 SGSharedPtr<HLADataType> fieldDataType = getDataType(i->second._fieldList[j]._dataType);
468 if (!fieldDataType.valid()) {
469 SG_LOG(SG_IO, SG_ALERT, "Could not get data type \"" << i->second._fieldList[j]._dataType
470 << "\" for field " << j << "of fixed record data type \"" << dataTypeName << "\".");
471 _dataTypeMap.erase(dataTypeName);
472 return 0;
473 }
474 dataType->addField(i->second._fieldList[j]._name, fieldDataType.get());
475 }
476 return dataType;
477 }
478
479 SGSharedPtr<HLAVariantRecordDataType>
getVariantRecordDataType(const std::string & dataTypeName)480 HLAOMTXmlVisitor::getVariantRecordDataType(const std::string& dataTypeName)
481 {
482 VariantRecordDataMap::const_iterator i = _variantRecordDataMap.find(dataTypeName);
483 if (i == _variantRecordDataMap.end())
484 return 0;
485 SGSharedPtr<HLAVariantRecordDataType> dataType = new HLAVariantRecordDataType(dataTypeName);
486 _dataTypeMap[dataTypeName] = dataType;
487
488 SGSharedPtr<HLAEnumeratedDataType> enumeratedDataType = getEnumeratedDataType(i->second._dataType);
489 if (!enumeratedDataType.valid()) {
490 SG_LOG(SG_IO, SG_ALERT, "Could not find enumerted data type \"" << i->second._dataType
491 << "\" for variant data type \"" << dataTypeName << "\".");
492 return 0;
493 }
494 dataType->setEnumeratedDataType(enumeratedDataType);
495
496 for (AlternativeList::const_iterator j = i->second._alternativeList.begin();
497 j != i->second._alternativeList.end(); ++j) {
498 SGSharedPtr<HLADataType> alternativeDataType = getDataType(j->_dataType);
499 if (!alternativeDataType.valid()) {
500 SG_LOG(SG_IO, SG_ALERT, "Could not resolve alternative dataType \"" << j->_dataType
501 << "\" for alternative \"" << j->_name << "\".");
502 _dataTypeMap.erase(dataTypeName);
503 return 0;
504 }
505 if (!dataType->addAlternative(j->_name, j->_enumerator, alternativeDataType.get(), j->_semantics)) {
506 SG_LOG(SG_IO, SG_ALERT, "Could not add alternative \"" << j->_name << "\".");
507 return 0;
508 }
509 }
510 return dataType;
511 }
512
513 HLAOMTXmlVisitor::Mode
getCurrentMode()514 HLAOMTXmlVisitor::getCurrentMode()
515 {
516 if (_modeStack.empty())
517 return UnknownMode;
518 return _modeStack.back();
519 }
520
521 void
pushMode(HLAOMTXmlVisitor::Mode mode)522 HLAOMTXmlVisitor::pushMode(HLAOMTXmlVisitor::Mode mode)
523 {
524 _modeStack.push_back(mode);
525 }
526
527 void
popMode()528 HLAOMTXmlVisitor::popMode()
529 {
530 _modeStack.pop_back();
531 }
532
533 void
startXML()534 HLAOMTXmlVisitor::startXML()
535 {
536 _modeStack.clear();
537 }
538
539 void
endXML()540 HLAOMTXmlVisitor::endXML()
541 {
542 if (!_modeStack.empty())
543 throw sg_exception("Internal parse error!");
544
545 // propagate parent attributes to the derived classes
546 // Note that this preserves the order of the attributes starting from the root object
547 for (ObjectClassList::const_iterator i = _objectClassList.begin(); i != _objectClassList.end(); ++i) {
548 SGSharedPtr<const ObjectClass> objectClass = (*i)->_parentObjectClass;
549 if (!objectClass.valid())
550 continue;
551 for (AttributeList::const_reverse_iterator j = objectClass->_attributes.rbegin();
552 j != objectClass->_attributes.rend(); ++j) {
553 (*i)->_attributes.insert((*i)->_attributes.begin(), *j);
554 }
555 }
556
557 // propagate parent parameter to the derived interactions
558 // Note that this preserves the order of the parameters starting from the root object
559 for (InteractionClassList::const_iterator i = _interactionClassList.begin(); i != _interactionClassList.end(); ++i) {
560 SGSharedPtr<const InteractionClass> interactionClass = (*i)->_parentInteractionClass;
561 if (!interactionClass.valid())
562 continue;
563 for (ParameterList::const_reverse_iterator j = interactionClass->_parameters.rbegin();
564 j != interactionClass->_parameters.rend(); ++j) {
565 (*i)->_parameters.insert((*i)->_parameters.begin(), *j);
566 }
567 }
568 }
569
570 void
startElement(const char * name,const XMLAttributes & atts)571 HLAOMTXmlVisitor::startElement(const char* name, const XMLAttributes& atts)
572 {
573 if (strcmp(name, "attribute") == 0) {
574 if (getCurrentMode() != ObjectClassMode)
575 throw sg_exception("attribute tag outside objectClass!");
576 pushMode(AttributeMode);
577
578 if (_objectClassList.empty())
579 throw sg_exception("attribute tag outside of an objectClass");
580
581 std::string name = getAttribute("name", atts);
582 if (name.empty())
583 throw sg_exception("attribute tag without name attribute");
584
585 SGSharedPtr<Attribute> attribute = new Attribute(name);
586
587 attribute->_dataType = getAttribute("dataType", atts);
588 attribute->_updateType = getAttribute("updateType", atts);
589 attribute->_updateCondition = getAttribute("updateCondition", atts);
590 attribute->_ownership = getAttribute("ownership", atts);
591 attribute->_sharing = getAttribute("sharing", atts);
592 attribute->_dimensions = getAttribute("dimensions", atts);
593 attribute->_transportation = getAttribute("transportation", atts);
594 attribute->_order = getAttribute("order", atts);
595
596 _objectClassStack.back()->_attributes.push_back(attribute);
597
598 } else if (strcmp(name, "objectClass") == 0) {
599 if (getCurrentMode() != ObjectsMode && getCurrentMode() != ObjectClassMode)
600 throw sg_exception("objectClass tag outside objectClass or objects!");
601 pushMode(ObjectClassMode);
602
603 std::string name = getAttribute("name", atts);
604 if (name.empty())
605 throw sg_exception("objectClass tag without name attribute");
606
607 std::string sharing = getAttribute("sharing", atts);
608
609 // The new ObjectClass
610 ObjectClass* objectClass = new ObjectClass(name, sharing);
611
612 // Inherit all previous attributes
613 if (!_objectClassStack.empty())
614 objectClass->_parentObjectClass = _objectClassStack.back();
615
616 _objectClassStack.push_back(objectClass);
617 _objectClassList.push_back(objectClass);
618
619 } else if (strcmp(name, "objects") == 0) {
620 if (getCurrentMode() != ObjectModelMode)
621 throw sg_exception("objects tag outside objectModel!");
622 pushMode(ObjectsMode);
623
624 } else if (strcmp(name, "parameter") == 0) {
625 if (getCurrentMode() != InteractionClassMode)
626 throw sg_exception("parameter tag outside interactionClass!");
627 pushMode(ParameterMode);
628
629 if (_interactionClassList.empty())
630 throw sg_exception("parameter tag outside of an interactionClass");
631
632 std::string name = getAttribute("name", atts);
633 if (name.empty())
634 throw sg_exception("parameter tag without name parameter");
635
636 SGSharedPtr<Parameter> parameter = new Parameter(name);
637 parameter->_dataType = getAttribute("dataType", atts);
638
639 _interactionClassStack.back()->_parameters.push_back(parameter);
640
641 } else if (strcmp(name, "interactionClass") == 0) {
642 if (getCurrentMode() != InteractionsMode && getCurrentMode() != InteractionClassMode)
643 throw sg_exception("interactionClass tag outside interactions or interactionClass!");
644 pushMode(InteractionClassMode);
645
646 std::string name = getAttribute("name", atts);
647 if (name.empty())
648 throw sg_exception("interactionClass tag without name attribute");
649
650 // The new ObjectClass
651 InteractionClass* interactionClass = new InteractionClass(name);
652 interactionClass->_dimensions = getAttribute("dimensions", atts);
653 interactionClass->_transportation = getAttribute("transportation", atts);
654 interactionClass->_order = getAttribute("order", atts);
655
656 // Inherit all previous attributes
657 if (!_interactionClassStack.empty())
658 interactionClass->_parentInteractionClass = _interactionClassStack.back();
659
660 _interactionClassStack.push_back(interactionClass);
661 _interactionClassList.push_back(interactionClass);
662
663 } else if (strcmp(name, "interactions") == 0) {
664 if (getCurrentMode() != ObjectModelMode)
665 throw sg_exception("interactions tag outside objectModel!");
666 pushMode(InteractionsMode);
667
668 } else if (strcmp(name, "basicData") == 0) {
669 if (getCurrentMode() != BasicDataRepresentationsMode)
670 throw sg_exception("basicData tag outside basicDataRepresentations!");
671 pushMode(BasicDataMode);
672
673 std::string name = getAttribute("name", atts);
674 if (name.empty())
675 throw sg_exception("basicData tag without name attribute");
676
677 _basicDataMap[name]._size = getAttribute("size", atts);
678 _basicDataMap[name]._endian = getAttribute("endian", atts);
679
680 } else if (strcmp(name, "basicDataRepresentations") == 0) {
681 if (getCurrentMode() != DataTypesMode)
682 throw sg_exception("basicDataRepresentations tag outside dataTypes!");
683 pushMode(BasicDataRepresentationsMode);
684
685 } else if (strcmp(name, "simpleData") == 0) {
686 if (getCurrentMode() != SimpleDataTypesMode)
687 throw sg_exception("simpleData tag outside simpleDataTypes!");
688 pushMode(SimpleDataMode);
689
690 std::string name = getAttribute("name", atts);
691 if (name.empty())
692 throw sg_exception("simpleData tag without name attribute");
693
694 _simpleDataMap[name]._representation = getAttribute("representation", atts);
695 _simpleDataMap[name]._units = getAttribute("units", atts);
696 _simpleDataMap[name]._resolution = getAttribute("resolution", atts);
697 _simpleDataMap[name]._accuracy = getAttribute("accuracy", atts);
698
699 } else if (strcmp(name, "simpleDataTypes") == 0) {
700 if (getCurrentMode() != DataTypesMode)
701 throw sg_exception("simpleDataTypes tag outside dataTypes!");
702 pushMode(SimpleDataTypesMode);
703
704 } else if (strcmp(name, "enumerator") == 0) {
705 if (getCurrentMode() != EnumeratedDataMode)
706 throw sg_exception("enumerator tag outside enumeratedData!");
707 pushMode(EnumeratorMode);
708
709 std::string name = getAttribute("name", atts);
710 if (name.empty())
711 throw sg_exception("enumerator tag without name attribute");
712
713 Enumerator enumerator;
714 enumerator._name = name;
715 enumerator._values = getAttribute("values", atts);
716 _enumeratedDataMap[_enumeratedDataName]._enumeratorList.push_back(enumerator);
717
718 } else if (strcmp(name, "enumeratedData") == 0) {
719 if (getCurrentMode() != EnumeratedDataTypesMode)
720 throw sg_exception("enumeratedData tag outside enumeratedDataTypes!");
721 pushMode(EnumeratedDataMode);
722
723 std::string name = getAttribute("name", atts);
724 if (name.empty())
725 throw sg_exception("enumeratedData tag without name attribute");
726
727 _enumeratedDataName = name;
728 _enumeratedDataMap[_enumeratedDataName]._representation = getAttribute("representation", atts);
729
730 } else if (strcmp(name, "enumeratedDataTypes") == 0) {
731 if (getCurrentMode() != DataTypesMode)
732 throw sg_exception("enumeratedDataTypes tag outside dataTypes!");
733 pushMode(EnumeratedDataTypesMode);
734
735 } else if (strcmp(name, "arrayData") == 0) {
736 if (getCurrentMode() != ArrayDataTypesMode)
737 throw sg_exception("arrayData tag outside arrayDataTypes!");
738 pushMode(ArrayDataMode);
739
740 std::string name = getAttribute("name", atts);
741 if (name.empty())
742 throw sg_exception("arrayData tag without name attribute");
743
744 _arrayDataMap[name]._dataType = getAttribute("dataType", atts);
745 _arrayDataMap[name]._cardinality = getAttribute("cardinality", atts);
746 _arrayDataMap[name]._encoding = getAttribute("encoding", atts);
747
748 } else if (strcmp(name, "arrayDataTypes") == 0) {
749 if (getCurrentMode() != DataTypesMode)
750 throw sg_exception("arrayDataTypes tag outside dataTypes!");
751 pushMode(ArrayDataTypesMode);
752
753 } else if (strcmp(name, "field") == 0) {
754 if (getCurrentMode() != FixedRecordDataMode)
755 throw sg_exception("field tag outside fixedRecordData!");
756 pushMode(FieldMode);
757
758 std::string name = getAttribute("name", atts);
759 if (name.empty())
760 throw sg_exception("field tag without name attribute");
761
762 Field field;
763 field._name = name;
764 field._dataType = getAttribute("dataType", atts);
765 _fixedRecordDataMap[_fixedRecordDataName]._fieldList.push_back(field);
766
767 } else if (strcmp(name, "fixedRecordData") == 0) {
768 if (getCurrentMode() != FixedRecordDataTypesMode)
769 throw sg_exception("fixedRecordData tag outside fixedRecordDataTypes!");
770 pushMode(FixedRecordDataMode);
771
772 std::string name = getAttribute("name", atts);
773 if (name.empty())
774 throw sg_exception("fixedRecordData tag without name attribute");
775
776 _fixedRecordDataName = name;
777 _fixedRecordDataMap[name]._encoding = getAttribute("encoding", atts);
778
779 } else if (strcmp(name, "fixedRecordDataTypes") == 0) {
780 if (getCurrentMode() != DataTypesMode)
781 throw sg_exception("fixedRecordDataTypes tag outside dataTypes!");
782 pushMode(FixedRecordDataTypesMode);
783
784 } else if (strcmp(name, "alternative") == 0) {
785
786 if (getCurrentMode() != VariantRecordDataMode)
787 throw sg_exception("alternative tag outside variantRecordData!");
788 pushMode(AlternativeDataMode);
789
790 std::string name = getAttribute("name", atts);
791 if (name.empty())
792 throw sg_exception("alternative tag without name attribute");
793
794 Alternative alternative;
795 alternative._name = name;
796 alternative._dataType = getAttribute("dataType", atts);
797 alternative._semantics = getAttribute("semantics", atts);
798 alternative._enumerator = getAttribute("enumerator", atts);
799 _variantRecordDataMap[_variantRecordDataName]._alternativeList.push_back(alternative);
800
801 } else if (strcmp(name, "variantRecordData") == 0) {
802 if (getCurrentMode() != VariantRecordDataTypesMode)
803 throw sg_exception("variantRecordData tag outside variantRecordDataTypes!");
804 pushMode(VariantRecordDataMode);
805
806 std::string name = getAttribute("name", atts);
807 if (name.empty())
808 throw sg_exception("fixedRecordData tag without name attribute");
809
810 _variantRecordDataName = name;
811 _variantRecordDataMap[name]._encoding = getAttribute("encoding", atts);
812 _variantRecordDataMap[name]._dataType = getAttribute("dataType", atts);
813 _variantRecordDataMap[name]._semantics = getAttribute("semantics", atts);
814 _variantRecordDataMap[name]._discriminant = getAttribute("discriminant", atts);
815
816 } else if (strcmp(name, "variantRecordDataTypes") == 0) {
817 if (getCurrentMode() != DataTypesMode)
818 throw sg_exception("variantRecordDataTypes tag outside dataTypes!");
819 pushMode(VariantRecordDataTypesMode);
820
821 } else if (strcmp(name, "dataTypes") == 0) {
822 if (getCurrentMode() != ObjectModelMode)
823 throw sg_exception("dataTypes tag outside objectModel!");
824 pushMode(DataTypesMode);
825
826 } else if (strcmp(name, "objectModel") == 0) {
827 if (!_modeStack.empty())
828 throw sg_exception("objectModel tag not at top level!");
829 pushMode(ObjectModelMode);
830
831 } else {
832 _modeStack.push_back(UnknownMode);
833 }
834 }
835
836 void
endElement(const char * name)837 HLAOMTXmlVisitor::endElement(const char* name)
838 {
839 if (strcmp(name, "objectClass") == 0) {
840 _objectClassStack.pop_back();
841 } else if (strcmp(name, "interactionClass") == 0) {
842 _interactionClassStack.pop_back();
843 } else if (strcmp(name, "enumeratedData") == 0) {
844 _enumeratedDataName.clear();
845 } else if (strcmp(name, "fixedRecordData") == 0) {
846 _fixedRecordDataName.clear();
847 } else if (strcmp(name, "variantRecordData") == 0) {
848 _variantRecordDataName.clear();
849 }
850
851 _modeStack.pop_back();
852 }
853
854 std::string
getAttribute(const char * name,const XMLAttributes & atts)855 HLAOMTXmlVisitor::getAttribute(const char* name, const XMLAttributes& atts)
856 {
857 int index = atts.findAttribute(name);
858 if (index < 0 || atts.size() <= index)
859 return std::string();
860 return std::string(atts.getValue(index));
861 }
862
863 std::string
getAttribute(const std::string & name,const XMLAttributes & atts)864 HLAOMTXmlVisitor::getAttribute(const std::string& name, const XMLAttributes& atts)
865 {
866 int index = atts.findAttribute(name.c_str());
867 if (index < 0 || atts.size() <= index)
868 return std::string();
869 return std::string(atts.getValue(index));
870 }
871
872 } // namespace simgear
873