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);