10 #include <fmt/format.h>
11 #include <log4cplus/loggingmacros.h>
18 namespace fs = std::filesystem;
21 constexpr
bool AlwaysFalse() {
33 JsonReporter(log4cplus::Logger logger) : m_logger(std::move(logger)) {
35 virtual void PostAlert(std::string
const&
id, std::string
const& message)
override {
36 LOG4CPLUS_WARN(m_logger,
"Alert: " << message);
37 Report(
"alert",
nlohmann::json({{
"id",
id}, {
"message", message}}));
43 std::chrono::nanoseconds(std::chrono::system_clock::now().time_since_epoch()).count();
44 nlohmann::json j{{
"type", type}, {
"timestamp", ts}, {
"content", content}};
47 log4cplus::Logger m_logger;
55 virtual void PostAlert(std::string
const&
id, std::string
const& message)
override {
56 std::cout <<
"[event] alert: " << message <<
'\n';
70 virtual void SortKeywords(std::vector<fits::LiteralKeyword>& keywords)
override {
76 if (!source.is_absolute()) {
83 auto processor = std::make_unique<StandardKeywordRuleProcessor>();
86 [&](
auto const& rule) {
87 using T = std::decay_t<decltype(rule)>;
88 if constexpr (std::is_same_v<T, DpSpec::Filter>) {
89 LOG4CPLUS_DEBUG(
"dpm.merge", fmt::format(
"Adding KeywordRule 'filter'"));
90 processor->AddRule([filter =
KeywordEx(std::begin(rule.selection_patterns),
91 std::end(rule.selection_patterns))](
93 fits::KeywordVector result;
94 result.reserve(kws.size());
95 Filter(std::begin(kws), std::end(kws), std::back_inserter(result), filter);
98 }
else if constexpr (std::is_same_v<T, DpSpec::Transform>) {
99 LOG4CPLUS_DEBUG(
"dpm.merge", fmt::format(
"Adding KeywordRule 'transform'"));
100 processor->AddRule([filter =
KeywordEx(std::begin(rule.selection_patterns),
101 std::end(rule.selection_patterns)),
102 regex = std::regex(rule.regex),
103 format = rule.format](
105 fits::KeywordVector result;
106 result.reserve(kws.size());
107 Transform(std::begin(kws),
109 std::back_inserter(result),
116 static_assert(AlwaysFalse<T>(),
"non exhaustive visitor");
125 std::optional<fs::path>
const& opt_out_path,
133 auto out_path = opt_out_path.value_or(
138 LOG4CPLUS_INFO(
"dpm.merge",
139 fmt::format(
"*in-place* target specified act as merge target: '{}'",
144 resolver.
Resolve({spec.target.source->source_name, spec.target.source->origin}),
151 fits::Open(path.c_str(), fits::OpenMode::ReadOnly));
157 LOG4CPLUS_INFO(
"dpm.merge",
158 "no *in-place* target specified -> creating minimal FITS file to "
159 "act as merge target");
167 std::make_unique<StandardKeywordRuleProcessor>(),
168 std::move(dry_run_file).GetOwnedFile());
173 "" , path, std::make_unique<StandardKeywordRuleProcessor>());
178 std::vector<SourceTypes> sources;
181 [&](
auto const& source) {
182 using T = std::decay_t<decltype(source)>;
185 if constexpr (std::is_same_v<T, DpSpec::SourceFitsKeywords>) {
186 sources.emplace_back(std::in_place_type<FitsKeywordsSource>,
189 std::move(kw_rules));
190 }
else if constexpr (std::is_same_v<T, DpSpec::SourceFitsFile>) {
193 sources.emplace_back(std::in_place_type<FitsFileSource>,
197 std::move(kw_rules));
199 static_assert(AlwaysFalse<T>(),
"non exhaustive visitor");
206 auto logger = log4cplus::Logger::getInstance(
"dpm.merge");
219 params.
origfile = out_path.filename().native();
222 Merge(ops, params, target_source, sources, dry_run);
224 std::throw_with_nested(std::runtime_error(
"Merge failed"));
228 target_source.Close();
231 fs::permissions(target_source.GetFilePath(),
232 fs::perms::owner_read | fs::perms::group_read | fs::perms::others_read,
233 fs::perm_options::replace);
234 fs::rename(target_source.GetFilePath(), out_path);