lib/eco/api/common/people/entry_factory.rb in eco-helpers-0.6.17 vs lib/eco/api/common/people/entry_factory.rb in eco-helpers-0.7.1

- old
+ new

@@ -1,33 +1,121 @@ module Eco module API module Common module People + # @attr_reader person_parser [Eco::API::Common::People::PersonParser] set of attribute, type and format parsers/serializers. class EntryFactory attr_reader :person_parser - def initialize(schema:, person_parser: nil, fields_mapper: nil, logger: ::Logger.new(IO::NULL)) - raise "Constructor needs a PersonSchema. Given: #{schema}" if !schema.is_a?(Ecoportal::API::V1::PersonSchema) - raise "Expecting PersonParser. Given: #{person_parser}" if person_parser && !person_parser.is_a?(Eco::API::Common::People::PersonParser) - raise "Expecting Mapper object. Given: #{fields_mapper}" if fields_mapper && !fields_mapper.is_a?(Eco::Data::Mapper) + # @param schema [Ecoportal::API::V1::PersonSchema] schema of person details that the parser will be based upon. + # @param person_parser [nil, Eco::API::Common::People::PersonParser] set of attribute, type and format parsers/serializers. + # @param attr_map [nil, Eco::Data::Mapper] attribute names mapper to translate external names into internal ones and _vice versa_. + # @param logger [Common::Session::Logger, ::Logger] object to manage logs. + def initialize(schema:, person_parser: nil, attr_map: nil, logger: ::Logger.new(IO::NULL)) + fatal "Constructor needs a PersonSchema. Given: #{schema}" if !schema.is_a?(Ecoportal::API::V1::PersonSchema) + fatal "Expecting PersonParser. Given: #{person_parser}" if person_parser && !person_parser.is_a?(Eco::API::Common::People::PersonParser) + fatal "Expecting Mapper object. Given: #{fields_mapper}" if attr_map && !attr_map.is_a?(Eco::Data::Mapper) @logger = logger @schema = Ecoportal::API::V1::PersonSchema.new(JSON.parse(schema.doc.to_json)) default_parser = Eco::API::Common::People::DefaultParsers.new(schema: @schema) - @parser = default_parser.merge(person_parser) + @person_parser = default_parser.merge(person_parser) - @fields_mapper = fields_mapper + @attr_map = attr_map end + # key method to generate objects of `PersonEntry` that share dependencies via this `EntryFactory` environment. + # @note this method is necessary to make the factory object work as a if it was a class `PersonEntry` you can call `new` on. + # @param data [Array<Hash>] data to be parsed. The external hashed entry. + # @return [Eco::API::Common::People::PersonEntry] def new(data, dependencies: {}) - PersonEntry.new(data, parser: @parser, mapper: @fields_mapper, dependencies: dependencies, logger: @logger) + PersonEntry.new( + data, + person_parser: @person_parser, + attr_map: @attr_map, + dependencies: dependencies, + logger: @logger + ) end - def entries(data) - Entries.new(data, klass: PersonEntry, factory: self) + # Helper that provides a collection of `Entries`, which in turn provides with further helpers to find and exclude entries. + # It accepts a `file:` and `format:` or `data:` but not both options together. + # @raise Exception + # - if you try to provide `data:` and `file:` at the same time. + # - if you provide `file:` but omit `format:`. + # - if the `format:` you provide is not a `Symbol`. + # - if there is no _parser/serializer_ defined for `format:`. + # @param data [Array<Hash>] data to be parsed. It cannot be used alongside with `file:` + # @param file [String] absolute or relative path to the input file. It cannot be used alongside with `data:`. + # @param format [Symbol] it must be used when you use the option `file:` (i.e. `:xml`, `:csv`), as it specifies the format of the input `file:`. + # @param encoding [String] optional parameter to read `file:` by expecting certain encoding. + # @return [Eco::API::Common::People::Entries] collection of `Eco::API::Common::People::PersonEntry`. + def entries(data: (no_data = true; nil), file: (no_file = true; nil), format: (no_format = true; nil), encoding: nil) + fatal("You should at least use data: or file:, but not both") if no_data == no_file + fatal("You must specify a valid format: (symbol) when you use file.") if file && no_format + fatal("Format should be a Symbol. Given '#{format}'") if format && !format.is_a?(Symbol) + fatal("There is no parser/serializer for format ':#{format.to_s}'") unless no_format || @person_parser.defined?(format) + + if file + arr_hash = [] + if Eco::API::Common::Session::FileManager.file_exists?(file) + encoding ||= Eco::API::Common::Session::FileManager.encoding(file) + file_content = File.read(file, encoding: encoding) + arr_hash = @person_parser.parse(format, file_content) + end + entries(data: arr_hash) + else + Entries.new(data, klass: PersonEntry, factory: self) + end end + + # Helper that generates a file out of `data:`. + # @raise Exception + # - if you try to provide `data:` in the wrong format. + # - if you `file:` is empty. + # - if the `format:` you provide is not a `Symbol`. + # - if there is no _parser/serializer_ defined for `format:`. + # @param data [Eco::API::Organization::People] data to be parsed. + # @param file [String] absolute or relative path to the ouput file. + # @param format [Symbol] it specifies the format of the output `file:` (i.e. `:xml`, `:csv`). There must be a parser/serializer defined for it. + # @param encoding [String] optional parameter to geneate `file:` content by unsing certain encoding. + # @return [Void]. + def export(data:, file: "export", format: :csv, encoding: "utf-8") + fatal("data: Expected Eco::API::Organization::People object. Given: #{data.class}") unless data.is_a?(Eco::API::Organization::People) + fatal("A file should be specified.") unless !file.to_s.strip.empty? + fatal("Format should be a Symbol. Given '#{format}'") if format && !format.is_a?(Symbol) + fatal("There is no parser/serializer for format ':#{format.to_s}'") unless @person_parser.defined?(format) + + run = true + if Eco::API::Common::Session::FileManager.file_exists?(file) + print "The file '#{file}' already exists. Do you want to overwrite it? (Y/n): " + res = STDIN.gets.strip + run = ["y", "Y", ""].include?(res) + end + + if run + deps = {"supervisor_id" => {people: data}} + + data_entries = data.map do |person| + self.new(person, dependencies: deps).to_hash + end + + File.open(file, "w", enconding: encoding) do |fd| + fd.write(@person_parser.serialize(format, data_entries)) + end + end + + end + + private + + def fatal(msg) + @logger.fatal(msg) + raise msg + end + end end end end