# Copyright (c) 2020 Jerome Arbez-Gindre # frozen_string_literal: true require('csv') require('defmastership/export/body_formatter') require('defmastership/export/header_formatter') module Defmastership # Module to host export classes module Export # Module to host CSV export classes module CSV # to export a CSV file class Formatter # @param doc [Document] the document to export # @param sep [String] the CSV separator def initialize(doc, sep) @doc = doc @sep = sep end # Export the document to a CSV file # # @param output_file [Strinf] filename for the export def export_to(output_file) column_list = build_column_list ::CSV.open(output_file, 'w:ISO-8859-1', col_sep: @sep) do |csv| csv << header(column_list) export_definitions_in(csv, column_list) end end private # Helper functions module Helper # @return [Array<Symbol>] the array of methods for columns inclusion # # @param column_spec [MethodSpec] the method to include or not with its guard # @param doc [Document] the Document to export def self.column_method(column_spec, doc) column_spec.guard.call(doc) ? [column_spec.column_method] : [] end # 2-uplet with one method to include or not depending of a lambda guard MethodSpec = Struct.new(:column_method, :guard) public_constant :MethodSpec end private_constant :Helper COLUMNS_METHODS_SPECIFICATIONS = [ Helper::MethodSpec.new(:type, ->(_) { true }), Helper::MethodSpec.new(:reference, ->(_) { true }), Helper::MethodSpec.new(:summary, lambda(&:summaries?)), Helper::MethodSpec.new(:value, ->(_) { true }), Helper::MethodSpec.new(:checksum, ->(_) { true }), Helper::MethodSpec.new(:wrong_explicit_checksum, lambda(&:wrong_explicit_checksum?)), Helper::MethodSpec.new(:explicit_version, lambda(&:explicit_version?)), Helper::MethodSpec.new(:labels, ->(doc) { !doc.labels.empty? }), Helper::MethodSpec.new(:eref, ->(doc) { !doc.eref.empty? }), Helper::MethodSpec.new(:iref, lambda(&:iref)), Helper::MethodSpec.new(:attributes, ->(doc) { !doc.attributes.empty? }) ].freeze private_constant :COLUMNS_METHODS_SPECIFICATIONS def export_definitions_in(csv, column_list) @doc.definitions.each { |definition| csv << body(definition, column_list) } end def header(column_list) header_formatter = HeaderFormatter.new(@doc) header_line = column_list.map { |part| header_formatter.public_send(part) } header_line.flatten end def body(definition, column_list) body_formatter = BodyFormatter.new(@doc, definition) body_line = column_list.map { |part| body_formatter.public_send(part) } body_line.flatten end def build_column_list COLUMNS_METHODS_SPECIFICATIONS.reduce([]) do |acc, column| acc + Helper.column_method(column, @doc) end end end end end end