lib/shirinji/resolver.rb
# frozen_string_literal: true
module Shirinji
class Resolver
ARG_TYPES = %i[key keyreq].freeze
attr_reader :map, :singletons
def initialize(map)
@map = map
@singletons = {}
end
def resolve(name)
bean = map.get(name)
if bean.access == :singleton
single = singletons[name]
return single if single
end
resolve_bean(bean).tap do |instance|
singletons[name] = instance if bean.access == :singleton
end
end
def reload(map)
@map = map
reset_cache
end
def reset_cache
@singletons = {}
end
private
def resolve_bean(bean)
send(:"resolve_#{bean.value ? :value : :class}_bean", bean)
end
def resolve_value_bean(bean)
bean.value.is_a?(Proc) ? bean.value.call : bean.value
end
def resolve_class_bean(bean)
klass, params = resolve_class(bean)
return klass unless bean.construct
return klass.new if params.empty?
check_params!(params)
args = params.each_with_object({}) do |(_type, arg), memo|
memo[arg] = resolve_attribute(bean, arg)
end
klass.new(**args)
end
def resolve_class(bean)
klass = bean.class_name.constantize
construct = klass.instance_method(:initialize)
[klass, construct.parameters]
end
def resolve_attribute(bean, arg)
return resolve(arg) unless (attr = bean.attributes[arg])
return attr.value if attr.value
resolve(attr.reference)
end
def check_params!(params)
params.each do |pair|
next if ARG_TYPES.include?(pair.first)
raise ArgumentError, 'Only key arguments are allowed'
end
end
end
end