>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