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