FOSSredder 0.5.0
Loading...
Searching...
No Matches
DefaultImportStatementStrategy.cpp
Go to the documentation of this file.
1
5
6#include "core/pch.h"
7
15#include "ImportConstants.h"
19#include <filesystem>
20#include <memory>
21#include <mutex>
22#include <chrono>
23#include <thread>
24
28
30namespace poppler = core::ports::pdf_rendering;
31namespace tesseract = core::ports::text_recognition;
32
33namespace {
34
35constexpr auto kPausePollInterval = std::chrono::milliseconds(50);
36
37bool waitWhilePaused(const ImportRequest& req)
38{
39 while (req.pauseFlag && req.pauseFlag->load()) {
40 if (req.cancelFlag && req.cancelFlag->load()) return false;
41 std::this_thread::sleep_for(kPausePollInterval);
42 }
43 return !(req.cancelFlag && req.cancelFlag->load());
44}
45
46}
47
49public:
50 DefaultImportStatementStrategy(std::shared_ptr<core::ports::pdf_rendering::IPdfRenderer> poppler,
51 std::shared_ptr<core::ports::document_image_processing::IDocumentImageProcessor> documentImageProcessor,
52 std::shared_ptr<core::ports::text_recognition::ITextRecognizer> tesseract,
53 std::shared_ptr<core::ports::diagnostics::IErrorReporter> errorReporter)
54 : poppler_(std::move(poppler))
55 , documentImageProcessor_(std::move(documentImageProcessor))
56 , tesseract_(std::move(tesseract))
57 , errorReporter_(std::move(errorReporter)) {
58 }
59
60 ImportResult run(const ImportRequest& req) override {
61 ImportResult out;
62 if (!poppler_ || !documentImageProcessor_ || !tesseract_) return out;
63 if (req.runRoot.empty()) return out;
64
66
67 const std::filesystem::path runRoot(req.runRoot);
68 core::application::importing::ensureDirectoryExists(runRoot, errorReporter_.get(), "core::import::DefaultImportStatementStrategy::createRunRoot");
69
70 auto report = core::application::importing::makeProgressReporter(req, errorReporter_.get());
71
73 if (!waitWhilePaused(req)) { report(0.0, std::string(constants::kProgressCanceled)); return out; }
74
75 std::vector<core::application::importing::draft::TransactionDraft> all;
76
77 const auto renderRequest = core::application::importing::makeRenderRequest(req);
78
79 core::errors::report(errorReporter_.get(), {
80 core::errors::ErrorSeverity::Info,
81 "core::import::DefaultImportStatementStrategy::run",
82 std::string("poppler render start: ") + renderRequest.pdfPath.string() + " dpi=" + std::to_string(renderRequest.dpi),
83 {}
84 });
85 if (!waitWhilePaused(req)) { report(0.0, std::string(constants::kProgressCanceled)); return out; }
87 const auto renderStart = core::application::importing::ImportClock::now();
88 auto renderRes = poppler_->render(renderRequest);
89 timings.renderSec = std::chrono::duration<double>(core::application::importing::ImportClock::now() - renderStart).count();
91
92 if (req.cancelFlag && req.cancelFlag->load()) { report(0.0, std::string(constants::kProgressCanceled)); return out; }
93 if (!waitWhilePaused(req)) { report(0.0, std::string(constants::kProgressCanceled)); return out; }
94
95 const auto extractRequest = core::application::importing::makeExtractRequest(renderRequest, req);
97 const auto extractStart = core::application::importing::ImportClock::now();
98 auto extractRes = poppler_->extract(extractRequest);
99 timings.extractSec = std::chrono::duration<double>(core::application::importing::ImportClock::now() - extractStart).count();
101 if (!waitWhilePaused(req)) { report(0.0, std::string(constants::kProgressCanceled)); return out; }
102
103 std::string carriedBookingDate;
104 int nextTxIndex = 1;
105
106 core::application::importing::SchedulerResources schedulerResources(
107 req, errorReporter_);
108 std::mutex artifactsMutex;
110 renderRes,
111 extractRes,
112 documentImageProcessor_,
113 tesseract_,
114 schedulerResources,
115 report,
116 errorReporter_.get(),
117 out,
118 artifactsMutex);
119
120 const size_t totalPages = pages.size();
121
122 const auto finalizeStart = core::application::importing::ImportClock::now();
123 const auto finalizeStats = finalizeParsedPages(req,
124 pages,
125 documentImageProcessor_,
126 out,
127 all,
128 carriedBookingDate,
129 nextTxIndex,
130 errorReporter_.get(),
131 report,
132 artifactsMutex);
133 timings.finalizeSec = std::chrono::duration<double>(core::application::importing::ImportClock::now() - finalizeStart).count();
134
135 if (!all.empty()) {
136 out.data = std::make_shared<Statement>();
137 auto statementName = std::filesystem::path(req.sourcePath).stem().string();
138 if (statementName.empty()) {
139 statementName = std::filesystem::path(req.sourcePath).filename().string();
140 }
141 if (statementName.empty()) {
142 statementName = "Imported statement";
143 }
144 out.data->rename(statementName);
145 std::vector<std::string> transactionIds;
146 transactionIds.reserve(all.size());
147 for (const auto& transaction : all) {
148 if (!transaction.id.empty()) {
149 transactionIds.push_back(transaction.id);
150 }
151 }
152 out.data->setTransactionIds(std::move(transactionIds));
153 out.transactions = std::move(all);
154 }
155
156 core::application::importing::attachMetricsArtifact(out, req, pages, totalPages, finalizeStats, timings, errorReporter_.get());
157
158 report(1.0, std::string(constants::kProgressDoneMessage));
159 return out;
160 }
161
162private:
163 std::shared_ptr<core::ports::pdf_rendering::IPdfRenderer> poppler_;
164 std::shared_ptr<core::ports::document_image_processing::IDocumentImageProcessor> documentImageProcessor_;
165 std::shared_ptr<core::ports::text_recognition::ITextRecognizer> tesseract_;
166 std::shared_ptr<core::ports::diagnostics::IErrorReporter> errorReporter_;
167};
168
169std::unique_ptr<IImportStatementStrategy> createDefaultImportStrategy(std::shared_ptr<core::ports::pdf_rendering::IPdfRenderer> poppler,
170 std::shared_ptr<core::ports::document_image_processing::IDocumentImageProcessor> documentImageProcessor,
171 std::shared_ptr<core::ports::text_recognition::ITextRecognizer> tesseract,
172 std::shared_ptr<core::ports::diagnostics::IErrorReporter> errorReporter) {
173 return std::make_unique<DefaultImportStatementStrategy>(std::move(poppler), std::move(documentImageProcessor), std::move(tesseract), std::move(errorReporter));
174}
175
176}
FinalizeStats finalizeParsedPages(const ImportRequest &req, const std::vector< PageWork > &pages, const std::shared_ptr< core::ports::document_image_processing::IDocumentImageProcessor > &documentImageProcessor, ImportResult &out, std::vector< core::application::importing::draft::TransactionDraft > &all, std::string &carriedBookingDate, int &nextTxIndex, core::ports::diagnostics::IErrorReporter *errorReporter, const ProgressReporter &report, std::mutex &artifactsMutex)
Provides shared helpers for reporting structured errors and exceptions.
Document image processing port for import workflows.
Declares the public statement import service interface and factory.
PDF rendering port for import workflows.
Text recognition port.
Defines private constants shared by core import orchestration.
Declares private helper types and functions for the import pipeline implementation.
Declares private import strategy contracts used only by core import implementation files.
Declares private support types and helpers for the default import strategy.
Request types for PDF rendering operations.
Domain model for statements.
DefaultImportStatementStrategy(std::shared_ptr< core::ports::pdf_rendering::IPdfRenderer > poppler, std::shared_ptr< core::ports::document_image_processing::IDocumentImageProcessor > documentImageProcessor, std::shared_ptr< core::ports::text_recognition::ITextRecognizer > tesseract, std::shared_ptr< core::ports::diagnostics::IErrorReporter > errorReporter)
Collects common core includes and aliases for precompiled-header builds.
constexpr std::string_view kProgressRenderedMessage
constexpr std::string_view kProgressExtractedMessage
constexpr std::string_view kProgressRenderingMessage
constexpr std::string_view kProgressExtractingMessage
constexpr std::string_view kProgressCanceled
constexpr std::string_view kProgressDoneMessage
constexpr std::string_view kProgressPreparingMessage
FinalizeStats finalizeParsedPages(const ImportRequest &req, const std::vector< PageWork > &pages, const std::shared_ptr< core::ports::document_image_processing::IDocumentImageProcessor > &documentImageProcessor, ImportResult &out, std::vector< core::application::importing::draft::TransactionDraft > &all, std::string &carriedBookingDate, int &nextTxIndex, core::ports::diagnostics::IErrorReporter *errorReporter, const ProgressReporter &report, std::mutex &artifactsMutex)
core::ports::pdf_rendering::RenderRequest makeRenderRequest(const ImportRequest &req)
std::vector< internal::PageWork > collectPageWork(const ImportRequest &req, const core::ports::pdf_rendering::RenderResult &renderResult, const core::ports::pdf_rendering::ExtractResult &extractResult, const std::shared_ptr< core::ports::document_image_processing::IDocumentImageProcessor > &documentImageProcessor, const std::shared_ptr< core::ports::text_recognition::ITextRecognizer > &tesseract, SchedulerResources &resources, const internal::ProgressReporter &report, core::ports::diagnostics::IErrorReporter *errorReporter, ImportResult &out, std::mutex &artifactsMutex)
std::unique_ptr< IImportStatementStrategy > createDefaultImportStrategy(std::shared_ptr< core::ports::pdf_rendering::IPdfRenderer > poppler, std::shared_ptr< core::ports::document_image_processing::IDocumentImageProcessor > documentImageProcessor, std::shared_ptr< core::ports::text_recognition::ITextRecognizer > tesseract, std::shared_ptr< core::ports::diagnostics::IErrorReporter > errorReporter)
internal::ProgressReporter makeProgressReporter(const ImportRequest &req, core::ports::diagnostics::IErrorReporter *errorReporter)
void ensureDirectoryExists(const std::filesystem::path &path, core::ports::diagnostics::IErrorReporter *errorReporter, const char *origin)
core::ports::pdf_rendering::ExtractRequest makeExtractRequest(const core::ports::pdf_rendering::RenderRequest &renderRequest, const ImportRequest &req)
void attachMetricsArtifact(ImportResult &out, const ImportRequest &req, const std::vector< internal::PageWork > &pages, size_t totalPages, const internal::FinalizeStats &finalizeStats, const ImportRunTimings &timings, core::ports::diagnostics::IErrorReporter *errorReporter)
void report(core::ports::diagnostics::IErrorReporter *reporter, const ErrorEvent &event)
Report an already constructed error event when a reporter exists.