Completed
Push — master ( 308a2c...1aebdd )
by Fike
01:00
created

Registry.initialize()   A

Complexity

Conditions 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 3
rs 10
cc 1
1
# frozen_String_literal: true
2
3
require_relative '../mixin/errors'
4
require_relative 'parameter'
5
require_relative 'builtin/enumerable_type'
6
require_relative 'builtin/array_type'
7
require_relative 'builtin/hash_type'
8
require_relative 'builtin/hash_tuple_type'
9
require_relative 'builtin/set_type'
10
require_relative 'builtin/primitive_type'
11
12
module AMA
13
  module Entity
14
    class Mapper
15
      class Type
16
        # Holds all registered types
17
        class Registry
18
          include Mixin::Errors
19
20
          attr_accessor :types
21
22
          def initialize
23
            @types = {}
24
          end
25
26
          # @return [AMA::Entity::Mapper::Type::Registry]
27
          def with_default_types
28
            register(BuiltIn::EnumerableType::INSTANCE)
29
            register(BuiltIn::ArrayType::INSTANCE)
30
            register(BuiltIn::HashType::INSTANCE)
31
            register(BuiltIn::SetType::INSTANCE)
32
            register(BuiltIn::HashTupleType::INSTANCE)
33
            register(BuiltIn::RationalType::INSTANCE)
34
            register(BuiltIn::DateTimeType::INSTANCE)
35
            BuiltIn::PrimitiveType::ALL.each do |type|
36
              register(type)
37
            end
38
            self
39
          end
40
41
          # @param [Class, Module] klass
42
          def [](klass)
43
            @types[klass]
44
          end
45
46
          # @param [AMA::Entity::Mapper::Type] type
47
          def register(type)
48
            @types[type.type] = type
49
          end
50
51
          # @param [Class] klass
52
          def key?(klass)
53
            @types.key?(klass)
54
          end
55
56
          alias registered? key?
57
58
          # @param [Class, Module] klass
59
          # @return [Array<AMA::Entity::Mapper::Type>]
60
          def select(klass)
61
            types = class_hierarchy(klass).map do |entry|
62
              @types[entry]
63
            end
64
            types.reject(&:nil?)
65
          end
66
67
          # @param [Class, Module] klass
68
          # @return [AMA::Entity::Mapper::Type, NilClass]
69
          def find(klass)
70
            candidates = select(klass)
71
            candidates.empty? ? nil : candidates.first
72
          end
73
74
          # @param [Class, Module] klass
75
          # @return [AMA::Entity::Mapper::Type]
76
          def find!(klass)
77
            candidate = find(klass)
78
            return candidate if candidate
79
            message = "Could not find any registered type for class #{klass}"
80
            compliance_error(message)
81
          end
82
83
          # @param [Class, Module] klass
84
          # @return [TrueClass, FalseClass]
85
          def resolvable?(klass)
86
            !select(klass).empty?
87
          end
88
89
          private
90
91
          # @param [Class, Module] klass
92
          def class_hierarchy(klass)
93
            ptr = klass
94
            chain = []
95
            loop do
96
              chain.push(*class_with_modules(ptr))
97
              break if !ptr.respond_to?(:superclass) || ptr.superclass.nil?
98
              ptr = ptr.superclass
99
            end
100
            chain
101
          end
102
103
          def class_with_modules(klass)
104
            if klass.superclass.nil?
105
              parent_modules = []
106
            else
107
              parent_modules = klass.superclass.included_modules
108
            end
109
            [klass, *(klass.included_modules - parent_modules)]
110
          end
111
        end
112
      end
113
    end
114
  end
115
end
116