>From b4b023db886082790eea144a0398b8527d31e768 Mon Sep 17 00:00:00 2001
From: Vadim Zeitlin
Date: Mon, 6 Jul 2015 01:33:14 +0200
Subject: [PATCH 3/4] Use ledger_emitter class instead of [pre_]emit_ledger()
functions.
Use of the class allows to preserve internal state between the calls to
pre_emit_ledger() and emit_ledger() which will be important for the premiums
PDF emission to be added soon.
Preserve emit_ledger() function for compatibility and ease of use when only a
single ledger is being emitted, but use the new class in group_values.cpp code.
---
emit_ledger.cpp | 354 +++++++++++++++++++++++++++++++++++++++++++++----------
emit_ledger.hpp | 29 ++++-
group_values.cpp | 22 ++--
3 files changed, 323 insertions(+), 82 deletions(-)
diff --git a/emit_ledger.cpp b/emit_ledger.cpp
index 7b3254f..a39adb2 100644
--- a/emit_ledger.cpp
+++ b/emit_ledger.cpp
@@ -44,36 +44,7 @@
#include
#include
-/// Prepare to emit ledger(s) in various guises.
-
-void pre_emit_ledger
- (fs::path const& tsv_filepath
- ,mcenum_emission emission
- )
-{
- if(emission & mce_emit_spreadsheet)
- {
- LMI_ASSERT(!tsv_filepath.empty());
- std::string spreadsheet_filename =
- tsv_filepath.string()
- + configurable_settings::instance().spreadsheet_file_extension()
- ;
- std::remove(spreadsheet_filename.c_str());
- }
- if(emission & mce_emit_group_roster)
- {
- LMI_ASSERT(!tsv_filepath.empty());
- std::string spreadsheet_filename =
- tsv_filepath.string()
- + ".roster"
- + configurable_settings::instance().spreadsheet_file_extension()
- ;
- std::remove(spreadsheet_filename.c_str());
- PrintRosterHeaders(spreadsheet_filename);
- }
-}
-
-/// Emit a ledger in various guises.
+/// Classes for emitting a ledger in various guises.
///
/// The commands for
/// mce_emit_pdf_file
@@ -95,33 +66,74 @@
/// for which a single output file encompasses all cells in a census,
/// whereas other output types produce a separate file for each cell.
-void emit_ledger
- (fs::path const& filepath
- ,fs::path const& tsv_filepath
- ,Ledger const& ledger
- ,mcenum_emission emission
- )
+/// Base class for all the emission types.
+///
+/// The only member function that must be overridden is add_ledger(), start()
+/// and end() are optional and do nothing by default.
+class ledger_single_format_emitter
+ :private lmi::uncopyable
{
- if((emission & mce_emit_composite_only) && !ledger.GetIsComposite())
- {
- return;
- }
+ public:
+ ledger_single_format_emitter() {}
+ virtual ~ledger_single_format_emitter() {}
- if(emission & mce_emit_pdf_file)
+ virtual void start() {}
+ virtual void add_ledger
+ (fs::path const& filepath
+ ,Ledger const& ledger
+ ) = 0;
+ virtual void end() {}
+};
+
+class ledger_emitter_pdf_file
+ :public ledger_single_format_emitter
+{
+ public:
+ virtual void add_ledger
+ (fs::path const& filepath
+ ,Ledger const& ledger
+ )
{
write_ledger_as_pdf(ledger, filepath);
}
- if(emission & mce_emit_pdf_to_printer)
+};
+
+class ledger_emitter_pdf_to_printer
+ :public ledger_single_format_emitter
+{
+ public:
+ virtual void add_ledger
+ (fs::path const& filepath
+ ,Ledger const& ledger
+ )
{
std::string pdf_out_file = write_ledger_as_pdf(ledger, filepath);
file_command()(pdf_out_file, "print");
}
- if(emission & mce_emit_pdf_to_viewer)
+};
+
+class ledger_emitter_pdf_to_viewer
+ :public ledger_single_format_emitter
+{
+ public:
+ virtual void add_ledger
+ (fs::path const& filepath
+ ,Ledger const& ledger
+ )
{
std::string pdf_out_file = write_ledger_as_pdf(ledger, filepath);
file_command()(pdf_out_file, "open");
}
- if(emission & mce_emit_test_data)
+};
+
+class ledger_emitter_test_data
+ :public ledger_single_format_emitter
+{
+ public:
+ virtual void add_ledger
+ (fs::path const& filepath
+ ,Ledger const& ledger
+ )
{
fs::ofstream ofs
(fs::change_extension(filepath, ".test")
@@ -129,36 +141,252 @@
);
ledger.Spew(ofs);
}
- if(emission & mce_emit_spreadsheet)
+};
+
+class ledger_emitter_text_stream
+ :public ledger_single_format_emitter
+{
+ public:
+ virtual void add_ledger
+ (fs::path const&
+ ,Ledger const& ledger
+ )
{
- LMI_ASSERT(!tsv_filepath.empty());
- PrintCellTabDelimited
- (ledger
- , tsv_filepath.string()
- + configurable_settings::instance().spreadsheet_file_extension()
- );
+ PrintLedgerFlatText(ledger, std::cout);
+ }
+};
+
+class ledger_emitter_custom_0
+ :public ledger_single_format_emitter
+{
+ public:
+ virtual void add_ledger
+ (fs::path const& filepath
+ ,Ledger const& ledger
+ )
+ {
+ custom_io_0_write(ledger, filepath.string());
+ }
+};
+
+class ledger_emitter_custom_1
+ :public ledger_single_format_emitter
+{
+ public:
+ virtual void add_ledger
+ (fs::path const& filepath
+ ,Ledger const& ledger
+ )
+ {
+ custom_io_1_write(ledger, filepath.string());
}
- if(emission & mce_emit_group_roster)
+};
+
+// Base class for the emission types using a single output file and thus
+// requiring the name of this file. Notice that the ctor removes any existing
+// file with this name.
+class ledger_emitter_single_output_base
+ :public ledger_single_format_emitter
+{
+ public:
+ explicit ledger_emitter_single_output_base
+ (fs::path const& tsv_filepath
+ ,std::string const& output_ext
+ )
+ :output_filename_(tsv_filepath.string() + output_ext)
{
LMI_ASSERT(!tsv_filepath.empty());
- PrintRosterTabDelimited
- (ledger
- , tsv_filepath.string()
- + ".roster"
+ std::remove(output_filename_.c_str());
+ }
+
+ protected:
+ std::string const output_filename_;
+};
+
+class ledger_emitter_spreadsheet
+ :public ledger_emitter_single_output_base
+{
+ public:
+ explicit ledger_emitter_spreadsheet
+ (fs::path const& tsv_filepath
+ )
+ :ledger_emitter_single_output_base
+ (tsv_filepath
+ ,configurable_settings::instance().spreadsheet_file_extension()
+ )
+ {
+ }
+
+ virtual void add_ledger
+ (fs::path const&
+ ,Ledger const& ledger
+ )
+ {
+ PrintCellTabDelimited(ledger, output_filename_);
+ }
+};
+
+class ledger_emitter_group_roster
+ :public ledger_emitter_single_output_base
+{
+ public:
+ explicit ledger_emitter_group_roster
+ (fs::path const& tsv_filepath
+ )
+ :ledger_emitter_single_output_base
+ (tsv_filepath
+ , ".roster"
+ configurable_settings::instance().spreadsheet_file_extension()
- );
+ )
+ {
}
- if(emission & mce_emit_text_stream)
+
+ virtual void start()
{
- PrintLedgerFlatText(ledger, std::cout);
+ PrintRosterHeaders(output_filename_);
}
- if(emission & mce_emit_custom_0)
+
+ virtual void add_ledger
+ (fs::path const&
+ ,Ledger const& ledger
+ )
{
- custom_io_0_write(ledger, filepath.string());
+ PrintRosterTabDelimited(ledger, output_filename_);
+ }
+};
+
+class ledger_emitter_impl
+ :private lmi::uncopyable
+{
+ public:
+ ledger_emitter_impl
+ (mcenum_emission emission
+ ,fs::path const& tsv_filepath
+ )
+ :emission_(emission)
+ {
+ if(emission & mce_emit_pdf_to_printer)
+ {
+ emitters_.push_back(new ledger_emitter_pdf_to_printer());
+ }
+ if(emission & mce_emit_pdf_to_viewer)
+ {
+ emitters_.push_back(new ledger_emitter_pdf_to_viewer());
+ }
+ if(emission & mce_emit_test_data)
+ {
+ emitters_.push_back(new ledger_emitter_test_data());
+ }
+ if(emission & mce_emit_spreadsheet)
+ {
+ emitters_.push_back(new ledger_emitter_spreadsheet(tsv_filepath));
+ }
+ if(emission & mce_emit_group_roster)
+ {
+ emitters_.push_back(new ledger_emitter_group_roster(tsv_filepath));
+ }
+ if(emission & mce_emit_text_stream)
+ {
+ emitters_.push_back(new ledger_emitter_text_stream());
+ }
+ if(emission & mce_emit_custom_0)
+ {
+ emitters_.push_back(new ledger_emitter_custom_0());
+ }
+ if(emission & mce_emit_custom_1)
+ {
+ emitters_.push_back(new ledger_emitter_custom_1());
+ }
}
- if(emission & mce_emit_custom_1)
+
+ ~ledger_emitter_impl()
{
- custom_io_1_write(ledger, filepath.string());
+ for(evci i = emitters_.begin(); i != emitters_.end(); ++i)
+ {
+ delete (*i);
+ }
+ }
+
+ typedef std::vector::const_iterator evci;
+
+ evci begin() const
+ {
+ return emitters_.begin();
}
+ evci end() const
+ {
+ return emitters_.end();
+ }
+
+ // This field is public, there is no benefit in hiding it behind an
+ // accessor.
+ mcenum_emission const emission_;
+
+ private:
+ std::vector emitters_;
+};
+
+ledger_emitter::ledger_emitter
+ (mcenum_emission emission
+ ,fs::path const& tsv_filepath
+ )
+ :impl_(new ledger_emitter_impl(emission, tsv_filepath))
+{
+}
+
+ledger_emitter::~ledger_emitter()
+{
+ // Trivial but out of line dtor to ensure that it is defined in a place
+ // where ledger_emitter_impl is fully declared.
+}
+
+void ledger_emitter::start()
+{
+ for(ledger_emitter_impl::evci i = impl_->begin(); i != impl_->end(); ++i)
+ {
+ (*i)->start();
+ }
+}
+
+void ledger_emitter::add_ledger
+ (fs::path const& filepath
+ ,Ledger const& ledger
+ )
+{
+ LMI_ASSERT(!ledger.GetIsComposite());
+
+ if(impl_->emission_ & mce_emit_composite_only)
+ {
+ return;
+ }
+
+ for(ledger_emitter_impl::evci i = impl_->begin(); i != impl_->end(); ++i)
+ {
+ (*i)->add_ledger(filepath, ledger);
+ }
+}
+
+void ledger_emitter::add_composite
+ (fs::path const& filepath
+ ,Ledger const& composite
+ )
+{
+ LMI_ASSERT(composite.GetIsComposite());
+
+ for(ledger_emitter_impl::evci i = impl_->begin(); i != impl_->end(); ++i)
+ {
+ (*i)->add_ledger(filepath, composite);
+ }
+}
+
+void emit_ledger
+ (fs::path const& filepath
+ ,fs::path const& tsv_filepath
+ ,Ledger const& ledger
+ ,mcenum_emission emission
+ )
+{
+ ledger_emitter emitter(emission, tsv_filepath);
+ emitter.add_ledger(filepath, ledger);
}
diff --git a/emit_ledger.hpp b/emit_ledger.hpp
index 9948dec..2d4602a 100644
--- a/emit_ledger.hpp
+++ b/emit_ledger.hpp
@@ -28,16 +28,36 @@
#include "mc_enum_type_enums.hpp" // enum mcenum_emission
#include "so_attributes.hpp"
+#include "uncopyable_lmi.hpp"
+#include
#include
class Ledger;
-void LMI_SO pre_emit_ledger
- (fs::path const& tsv_filepath
- ,mcenum_emission emission
- );
+class ledger_emitter_impl;
+
+/// General purpose class to be used for emitting more than one ledger.
+
+class LMI_SO ledger_emitter
+ :private lmi::uncopyable
+{
+ public:
+ explicit ledger_emitter
+ (mcenum_emission emission
+ ,fs::path const& tsv_filepath
+ );
+ ~ledger_emitter();
+ void start();
+ void add_ledger(fs::path const& filepath, Ledger const& ledger);
+ void add_composite(fs::path const& filepath, Ledger const& composite);
+
+ private:
+ boost::scoped_ptr const impl_;
+};
+
+/// Convenience function for emitting a single ledger.
void LMI_SO emit_ledger
(fs::path const& filepath
,fs::path const& tsv_filepath
@@ -46,4 +66,3 @@ void LMI_SO emit_ledger
);
#endif // emit_ledger_hpp
-
diff --git a/group_values.cpp b/group_values.cpp
index 7833786..9ac0589 100644
--- a/group_values.cpp
+++ b/group_values.cpp
@@ -131,7 +131,8 @@ census_run_result run_census_in_series::operator()
);
Timer timer_output;
- pre_emit_ledger(file, emission);
+ ledger_emitter emitter(emission, file);
+ emitter.start();
result.seconds_for_output_ += timer_output.stop().elapsed_seconds();
for(unsigned int j = 0; j < cells.size(); ++j)
@@ -143,11 +144,9 @@ census_run_result run_census_in_series::operator()
IV.run(cells[j]);
composite.PlusEq(*IV.ledger());
timer_output.restart();
- emit_ledger
+ emitter.add_ledger
(serial_file_path(file, name, j, "hastur")
- ,file
,*IV.ledger()
- ,emission
);
result.seconds_for_output_ += timer_output.stop().elapsed_seconds();
meter->dawdle(intermission_between_printouts(emission));
@@ -161,11 +160,9 @@ census_run_result run_census_in_series::operator()
meter->culminate();
timer_output.restart();
- emit_ledger
+ emitter.add_composite
(serial_file_path(file, "composite", -1, "hastur")
- ,file
,composite
- ,emission
);
result.seconds_for_output_ += timer_output.stop().elapsed_seconds();
@@ -254,6 +251,7 @@ census_run_result run_census_in_parallel::operator()
Timer timer;
Timer timer_output;
census_run_result result;
+ ledger_emitter emitter(emission, file);
std::vector::const_iterator ip;
std::vector > cell_values;
@@ -642,7 +640,7 @@ census_run_result run_census_in_parallel::operator()
meter->culminate();
timer_output.restart();
- pre_emit_ledger(file, emission);
+ emitter.start();
result.seconds_for_output_ += timer_output.stop().elapsed_seconds();
meter = create_progress_meter
@@ -654,11 +652,9 @@ census_run_result run_census_in_parallel::operator()
{
std::string const name(cells[j]["InsuredName"].str());
timer_output.restart();
- emit_ledger
+ emitter.add_ledger
(serial_file_path(file, name, j, "hastur")
- ,file
,*(*i)->ledger_from_av()
- ,emission
);
result.seconds_for_output_ += timer_output.stop().elapsed_seconds();
meter->dawdle(intermission_between_printouts(emission));
@@ -671,11 +667,9 @@ census_run_result run_census_in_parallel::operator()
meter->culminate();
timer_output.restart();
- emit_ledger
+ emitter.add_composite
(serial_file_path(file, "composite", -1, "hastur")
- ,file
,composite
- ,emission
);
result.seconds_for_output_ += timer_output.stop().elapsed_seconds();
--
2.1.0