# frozen_string_literal: true require 'singleton' require 'libis/tools/logger' require 'libis/format/config' require_relative 'chain' module Libis module Format module Converter class Repository include Singleton include ::Libis::Tools::Logger attr_reader :converters attr_accessor :converters_glob def initialize @converters = Set.new @converters_glob = File.join(File.dirname(__FILE__), '*_converter.rb') end def self.register(converter_class) instance.converters.add? converter_class end def self.get_converters # rubocop:disable Naming/AccessorMethodName instance.get_converters end def get_converters # rubocop:disable Naming/AccessorMethodName if converters.empty? Dir.glob(converters_glob).each do |filename| # noinspection RubyResolve require File.expand_path(filename) end end converters end def self.get_converter_chain(src_type, tgt_type, operations = {}) instance.get_converter_chain src_type, tgt_type, operations end def get_converter_chain(src_type, tgt_type, operations = {}) msg = "conversion from #{src_type} to #{tgt_type}" chain_list = find_chains src_type, tgt_type, operations # if chain_list.length > 1 # warn "Found more than one conversion chain for #{msg}. Picking the first one." # end if chain_list.empty? error "No conversion chain found for #{msg}" return nil end # chain_list.each do |chain| # debug "Matched chain: #{chain}" # end chain_list[0] end private def find_chains(src_type, tgt_type, operations) chain = Libis::Format::Converter::Chain.new(src_type, tgt_type, operations) build_chains(chain) end def build_chains(chain) found = [] chains = [chain] # Avoid chains that are too long Libis::Format::Config[:converter_chain_max_level].times do new_chains = [] get_converters.each do |converter| new_chains += chains.map { |c| c.append(converter) }.flatten end found = new_chains.select(&:valid?) return found unless found.empty? chains = new_chains end found end end end end end