26 for (
auto& [ attributeId, attribute ] :
attributes[
nullptr] ) {
27 if ( attribute->expression ) {
30 globals[attr->index] = value;
32 auto value = attribute->expression->execute(
Values{},
Values{}, globals);
33 if ( !value.has_value() ) {
34 throw std::runtime_error(
"StaticDataProvider: failed to evaluate global attribute '" + attribute->id +
"'");
53 throw std::runtime_error(
"StaticDataProvider: table '" +
reader->instanceFileOrString +
"' is empty");
56 if (table.size() < 2) {
57 throw std::runtime_error(
"StaticDataProvider: table must have at least a header and one data row");
60 size_t columnCount = table[0].size();
61 if (columnCount != 3) {
62 throw std::runtime_error(
"StaticDataProvider: expected 3 columns (INSTANCE_ID, NODE_ID, INITIALIZATION), got " + std::to_string(columnCount));
65 enum { INSTANCE_ID, NODE_ID, INITIALIZATION };
67 for (
auto& row : table | std::views::drop(1)) {
71 if (row.size() != 3) {
72 throw std::runtime_error(
"StaticDataProvider: inconsistent number of cells");
76 if (!std::holds_alternative<std::string>(row.at(INSTANCE_ID))) {
77 throw std::runtime_error(
"StaticDataProvider: illegal instance id");
79 std::string instanceIdentifier = std::get<std::string>(row.at(INSTANCE_ID));
82 if (!std::holds_alternative<std::string>(row.at(NODE_ID))) {
83 throw std::runtime_error(
"StaticDataProvider: illegal node id");
85 std::string nodeId = std::get<std::string>(row.at(NODE_ID));
88 if (!std::holds_alternative<std::string>(row.at(INITIALIZATION))) {
89 throw std::runtime_error(
"StaticDataProvider: illegal initialization");
91 std::string initialization = std::get<std::string>(row.at(INITIALIZATION));
93 if (instanceIdentifier.empty() && nodeId.empty()) {
95 if (initialization.empty()) {
101 for (
auto& [
id, globalAttribute] :
attributes[
nullptr]) {
102 if (globalAttribute->name == attributeName) {
103 attribute = globalAttribute;
108 throw std::runtime_error(
"StaticDataProvider: unknown global attribute '" + attributeName +
"'");
113 globals[globalAttribute->index] = value;
118 if (!value.has_value()) {
119 throw std::runtime_error(
"StaticDataProvider: failed to evaluate global '" + attributeName +
"'");
123 else if (instanceIdentifier.empty()) {
124 throw std::runtime_error(
"StaticDataProvider: instance id required when node id is provided");
136 throw std::runtime_error(
"StaticDataProvider: first row for instance '" + instanceIdentifier +
"' must reference a process node, got '" + nodeId +
"'");
143 if (initialization.empty()) {
152 if (!extensionElements->attributeRegistry.contains(attributeName)) {
153 throw std::runtime_error(
"StaticDataProvider: node '" + nodeId +
"' has no attribute '" + attributeName +
"'");
157 if (attribute->expression) {
158 throw std::runtime_error(
"StaticDataProvider: value of attribute '" + attributeName +
"' is initialized by expression and must not be provided explicitly");
183 auto pos = initialization.find(
":=");
184 if ( pos == std::string::npos ) {
185 throw std::runtime_error(
"StaticDataProvider: initialization must be in format 'attribute := expression', got '" + initialization +
"'");
188 std::string attributeName = initialization.substr(0, pos);
189 std::string expression = initialization.substr(pos + 2);
192 auto trimStart = attributeName.find_first_not_of(
" \t");
193 auto trimEnd = attributeName.find_last_not_of(
" \t");
194 if ( trimStart == std::string::npos ) {
195 throw std::runtime_error(
"StaticDataProvider: empty attribute name in initialization '" + initialization +
"'");
197 attributeName = attributeName.substr(trimStart, trimEnd - trimStart + 1);
199 trimStart = expression.find_first_not_of(
" \t");
200 trimEnd = expression.find_last_not_of(
" \t");
201 if ( trimStart == std::string::npos ) {
202 throw std::runtime_error(
"StaticDataProvider: empty expression in initialization '" + initialization +
"'");
204 expression = expression.substr(trimStart, trimEnd - trimStart + 1);
206 return {attributeName, expression};