123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655 |
- /*
- * Copyright QTronic GmbH. All rights reserved.
- */
- /* ---------------------------------------------------------------------------*
- * XmlElement.cpp
- * Elements implementation that describe content of model description of a
- * FMI 2.0 model. All elements have Element as parent class. Elements have
- * attributes and other specific content.
- *
- * Author: Adrian Tirea
- * ---------------------------------------------------------------------------*/
- #include "XmlElement.h"
- #include <assert.h>
- #include <map>
- #include <string>
- #include <vector>
- #include "XmlParserException.h"
- #ifdef STANDALONE_XML_PARSER
- #define logThis(n, ...) printf(__VA_ARGS__); printf("\n")
- #else
- #include "GlobalIncludes.h"
- #include "logging.h" // logThis
- #endif // STANDALONE_XML_PARSER
- Element::~Element() {
- for (std::map<XmlParser::Att, char *>::const_iterator it = attributes.begin(); it != attributes.end(); ++it) {
- free(it->second);
- }
- attributes.clear();
- }
- template <typename T> void Element::deleteListOfElements(const std::vector<T *> &list) {
- typename std::vector<T*>::const_iterator it;
- for (it = list.begin(); it != list.end(); ++it) {
- delete *it;
- }
- }
- void Element::handleElement(XmlParser *parser, const char *childName, int isEmptyElement) {
- throw XmlParserException("Elements are not expected inside '%s'. Found instead '%s'",
- XmlParser::elmNames[type],
- childName);
- }
- void Element::printElement(int indent) {
- std::string indentS(indent, ' ');
- logThis(ERROR_INFO, "%s%s", indentS.c_str(), XmlParser::elmNames[type]);
- for (std::map<XmlParser::Att, char *>::const_iterator it = attributes.begin(); it != attributes.end(); ++it) {
- logThis(ERROR_INFO, "%s%s=%s", indentS.c_str(), XmlParser::attNames[it->first], it->second);
- }
- }
- template <typename T> void Element::printListOfElements(int indent, const std::vector<T *> &list) {
- typename std::vector<T*>::const_iterator it;
- for (it = list.begin(); it != list.end(); ++it) {
- (*it)->printElement(indent);
- }
- }
- const char *Element::getAttributeValue(XmlParser::Att att) {
- std::map<XmlParser::Att, char *>::const_iterator it = attributes.find(att);
- if (it != attributes.end()) {
- return it->second;
- }
- return NULL;
- }
- int Element::getAttributeInt(XmlParser::Att att, XmlParser::ValueStatus *vs) {
- int n = 0;
- const char *value = getAttributeValue(att);
- if (!value) { *vs = XmlParser::valueMissing; return n; }
- *vs = (1 == sscanf(value, "%d", &n)) ? XmlParser::valueDefined : XmlParser::valueIllegal;
- return n;
- }
- unsigned int Element::getAttributeUInt(XmlParser::Att att, XmlParser::ValueStatus *vs) {
- unsigned int u = -1;
- const char* value = getAttributeValue(att);
- if (!value) { *vs = XmlParser::valueMissing; return u; }
- *vs = (1 == sscanf(value, "%u", &u)) ? XmlParser::valueDefined : XmlParser::valueIllegal;
- return u;
- }
- double Element::getAttributeDouble(XmlParser::Att att, XmlParser::ValueStatus *vs) {
- double d = 0;
- const char* value = getAttributeValue(att);
- if (!value) { *vs = XmlParser::valueMissing; return d; }
- *vs = (1 == sscanf(value, "%lf", &d)) ? XmlParser::valueDefined : XmlParser::valueIllegal;
- return d;
- }
- bool Element::getAttributeBool(XmlParser::Att att, XmlParser::ValueStatus *vs) {
- const char* value = getAttributeValue(att);
- if (!value) {*vs = XmlParser::valueMissing; return false;}
- *vs = XmlParser::valueDefined;
- if (!strcmp(value, "true")) return true;
- if (!strcmp(value, "false")) return false;
- *vs = XmlParser::valueIllegal;
- return false;
- }
- ListElement::~ListElement() {
- deleteListOfElements(list);
- }
- void ListElement::handleElement(XmlParser *parser, const char *childName, int isEmptyElement) {
- XmlParser::Elm childType = parser->checkElement(childName);
- if (childType == XmlParser::elm_Item) {
- Element *item = new Element;
- item->type = childType;
- parser->parseElementAttributes(item);
- if (!isEmptyElement) {
- parser->parseEndElement();
- }
- list.push_back(item);
- } else {
- throw XmlParserException("Expected '%s' element inside '%s'. Found instead: '%s'.",
- XmlParser::elmNames[XmlParser::elm_Item],
- XmlParser::elmNames[XmlParser::elm_Enumeration],
- childName);
- }
- }
- void ListElement::printElement(int indent) {
- Element::printElement(indent);
- int childIndent = indent + 1;
- printListOfElements(childIndent, list);
- }
- Unit::Unit() {
- baseUnit = NULL;
- }
- Unit::~Unit() {
- if (baseUnit) delete baseUnit;
- deleteListOfElements(displayUnits);
- }
- void Unit::handleElement(XmlParser *parser, const char *childName, int isEmptyElement) {
- XmlParser::Elm childType = parser->checkElement(childName);
- if (childType == XmlParser::elm_BaseUnit) {
- baseUnit = new Element;
- baseUnit->type = childType;
- parser->parseElementAttributes(baseUnit);
- if (!isEmptyElement) {
- parser->parseEndElement();
- }
- } else if (childType == XmlParser::elm_DisplayUnit) {
- Element *displayUnit = new Element;
- displayUnit->type = childType;
- parser->parseElementAttributes(displayUnit);
- displayUnits.push_back(displayUnit);
- if (!isEmptyElement) {
- parser->parseEndElement();
- }
- } else {
- throw XmlParserException("Expected '%s' | '%s' element inside '%s'. Found instead: '%s'.",
- XmlParser::elmNames[XmlParser::elm_BaseUnit],
- XmlParser::elmNames[XmlParser::elm_DisplayUnit],
- XmlParser::elmNames[XmlParser::elm_SourceFiles],
- childName);
- }
- }
- void Unit::printElement(int indent) {
- Element::printElement(indent);
- int childIndent = indent + 1;
- if (baseUnit) baseUnit->printElement(childIndent);
- printListOfElements(childIndent, displayUnits);
- }
- SimpleType::SimpleType() {
- typeSpec = NULL;
- }
- SimpleType::~SimpleType() {
- if (typeSpec) delete typeSpec;
- }
- void SimpleType::handleElement(XmlParser *parser, const char *childName, int isEmptyElement) {
- XmlParser::Elm childType = parser->checkElement(childName);
- switch (childType) {
- case XmlParser::elm_Real:
- case XmlParser::elm_Integer:
- case XmlParser::elm_Boolean:
- case XmlParser::elm_String: {
- typeSpec = new Element;
- typeSpec->type = childType;
- parser->parseElementAttributes(typeSpec);
- if (!isEmptyElement) {
- parser->parseEndElement();
- }
- break;
- }
- case XmlParser::elm_Enumeration: {
- typeSpec = new ListElement;
- typeSpec->type = childType;
- parser->parseElementAttributes(typeSpec);
- if (!isEmptyElement) {
- parser->parseChildElements(typeSpec);
- }
- break;
- }
- default: {
- throw XmlParserException(
- "Expected '%s' | '%s' | '%s' | '%s' | '%s' element inside '%s'. Found instead: '%s'.",
- XmlParser::elmNames[XmlParser::elm_Real],
- XmlParser::elmNames[XmlParser::elm_Integer],
- XmlParser::elmNames[XmlParser::elm_Boolean],
- XmlParser::elmNames[XmlParser::elm_String],
- XmlParser::elmNames[XmlParser::elm_Enumeration],
- XmlParser::elmNames[type],
- childName);
- }
- }
- }
- void SimpleType::printElement(int indent) {
- Element::printElement(indent);
- int childIndent = indent + 1;
- if (typeSpec) typeSpec->printElement(childIndent);
- }
- Component::~Component() {
- deleteListOfElements(files);
- }
- void Component::handleElement(XmlParser *parser, const char *childName, int isEmptyElement) {
- XmlParser::Elm childType = parser->checkElement(childName);
- if (childType == XmlParser::elm_SourceFiles) {
- if (!isEmptyElement) {
- parser->parseChildElements(this);
- }
- } else if (childType == XmlParser::elm_File) {
- Element *sourceFile = new Element;
- sourceFile->type = childType;
- parser->parseElementAttributes(sourceFile);
- if (!isEmptyElement) {
- parser->parseEndElement();
- }
- files.push_back(sourceFile);
- } else {
- throw XmlParserException("Expected '%s' | '%s' element inside '%s'. Found instead: '%s'.",
- XmlParser::elmNames[XmlParser::elm_File],
- XmlParser::elmNames[XmlParser::elm_SourceFiles],
- XmlParser::elmNames[type],
- childName);
- }
- }
- void Component::printElement(int indent) {
- Element::printElement(indent);
- int childIndent = indent + 1;
- printListOfElements(childIndent, files);
- }
- ScalarVariable::ScalarVariable() {
- typeSpec = NULL;
- }
- ScalarVariable::~ScalarVariable() {
- delete typeSpec;
- deleteListOfElements(annotations);
- }
- void ScalarVariable::handleElement(XmlParser *parser, const char *childName, int isEmptyElement) {
- XmlParser::Elm childType = parser->checkElement(childName);
- switch (childType) {
- case XmlParser::elm_Real:
- case XmlParser::elm_Integer:
- case XmlParser::elm_Boolean:
- case XmlParser::elm_String:
- case XmlParser::elm_Enumeration: {
- typeSpec = new Element;
- typeSpec->type = childType;
- parser->parseElementAttributes(typeSpec);
- if (!isEmptyElement) {
- parser->parseEndElement();
- }
- break;
- }
- case XmlParser::elm_Annotations: {
- // no attributes expected; this class handles also the Tool
- if (!isEmptyElement) parser->parseChildElements(this);
- break;
- }
- case XmlParser::elm_Tool: {
- Element *tool = new Element;
- tool->type = childType;
- parser->parseElementAttributes(tool, false);
- if (!isEmptyElement) {
- parser->parseSkipChildElement();
- }
- annotations.push_back(tool);
- break;
- }
- default: {
- throw XmlParserException(
- "Expected '%s' | '%s' | '%s' | '%s' | '%s' | '%s' | '%s' element inside '%s'. Found instead: '%s'.",
- XmlParser::elmNames[XmlParser::elm_Real],
- XmlParser::elmNames[XmlParser::elm_Integer],
- XmlParser::elmNames[XmlParser::elm_Boolean],
- XmlParser::elmNames[XmlParser::elm_String],
- XmlParser::elmNames[XmlParser::elm_Enumeration],
- XmlParser::elmNames[XmlParser::elm_Annotations],
- XmlParser::elmNames[XmlParser::elm_Tool],
- XmlParser::elmNames[type],
- childName);
- }
- }
- }
- fmi2ValueReference ScalarVariable::getValueReference() {
- XmlParser::ValueStatus vs;
- fmi2ValueReference ref = getAttributeUInt(XmlParser::att_valueReference, &vs);
- assert(vs == XmlParser::valueDefined); // this is a required attribute
- return ref;
- }
- XmlParser::Enu ScalarVariable::getVariability() {
- const char *value = getAttributeValue(XmlParser::att_variability);
- if (!value) {
- return XmlParser::enu_continuous; // default
- }
- try {
- return XmlParser::checkEnumValue(value);
- } catch (XmlParserException& ) {
- return XmlParser::enu_BAD_DEFINED;
- }
- }
- XmlParser::Enu ScalarVariable::getCausality() {
- const char *value = getAttributeValue(XmlParser::att_causality);
- if (!value) {
- return XmlParser::enu_local; // default
- }
- try {
- return XmlParser::checkEnumValue(value);
- } catch (XmlParserException& ) {
- return XmlParser::enu_BAD_DEFINED;
- }
- }
- void ScalarVariable::printElement(int indent) {
- Element::printElement(indent);
- int childIndent = indent + 1;
- typeSpec->printElement(childIndent);
- printListOfElements(childIndent, annotations);
- }
- ModelStructure::ModelStructure() {
- unknownParentType = XmlParser::elm_BAD_DEFINED;
- }
- ModelStructure::~ModelStructure() {
- deleteListOfElements(outputs);
- deleteListOfElements(derivatives);
- deleteListOfElements(discreteStates);
- deleteListOfElements(initialUnknowns);
- }
- void ModelStructure::handleElement(XmlParser *parser, const char *childName, int isEmptyElement) {
- XmlParser::Elm childType = parser->checkElement(childName);
- switch (childType) {
- case XmlParser::elm_Outputs:
- case XmlParser::elm_Derivatives:
- case XmlParser::elm_DiscreteStates:
- case XmlParser::elm_InitialUnknowns:
- {
- // no attributes expected; this class handles also the Unknown
- if (!isEmptyElement) {
- unknownParentType = childType;
- parser->parseChildElements(this);
- }
- break;
- }
- case XmlParser::elm_Unknown:
- {
- Element *unknown = new Element;
- unknown->type = childType;
- parser->parseElementAttributes(unknown);
- if (!isEmptyElement) {
- parser->parseEndElement();
- }
- switch (unknownParentType) {
- case XmlParser::elm_Outputs:
- outputs.push_back(unknown);
- break;
- case XmlParser::elm_Derivatives:
- derivatives.push_back(unknown);
- break;
- case XmlParser::elm_DiscreteStates:
- discreteStates.push_back(unknown);
- break;
- case XmlParser::elm_InitialUnknowns:
- initialUnknowns.push_back(unknown);
- break;
- default: {
- throw XmlParserException(
- "Element '%s' must be inside of '%s' | '%s' | '%s' | '%s'.",
- XmlParser::elmNames[XmlParser::elm_Unknown],
- XmlParser::elmNames[XmlParser::elm_Outputs],
- XmlParser::elmNames[XmlParser::elm_Derivatives],
- XmlParser::elmNames[XmlParser::elm_DiscreteStates],
- XmlParser::elmNames[XmlParser::elm_InitialUnknowns]);
- }
- }
- break;
- }
- default:
- {
- throw XmlParserException(
- "Expected '%s' | '%s' | '%s' | '%s' | '%s' element inside '%s'. Found instead: '%s'.",
- XmlParser::elmNames[XmlParser::elm_Outputs],
- XmlParser::elmNames[XmlParser::elm_Derivatives],
- XmlParser::elmNames[XmlParser::elm_DiscreteStates],
- XmlParser::elmNames[XmlParser::elm_InitialUnknowns],
- XmlParser::elmNames[XmlParser::elm_Unknown],
- XmlParser::elmNames[type],
- childName);
- }
- }
- }
- void ModelStructure::printElement(int indent) {
- Element::printElement(indent);
- int childIndent = indent + 1;
- printListOfElements(childIndent, outputs);
- printListOfElements(childIndent, derivatives);
- printListOfElements(childIndent, discreteStates);
- printListOfElements(childIndent, initialUnknowns);
- }
- ModelDescription::ModelDescription() {
- modelExchange = NULL;
- coSimulation = NULL;
- defaultExperiment = NULL;
- modelStructure = NULL;
- }
- ModelDescription::~ModelDescription() {
- deleteListOfElements(unitDefinitions);
- deleteListOfElements(typeDefinitions);
- if (coSimulation) delete coSimulation;
- if (modelExchange) delete modelExchange;
- deleteListOfElements(logCategories);
- if (defaultExperiment) delete defaultExperiment;
- deleteListOfElements(vendorAnnotations);
- deleteListOfElements(modelVariables);
- if (modelStructure) delete modelStructure;
- }
- void ModelDescription::handleElement(XmlParser *parser, const char *childName, int isEmptyElement) {
- XmlParser::Elm childType = parser->checkElement(childName);
- switch (childType) {
- case XmlParser::elm_CoSimulation:
- {
- coSimulation = new Component;
- coSimulation->type = childType;
- parser->parseElementAttributes(coSimulation);
- if (!isEmptyElement) {
- parser->parseChildElements(coSimulation);
- }
- break;
- }
- case XmlParser::elm_ModelExchange:
- {
- modelExchange = new Component;
- modelExchange->type = childType;
- parser->parseElementAttributes(modelExchange);
- if (!isEmptyElement) {
- parser->parseChildElements(modelExchange);
- }
- break;
- }
- case XmlParser::elm_UnitDefinitions:
- {
- // no attributes expected; this class handles the Category
- if (!isEmptyElement) parser->parseChildElements(this);
- break;
- }
- case XmlParser::elm_Unit:
- {
- Unit *unit = new Unit;
- unit->type = childType;
- parser->parseElementAttributes(unit);
- if (!isEmptyElement) {
- parser->parseChildElements(unit);
- }
- unitDefinitions.push_back(unit);
- break;
- }
- case XmlParser::elm_TypeDefinitions:
- {
- // no attributes expected; this class handles also the SimpleType
- if (!isEmptyElement) parser->parseChildElements(this);
- break;
- }
- case XmlParser::elm_SimpleType:
- {
- SimpleType *type = new SimpleType;
- type->type = childType;
- parser->parseElementAttributes(type);
- if (!isEmptyElement) {
- parser->parseChildElements(type);
- }
- typeDefinitions.push_back(type);
- break;
- }
- case XmlParser::elm_DefaultExperiment:
- {
- defaultExperiment = new Element;
- defaultExperiment->type = childType;
- parser->parseElementAttributes(defaultExperiment);
- if (!isEmptyElement) {
- parser->parseEndElement();
- }
- break;
- }
- case XmlParser::elm_LogCategories:
- {
- // no attributes expected; this class handles also the Category
- if (!isEmptyElement) parser->parseChildElements(this);
- break;
- }
- case XmlParser::elm_Category:
- {
- Element *category = new Element;
- category->type = childType;
- parser->parseElementAttributes(category);
- if (!isEmptyElement) {
- parser->parseEndElement();
- }
- logCategories.push_back(category);
- break;
- }
- case XmlParser::elm_VendorAnnotations:
- {
- // no attributes expected; this class handles also the Tool
- if (!isEmptyElement) parser->parseChildElements(this);
- break;
- }
- case XmlParser::elm_Tool:
- {
- Element *tool = new Element;
- tool->type = childType;
- parser->parseElementAttributes(tool, false);
- if (!isEmptyElement) {
- parser->parseSkipChildElement();
- }
- vendorAnnotations.push_back(tool);
- break;
- }
- case XmlParser::elm_ModelVariables:
- {
- // no attributes expected; this class handles also the ScalarVariable
- if (!isEmptyElement) parser->parseChildElements(this);
- break;
- }
- case XmlParser::elm_ScalarVariable:
- {
- ScalarVariable *variable = new ScalarVariable;
- variable->type = childType;
- parser->parseElementAttributes(variable);
- if (!isEmptyElement) {
- parser->parseChildElements(variable);
- }
- modelVariables.push_back(variable);
- break;
- }
- case XmlParser::elm_ModelStructure:
- {
- modelStructure = new ModelStructure;
- modelStructure->type = childType;
- parser->parseElementAttributes(modelStructure);
- if (!isEmptyElement) {
- parser->parseChildElements(modelStructure);
- }
- break;
- }
- default:
- throw XmlParserException("Element '%s' is not expected inside of '%s' | '%s' | '%s' | '%s'.",
- childName,
- XmlParser::elmNames[type]);
- }
- }
- void ModelDescription::printElement(int indent) {
- Element::printElement(indent);
- int childIndent = indent + 1;
- if (coSimulation) coSimulation->printElement(childIndent);
- if (modelExchange) modelExchange->printElement(childIndent);
- for (std::vector<Unit *>::const_iterator it = unitDefinitions.begin(); it != unitDefinitions.end(); ++it) {
- (*it)->printElement(childIndent);
- }
- for (std::vector<SimpleType *>::const_iterator it = typeDefinitions.begin(); it != typeDefinitions.end(); ++it) {
- (*it)->printElement(childIndent);
- }
- for (std::vector<Element *>::const_iterator it = logCategories.begin(); it != logCategories.end(); ++it) {
- (*it)->printElement(childIndent);
- }
- if (defaultExperiment) defaultExperiment->printElement(childIndent);
- for (std::vector<Element *>::const_iterator it = vendorAnnotations.begin(); it != vendorAnnotations.end(); ++it) {
- (*it)->printElement(childIndent);
- }
- for (std::vector<ScalarVariable *>::const_iterator it = modelVariables.begin(); it != modelVariables.end(); ++it) {
- (*it)->printElement(childIndent);
- }
- if (modelStructure) modelStructure->printElement(childIndent);
- }
- SimpleType *ModelDescription::getSimpleType(const char *name) {
- for (std::vector<SimpleType *>::const_iterator it = typeDefinitions.begin(); it != typeDefinitions.end(); ++it) {
- const char *typeName = (*it)->getAttributeValue(XmlParser::att_name);
- if (typeName && 0 == strcmp(typeName, name)) {
- return (*it);
- }
- }
- return NULL;
- }
- ScalarVariable *ModelDescription::getVariable(const char *name) {
- if (!name) return NULL;
- for (std::vector<ScalarVariable *>::const_iterator it = modelVariables.begin(); it != modelVariables.end(); ++it) {
- const char *varName = (*it)->getAttributeValue(XmlParser::att_name);
- if (varName && 0 == strcmp(name, varName)) {
- return (*it);
- }
- }
- return NULL;
- }
- // Enumeration and Integer have the same base type while
- // Real, String, Boolean define own base types.
- static int sameBaseType(XmlParser::Elm t1, XmlParser::Elm t2){
- return t1 == t2 ||
- t1 == XmlParser::elm_Enumeration && t2 == XmlParser::elm_Integer ||
- t2 == XmlParser::elm_Enumeration && t1 == XmlParser::elm_Integer;
- }
- ScalarVariable *ModelDescription::getVariable(fmi2ValueReference vr, XmlParser::Elm type) {
- for (std::vector<ScalarVariable *>::const_iterator it = modelVariables.begin(); it != modelVariables.end(); ++it) {
- if (vr == (*it)->getValueReference() && sameBaseType(type, (*it)->typeSpec->type)) {
- return (*it);
- }
- }
- return NULL;
- }
- const char *ModelDescription::getDescriptionForVariable(ScalarVariable *sv) {
- const char *desc = sv->getAttributeValue(XmlParser::att_description);
- // found description
- if (desc) return desc;
- // look for description of declared type:
- const char *typeName = sv->typeSpec->getAttributeValue(XmlParser::att_declaredType);
- if (typeName) {
- SimpleType *type = getSimpleType(typeName);
- if (type) return type->getAttributeValue(XmlParser::att_description);
- }
- return NULL;
- }
- const char *ModelDescription::getAttributeFromTypeOrDeclaredType(ScalarVariable *sv, XmlParser::Att a) {
- const char *stringValue = sv->typeSpec->getAttributeValue(a);
- if (stringValue) return stringValue;
- // look for stringValue inside declared type:
- const char *typeName = sv->typeSpec->getAttributeValue(XmlParser::att_declaredType);
- if (typeName) {
- SimpleType *type = getSimpleType(typeName);
- if (type) return type->getAttributeValue(a);
- }
- return NULL;
- }
|