]> git.mxchange.org Git - simgear.git/blob - simgear/hla/HLAOMTXmlVisitor.cxx
hla: add missing file fir the last commit.
[simgear.git] / simgear / hla / HLAOMTXmlVisitor.cxx
1 // Copyright (C) 2009 - 2011  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     // Check if this should be a string data type
443     if (elementDataType->toBasicDataType()) {
444         if (dataTypeName == "HLAopaqueData") {
445             arrayDataType->setIsOpaque(true);
446         } else if (dataTypeName.find("String") != std::string::npos || dataTypeName.find("string") != std::string::npos) {
447             arrayDataType->setIsString(true);
448         }
449     }
450
451     return arrayDataType;
452 }
453
454 SGSharedPtr<HLAFixedRecordDataType>
455 HLAOMTXmlVisitor::getFixedRecordDataType(const std::string& dataTypeName, HLAOMTXmlVisitor::StringDataTypeMap& dataTypeMap) const
456 {
457     FixedRecordDataMap::const_iterator i = _fixedRecordDataMap.find(dataTypeName);
458     if (i == _fixedRecordDataMap.end())
459         return 0;
460
461     SGSharedPtr<HLAFixedRecordDataType> dataType = new HLAFixedRecordDataType(dataTypeName);
462     dataTypeMap[dataTypeName] = dataType;
463     for (FieldList::size_type j = 0; j < i->second._fieldList.size(); ++j) {
464         SGSharedPtr<HLADataType> fieldDataType = getDataType(i->second._fieldList[j]._dataType, dataTypeMap);
465         if (!fieldDataType.valid()) {
466             SG_LOG(SG_IO, SG_ALERT, "Could not get data type \"" << i->second._fieldList[j]._dataType
467                    << "\" for field " << j << "of fixed record data type \"" << dataTypeName << "\".");
468             dataTypeMap.erase(dataTypeName);
469             return 0;
470         }
471         dataType->addField(i->second._fieldList[j]._name, fieldDataType.get());
472     }
473     return dataType;
474 }
475
476 SGSharedPtr<HLAVariantDataType>
477 HLAOMTXmlVisitor::getVariantDataType(const std::string& dataTypeName, HLAOMTXmlVisitor::StringDataTypeMap& dataTypeMap) const
478 {
479     VariantRecordDataMap::const_iterator i = _variantRecordDataMap.find(dataTypeName);
480     if (i == _variantRecordDataMap.end())
481         return 0;
482     SGSharedPtr<HLAVariantDataType> dataType = new HLAVariantDataType(dataTypeName);
483     dataTypeMap[dataTypeName] = dataType;
484
485     SGSharedPtr<HLAEnumeratedDataType> enumeratedDataType = getEnumeratedDataType(i->second._dataType);
486     if (!enumeratedDataType.valid()) {
487         SG_LOG(SG_IO, SG_ALERT, "Could not find enumerted data type \"" << i->second._dataType
488                << "\" for variant data type \"" << dataTypeName << "\".");
489         return 0;
490     }
491     dataType->setEnumeratedDataType(enumeratedDataType);
492
493     for (AlternativeList::const_iterator j = i->second._alternativeList.begin();
494          j != i->second._alternativeList.end(); ++j) {
495         SGSharedPtr<HLADataType> alternativeDataType = getDataType(j->_dataType, dataTypeMap);
496         if (!alternativeDataType.valid()) {
497             SG_LOG(SG_IO, SG_ALERT, "Could not resolve alternative dataType \"" << j->_dataType
498                    << "\" for alternative \"" << j->_name << "\".");
499             dataTypeMap.erase(dataTypeName);
500             return 0;
501         }
502         if (!dataType->addAlternative(j->_name, j->_enumerator, alternativeDataType.get(), j->_semantics)) {
503             SG_LOG(SG_IO, SG_ALERT, "Could not add alternative \"" << j->_name << "\".");
504             return 0;
505         }
506     }
507     return dataType;
508 }
509
510 HLAOMTXmlVisitor::Mode
511 HLAOMTXmlVisitor::getCurrentMode()
512 {
513     if (_modeStack.empty())
514         return UnknownMode;
515     return _modeStack.back();
516 }
517
518 void
519 HLAOMTXmlVisitor::pushMode(HLAOMTXmlVisitor::Mode mode)
520 {
521     _modeStack.push_back(mode);
522 }
523
524 void
525 HLAOMTXmlVisitor::popMode()
526 {
527     _modeStack.pop_back();
528 }
529
530 void
531 HLAOMTXmlVisitor::startXML()
532 {
533     _modeStack.clear();
534 }
535
536 void
537 HLAOMTXmlVisitor::endXML()
538 {
539     if (!_modeStack.empty())
540         throw sg_exception("Internal parse error!");
541
542     // propagate parent attributes to the derived classes
543     for (ObjectClassList::const_iterator i = _objectClassList.begin(); i != _objectClassList.end(); ++i) {
544         SGSharedPtr<const ObjectClass> objectClass = (*i)->_parentObjectClass;
545         while (objectClass) {
546             for (AttributeList::const_reverse_iterator j = objectClass->_attributes.rbegin();
547                  j != objectClass->_attributes.rend(); ++j) {
548                 (*i)->_attributes.insert((*i)->_attributes.begin(), *j);
549             }
550             objectClass = objectClass->_parentObjectClass;
551         }
552     }
553
554     // propagate parent parameter to the derived interactions
555     for (InteractionClassList::const_iterator i = _interactionClassList.begin(); i != _interactionClassList.end(); ++i) {
556         SGSharedPtr<const InteractionClass> interactionClass = (*i)->_parentInteractionClass;
557         while (interactionClass) {
558             for (ParameterList::const_reverse_iterator j = interactionClass->_parameters.rbegin();
559                  j != interactionClass->_parameters.rend(); ++j) {
560                 (*i)->_parameters.insert((*i)->_parameters.begin(), *j);
561             }
562             interactionClass = interactionClass->_parentInteractionClass;
563         }
564     }
565 }
566
567 void
568 HLAOMTXmlVisitor::startElement(const char* name, const XMLAttributes& atts)
569 {
570     if (strcmp(name, "attribute") == 0) {
571         if (getCurrentMode() != ObjectClassMode)
572             throw sg_exception("attribute tag outside objectClass!");
573         pushMode(AttributeMode);
574
575         if (_objectClassList.empty())
576             throw sg_exception("attribute tag outside of an objectClass");
577
578         std::string name = getAttribute("name", atts);
579         if (name.empty())
580             throw sg_exception("attribute tag without name attribute");
581
582         SGSharedPtr<Attribute> attribute = new Attribute(name);
583
584         attribute->_dataType = getAttribute("dataType", atts);
585         attribute->_updateType = getAttribute("updateType", atts);
586         attribute->_updateCondition = getAttribute("updateCondition", atts);
587         attribute->_ownership = getAttribute("ownership", atts);
588         attribute->_sharing = getAttribute("sharing", atts);
589         attribute->_dimensions = getAttribute("dimensions", atts);
590         attribute->_transportation = getAttribute("transportation", atts);
591         attribute->_order = getAttribute("order", atts);
592
593         _objectClassStack.back()->_attributes.push_back(attribute);
594
595     } else if (strcmp(name, "objectClass") == 0) {
596         if (getCurrentMode() != ObjectsMode && getCurrentMode() != ObjectClassMode)
597             throw sg_exception("objectClass tag outside objectClass or objects!");
598         pushMode(ObjectClassMode);
599
600         std::string name = getAttribute("name", atts);
601         if (name.empty())
602             throw sg_exception("objectClass tag without name attribute");
603
604         std::string sharing = getAttribute("sharing", atts);
605
606         // The new ObjectClass
607         ObjectClass* objectClass = new ObjectClass(name, sharing);
608
609         // Inherit all previous attributes
610         if (!_objectClassStack.empty())
611             objectClass->_parentObjectClass = _objectClassStack.back();
612
613         _objectClassStack.push_back(objectClass);
614         _objectClassList.push_back(objectClass);
615
616     } else if (strcmp(name, "objects") == 0) {
617         if (getCurrentMode() != ObjectModelMode)
618             throw sg_exception("objects tag outside objectModel!");
619         pushMode(ObjectsMode);
620
621     } else if (strcmp(name, "parameter") == 0) {
622         if (getCurrentMode() != InteractionClassMode)
623             throw sg_exception("parameter tag outside interactionClass!");
624         pushMode(ParameterMode);
625
626         if (_interactionClassList.empty())
627             throw sg_exception("parameter tag outside of an interactionClass");
628
629         std::string name = getAttribute("name", atts);
630         if (name.empty())
631             throw sg_exception("parameter tag without name parameter");
632
633         SGSharedPtr<Parameter> parameter = new Parameter(name);
634         parameter->_dataType = getAttribute("dataType", atts);
635
636         _interactionClassStack.back()->_parameters.push_back(parameter);
637
638     } else if (strcmp(name, "interactionClass") == 0) {
639         if (getCurrentMode() != InteractionsMode && getCurrentMode() != InteractionClassMode)
640             throw sg_exception("interactionClass tag outside interactions or interactionClass!");
641         pushMode(InteractionClassMode);
642
643         std::string name = getAttribute("name", atts);
644         if (name.empty())
645             throw sg_exception("interactionClass tag without name attribute");
646
647         // The new ObjectClass
648         InteractionClass* interactionClass = new InteractionClass(name);
649         interactionClass->_dimensions = getAttribute("dimensions", atts);
650         interactionClass->_transportation = getAttribute("transportation", atts);
651         interactionClass->_order = getAttribute("order", atts);
652
653         // Inherit all previous attributes
654         if (!_interactionClassStack.empty())
655             interactionClass->_parentInteractionClass = _interactionClassStack.back();
656
657         _interactionClassStack.push_back(interactionClass);
658         _interactionClassList.push_back(interactionClass);
659
660     } else if (strcmp(name, "interactions") == 0) {
661         if (getCurrentMode() != ObjectModelMode)
662             throw sg_exception("interactions tag outside objectModel!");
663         pushMode(InteractionsMode);
664
665     } else if (strcmp(name, "basicData") == 0) {
666         if (getCurrentMode() != BasicDataRepresentationsMode)
667             throw sg_exception("basicData tag outside basicDataRepresentations!");
668         pushMode(BasicDataMode);
669
670         std::string name = getAttribute("name", atts);
671         if (name.empty())
672             throw sg_exception("basicData tag without name attribute");
673
674         _basicDataMap[name]._size = getAttribute("size", atts);
675         _basicDataMap[name]._endian = getAttribute("endian", atts);
676
677     } else if (strcmp(name, "basicDataRepresentations") == 0) {
678         if (getCurrentMode() != DataTypesMode)
679             throw sg_exception("basicDataRepresentations tag outside dataTypes!");
680         pushMode(BasicDataRepresentationsMode);
681
682     } else if (strcmp(name, "simpleData") == 0) {
683         if (getCurrentMode() != SimpleDataTypesMode)
684             throw sg_exception("simpleData tag outside simpleDataTypes!");
685         pushMode(SimpleDataMode);
686
687         std::string name = getAttribute("name", atts);
688         if (name.empty())
689             throw sg_exception("simpleData tag without name attribute");
690
691         _simpleDataMap[name]._representation = getAttribute("representation", atts);
692         _simpleDataMap[name]._units = getAttribute("units", atts);
693         _simpleDataMap[name]._resolution = getAttribute("resolution", atts);
694         _simpleDataMap[name]._accuracy = getAttribute("accuracy", atts);
695
696     } else if (strcmp(name, "simpleDataTypes") == 0) {
697         if (getCurrentMode() != DataTypesMode)
698             throw sg_exception("simpleDataTypes tag outside dataTypes!");
699         pushMode(SimpleDataTypesMode);
700
701     } else if (strcmp(name, "enumerator") == 0) {
702         if (getCurrentMode() != EnumeratedDataMode)
703             throw sg_exception("enumerator tag outside enumeratedData!");
704         pushMode(EnumeratorMode);
705
706         std::string name = getAttribute("name", atts);
707         if (name.empty())
708             throw sg_exception("enumerator tag without name attribute");
709
710         Enumerator enumerator;
711         enumerator._name = name;
712         enumerator._values = getAttribute("values", atts);
713         _enumeratedDataMap[_enumeratedDataName]._enumeratorList.push_back(enumerator);
714
715     } else if (strcmp(name, "enumeratedData") == 0) {
716         if (getCurrentMode() != EnumeratedDataTypesMode)
717             throw sg_exception("enumeratedData tag outside enumeratedDataTypes!");
718         pushMode(EnumeratedDataMode);
719
720         std::string name = getAttribute("name", atts);
721         if (name.empty())
722             throw sg_exception("enumeratedData tag without name attribute");
723
724         _enumeratedDataName = name;
725         _enumeratedDataMap[_enumeratedDataName]._representation = getAttribute("representation", atts);
726
727     } else if (strcmp(name, "enumeratedDataTypes") == 0) {
728         if (getCurrentMode() != DataTypesMode)
729             throw sg_exception("enumeratedDataTypes tag outside dataTypes!");
730         pushMode(EnumeratedDataTypesMode);
731
732         Enumerator enumerator;
733         enumerator._name = getAttribute("name", atts);
734         enumerator._values = getAttribute("values", atts);
735         _enumeratedDataMap[_enumeratedDataName]._enumeratorList.push_back(enumerator);
736
737     } else if (strcmp(name, "arrayData") == 0) {
738         if (getCurrentMode() != ArrayDataTypesMode)
739             throw sg_exception("arrayData tag outside arrayDataTypes!");
740         pushMode(ArrayDataMode);
741
742         std::string name = getAttribute("name", atts);
743         if (name.empty())
744             throw sg_exception("arrayData tag without name attribute");
745
746         _arrayDataMap[name]._dataType = getAttribute("dataType", atts);
747         _arrayDataMap[name]._cardinality = getAttribute("cardinality", atts);
748         _arrayDataMap[name]._encoding = getAttribute("encoding", atts);
749
750     } else if (strcmp(name, "arrayDataTypes") == 0) {
751         if (getCurrentMode() != DataTypesMode)
752             throw sg_exception("arrayDataTypes tag outside dataTypes!");
753         pushMode(ArrayDataTypesMode);
754
755     } else if (strcmp(name, "field") == 0) {
756         if (getCurrentMode() != FixedRecordDataMode)
757             throw sg_exception("field tag outside fixedRecordData!");
758         pushMode(FieldMode);
759
760         std::string name = getAttribute("name", atts);
761         if (name.empty())
762             throw sg_exception("field tag without name attribute");
763
764         Field field;
765         field._name = name;
766         field._dataType = getAttribute("dataType", atts);
767         _fixedRecordDataMap[_fixedRecordDataName]._fieldList.push_back(field);
768
769     } else if (strcmp(name, "fixedRecordData") == 0) {
770         if (getCurrentMode() != FixedRecordDataTypesMode)
771             throw sg_exception("fixedRecordData tag outside fixedRecordDataTypes!");
772         pushMode(FixedRecordDataMode);
773
774         std::string name = getAttribute("name", atts);
775         if (name.empty())
776             throw sg_exception("fixedRecordData tag without name attribute");
777
778         _fixedRecordDataName = name;
779         _fixedRecordDataMap[name]._encoding = getAttribute("encoding", atts);
780
781     } else if (strcmp(name, "fixedRecordDataTypes") == 0) {
782         if (getCurrentMode() != DataTypesMode)
783             throw sg_exception("fixedRecordDataTypes tag outside dataTypes!");
784         pushMode(FixedRecordDataTypesMode);
785
786     } else if (strcmp(name, "alternative") == 0) {
787
788         if (getCurrentMode() != VariantRecordDataMode)
789             throw sg_exception("alternative tag outside variantRecordData!");
790         pushMode(AlternativeDataMode);
791
792         std::string name = getAttribute("name", atts);
793         if (name.empty())
794             throw sg_exception("alternative tag without name attribute");
795
796         Alternative alternative;
797         alternative._name = name;
798         alternative._dataType = getAttribute("dataType", atts);
799         alternative._semantics = getAttribute("semantics", atts);
800         alternative._enumerator = getAttribute("enumerator", atts);
801         _variantRecordDataMap[_variantRecordDataName]._alternativeList.push_back(alternative);
802
803     } else if (strcmp(name, "variantRecordData") == 0) {
804         if (getCurrentMode() != VariantRecordDataTypesMode)
805             throw sg_exception("variantRecordData tag outside variantRecordDataTypes!");
806         pushMode(VariantRecordDataMode);
807
808         std::string name = getAttribute("name", atts);
809         if (name.empty())
810             throw sg_exception("fixedRecordData tag without name attribute");
811
812         _variantRecordDataName = name;
813         _variantRecordDataMap[name]._encoding = getAttribute("encoding", atts);
814         _variantRecordDataMap[name]._dataType = getAttribute("dataType", atts);
815         _variantRecordDataMap[name]._semantics = getAttribute("semantics", atts);
816         _variantRecordDataMap[name]._discriminant = getAttribute("discriminant", atts);
817
818     } else if (strcmp(name, "variantRecordDataTypes") == 0) {
819         if (getCurrentMode() != DataTypesMode)
820             throw sg_exception("variantRecordDataTypes tag outside dataTypes!");
821         pushMode(VariantRecordDataTypesMode);
822
823     } else if (strcmp(name, "dataTypes") == 0) {
824         if (getCurrentMode() != ObjectModelMode)
825             throw sg_exception("dataTypes tag outside objectModel!");
826         pushMode(DataTypesMode);
827
828     } else if (strcmp(name, "objectModel") == 0) {
829         if (!_modeStack.empty())
830             throw sg_exception("objectModel tag not at top level!");
831         pushMode(ObjectModelMode);
832
833     } else {
834         _modeStack.push_back(UnknownMode);
835     }
836 }
837
838 void
839 HLAOMTXmlVisitor::endElement(const char* name)
840 {
841     if (strcmp(name, "objectClass") == 0) {
842         _objectClassStack.pop_back();
843     } else if (strcmp(name, "interactionClass") == 0) {
844         _interactionClassStack.pop_back();
845     } else if (strcmp(name, "enumeratedData") == 0) {
846         _enumeratedDataName.clear();
847     } else if (strcmp(name, "fixedRecordData") == 0) {
848         _fixedRecordDataName.clear();
849     } else if (strcmp(name, "variantRecordData") == 0) {
850         _variantRecordDataName.clear();
851     }
852
853     _modeStack.pop_back();
854 }
855
856 std::string
857 HLAOMTXmlVisitor::getAttribute(const char* name, const XMLAttributes& atts)
858 {
859     int index = atts.findAttribute(name);
860     if (index < 0 || atts.size() <= index)
861         return std::string();
862     return std::string(atts.getValue(index));
863 }
864
865 std::string
866 HLAOMTXmlVisitor::getAttribute(const std::string& name, const XMLAttributes& atts)
867 {
868     int index = atts.findAttribute(name.c_str());
869     if (index < 0 || atts.size() <= index)
870         return std::string();
871     return std::string(atts.getValue(index));
872 }
873
874 } // namespace simgear