module Eco module API class UseCases # Basic class to manage InputOuput for usecases class BaseIO < BaseCase @types = BaseCase.types include Eco::Language::Methods::DslAble include Eco::Language::AuxiliarLogger class MissingParameter < StandardError attr_reader :type, :required, :given def initialize(msg = nil, required:, given:, type: nil) @type = type @required = required @given = given msg += " of type '#{type}'" if type msg += " requires an object '#{required}'. Given: #{given}." super(msg) end end class << self def input_required?(type) !valid_type?(type) || %i[import sync].include?(type) end def people_required?(type) !valid_type?(type) || %i[filter transform sync error_handler export].include?(type) end end attr_reader :input, :people, :session, :options attr_reader :type attr_accessor :output # @param type [Symbol] a valid type (among `self.class.types`) # @param input [Eco::API::Common::People::Entries, Eco::API::Organization::People] the input data of reference. # @param people [Eco::API::Organization::People] people object. # @param session [Eco::API:Session] # @param options [Hash] hash with symbol keys (i.e. behaviour modifiers, cli trackers, filters, etc.) def initialize( # rubocop:disable Lint/MissingSuper session:, type: nil, input: nil, people: nil, options: {}, output: nil, validate: true ) self.type = type if type if self.type && validate # rubocop:disable Style/IfUnlessModifier validate_args(input: input, people: people, session: session, options: options) end @output = output @input = input @people = people @session = session @options = options end # @param value [Symbol] a valid type (among `self.class.types`) def type=(value) self.class.validate_type(value) @type = value end # Helper to obtain an `BaseIO` object from any child class. # @return [Eco::API::UseCases::BaseIO] def base kargs = params(keyed: true).merge({ type: type, output: output }).slice(:type, :input, :people, :session, :options, :output) # :validate <- ? Eco::API::UseCases::BaseIO.new(**kargs) end # @see Eco::API::UseCases::BaseIO#initialize # @return [Eco::API::UseCases::BaseIO] def new(**kargs) default = { type: type, input: input, people: people, session: session, options: options, output: output, validate: true } self.class.new(**default.merge(kargs)) end # Helper to build a `Hash` of symbol keys or `Array` with params to do callbacks. def params(keyed: false, all: false) kargs = {} kargs.merge!(input: input) if input_required? || all kargs.merge!(people: people) if people_required? || all kargs.merge!(session: session, options: options) keyed ? kargs : kargs.values end # Shortcut to run a usecase passing this `io` as parameter # @note # 1. It swaps `output` to `input` or `people` depending on `self.type` # 2. does this, **before** the target `case_name` launch and **after # @return [Eco::API::UseCases::BaseIO] def process_case(case_name, case_type, **params) session.process_case(case_name, io: chained, type: case_type, **params).chained end # Does the switch from output to result in a new IO object. # @note if there isn't `output` it doesn't do the switch, # provided that it preserves the target parameter # (otherise it would blank it) # @return [Eco::API::UseCases::BaseIO] def chained(as: type) # rubocop:disable Naming/MethodParameterName base.tap do |io_base| next unless io_base.output case as when :import io_base.output_be_input! when :filter io_base.output_be_people! # when :transform, :sync, :export, :error_handler, :other end end end protected def output_be_input! @input, @output = output, nil # rubocop:disable Style/ParallelAssignment input end def output_be_people! @people, @output = output, nil # rubocop:disable Style/ParallelAssignment people end private def validate_args(input:, people:, session:, options:) if !session.is_a?(Eco::API::Session) raise MissingParameter.new("UseCase", required: :session, given: session.class) elsif input_required? && !input raise MissingParameter.new("UseCase", type: type, required: :input, given: input.class) elsif people_required? && !people.is_a?(Eco::API::Organization::People) raise MissingParameter.new("UseCase", type: type, required: :people, given: people.class) elsif !options || (options && !options.is_a?(Hash)) raise MissingParameter.new("Use Case options", required: :Hash, given: options.class) end true end def input_required? self.class.input_required?(type) end def people_required? self.class.people_required?(type) end end end end end