ifw-daq  3.0.0-pre2
IFW Data Acquisition modules
startDaqV2.cpp
Go to the documentation of this file.
1 /**
2  * @file
3  * @ingroup daq_libjson
4  * @copyright
5  * (c) Copyright ESO 2022
6  * All Rights Reserved
7  * ESO (eso.org) is an Intergovernmental Organisation, and therefore special legal conditions apply.
8  */
10 
11 #include <fmt/format.h>
12 
13 #include "internalParseUtils.hpp"
14 
15 using Json = nlohmann::json;
16 using JsonPointer = nlohmann::json_pointer<Json>;
17 
18 namespace daq::json {
19 
21 
22 /**
23  * Parse the common parts of PrimaryDataSource and MetadataSource.
24  *
25  * {
26  * "sourceName": <str>,
27  * "rrUri": <str>,
28  * "keywordRules": [<keywordrules]
29  * }
30  */
32  Json const& json,
33  JsonPointer const& breadcrumb) {
34  AssertIsObject<ErrorType>(json, breadcrumb);
35  out.source_name = JsonObject<ErrorType, std::string>::Get(json, "sourceName", breadcrumb);
36  out.rr_uri = JsonObject<ErrorType, std::string>::Get(json, "rrUri", breadcrumb);
37  if (json.contains("initialKeywords")) {
38  out.initial_keywords =
39  ParseInitialKeywords(json["initialKeywords"], breadcrumb / "initialKeywords");
40  }
41  if (json.contains("keywordRules")) {
42  out.keyword_rules = ParseKeywordRules(json["keywordRules"], breadcrumb / "keywordRules");
43  }
44 }
45 
46 StartDaqV2Spec ParseStartDaqV2Spec(nlohmann::json const& json) {
47  try {
48  StartDaqV2Spec result = {};
49 
50  JsonPointer breadcrumb("");
51  AssertIsObject<StartDaqV2SpecError>(json, breadcrumb);
52 
53  if (json.contains("id")) {
54  result.id = JsonObject<ErrorType, std::string>::Get(json, "id", breadcrumb, true);
55  }
56 
57  if (json.contains("filePrefix")) {
58  result.file_prefix =
59  JsonObject<ErrorType, std::string>::Get(json, "filePrefix", breadcrumb, true);
60  }
61  if (json.contains("awaitCompletionInterval")) {
62  auto value =
63  JsonObject<ErrorType, double>::Get(json, "awaitCompletionInterval", breadcrumb);
64  if (value < 0.0) {
65  throw MakeParseException<ErrorType>(breadcrumb / "awaitCompletionInterval",
66  "interval must be > 0.0s");
67  }
69  std::chrono::duration_cast<std::chrono::milliseconds>(
70  std::chrono::duration<double>(value));
71  }
72 
73  {
74  auto [json_sources, breadcrumb_sources] = GetMember<ErrorType>(
75  json, "sources", breadcrumb, [](Json const& member, JsonPointer const& breadcrumb) {
76  AssertIsArray<ErrorType>(member, breadcrumb);
77  });
78  auto index = 0u;
79  for (auto const& json_source : json_sources) {
80  auto breadcrumb_source = breadcrumb_sources / index;
81  auto source_type =
82  JsonObject<ErrorType, std::string>::Get(json_source, "type", breadcrumb_source);
83  if (source_type == "primaryDataSource") {
85  ParseDataSource(s, json_source, breadcrumb_source);
86  result.sources.emplace_back(std::move(s));
87  } else if (source_type == "metadataSource") {
89  ParseDataSource(s, json_source, breadcrumb_source);
90  result.sources.emplace_back(std::move(s));
91  } else if (source_type == "fitsKeywords") {
92  auto kws = ParseFitsKeywordsSource(json_source, breadcrumb_source);
93  result.sources.emplace_back(std::move(kws));
94  } else if (source_type == "fitsFile") {
95  auto file = ParseFitsFileSource(json_source, breadcrumb_source);
96  result.sources.emplace_back(std::move(file));
97  } else {
98  throw MakeUnknownVariantException<ErrorType>(
99  breadcrumb_source / "type",
100  "'primaryDataSource', 'metadataSource', 'fitsFile' or 'fitsKeywords'",
101  source_type.c_str());
102  }
103  index++;
104  }
105  }
106  return result;
107  } catch (ErrorType const&) {
108  throw;
109  } catch (SchemaError const& e) {
110  throw ErrorType(e.what());
111  } catch (std::exception const& e) { // GCOVR_EXCL_START
112  std::throw_with_nested(
113  StartDaqV2SpecError(fmt::format("Unknown parsing error: {}", e.what())));
114  } // GCOVR_EXCL_STOP
115 }
116 
118  StartDaqV2Spec::PrimaryDataSource const& rhs) noexcept {
119  return lhs.source_name == rhs.source_name && lhs.rr_uri == rhs.rr_uri &&
120  lhs.keyword_rules == rhs.keyword_rules;
121 }
122 
124  StartDaqV2Spec::MetadataSource const& rhs) noexcept {
125  return lhs.source_name == rhs.source_name && lhs.rr_uri == rhs.rr_uri &&
126  lhs.keyword_rules == rhs.keyword_rules;
127 }
128 
130  StartDaqV2Spec::MergeTarget const& rhs) noexcept {
131  return lhs.source_name == rhs.source_name;
132 }
133 
134 bool operator==(StartDaqV2Spec const& lhs, StartDaqV2Spec const& rhs) noexcept {
135  return lhs.id == rhs.id && lhs.file_prefix == rhs.file_prefix &&
136  lhs.await_completion_interval == rhs.await_completion_interval &&
137  lhs.merge_target == rhs.merge_target && lhs.sources == rhs.sources;
138 }
139 
140 // NOLINTNEXTLINE
141 void to_json(nlohmann::json& out, StartDaqV2Spec::DataSource const& s) {
142  out = Json{{"sourceName", s.source_name}, {"rrUri", s.rr_uri}};
143  if (s.initial_keywords.has_value()) {
144  out["initialKeywords"] = *s.initial_keywords;
145  }
146  if (!s.keyword_rules.empty()) {
147  out["keywordRules"] = s.keyword_rules;
148  }
149 }
150 
151 // NOLINTNEXTLINE
152 void to_json(nlohmann::json& out, StartDaqV2Spec::PrimaryDataSource const& s) {
153  to_json(out, static_cast<StartDaqV2Spec::DataSource const&>(s));
154  out["type"] = "primaryDataSource";
155 }
156 
157 // NOLINTNEXTLINE
158 void to_json(nlohmann::json& out, StartDaqV2Spec::MetadataSource const& s) {
159  to_json(out, static_cast<StartDaqV2Spec::DataSource const&>(s));
160  out["type"] = "metadataSource";
161 }
162 
163 // NOLINTNEXTLINE
164 void to_json(nlohmann::json& out, StartDaqV2Spec::DataSourceTypes const& s) {
165  std::visit([&](auto const& ds) { to_json(out, ds); }, s);
166 }
167 
168 // NOLINTNEXTLINE
169 void to_json(nlohmann::json& out, StartDaqV2Spec::MergeTarget const& t) {
170  out = Json{{"sourceName", t.source_name}};
171 }
172 
173 // NOLINTNEXTLINE
174 void to_json(nlohmann::json& json, StartDaqV2Spec const& spec) {
175  json = nlohmann::json{
176  {"id", spec.id}, {"filePrefix", spec.file_prefix}, {"sources", spec.sources}};
177  if (spec.await_completion_interval.has_value()) {
178  json["awaitCompletionInterval"] = std::chrono::duration_cast<std::chrono::duration<double>>(
180  .count();
181  }
182  if (spec.merge_target.has_value()) {
183  json["mergeTarget"] = *spec.merge_target;
184  }
185 }
186 
187 } // namespace daq::json
nlohmann::json_pointer< Json > JsonPointer
Definition: json.cpp:19
nlohmann::json Json
Definition: json.cpp:18
StartDaqV2SpecError ErrorType
Definition: startDaqV2.cpp:20
KeywordRules ParseKeywordRules(Json const &json, JsonPointer const &breadcrumb)
InitialKeywords ParseInitialKeywords(nlohmann::json const &json, nlohmann::json_pointer< nlohmann::json > const &breadcrumb)
std::optional< MergeTarget > merge_target
Definition: startDaqV2.hpp:52
std::optional< std::chrono::milliseconds > await_completion_interval
Definition: startDaqV2.hpp:53
void ParseDataSource(StartDaqV2Spec::DataSource &out, Json const &json, JsonPointer const &breadcrumb)
Parse the common parts of PrimaryDataSource and MetadataSource.
Definition: startDaqV2.cpp:31
FitsFileSource ParseFitsFileSource(Json const &json, JsonPointer const &breadcrumb)
bool operator==(KeywordFilter const &lhs, KeywordFilter const &rhs) noexcept
FitsKeywordsSource ParseFitsKeywordsSource(Json const &json, JsonPointer const &breadcrumb)
std::variant< PrimaryDataSource, MetadataSource, FitsKeywordsSource, FitsFileSource > DataSourceTypes
Definition: startDaqV2.hpp:44
StartDaqV2Spec ParseStartDaqV2Spec(nlohmann::json const &json)
Parse StartDaqSpec.
Definition: startDaqV2.cpp:46
void to_json(nlohmann::json &out, KeywordFilter const &s)
std::vector< DataSourceTypes > sources
Definition: startDaqV2.hpp:51
Structure with a close mapping from JSON representation in the StartDaqV2 MAL request.
Definition: startDaqV2.hpp:33
static T Get(Json const &json, char const *name, JsonPointer const &breadcrumb, bool allow_empty=true)
JSON Schema error.
Definition: schemaError.hpp:18
std::optional< InitialKeywords > initial_keywords
Definition: startDaqV2.hpp:37