ifw-daq 3.1.0
IFW Data Acquisition modules
Loading...
Searching...
No Matches
dpSpec.cpp
Go to the documentation of this file.
1/**
2 * @file
3 * @ingroup daq_dpm_libmerge
4 * @copyright ESO - European Southern Observatory
5 */
6#include <daq/json/dpSpec.hpp>
7#include <iostream>
8
9#include <fmt/format.h>
10
11#include <daq/fits/json.hpp>
12
14
15using Json = nlohmann::json;
16using JsonPointer = nlohmann::json_pointer<Json>;
17
18namespace daq::json {
19
20DpSpec::Target ParseTarget(Json const& json, JsonPointer const& breadcrumb) {
21 AssertIsObject<DpSpecError>(json, breadcrumb);
22 DpSpec::Target obj{};
23 obj.file_id = JsonObject<DpSpecError, std::string>::Get(json, "fileId", breadcrumb);
24 if (json.contains("source")) {
25 obj.source = ParseFitsFileSource(json["source"], breadcrumb / "source");
26 }
27 if (json.contains("filePrefix")) {
28 obj.file_prefix =
29 JsonObject<DpSpecError, std::string>::Get(json, "filePrefix", breadcrumb, true);
30 }
31 return obj;
32}
33
34DpSpec::SourceTypes ParseSource(Json const& json, JsonPointer const& breadcrumb) {
35 AssertIsObject<DpSpecError>(json, breadcrumb);
36 auto type = JsonObject<DpSpecError, std::string>::Get(json, "type", breadcrumb);
37 if (type == "fitsKeywords") {
38 return ParseFitsKeywordsSource(json, breadcrumb);
39 } else if (type == "fitsFile") {
40 return ParseFitsFileSource(json, breadcrumb);
41 } else {
42 throw MakeUnknownVariantException<DpSpecError>(
43 breadcrumb / "type", "'fitsKeywords' or 'fitsFile'", type.c_str());
44 }
45}
46
47DpSpec ParseDpSpec(Json const& json) {
48 try {
49 JsonPointer breadcrumb("");
50 AssertIsObject<DpSpecError>(json, breadcrumb);
51
52 DpSpec spec{};
53 spec.id = JsonObject<DpSpecError, std::string>::Get(json, "id", breadcrumb);
54 if (!json.contains("target")) {
55 throw MakeValueMissingException<DpSpecError>(breadcrumb / "target");
56 }
57 spec.target = ParseTarget(json["target"], breadcrumb / "target");
58
59 if (json.contains("sources")) {
60 auto const& json_sources = json["sources"];
61 AssertIsArray<DpSpecError>(json_sources, breadcrumb / "sources");
62
63 auto index = 0u;
64 for (auto const& json_source : json_sources) {
65 // cppcheck-suppress zerodiv
66 spec.sources.emplace_back(ParseSource(json_source, breadcrumb / "sources" / index));
67 index++;
68 }
69 }
70 // Check that there's at least one source
71 if (!spec.target.source && spec.sources.empty()) {
72 throw MakeParseException<DpSpecError>(
73 breadcrumb / "sources",
74 "At least one source must be provided if '/target/source' is not used");
75 }
76 if (json.contains("receivers")) {
77 spec.receivers = ParseReceiverList(json["receivers"], breadcrumb / "receivers");
78 }
79 return spec;
80 } catch (DpSpecError const&) {
81 throw;
82 } catch (SchemaError const& e) {
83 std::throw_with_nested(DpSpecError("Schema error"));
84 } catch (...) { // GCOVR_EXCL_START
85 std::throw_with_nested(DpSpecError("Unknown parsing error"));
86 // GCOVR_EXCL_STOP
87 }
88}
89
90Location ParseSourceLocation(std::string const& location_str) {
91 Location location;
92 // location str may contain a 'user@' component which we don't care about
93 auto start_pos = location_str.find('@');
94 if (start_pos == std::string::npos) {
95 // no '@' found -> start at 0
96 start_pos = 0u;
97 } else {
98 if (start_pos > location_str.size()) {
99 throw std::invalid_argument(
100 fmt::format("Invalid format of location string: '{}'", location_str));
101 }
102 // skip '@' sign
103 start_pos++;
104 }
105
106 auto pos = location_str.find(':', start_pos);
107 if (pos != std::string::npos) {
108 // Split at 'pos'
109 location.host = location_str.substr(start_pos, pos - start_pos);
110 location.path = location_str.substr(pos + 1, std::string::npos);
111 } else {
112 location.path = location_str.substr(start_pos);
113 }
114 if (location.path.empty()) {
115 throw std::invalid_argument(
116 fmt::format("Invalid format of location string: '{}'", location_str));
117 }
118 return location;
119}
120
121std::string Location::RsyncPath() const {
122 if (host.empty()) {
123 return path;
124 }
125 return (host + std::string(":") + path.native());
126}
127
128// NOLINTNEXTLINE
129void to_json(nlohmann::json& j, DpSpec const& s) {
130 j = Json{
131 {"id", s.id}, {"sources", s.sources}, {"target", s.target}, {"receivers", s.receivers}};
132}
133
134// NOLINTNEXTLINE
135void to_json(nlohmann::json& j, DpSpec::Target const& s) {
136 j = Json{{"fileId", s.file_id}, {"filePrefix", s.file_prefix}};
137 if (s.source.has_value()) {
138 j["source"] = *s.source;
139 }
140}
141
142// NOLINTNEXTLINE
143void to_json(nlohmann::json& j, DpSpec::SourceTypes const& s) {
144 std::visit([&](auto const& val) { j = Json(val); }, s);
145}
146
147} // namespace daq::json
Contains data structure for FITS keywords.
nlohmann::json_pointer< Json > JsonPointer
Definition: json.cpp:19
nlohmann::json Json
Definition: json.cpp:18
std::string id
DAQ id.
Definition: dpSpec.hpp:45
Location ParseSourceLocation(std::string const &location_str)
Parse location string from DpSpec into component parts.
Definition: dpSpec.cpp:90
DpSpec ParseDpSpec(Json const &json)
Parse JSON to construct the DpSpec structure.
Definition: dpSpec.cpp:47
Target target
Describes target which will become the data produtc.
Definition: dpSpec.hpp:49
nlohmann::json Json
std::optional< FitsFileSource > source
Definition: dpSpec.hpp:37
nlohmann::json_pointer< Json > JsonPointer
ReceiverList receivers
Ordered container of receivers where to deliver the target data product.
Definition: dpSpec.hpp:59
std::vector< SourceTypes > sources
List of sources to create data product from.
Definition: dpSpec.hpp:54
std::variant< FitsKeywordsSource, FitsFileSource > SourceTypes
Definition: dpSpec.hpp:40
DpSpec::SourceTypes ParseSource(Json const &json, JsonPointer const &breadcrumb)
Definition: dpSpec.cpp:34
std::string file_prefix
Optioal user chosen file prefix to make it easier to identify the produced file.
Definition: dpSpec.hpp:36
FitsFileSource ParseFitsFileSource(Json const &json, JsonPointer const &breadcrumb)
FitsKeywordsSource ParseFitsKeywordsSource(Json const &json, JsonPointer const &breadcrumb)
ReceiverList ParseReceiverList(Json const &json, JsonPointer const &breadcrumb)
void to_json(nlohmann::json &out, KeywordFilter const &s)
DpSpec::Target ParseTarget(Json const &json, JsonPointer const &breadcrumb)
Definition: dpSpec.cpp:20
Close representation of the JSON structure but with stronger types.
Definition: dpSpec.hpp:30
static T Get(Json const &json, char const *name, JsonPointer const &breadcrumb, bool allow_empty=true)
Describes parsed location string into its components "host" and "path".
Definition: dpSpec.hpp:73
std::filesystem::path path
Definition: dpSpec.hpp:79
std::string RsyncPath() const
Definition: dpSpec.cpp:121
std::string host
Definition: dpSpec.hpp:78
JSON Schema error.
Definition: schemaError.hpp:18