helics  3.6.1
fileConnections.hpp
1 /*
2 Copyright (c) 2017-2025,
3 Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable
4 Energy, LLC. See the top-level NOTICE for additional details. All rights reserved.
5 SPDX-License-Identifier: BSD-3-Clause
6 */
7 #pragma once
8 
9 #include "../common/JsonProcessingFunctions.hpp"
10 #include "../common/TomlProcessingFunctions.hpp"
11 #include "../common/addTargets.hpp"
12 #include "Broker.hpp"
13 #include "Core.hpp"
14 #include "core-exceptions.hpp"
15 
16 #include <string>
17 #include <type_traits>
18 
19 namespace helics::fileops {
20 
21 template<class brkX>
22 void makeConnectionsToml(brkX* brk, const std::string& file)
23 {
24  toml::value uVal;
25  static_assert(std::is_base_of<Broker, brkX>::value || std::is_base_of<Core, brkX>::value,
26  "broker must be Core or broker");
27  toml::value doc;
28  try {
29  doc = loadToml(file);
30  }
31  catch (const std::invalid_argument& ia) {
32  throw(helics::InvalidParameter(ia.what()));
33  }
34 
35  auto conns = toml::find_or(doc, "connections", uVal);
36  if (!conns.is_empty()) {
37  auto& connArray = conns.as_array();
38  for (const auto& conn : connArray) {
39  if (conn.is_array()) {
40  auto& connAct = conn.as_array();
41  brk->dataLink(connAct[0].as_string(), connAct[1].as_string());
42  } else {
43  std::string pub = getOrDefault(conn, "publication", std::string());
44  if (!pub.empty()) {
45  addTargets(conn, "targets", [brk, &pub](const std::string& target) {
46  brk->dataLink(pub, target);
47  });
48  } else {
49  std::string ipt = getOrDefault(conn, "input", std::string());
50  if (!ipt.empty()) {
51  addTargets(conn, "targets", [brk, &ipt](const std::string& target) {
52  brk->dataLink(target, ipt);
53  });
54  addTargets(conn, "sources", [brk, &ipt](const std::string& source) {
55  brk->dataLink(source, ipt);
56  });
57  } else {
58  std::string ept = getOrDefault(conn, "endpoint", std::string());
59  if (!ept.empty()) {
60  addTargets(conn, "targets", [brk, &ept](const std::string& target) {
61  brk->linkEndpoints(ept, target);
62  });
63  addTargets(conn, "sources", [brk, &ept](const std::string& source) {
64  brk->linkEndpoints(source, ept);
65  });
66  }
67  }
68  }
69  }
70  }
71  }
72  auto lnks = toml::find_or(doc, "links", uVal);
73  if (!lnks.is_empty()) {
74  auto& connArray = lnks.as_array();
75  for (const auto& conn : connArray) {
76  if (conn.is_array()) {
77  auto& connAct = conn.as_array();
78  brk->linkEndpoints(connAct[0].as_string(), connAct[1].as_string());
79  } else {
80  std::string pub = getOrDefault(conn, "publication", std::string());
81  if (!pub.empty()) {
82  addTargets(conn, "targets", [brk, &pub](const std::string& target) {
83  brk->dataLink(pub, target);
84  });
85  } else {
86  std::string ipt = getOrDefault(conn, "input", std::string());
87  if (!ipt.empty()) {
88  addTargets(conn, "targets", [brk, &ipt](const std::string& target) {
89  brk->dataLink(target, ipt);
90  });
91  addTargets(conn, "sources", [brk, &ipt](const std::string& source) {
92  brk->dataLink(source, ipt);
93  });
94  } else {
95  std::string ept = getOrDefault(conn, "endpoint", std::string());
96  if (!ept.empty()) {
97  addTargets(conn, "targets", [brk, &ept](const std::string& target) {
98  brk->linkEndpoints(ept, target);
99  });
100  addTargets(conn, "sources", [brk, &ept](const std::string& source) {
101  brk->linkEndpoints(source, ept);
102  });
103  }
104  }
105  }
106  }
107  }
108  }
109  auto filts = toml::find_or(doc, "filters", uVal);
110  if (!filts.is_empty()) {
111  auto& filtArray = filts.as_array();
112  for (const auto& filt : filtArray) {
113  if (filt.is_array()) {
114  auto& filtAct = filt.as_array();
115  brk->addSourceFilterToEndpoint(filtAct[0].as_string(), filtAct[1].as_string());
116  } else {
117  std::string fname = getOrDefault(filt, "filter", std::string());
118  if (!fname.empty()) {
119  auto asrc = [brk, &fname](const std::string& ept) {
120  brk->addSourceFilterToEndpoint(fname, ept);
121  };
122  addTargets(filt, "endpoints", asrc);
123  addTargets(filt, "source_endpoints", asrc);
124  addTargets(filt, "sourceEndpoints", asrc);
125  auto adst = [brk, &fname](const std::string& ept) {
126  brk->addDestinationFilterToEndpoint(fname, ept);
127  };
128  addTargets(filt, "dest_endpoints", adst);
129  addTargets(filt, "destEndpoints", adst);
130  }
131  }
132  }
133  }
134  auto globals = toml::find_or(doc, "globals", uVal);
135  if (!globals.is_empty()) {
136  if (globals.is_array()) {
137  for (auto& val : globals.as_array()) {
138  brk->setGlobal(val.as_array()[0].as_string(), val.as_array()[1].as_string());
139  }
140  } else {
141  for (const auto& val : globals.as_table()) {
142  brk->setGlobal(val.first, val.second.as_string());
143  }
144  }
145  }
146  auto aliases = toml::find_or(doc, "aliases", uVal);
147  if (!aliases.is_empty()) {
148  if (aliases.is_array()) {
149  for (auto& val : aliases.as_array()) {
150  brk->addAlias(val.as_array()[0].as_string(), val.as_array()[1].as_string());
151  }
152  } else {
153  for (const auto& val : aliases.as_table()) {
154  brk->addAlias(val.first, val.second.as_string());
155  }
156  }
157  }
158 }
159 
160 template<class brkX>
161 void makeConnectionsJson(brkX* brk, const std::string& file)
162 {
163  static_assert(std::is_base_of<Broker, brkX>::value || std::is_base_of<Core, brkX>::value,
164  "input must be Core or Broker");
165  nlohmann::json doc;
166  try {
167  doc = loadJson(file);
168  }
169  catch (const std::invalid_argument& ia) {
170  throw(helics::InvalidParameter(ia.what()));
171  }
172 
173  if (doc.contains("connections")) {
174  for (const auto& conn : doc["connections"]) {
175  if (conn.is_array() && conn.size() >= 2) {
176  brk->dataLink(conn[0].get<std::string>(), conn[1].get<std::string>());
177  } else {
178  std::string pub = fileops::getOrDefault(conn, "publication", std::string_view());
179  if (!pub.empty()) {
180  addTargets(conn, "targets", [brk, &pub](std::string_view target) {
181  brk->dataLink(pub, target);
182  });
183  } else {
184  std::string ipt = fileops::getOrDefault(conn, "input", std::string_view());
185  if (!ipt.empty()) {
186  addTargets(conn, "targets", [brk, &ipt](std::string_view target) {
187  brk->dataLink(target, ipt);
188  });
189  addTargets(conn, "sources", [brk, &ipt](std::string_view source) {
190  brk->dataLink(source, ipt);
191  });
192  } else {
193  std::string ept =
194  fileops::getOrDefault(conn, "endpoint", std::string_view());
195  if (!ept.empty()) {
196  addTargets(conn, "targets", [brk, &ept](std::string_view target) {
197  brk->linkEndpoints(ept, target);
198  });
199  addTargets(conn, "sources", [brk, &ept](std::string_view source) {
200  brk->linkEndpoints(source, ept);
201  });
202  }
203  }
204  }
205  }
206  }
207  }
208  if (doc.contains("links")) {
209  for (const auto& conn : doc["links"]) {
210  if (conn.is_array() && conn.size() >= 2) {
211  brk->linkEndpoints(conn[0].get<std::string>(), conn[1].get<std::string>());
212  } else {
213  std::string pub = fileops::getOrDefault(conn, "publication", std::string_view());
214  if (!pub.empty()) {
215  addTargets(conn, "targets", [brk, &pub](std::string_view target) {
216  brk->dataLink(pub, target);
217  });
218  } else {
219  std::string ipt = fileops::getOrDefault(conn, "input", std::string());
220  if (!ipt.empty()) {
221  addTargets(conn, "targets", [brk, &ipt](std::string_view target) {
222  brk->dataLink(target, ipt);
223  });
224  addTargets(conn, "sources", [brk, &ipt](std::string_view source) {
225  brk->dataLink(source, ipt);
226  });
227  } else {
228  std::string ept = fileops::getOrDefault(conn, "endpoint", std::string());
229  if (!ept.empty()) {
230  addTargets(conn, "targets", [brk, &ept](std::string_view target) {
231  brk->linkEndpoints(ept, target);
232  });
233  addTargets(conn, "sources", [brk, &ept](std::string_view source) {
234  brk->linkEndpoints(source, ept);
235  });
236  }
237  }
238  }
239  }
240  }
241  }
242  if (doc.contains("filters")) {
243  for (const auto& filt : doc["filters"]) {
244  if (filt.is_array()) {
245  brk->addSourceFilterToEndpoint(filt[0].get<std::string>(),
246  filt[1].get<std::string>());
247  } else {
248  std::string fname = fileops::getOrDefault(filt, "filter", std::string_view());
249  if (!fname.empty()) {
250  auto asrc = [brk, &fname](std::string_view ept) {
251  brk->addSourceFilterToEndpoint(fname, ept);
252  };
253  addTargets(filt, "endpoints", asrc);
254  addTargets(filt, "source_endpoints", asrc);
255  addTargets(filt, "sourceEndpoints", asrc);
256  auto adst = [brk, &fname](std::string_view ept) {
257  brk->addDestinationFilterToEndpoint(fname, ept);
258  };
259  addTargets(filt, "dest_endpoints", adst);
260  addTargets(filt, "destEndpoints", adst);
261  }
262  }
263  }
264  }
265  if (doc.contains("globals")) {
266  if (doc["globals"].is_array()) {
267  for (const auto& val : doc["globals"]) {
268  brk->setGlobal(val[0].get<std::string>(), val[1].get<std::string>());
269  }
270  } else {
271  for (const auto& member : doc["globals"].items()) {
272  brk->setGlobal(member.key(), member.value().get<std::string>());
273  }
274  }
275  }
276 
277  if (doc.contains("aliases")) {
278  if (doc["aliases"].is_array()) {
279  for (const auto& val : doc["aliases"]) {
280  brk->addAlias(val[0].get<std::string>(), val[1].get<std::string>());
281  }
282  } else {
283  for (const auto& member : doc["aliases"].items()) {
284  brk->addAlias(member.key(), member.value().get<std::string>());
285  }
286  }
287  }
288 
289  if constexpr (std::is_base_of<Core, brkX>::value) {
290  loadTags(doc, [brk](std::string_view tagname, std::string_view tagvalue) {
291  brk->setFederateTag(gLocalCoreId, tagname, tagvalue);
292  });
293  }
294 }
295 } // namespace helics::fileops
toml::value loadToml(const std::string &tomlString)
Definition: core-exceptions.hpp:47
constexpr LocalFederateId gLocalCoreId(-259)