diff --git a/src/cpp/cse_config_parser.cpp b/src/cpp/cse_config_parser.cpp index f35c23550..e171aa09f 100644 --- a/src/cpp/cse_config_parser.cpp +++ b/src/cpp/cse_config_parser.cpp @@ -564,6 +564,7 @@ struct variable_group_description std::string name; std::string type; std::vector variables; + std::vector variable_group_descriptions; }; struct extended_model_description @@ -584,19 +585,28 @@ struct extended_model_description const auto variableGroupsElement = static_cast(rootElement->getElementsByTagName(tc("VariableGroups").get())->item(0)); for (auto variableGroupElement = variableGroupsElement->getFirstElementChild(); variableGroupElement != nullptr; variableGroupElement = variableGroupElement->getNextElementSibling()) { - variable_group_description vgd; - vgd.name = tc(variableGroupElement->getAttribute(tc("name").get())).get(); - vgd.type = tc(variableGroupElement->getAttribute(tc("type").get())).get(); + variable_group_description vgd = create_variable_group_description(variableGroupElement); + variableGroups[vgd.name] = std::move(vgd); + } + } + + static variable_group_description create_variable_group_description(xercesc::DOMElement *variableGroupElement) { + variable_group_description variableGroupDescription; - auto variableElements = variableGroupElement->getElementsByTagName(tc("Variable").get()); - for (size_t i = 0; i < variableElements->getLength(); i++) { - auto variableElement = static_cast(variableElements->item(i)); + variableGroupDescription.name = tc(variableGroupElement->getAttribute(tc("name").get())).get(); + variableGroupDescription.type = tc(variableGroupElement->getTagName()).get(); - std::string variableName = tc(variableElement->getAttribute(tc("name").get())).get(); - vgd.variables.push_back(std::move(variableName)); + for (auto variableGroupChildElement = variableGroupElement->getFirstElementChild(); variableGroupChildElement != nullptr; variableGroupChildElement = variableGroupChildElement->getNextElementSibling()) { + std::string tagName(tc(variableGroupChildElement->getTagName()).get()); + if (tagName == "Variable") { + std::string variableName = tc(variableGroupChildElement->getAttribute(tc("ref").get())).get(); + variableGroupDescription.variables.push_back(std::move(variableName)); + } else { + variableGroupDescription.variable_group_descriptions.push_back(create_variable_group_description(variableGroupChildElement)); } - variableGroups[vgd.name] = std::move(vgd); } + + return variableGroupDescription; } std::unordered_map variableGroups; @@ -718,18 +728,37 @@ extended_model_description get_emd( std::vector get_variable_group_variables( const std::unordered_map& descriptions, - const std::string& element, - const std::string& connector) + const cse_config_parser::VariableEndpoint endpoint) { - auto groupIt = descriptions.find(connector); + auto groupIt = descriptions.find(endpoint.name); if (groupIt == descriptions.end()) { + for (const auto& description : descriptions) { + if (description.second.variable_group_descriptions.size() != 0) { + std::unordered_map nestedDescriptions; + for (const auto& variableGroupDescr : description.second.variable_group_descriptions) { + nestedDescriptions.insert({variableGroupDescr.name, variableGroupDescr}); + } + return get_variable_group_variables(nestedDescriptions, endpoint); + } + } std::ostringstream oss; - oss << "Cannot find variable group description: " << element << ":" << connector; + oss << "Cannot find variable group description: " << endpoint.simulator << ":" << endpoint.name; throw std::out_of_range(oss.str()); } return groupIt->second.variables; } +std::vector get_variable_groups( + const std::unordered_map& descriptions, + const std::string& connector) +{ + auto groupIt = descriptions.find(connector); + if (groupIt == descriptions.end()) { + return {}; + } + return groupIt->second.variable_group_descriptions; +} + void connect_variable_groups( const std::vector& variableGroupConnections, const std::unordered_map& slaves, @@ -739,11 +768,31 @@ void connect_variable_groups( for (const auto& connection : variableGroupConnections) { const auto& emdA = get_emd(emds, connection.variableA.simulator); - const auto& variablesA = - get_variable_group_variables(emdA.variableGroups, connection.variableA.simulator, connection.variableA.name); const auto& emdB = get_emd(emds, connection.variableB.simulator); - const auto& variablesB = - get_variable_group_variables(emdB.variableGroups, connection.variableB.simulator, connection.variableB.name); + const auto& variablesA = get_variable_group_variables(emdA.variableGroups, connection.variableA); + const auto& variablesB = get_variable_group_variables(emdB.variableGroups, connection.variableB); + const auto& variableGroupsA = get_variable_groups(emdA.variableGroups, connection.variableA.name); + const auto& variableGroupsB = get_variable_groups(emdB.variableGroups, connection.variableB.name); + + if (variableGroupsA.size() != variableGroupsB.size()) { + std::ostringstream oss; + oss << "Cannot create connection between variable groups. Variable group " + << connection.variableA.simulator << ":" << connection.variableA.name + << " has different size [" << variableGroupsA.size() << "] than variable group " + << connection.variableB.simulator << ":" << connection.variableB.name + << " size [" << variableGroupsB.size() << "]"; + throw std::runtime_error(oss.str()); + } + + std::vector nestedVariableGroupConnections; + // clang-format off + for (std::size_t i = 0; i < variableGroupsA.size(); ++i) { + nestedVariableGroupConnections.push_back({ + {connection.variableA.simulator, variableGroupsA.at(i).name}, + {connection.variableB.simulator, variableGroupsB.at(i).name}}); + } + // clang-format on + connect_variable_groups(nestedVariableGroupConnections, slaves, execution, emds); if (variablesA.size() != variablesB.size()) { std::ostringstream oss; diff --git a/test/data/msmi/CraneController_OspModelDescription.xml b/test/data/msmi/CraneController_OspModelDescription.xml index 36dada791..e0d48880f 100644 --- a/test/data/msmi/CraneController_OspModelDescription.xml +++ b/test/data/msmi/CraneController_OspModelDescription.xml @@ -10,20 +10,22 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + diff --git a/test/data/msmi/KnuckleBoomCrane_OspModelDescription.xml b/test/data/msmi/KnuckleBoomCrane_OspModelDescription.xml index 4985095c1..03f19deb7 100644 --- a/test/data/msmi/KnuckleBoomCrane_OspModelDescription.xml +++ b/test/data/msmi/KnuckleBoomCrane_OspModelDescription.xml @@ -2,20 +2,22 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + diff --git a/test/data/msmi/OspSystemStructure_Bond.xml b/test/data/msmi/OspSystemStructure_Bond.xml index dbe89be95..2c0ed998b 100644 --- a/test/data/msmi/OspSystemStructure_Bond.xml +++ b/test/data/msmi/OspSystemStructure_Bond.xml @@ -37,14 +37,9 @@ - - - - - - - + + diff --git a/test/data/msmi/com.open-simulation-platform.vector_OspModelDescription.xml b/test/data/msmi/com.open-simulation-platform.vector_OspModelDescription.xml index 9b3ae38d0..2a7a9232e 100644 --- a/test/data/msmi/com.open-simulation-platform.vector_OspModelDescription.xml +++ b/test/data/msmi/com.open-simulation-platform.vector_OspModelDescription.xml @@ -1,15 +1,15 @@ - - - - - - - - - - + + + + + + + + + + diff --git a/test/data/msmi/schema/OspModelDescription.xsd b/test/data/msmi/schema/OspModelDescription.xsd index 8cd73395a..644bb7f76 100644 --- a/test/data/msmi/schema/OspModelDescription.xsd +++ b/test/data/msmi/schema/OspModelDescription.xsd @@ -1,68 +1,66 @@ - + - + + + + + + + + + + + + - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - OspModelDescription version - - + - + \ No newline at end of file