#pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "Core/Base/JSON.h" class Global; struct External_Database_Row { std::map> columns; External_Database_Row() = default; External_Database_Row(const External_Database_Row&) = default; External_Database_Row& operator=(const External_Database_Row&) = default; External_Database_Row(External_Database_Row&&) noexcept = default; External_Database_Row& operator=(External_Database_Row&&) noexcept = default; [[nodiscard]] std::optional get(const std::string& column) const; [[nodiscard]] Psc::JSON to_json() const; }; using External_Database_Row_Map = std::map>; struct External_Resource_Status { std::string name; std::size_t row_count{}; bool downloaded{}; bool imported{}; std::string message; }; class External_Resources { public: External_Resources(std::string name, std::string cache_file_name, std::string download_url, std::string description, std::uint64_t update_interval_seconds); virtual ~External_Resources() = default; [[nodiscard]] std::size_t row_count(SQLite::Database& db) const; virtual void create_table(SQLite::Database& db) const = 0; External_Resource_Status update(SQLite::Database& db, const std::filesystem::path& cache_pos, bool force_download, bool only_when_empty); External_Resource_Status import_offline(SQLite::Database& db, const std::filesystem::path& source_file); External_Resource_Status clear_table(SQLite::Database& db, const std::filesystem::path& cache_pos); [[nodiscard]] std::optional query_one( SQLite::Database& db, const std::vector& primary_key_values) const; void init(const Psc::JSON* that_json) { Get_J(name) Get_J(download_url) Get_J(description) Get_J(update_interval_seconds) Get_J(last_updated_at) } [[nodiscard]] Psc::JSON to_json() const { Psc::JSON ret = Psc::JSON::object(); Ret_J(name) Ret_J(download_url) Ret_J(description) Ret_J(update_interval_seconds) Ret_J(last_updated_at) return ret; } std::string name; std::string cache_file_name; std::string download_url; std::string description; std::uint64_t update_interval_seconds{}; std::time_t last_updated_at{}; protected: [[nodiscard]] virtual std::filesystem::path source_file( const std::filesystem::path& cache_pos) const; virtual bool fetch(const std::filesystem::path& cache_pos, bool force_download) const; virtual std::size_t import_file(SQLite::Database& db, const std::filesystem::path& source_file) const = 0; [[nodiscard]] virtual const std::vector& primary_key_columns() const = 0; void mark_updated(); void clear_last_updated_at(); }; class External_Resources_Manager { public: using Status_Callback = std::function; using Status_List_Callback = std::function)>; using Row_Callback = std::function)>; using Row_Map_Callback = std::function; External_Resources_Manager(); void init(const Psc::JSON* that_json); [[nodiscard]] Psc::JSON to_json() const; void server(Global* g); void load_sqlite_db(std::string path); std::vector refresh_external_databases(bool force_download = true); External_Resource_Status refresh_external_database(const std::string& resource_name, bool force_download = true); External_Resource_Status import_external_database( const std::string& resource_name, const std::filesystem::path& source_file); External_Resource_Status clear_external_database_table(const std::string& resource_name); [[nodiscard]] std::optional query_external_database( const std::string& resource_name, const std::vector& primary_key_values) const; [[nodiscard]] std::map> query_aircraft_external_databases(const std::string& icao24) const; [[nodiscard]] std::map> query_callsign_external_databases( const std::optional& callsign) const; [[nodiscard]] std::vector external_database_status() const; void async_refresh_external_databases(bool force_download, Status_List_Callback callback); void async_refresh_external_database(std::string resource_name, bool force_download, Status_Callback callback); void async_import_external_database(std::string resource_name, std::filesystem::path source_file, Status_Callback callback); void async_clear_external_database_table(std::string resource_name, Status_Callback callback); void async_query_external_database(std::string resource_name, std::vector primary_key_values, Row_Callback callback) const; void async_query_aircraft_external_databases(std::string icao24, Row_Map_Callback callback) const; void async_query_callsign_external_databases(std::optional callsign, Row_Map_Callback callback) const; void async_external_database_status(Status_List_Callback callback) const; [[nodiscard]] concurrencpp::result> refresh_external_databases_coro(bool force_download = true); [[nodiscard]] concurrencpp::result refresh_external_database_coro(std::string resource_name, bool force_download = true); [[nodiscard]] concurrencpp::result import_external_database_coro(std::string resource_name, std::filesystem::path source_file); [[nodiscard]] concurrencpp::result clear_external_database_table_coro(std::string resource_name); [[nodiscard]] concurrencpp::result> query_external_database_coro(std::string resource_name, std::vector primary_key_values) const; [[nodiscard]] concurrencpp::result> query_aircraft_external_databases_coro(std::string icao24) const; [[nodiscard]] concurrencpp::result> query_callsign_external_databases_coro(std::optional callsign) const; [[nodiscard]] concurrencpp::result> external_database_status_coro() const; void register_external_resource(std::unique_ptr external_res); void initialize(SQLite::Database& db, std::filesystem::path cache_pos); std::vector sync_missing(SQLite::Database& db); std::vector refresh_all(SQLite::Database& db, bool force_download = true); External_Resource_Status refresh_one(SQLite::Database& db, const std::string& resource_name, bool force_download = true); External_Resource_Status import_offline(SQLite::Database& db, const std::string& resource_name, const std::filesystem::path& source_file); External_Resource_Status clear_table(SQLite::Database& db, const std::string& resource_name); [[nodiscard]] std::optional query_one( SQLite::Database& db, const std::string& resource_name, const std::vector& primary_key_values) const; [[nodiscard]] std::map> query_aircraft(SQLite::Database& db, const std::string& icao24) const; [[nodiscard]] std::map> query_callsign(SQLite::Database& db, const std::optional& callsign) const; [[nodiscard]] std::vector status(SQLite::Database& db) const; std::string ecap_sqlite_path; std::filesystem::path cache_pos_; private: [[nodiscard]] SQLite::Database& require_db() const; External_Resources& get_resource(const std::string& resource_name) const; std::vector update_all(SQLite::Database& db, bool force_download, bool only_when_empty); std::unique_ptr db_; std::vector> resources_; mutable std::mutex mtx_; };