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