lutaml-model 0.6.7 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/dependent-repos-todo.json +7 -0
- data/.github/workflows/dependent-repos.json +17 -9
- data/.rubocop.yml +1 -1
- data/.rubocop_todo.yml +51 -65
- data/Gemfile +4 -1
- data/README.adoc +5083 -2612
- data/RELEASE_NOTES.adoc +346 -0
- data/docs/custom_adapters.adoc +144 -0
- data/lib/lutaml/model/attribute.rb +101 -16
- data/lib/lutaml/model/choice.rb +7 -0
- data/lib/lutaml/model/comparable_model.rb +48 -9
- data/lib/lutaml/model/config.rb +48 -42
- data/lib/lutaml/model/error/collection_count_out_of_range_error.rb +1 -1
- data/lib/lutaml/model/error/polymorphic_error.rb +14 -0
- data/lib/lutaml/model/error.rb +1 -0
- data/lib/lutaml/model/format_registry.rb +41 -0
- data/lib/lutaml/model/hash/document.rb +11 -0
- data/lib/lutaml/model/hash/mapping.rb +19 -0
- data/lib/lutaml/model/hash/mapping_rule.rb +9 -0
- data/lib/lutaml/model/hash/standard_adapter.rb +17 -0
- data/lib/lutaml/model/hash/transform.rb +8 -0
- data/lib/lutaml/model/hash.rb +21 -0
- data/lib/lutaml/model/json/document.rb +11 -0
- data/lib/lutaml/model/json/mapping.rb +19 -0
- data/lib/lutaml/model/json/mapping_rule.rb +9 -0
- data/lib/lutaml/model/{json_adapter → json}/multi_json_adapter.rb +4 -5
- data/lib/lutaml/model/{json_adapter/standard_json_adapter.rb → json/standard_adapter.rb} +5 -3
- data/lib/lutaml/model/json/transform.rb +8 -0
- data/lib/lutaml/model/json.rb +21 -0
- data/lib/lutaml/model/key_value_document.rb +27 -0
- data/lib/lutaml/model/{key_value_mapping.rb → mapping/key_value_mapping.rb} +64 -16
- data/lib/lutaml/model/{key_value_mapping_rule.rb → mapping/key_value_mapping_rule.rb} +18 -2
- data/lib/lutaml/model/mapping/mapping.rb +13 -0
- data/lib/lutaml/model/mapping/mapping_rule.rb +300 -0
- data/lib/lutaml/model/schema/xml_compiler.rb +15 -15
- data/lib/lutaml/model/sequence.rb +2 -2
- data/lib/lutaml/model/serialization_adapter.rb +22 -0
- data/lib/lutaml/model/serialize.rb +219 -444
- data/lib/lutaml/model/services/logger.rb +54 -0
- data/lib/lutaml/model/services/transformer.rb +48 -0
- data/lib/lutaml/model/services.rb +2 -0
- data/lib/lutaml/model/toml/document.rb +11 -0
- data/lib/lutaml/model/toml/mapping.rb +27 -0
- data/lib/lutaml/model/toml/mapping_rule.rb +9 -0
- data/lib/lutaml/model/{toml_adapter → toml}/toml_rb_adapter.rb +3 -3
- data/lib/lutaml/model/toml/tomlib_adapter.rb +19 -0
- data/lib/lutaml/model/toml/transform.rb +8 -0
- data/lib/lutaml/model/toml.rb +30 -0
- data/lib/lutaml/model/transform/key_value_transform.rb +291 -0
- data/lib/lutaml/model/transform/xml_transform.rb +239 -0
- data/lib/lutaml/model/transform.rb +78 -0
- data/lib/lutaml/model/type/date.rb +1 -1
- data/lib/lutaml/model/type/date_time.rb +2 -2
- data/lib/lutaml/model/type/hash.rb +1 -1
- data/lib/lutaml/model/type/time.rb +2 -2
- data/lib/lutaml/model/type/time_without_date.rb +2 -2
- data/lib/lutaml/model/type/value.rb +6 -9
- data/lib/lutaml/model/uninitialized_class.rb +64 -0
- data/lib/lutaml/model/utils.rb +44 -0
- data/lib/lutaml/model/validation.rb +1 -0
- data/lib/lutaml/model/version.rb +1 -1
- data/lib/lutaml/model/{xml_adapter → xml}/builder/nokogiri.rb +2 -2
- data/lib/lutaml/model/{xml_adapter → xml}/builder/oga.rb +10 -10
- data/lib/lutaml/model/{xml_adapter → xml}/builder/ox.rb +1 -1
- data/lib/lutaml/model/{xml_adapter/xml_document.rb → xml/document.rb} +41 -21
- data/lib/lutaml/model/xml/element.rb +32 -0
- data/lib/lutaml/model/xml/mapping.rb +410 -0
- data/lib/lutaml/model/xml/mapping_rule.rb +141 -0
- data/lib/lutaml/model/xml/nokogiri_adapter.rb +232 -0
- data/lib/lutaml/model/{xml_adapter → xml}/oga/document.rb +1 -1
- data/lib/lutaml/model/{xml_adapter → xml}/oga/element.rb +3 -1
- data/lib/lutaml/model/xml/oga_adapter.rb +171 -0
- data/lib/lutaml/model/xml/ox_adapter.rb +215 -0
- data/lib/lutaml/model/xml/transform.rb +8 -0
- data/lib/lutaml/model/{xml_adapter → xml}/xml_attribute.rb +1 -1
- data/lib/lutaml/model/{xml_adapter → xml}/xml_element.rb +23 -10
- data/lib/lutaml/model/{xml_adapter → xml}/xml_namespace.rb +1 -1
- data/lib/lutaml/model/xml.rb +31 -0
- data/lib/lutaml/model/xml_adapter/element.rb +11 -25
- data/lib/lutaml/model/xml_adapter/nokogiri_adapter.rb +6 -223
- data/lib/lutaml/model/xml_adapter/oga_adapter.rb +13 -163
- data/lib/lutaml/model/xml_adapter/ox_adapter.rb +10 -207
- data/lib/lutaml/model/yaml/document.rb +10 -0
- data/lib/lutaml/model/yaml/mapping.rb +19 -0
- data/lib/lutaml/model/yaml/mapping_rule.rb +9 -0
- data/lib/lutaml/model/{yaml_adapter/standard_yaml_adapter.rb → yaml/standard_adapter.rb} +4 -3
- data/lib/lutaml/model/yaml/transform.rb +8 -0
- data/lib/lutaml/model/yaml.rb +21 -0
- data/lib/lutaml/model.rb +40 -4
- data/lutaml-model.gemspec +0 -4
- data/spec/benchmarks/xml_parsing_benchmark_spec.rb +7 -7
- data/spec/fixtures/person.rb +5 -5
- data/spec/lutaml/model/attribute_spec.rb +37 -1
- data/spec/lutaml/model/cdata_spec.rb +9 -9
- data/spec/lutaml/model/collection_spec.rb +50 -2
- data/spec/lutaml/model/comparable_model_spec.rb +92 -27
- data/spec/lutaml/model/custom_bibtex_adapter_spec.rb +598 -0
- data/spec/lutaml/model/custom_vobject_adapter_spec.rb +1226 -0
- data/spec/lutaml/model/defaults_spec.rb +1 -1
- data/spec/lutaml/model/enum_spec.rb +1 -1
- data/spec/lutaml/model/group_spec.rb +333 -20
- data/spec/lutaml/model/hash/adapter_spec.rb +255 -0
- data/spec/lutaml/model/json_adapter_spec.rb +6 -6
- data/spec/lutaml/model/key_value_mapping_spec.rb +65 -3
- data/spec/lutaml/model/mixed_content_spec.rb +24 -24
- data/spec/lutaml/model/multiple_mapping_spec.rb +5 -5
- data/spec/lutaml/model/ordered_content_spec.rb +6 -6
- data/spec/lutaml/model/polymorphic_spec.rb +526 -0
- data/spec/lutaml/model/render_empty_spec.rb +194 -0
- data/spec/lutaml/model/render_nil_spec.rb +206 -22
- data/spec/lutaml/model/root_mappings_spec.rb +3 -3
- data/spec/lutaml/model/schema/xml_compiler_spec.rb +6 -6
- data/spec/lutaml/model/serializable_spec.rb +179 -103
- data/spec/lutaml/model/simple_model_spec.rb +9 -9
- data/spec/lutaml/model/toml_adapter_spec.rb +6 -6
- data/spec/lutaml/model/toml_spec.rb +51 -0
- data/spec/lutaml/model/transformation_spec.rb +72 -15
- data/spec/lutaml/model/uninitialized_class_spec.rb +96 -0
- data/spec/lutaml/model/value_map_spec.rb +240 -0
- data/spec/lutaml/model/xml/namespace/nested_with_explicit_namespace_spec.rb +85 -0
- data/spec/lutaml/model/xml/namespace_spec.rb +57 -0
- data/spec/lutaml/model/xml/xml_element_spec.rb +93 -0
- data/spec/lutaml/model/xml_adapter/nokogiri_adapter_spec.rb +2 -2
- data/spec/lutaml/model/xml_adapter/oga_adapter_spec.rb +2 -2
- data/spec/lutaml/model/xml_adapter/ox_adapter_spec.rb +2 -2
- data/spec/lutaml/model/xml_adapter/xml_namespace_spec.rb +6 -6
- data/spec/lutaml/model/xml_adapter_spec.rb +6 -6
- data/spec/lutaml/model/xml_mapping_rule_spec.rb +105 -5
- data/spec/lutaml/model/xml_mapping_spec.rb +70 -16
- data/spec/lutaml/model/xml_spec.rb +63 -0
- data/spec/lutaml/model/yaml_adapter_spec.rb +3 -5
- data/spec/sample_model_spec.rb +3 -3
- data/spec/spec_helper.rb +3 -3
- metadata +76 -59
- data/lib/lutaml/model/json_adapter/json_document.rb +0 -20
- data/lib/lutaml/model/json_adapter/json_object.rb +0 -28
- data/lib/lutaml/model/loggable.rb +0 -15
- data/lib/lutaml/model/mapping_rule.rb +0 -109
- data/lib/lutaml/model/toml_adapter/toml_document.rb +0 -20
- data/lib/lutaml/model/toml_adapter/toml_object.rb +0 -28
- data/lib/lutaml/model/toml_adapter/tomlib_adapter.rb +0 -20
- data/lib/lutaml/model/toml_adapter.rb +0 -6
- data/lib/lutaml/model/xml_mapping.rb +0 -307
- data/lib/lutaml/model/xml_mapping_rule.rb +0 -122
- data/lib/lutaml/model/yaml_adapter/yaml_document.rb +0 -20
- data/lib/lutaml/model/yaml_adapter/yaml_object.rb +0 -28
- data/lib/lutaml/model/yaml_adapter.rb +0 -8
@@ -12,21 +12,61 @@ module Lutaml
|
|
12
12
|
# Checks if two objects are equal based on their attributes
|
13
13
|
# @param other [Object] The object to compare with
|
14
14
|
# @return [Boolean] True if objects are equal, false otherwise
|
15
|
-
def eql?(other)
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
def eql?(other, compared_objects = {})
|
16
|
+
return true if equal?(other)
|
17
|
+
return false unless same_class?(other)
|
18
|
+
return true if already_compared?(other, compared_objects)
|
19
|
+
|
20
|
+
compared_objects[comparison_key(other)] = true
|
21
|
+
self.class.attributes.all? do |attr, _|
|
22
|
+
attr_value = send(attr)
|
23
|
+
other_value = other.send(attr)
|
24
|
+
|
25
|
+
if attr_value.respond_to?(:eql?) && same_class?(attr_value)
|
26
|
+
attr_value.eql?(other_value, compared_objects)
|
27
|
+
else
|
28
|
+
attr_value == other_value
|
19
29
|
end
|
30
|
+
end
|
20
31
|
end
|
21
32
|
|
22
33
|
alias == eql?
|
23
34
|
|
35
|
+
def same_class?(other)
|
36
|
+
other.instance_of?(self.class)
|
37
|
+
end
|
38
|
+
|
39
|
+
def comparison_key(other)
|
40
|
+
"#{object_id}:#{other.object_id}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def already_compared?(other, compared_objects)
|
44
|
+
compared_objects[comparison_key(other)]
|
45
|
+
end
|
46
|
+
|
24
47
|
# Generates a hash value for the object
|
25
48
|
# @return [Integer] The hash value
|
26
49
|
def hash
|
27
|
-
|
28
|
-
|
29
|
-
|
50
|
+
calculate_hash
|
51
|
+
end
|
52
|
+
|
53
|
+
def calculate_hash(processed_objects = {}.compare_by_identity)
|
54
|
+
return if processed_objects.key?(self)
|
55
|
+
|
56
|
+
processed_objects[self] = true
|
57
|
+
([self.class] + attributes_hash(processed_objects)).hash
|
58
|
+
end
|
59
|
+
|
60
|
+
def attributes_hash(processed_objects)
|
61
|
+
self.class.attributes.map do |attr, _|
|
62
|
+
attr_value = send(attr)
|
63
|
+
|
64
|
+
if attr_value.respond_to?(:calculate_hash)
|
65
|
+
attr_value.calculate_hash(processed_objects)
|
66
|
+
else
|
67
|
+
attr_value.hash
|
68
|
+
end
|
69
|
+
end
|
30
70
|
end
|
31
71
|
|
32
72
|
# Class methods added to the class that includes ComparableModel
|
@@ -419,8 +459,7 @@ module Lutaml
|
|
419
459
|
# @param label [String] The label for the value
|
420
460
|
# @param type_info [String, nil] Additional type information
|
421
461
|
# @return [String] Formatted value tree
|
422
|
-
def format_value_tree(value1, value2, parent_node, label,
|
423
|
-
type_info = nil)
|
462
|
+
def format_value_tree(value1, value2, parent_node, label, type_info = nil)
|
424
463
|
return if value1 == value2 && !@show_unchanged
|
425
464
|
|
426
465
|
if value1 == value2
|
data/lib/lutaml/model/config.rb
CHANGED
@@ -3,12 +3,7 @@ module Lutaml
|
|
3
3
|
module Config
|
4
4
|
extend self
|
5
5
|
|
6
|
-
|
7
|
-
attr_writer :json_adapter, :yaml_adapter
|
8
|
-
|
9
|
-
attr_accessor :xml_adapter, :toml_adapter
|
10
|
-
|
11
|
-
AVAILABLE_FORMATS = %i[xml json yaml toml].freeze
|
6
|
+
AVAILABLE_FORMATS = %i[xml json yaml toml hash].freeze
|
12
7
|
KEY_VALUE_FORMATS = AVAILABLE_FORMATS - %i[xml]
|
13
8
|
|
14
9
|
def configure
|
@@ -42,55 +37,66 @@ module Lutaml
|
|
42
37
|
# one of [:tomlib, :toml_rb]
|
43
38
|
# @example
|
44
39
|
# Lutaml::Model::Config.toml_adapter = :tomlib
|
40
|
+
#
|
41
|
+
# AVAILABLE_FORMATS.each do |adapter_name|
|
42
|
+
# define_method(:"#{adapter_name}_adapter_type=") do |type_name|
|
43
|
+
# Lutaml::Model::FormatRegistry.send(:"#{adapter_name}_adapter_type=", type_name)
|
44
|
+
# end
|
45
|
+
# end
|
46
|
+
|
45
47
|
AVAILABLE_FORMATS.each do |adapter_name|
|
46
48
|
define_method(:"#{adapter_name}_adapter_type=") do |type_name|
|
47
|
-
adapter =
|
48
|
-
type =
|
49
|
+
adapter = adapter_name.to_s
|
50
|
+
type = normalize_type_name(type_name, adapter_name)
|
51
|
+
load_adapter_file(adapter, type)
|
52
|
+
load_moxml_adapter(type_name, adapter_name)
|
53
|
+
set_adapter_for(adapter_name, class_for(adapter, type))
|
54
|
+
end
|
55
|
+
end
|
49
56
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
rescue LoadError
|
54
|
-
raise(
|
55
|
-
Lutaml::Model::UnknownAdapterTypeError.new(
|
56
|
-
adapter_name,
|
57
|
-
type_name,
|
58
|
-
),
|
59
|
-
cause: nil,
|
60
|
-
)
|
61
|
-
end
|
62
|
-
Moxml::Adapter.load(type_name) unless KEY_VALUE_FORMATS.include?(adapter_name)
|
57
|
+
def adapter_for(format)
|
58
|
+
public_send(:"#{format}_adapter")
|
59
|
+
end
|
63
60
|
|
64
|
-
|
65
|
-
|
66
|
-
Lutaml::Model.const_get(to_class_name(adapter))
|
67
|
-
.const_get(to_class_name(type)),
|
68
|
-
)
|
69
|
-
end
|
61
|
+
def set_adapter_for(format, adapter)
|
62
|
+
public_send(:"#{format}_adapter=", adapter)
|
70
63
|
end
|
71
64
|
|
72
|
-
|
73
|
-
|
74
|
-
# @example
|
75
|
-
# Lutaml::Model::Config.json_adapter
|
76
|
-
# # => Lutaml::Model::YamlAdapter::StandardJsonAdapter
|
77
|
-
def json_adapter
|
78
|
-
@json_adapter || Lutaml::Model::JsonAdapter::StandardJsonAdapter
|
65
|
+
def mappings_class_for(format)
|
66
|
+
Lutaml::Model::FormatRegistry.mappings_class_for(format)
|
79
67
|
end
|
80
68
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
69
|
+
def transformer_for(format)
|
70
|
+
Lutaml::Model::FormatRegistry.transformer_for(format)
|
71
|
+
end
|
72
|
+
|
73
|
+
def class_for(adapter, type)
|
74
|
+
Lutaml::Model.const_get(to_class_name(adapter))
|
75
|
+
.const_get(to_class_name(type))
|
88
76
|
end
|
89
77
|
|
90
|
-
# @api private
|
91
78
|
def to_class_name(str)
|
92
79
|
str.to_s.split("_").map(&:capitalize).join
|
93
80
|
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def normalize_type_name(type_name, adapter_name)
|
85
|
+
"#{type_name.to_s.gsub("_#{adapter_name}", '')}_adapter"
|
86
|
+
end
|
87
|
+
|
88
|
+
def load_adapter_file(adapter, type)
|
89
|
+
adapter_file = File.join(adapter, type)
|
90
|
+
require_relative adapter_file
|
91
|
+
rescue LoadError
|
92
|
+
raise UnknownAdapterTypeError.new(adapter, type), cause: nil
|
93
|
+
end
|
94
|
+
|
95
|
+
def load_moxml_adapter(type_name, adapter_name)
|
96
|
+
return if KEY_VALUE_FORMATS.include?(adapter_name)
|
97
|
+
|
98
|
+
Moxml::Adapter.load(type_name)
|
99
|
+
end
|
94
100
|
end
|
95
101
|
end
|
96
102
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Lutaml
|
2
|
+
module Model
|
3
|
+
class PolymorphicError < Error
|
4
|
+
def initialize(value, options, type)
|
5
|
+
error = if options[:polymorphic].is_a?(Array)
|
6
|
+
"#{value.class} not in #{options[:polymorphic]}"
|
7
|
+
else
|
8
|
+
"#{value.class} is not valid sub class of #{type}"
|
9
|
+
end
|
10
|
+
super(error)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/lutaml/model/error.rb
CHANGED
@@ -0,0 +1,41 @@
|
|
1
|
+
module Lutaml
|
2
|
+
module Model
|
3
|
+
class FormatRegistry
|
4
|
+
class << self
|
5
|
+
attr_reader :format, :mapping_class, :adapter_class
|
6
|
+
|
7
|
+
def register(format, mapping_class:, adapter_class:, transformer:)
|
8
|
+
registered_formats[format] = {
|
9
|
+
mapping_class: mapping_class,
|
10
|
+
transformer: transformer,
|
11
|
+
}
|
12
|
+
|
13
|
+
::Lutaml::Model::Type::Value.register_format_to_from_methods(format)
|
14
|
+
::Lutaml::Model::Serialize.register_format_mapping_method(format)
|
15
|
+
::Lutaml::Model::Serialize.register_from_format_method(format)
|
16
|
+
::Lutaml::Model::Serialize.register_to_format_method(format)
|
17
|
+
|
18
|
+
Lutaml::Model::Config.define_singleton_method(:"#{format}_adapter") do
|
19
|
+
instance_variable_get(:"@#{format}_adapter") || adapter_class
|
20
|
+
end
|
21
|
+
|
22
|
+
Lutaml::Model::Config.define_singleton_method(:"#{format}_adapter=") do |adapter_klass|
|
23
|
+
instance_variable_set(:"@#{format}_adapter", adapter_klass)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def mappings_class_for(format)
|
28
|
+
registered_formats.dig(format, :mapping_class)
|
29
|
+
end
|
30
|
+
|
31
|
+
def transformer_for(format)
|
32
|
+
registered_formats.dig(format, :transformer)
|
33
|
+
end
|
34
|
+
|
35
|
+
def registered_formats
|
36
|
+
@registered_formats ||= {}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative "../mapping/key_value_mapping"
|
2
|
+
|
3
|
+
module Lutaml
|
4
|
+
module Model
|
5
|
+
module HashAdapter
|
6
|
+
class Mapping < Lutaml::Model::KeyValueMapping
|
7
|
+
def initialize
|
8
|
+
super(:hash)
|
9
|
+
end
|
10
|
+
|
11
|
+
def deep_dup
|
12
|
+
self.class.new.tap do |new_mapping|
|
13
|
+
new_mapping.instance_variable_set(:@mappings, duplicate_mappings)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative "document"
|
2
|
+
|
3
|
+
module Lutaml
|
4
|
+
module Model
|
5
|
+
module HashAdapter
|
6
|
+
class StandardAdapter < Document
|
7
|
+
def self.parse(hsh, _options = {})
|
8
|
+
hsh
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_hash(_options = {})
|
12
|
+
@attributes
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lutaml
|
4
|
+
module Model
|
5
|
+
module HashAdapter
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
require_relative "hash/standard_adapter"
|
11
|
+
require_relative "hash/document"
|
12
|
+
require_relative "hash/mapping"
|
13
|
+
require_relative "hash/mapping_rule"
|
14
|
+
require_relative "hash/transform"
|
15
|
+
|
16
|
+
Lutaml::Model::FormatRegistry.register(
|
17
|
+
:hash,
|
18
|
+
mapping_class: Lutaml::Model::HashAdapter::Mapping,
|
19
|
+
adapter_class: Lutaml::Model::HashAdapter::StandardAdapter,
|
20
|
+
transformer: Lutaml::Model::HashAdapter::Transform,
|
21
|
+
)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative "../mapping/key_value_mapping"
|
2
|
+
|
3
|
+
module Lutaml
|
4
|
+
module Model
|
5
|
+
module Json
|
6
|
+
class Mapping < Lutaml::Model::KeyValueMapping
|
7
|
+
def initialize
|
8
|
+
super(:json)
|
9
|
+
end
|
10
|
+
|
11
|
+
def deep_dup
|
12
|
+
self.class.new.tap do |new_mapping|
|
13
|
+
new_mapping.instance_variable_set(:@mappings, duplicate_mappings)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,13 +1,12 @@
|
|
1
1
|
require "multi_json"
|
2
|
-
require_relative "
|
2
|
+
require_relative "document"
|
3
3
|
|
4
4
|
module Lutaml
|
5
5
|
module Model
|
6
|
-
module
|
7
|
-
class MultiJsonAdapter <
|
6
|
+
module Json
|
7
|
+
class MultiJsonAdapter < Document
|
8
8
|
def self.parse(json, _options = {})
|
9
|
-
|
10
|
-
new(data)
|
9
|
+
MultiJson.load(json)
|
11
10
|
end
|
12
11
|
|
13
12
|
def to_json(*args)
|
@@ -1,10 +1,12 @@
|
|
1
1
|
require "json"
|
2
|
-
require_relative "
|
2
|
+
require_relative "document"
|
3
3
|
|
4
4
|
module Lutaml
|
5
5
|
module Model
|
6
|
-
module
|
7
|
-
class
|
6
|
+
module Json
|
7
|
+
class StandardAdapter < Document
|
8
|
+
FORMAT_SYMBOL = :json
|
9
|
+
|
8
10
|
def self.parse(json, _options = {})
|
9
11
|
JSON.parse(json, create_additions: false)
|
10
12
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lutaml
|
4
|
+
module Model
|
5
|
+
module Json
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
require_relative "json/standard_adapter"
|
11
|
+
require_relative "json/document"
|
12
|
+
require_relative "json/mapping"
|
13
|
+
require_relative "json/mapping_rule"
|
14
|
+
require_relative "json/transform"
|
15
|
+
|
16
|
+
Lutaml::Model::FormatRegistry.register(
|
17
|
+
:json,
|
18
|
+
mapping_class: Lutaml::Model::Json::Mapping,
|
19
|
+
adapter_class: Lutaml::Model::Json::StandardAdapter,
|
20
|
+
transformer: Lutaml::Model::Json::Transform,
|
21
|
+
)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Lutaml
|
2
|
+
module Model
|
3
|
+
class KeyValueDocument
|
4
|
+
attr_reader :attributes
|
5
|
+
|
6
|
+
def initialize(attributes = {})
|
7
|
+
@attributes = attributes
|
8
|
+
end
|
9
|
+
|
10
|
+
def [](key)
|
11
|
+
@attributes[key]
|
12
|
+
end
|
13
|
+
|
14
|
+
def []=(key, value)
|
15
|
+
@attributes[key] = value
|
16
|
+
end
|
17
|
+
|
18
|
+
def key?(key)
|
19
|
+
@attributes.key?(key)
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_h
|
23
|
+
@attributes
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -1,12 +1,15 @@
|
|
1
|
+
require_relative "mapping"
|
1
2
|
require_relative "key_value_mapping_rule"
|
2
3
|
|
3
4
|
module Lutaml
|
4
5
|
module Model
|
5
|
-
class KeyValueMapping
|
6
|
-
attr_reader :mappings
|
6
|
+
class KeyValueMapping < Mapping
|
7
|
+
attr_reader :mappings, :format
|
7
8
|
|
8
|
-
def initialize
|
9
|
-
|
9
|
+
def initialize(format = nil)
|
10
|
+
super()
|
11
|
+
|
12
|
+
@format = format
|
10
13
|
end
|
11
14
|
|
12
15
|
def map(
|
@@ -14,25 +17,39 @@ module Lutaml
|
|
14
17
|
to: nil,
|
15
18
|
render_nil: false,
|
16
19
|
render_default: false,
|
20
|
+
render_empty: false,
|
21
|
+
treat_nil: nil,
|
22
|
+
treat_empty: nil,
|
23
|
+
treat_omitted: nil,
|
17
24
|
with: {},
|
18
25
|
delegate: nil,
|
19
26
|
child_mappings: nil,
|
20
27
|
root_mappings: nil,
|
21
|
-
|
28
|
+
polymorphic: {},
|
29
|
+
polymorphic_map: {},
|
30
|
+
transform: {},
|
31
|
+
value_map: {}
|
22
32
|
)
|
23
33
|
mapping_name = name_for_mapping(root_mappings, name)
|
24
|
-
validate!(mapping_name, to, with)
|
34
|
+
validate!(mapping_name, to, with, render_nil, render_empty)
|
25
35
|
|
26
36
|
@mappings << KeyValueMappingRule.new(
|
27
37
|
mapping_name,
|
28
38
|
to: to,
|
29
39
|
render_nil: render_nil,
|
30
40
|
render_default: render_default,
|
41
|
+
render_empty: render_empty,
|
42
|
+
treat_nil: treat_nil,
|
43
|
+
treat_empty: treat_empty,
|
44
|
+
treat_omitted: treat_omitted,
|
31
45
|
with: with,
|
32
46
|
delegate: delegate,
|
33
47
|
child_mappings: child_mappings,
|
34
48
|
root_mappings: root_mappings,
|
49
|
+
polymorphic: polymorphic,
|
50
|
+
polymorphic_map: polymorphic_map,
|
35
51
|
transform: transform,
|
52
|
+
value_map: value_map,
|
36
53
|
)
|
37
54
|
end
|
38
55
|
|
@@ -46,7 +63,7 @@ module Lutaml
|
|
46
63
|
delegate: nil
|
47
64
|
)
|
48
65
|
@raw_mapping = true
|
49
|
-
validate!(Constants::RAW_MAPPING_KEY, to, with)
|
66
|
+
validate!(Constants::RAW_MAPPING_KEY, to, with, render_nil, nil)
|
50
67
|
@mappings << KeyValueMappingRule.new(
|
51
68
|
Constants::RAW_MAPPING_KEY,
|
52
69
|
to: to,
|
@@ -65,28 +82,49 @@ module Lutaml
|
|
65
82
|
name
|
66
83
|
end
|
67
84
|
|
68
|
-
def validate!(key, to, with)
|
85
|
+
def validate!(key, to, with, render_nil, render_empty)
|
69
86
|
validate_mappings!(key)
|
87
|
+
validate_to_and_with_arguments!(key, to, with)
|
88
|
+
|
89
|
+
# Validate `render_nil` for unsupported value
|
90
|
+
validate_blank_mappings!(render_nil, render_empty)
|
91
|
+
validate_root_mappings!(key)
|
92
|
+
end
|
70
93
|
|
94
|
+
def validate_to_and_with_arguments!(key, to, with)
|
71
95
|
if to.nil? && with.empty? && !@raw_mapping
|
72
|
-
|
73
|
-
|
96
|
+
raise IncorrectMappingArgumentsError.new(
|
97
|
+
":to or :with argument is required for mapping '#{key}'",
|
98
|
+
)
|
74
99
|
end
|
75
100
|
|
101
|
+
validate_with_options!(to, key, with)
|
102
|
+
end
|
103
|
+
|
104
|
+
def validate_with_options!(to, key, with)
|
105
|
+
return true if to
|
106
|
+
|
76
107
|
if !with.empty? && (with[:from].nil? || with[:to].nil?) && !@raw_mapping
|
77
|
-
|
78
|
-
|
108
|
+
raise IncorrectMappingArgumentsError.new(
|
109
|
+
":with argument for mapping '#{key}' requires :to and :from keys",
|
110
|
+
)
|
79
111
|
end
|
80
|
-
|
81
|
-
validate_mappings(key)
|
82
112
|
end
|
83
113
|
|
84
|
-
def
|
114
|
+
def validate_root_mappings!(name)
|
85
115
|
if @mappings.any?(&:root_mapping?) || (name == "root_mapping" && @mappings.any?)
|
86
116
|
raise MultipleMappingsError.new("root_mappings cannot be used with other mappings")
|
87
117
|
end
|
88
118
|
end
|
89
119
|
|
120
|
+
def validate_blank_mappings!(render_nil, render_empty)
|
121
|
+
if render_nil == :as_blank || render_empty == :as_blank
|
122
|
+
raise IncorrectMappingArgumentsError.new(
|
123
|
+
":as_blank is not supported for key-value mappings",
|
124
|
+
)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
90
128
|
def validate_mappings!(_type)
|
91
129
|
if (@raw_mapping && Utils.present?(@mappings)) || (!@raw_mapping && @mappings.any?(&:raw_mapping?))
|
92
130
|
raise StandardError, "map_all is not allowed with other mappings"
|
@@ -94,7 +132,7 @@ module Lutaml
|
|
94
132
|
end
|
95
133
|
|
96
134
|
def deep_dup
|
97
|
-
self.class.new.tap do |new_mapping|
|
135
|
+
self.class.new(@format).tap do |new_mapping|
|
98
136
|
new_mapping.instance_variable_set(:@mappings, duplicate_mappings)
|
99
137
|
end
|
100
138
|
end
|
@@ -106,6 +144,16 @@ module Lutaml
|
|
106
144
|
def find_by_to(to)
|
107
145
|
@mappings.find { |m| m.to.to_s == to.to_s }
|
108
146
|
end
|
147
|
+
|
148
|
+
def polymorphic_mapping
|
149
|
+
@mappings.find(&:polymorphic_mapping?)
|
150
|
+
end
|
151
|
+
|
152
|
+
Lutaml::Model::Config::KEY_VALUE_FORMATS.each do |format|
|
153
|
+
define_method(:"format_#{format}?") do
|
154
|
+
@format == format
|
155
|
+
end
|
156
|
+
end
|
109
157
|
end
|
110
158
|
end
|
111
159
|
end
|