Completed
Push — dev ( ffd8f7...ec8098 )
by Fike
51s
created

Entity.supports()   A

Complexity

Conditions 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 3
rs 10
cc 1
1
# frozen_string_literal: true
2
3
require_relative '../../../../lib/mapper/mixin/reflection'
4
require_relative '../../../../lib/mapper/mixin/errors'
5
6
module AMA
7
  module Entity
8
    class Mapper
9
      class Engine
10
        class Denormalizer
11
          # Standard-interface entity denormalizer
12
          class Entity
13
            include ::AMA::Entity::Mapper::Mixin::Reflection
14
            include ::AMA::Entity::Mapper::Mixin::Errors
15
16
            def initialize(registry)
17
              @registry = registry
18
            end
19
20
            # @param [AMA::Entity::Mapper::Type::Concrete] type
21
            def supports(type)
22
              @registry.registered?(type.type)
23
            end
24
25
            # @param [Object] value
26
            # @param [AMA::Entity::Mapper::Engine::Context] context
27
            # @param [AMA::Entity::Mapper::Type::Concrete] target_type
28
            def denormalize(value, context, target_type)
29
              return value if value.is_a?(target_type.type)
30
              denormalizer = target_type.denormalizer
31
              unless denormalizer
32
                return denormalize_entity(value, context, target_type)
33
              end
34
              denormalizer.call(value, context, target_type) do |processed|
35
                denormalize_entity(processed, context, target_type)
36
              end
37
            end
38
39
            private
40
41
            def denormalize_entity(structure, context, target_type)
42
              unless structure.is_a?(Hash)
43
                message = "Can't denormalize #{target_type} from " \
44
                  "anything but hash (#{structure.class} supplied)"
45
                mapping_error(message, context: context)
46
              end
47
              entity = target_type.factory.create(context, structure)
48
              attributes = target_type.attributes.values
49
              attributes = filter_attributes(attributes, structure)
50
              extracted_attributes = extract_attributes(structure, attributes)
51
              # TODO: use acceptor
52
              set_object_attributes(entity, extracted_attributes)
53
            end
54
55
            def filter_attributes(attributes, structure)
56
              attributes.reject do |attribute|
57
                next true if attribute.virtual
58
                name = attribute.name
59
                !structure.key?(name) && !structure.key?(name.to_s)
60
              end
61
            end
62
63
            def extract_attributes(structure, attributes)
64
              # TODO: add attribute denormalizer support
65
              intermediate = attributes.map do |attribute|
66
                name = attribute.name
67
                value = structure.fetch(name, nil)
68
                value ||= structure.fetch(name.to_s, nil)
69
                [name, value]
70
              end
71
              Hash[intermediate]
72
            end
73
          end
74
        end
75
      end
76
    end
77
  end
78
end
79