lutaml-model 0.7.1 → 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.
Files changed (124) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/.rubocop_todo.yml +49 -48
  4. data/Gemfile +4 -1
  5. data/README.adoc +791 -143
  6. data/RELEASE_NOTES.adoc +346 -0
  7. data/docs/custom_adapters.adoc +144 -0
  8. data/lib/lutaml/model/attribute.rb +17 -11
  9. data/lib/lutaml/model/config.rb +48 -42
  10. data/lib/lutaml/model/error/polymorphic_error.rb +7 -2
  11. data/lib/lutaml/model/format_registry.rb +41 -0
  12. data/lib/lutaml/model/hash/document.rb +11 -0
  13. data/lib/lutaml/model/hash/mapping.rb +19 -0
  14. data/lib/lutaml/model/hash/mapping_rule.rb +9 -0
  15. data/lib/lutaml/model/hash/standard_adapter.rb +17 -0
  16. data/lib/lutaml/model/hash/transform.rb +8 -0
  17. data/lib/lutaml/model/hash.rb +21 -0
  18. data/lib/lutaml/model/json/document.rb +11 -0
  19. data/lib/lutaml/model/json/mapping.rb +19 -0
  20. data/lib/lutaml/model/json/mapping_rule.rb +9 -0
  21. data/lib/lutaml/model/{json_adapter → json}/multi_json_adapter.rb +4 -5
  22. data/lib/lutaml/model/{json_adapter/standard_json_adapter.rb → json/standard_adapter.rb} +5 -3
  23. data/lib/lutaml/model/json/transform.rb +8 -0
  24. data/lib/lutaml/model/json.rb +21 -0
  25. data/lib/lutaml/model/key_value_document.rb +27 -0
  26. data/lib/lutaml/model/mapping/key_value_mapping.rb +8 -4
  27. data/lib/lutaml/model/mapping/mapping.rb +13 -0
  28. data/lib/lutaml/model/mapping/mapping_rule.rb +7 -6
  29. data/lib/lutaml/model/serialization_adapter.rb +22 -0
  30. data/lib/lutaml/model/serialize.rb +146 -521
  31. data/lib/lutaml/model/services/logger.rb +54 -0
  32. data/lib/lutaml/model/services/transformer.rb +48 -0
  33. data/lib/lutaml/model/services.rb +2 -0
  34. data/lib/lutaml/model/toml/document.rb +11 -0
  35. data/lib/lutaml/model/toml/mapping.rb +27 -0
  36. data/lib/lutaml/model/toml/mapping_rule.rb +9 -0
  37. data/lib/lutaml/model/{toml_adapter → toml}/toml_rb_adapter.rb +3 -3
  38. data/lib/lutaml/model/toml/tomlib_adapter.rb +19 -0
  39. data/lib/lutaml/model/toml/transform.rb +8 -0
  40. data/lib/lutaml/model/toml.rb +30 -0
  41. data/lib/lutaml/model/transform/key_value_transform.rb +291 -0
  42. data/lib/lutaml/model/transform/xml_transform.rb +239 -0
  43. data/lib/lutaml/model/transform.rb +78 -0
  44. data/lib/lutaml/model/type/value.rb +6 -9
  45. data/lib/lutaml/model/uninitialized_class.rb +1 -1
  46. data/lib/lutaml/model/utils.rb +30 -0
  47. data/lib/lutaml/model/version.rb +1 -1
  48. data/lib/lutaml/model/{xml_adapter → xml}/builder/nokogiri.rb +2 -2
  49. data/lib/lutaml/model/{xml_adapter → xml}/builder/oga.rb +10 -10
  50. data/lib/lutaml/model/{xml_adapter → xml}/builder/ox.rb +1 -1
  51. data/lib/lutaml/model/{xml_adapter/xml_document.rb → xml/document.rb} +6 -7
  52. data/lib/lutaml/model/xml/element.rb +32 -0
  53. data/lib/lutaml/model/xml/mapping.rb +410 -0
  54. data/lib/lutaml/model/xml/mapping_rule.rb +141 -0
  55. data/lib/lutaml/model/xml/nokogiri_adapter.rb +232 -0
  56. data/lib/lutaml/model/{xml_adapter → xml}/oga/document.rb +1 -1
  57. data/lib/lutaml/model/{xml_adapter → xml}/oga/element.rb +3 -1
  58. data/lib/lutaml/model/xml/oga_adapter.rb +171 -0
  59. data/lib/lutaml/model/xml/ox_adapter.rb +215 -0
  60. data/lib/lutaml/model/xml/transform.rb +8 -0
  61. data/lib/lutaml/model/{xml_adapter → xml}/xml_attribute.rb +1 -1
  62. data/lib/lutaml/model/{xml_adapter → xml}/xml_element.rb +6 -3
  63. data/lib/lutaml/model/{xml_adapter → xml}/xml_namespace.rb +1 -1
  64. data/lib/lutaml/model/xml.rb +31 -0
  65. data/lib/lutaml/model/xml_adapter/element.rb +11 -25
  66. data/lib/lutaml/model/xml_adapter/nokogiri_adapter.rb +6 -223
  67. data/lib/lutaml/model/xml_adapter/oga_adapter.rb +13 -163
  68. data/lib/lutaml/model/xml_adapter/ox_adapter.rb +10 -207
  69. data/lib/lutaml/model/yaml/document.rb +10 -0
  70. data/lib/lutaml/model/yaml/mapping.rb +19 -0
  71. data/lib/lutaml/model/yaml/mapping_rule.rb +9 -0
  72. data/lib/lutaml/model/{yaml_adapter/standard_yaml_adapter.rb → yaml/standard_adapter.rb} +4 -3
  73. data/lib/lutaml/model/yaml/transform.rb +8 -0
  74. data/lib/lutaml/model/yaml.rb +21 -0
  75. data/lib/lutaml/model.rb +39 -4
  76. data/lutaml-model.gemspec +0 -4
  77. data/spec/benchmarks/xml_parsing_benchmark_spec.rb +4 -4
  78. data/spec/lutaml/model/cdata_spec.rb +7 -7
  79. data/spec/lutaml/model/custom_bibtex_adapter_spec.rb +598 -0
  80. data/spec/lutaml/model/custom_vobject_adapter_spec.rb +1226 -0
  81. data/spec/lutaml/model/group_spec.rb +18 -7
  82. data/spec/lutaml/model/hash/adapter_spec.rb +255 -0
  83. data/spec/lutaml/model/json_adapter_spec.rb +6 -6
  84. data/spec/lutaml/model/key_value_mapping_spec.rb +25 -1
  85. data/spec/lutaml/model/mixed_content_spec.rb +24 -24
  86. data/spec/lutaml/model/multiple_mapping_spec.rb +5 -5
  87. data/spec/lutaml/model/ordered_content_spec.rb +6 -6
  88. data/spec/lutaml/model/polymorphic_spec.rb +178 -0
  89. data/spec/lutaml/model/root_mappings_spec.rb +3 -3
  90. data/spec/lutaml/model/schema/xml_compiler_spec.rb +6 -6
  91. data/spec/lutaml/model/serializable_spec.rb +179 -103
  92. data/spec/lutaml/model/toml_adapter_spec.rb +6 -6
  93. data/spec/lutaml/model/toml_spec.rb +51 -0
  94. data/spec/lutaml/model/transformation_spec.rb +72 -15
  95. data/spec/lutaml/model/uninitialized_class_spec.rb +96 -0
  96. data/spec/lutaml/model/xml/namespace_spec.rb +57 -0
  97. data/spec/lutaml/model/xml/xml_element_spec.rb +1 -1
  98. data/spec/lutaml/model/xml_adapter/nokogiri_adapter_spec.rb +2 -2
  99. data/spec/lutaml/model/xml_adapter/oga_adapter_spec.rb +2 -2
  100. data/spec/lutaml/model/xml_adapter/ox_adapter_spec.rb +2 -2
  101. data/spec/lutaml/model/xml_adapter/xml_namespace_spec.rb +6 -6
  102. data/spec/lutaml/model/xml_adapter_spec.rb +6 -6
  103. data/spec/lutaml/model/xml_mapping_rule_spec.rb +3 -3
  104. data/spec/lutaml/model/xml_mapping_spec.rb +26 -14
  105. data/spec/lutaml/model/xml_spec.rb +63 -0
  106. data/spec/lutaml/model/yaml_adapter_spec.rb +3 -5
  107. data/spec/spec_helper.rb +3 -3
  108. metadata +64 -59
  109. data/lib/lutaml/model/json_adapter/json_document.rb +0 -20
  110. data/lib/lutaml/model/json_adapter/json_object.rb +0 -28
  111. data/lib/lutaml/model/loggable.rb +0 -15
  112. data/lib/lutaml/model/mapping/json_mapping.rb +0 -17
  113. data/lib/lutaml/model/mapping/toml_mapping.rb +0 -25
  114. data/lib/lutaml/model/mapping/xml_mapping.rb +0 -389
  115. data/lib/lutaml/model/mapping/xml_mapping_rule.rb +0 -139
  116. data/lib/lutaml/model/mapping/yaml_mapping.rb +0 -17
  117. data/lib/lutaml/model/mapping.rb +0 -14
  118. data/lib/lutaml/model/toml_adapter/toml_document.rb +0 -20
  119. data/lib/lutaml/model/toml_adapter/toml_object.rb +0 -28
  120. data/lib/lutaml/model/toml_adapter/tomlib_adapter.rb +0 -20
  121. data/lib/lutaml/model/toml_adapter.rb +0 -6
  122. data/lib/lutaml/model/yaml_adapter/yaml_document.rb +0 -20
  123. data/lib/lutaml/model/yaml_adapter/yaml_object.rb +0 -28
  124. data/lib/lutaml/model/yaml_adapter.rb +0 -8
@@ -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,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lutaml
4
+ module Model
5
+ module HashAdapter
6
+ # Base class for Hash documents
7
+ class Document < KeyValueDocument
8
+ end
9
+ end
10
+ end
11
+ 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,9 @@
1
+ require_relative "../mapping/key_value_mapping_rule"
2
+
3
+ module Lutaml
4
+ module Model
5
+ module HashAdapter
6
+ class MappingRule < Lutaml::Model::KeyValueMappingRule; end
7
+ end
8
+ end
9
+ 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,8 @@
1
+ module Lutaml
2
+ module Model
3
+ module HashAdapter
4
+ class Transform < Lutaml::Model::KeyValueTransform
5
+ end
6
+ end
7
+ end
8
+ 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,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lutaml
4
+ module Model
5
+ module Json
6
+ # Base class for JSON documents
7
+ class Document < Lutaml::Model::KeyValueDocument
8
+ end
9
+ end
10
+ end
11
+ end
@@ -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
@@ -0,0 +1,9 @@
1
+ require_relative "../mapping/key_value_mapping_rule"
2
+
3
+ module Lutaml
4
+ module Model
5
+ module Json
6
+ class MappingRule < Lutaml::Model::KeyValueMappingRule; end
7
+ end
8
+ end
9
+ end
@@ -1,13 +1,12 @@
1
1
  require "multi_json"
2
- require_relative "json_document"
2
+ require_relative "document"
3
3
 
4
4
  module Lutaml
5
5
  module Model
6
- module JsonAdapter
7
- class MultiJsonAdapter < JsonDocument
6
+ module Json
7
+ class MultiJsonAdapter < Document
8
8
  def self.parse(json, _options = {})
9
- data = MultiJson.load(json)
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 "json_document"
2
+ require_relative "document"
3
3
 
4
4
  module Lutaml
5
5
  module Model
6
- module JsonAdapter
7
- class StandardJsonAdapter < JsonDocument
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,8 @@
1
+ module Lutaml
2
+ module Model
3
+ module Json
4
+ class Transform < Lutaml::Model::KeyValueTransform
5
+ end
6
+ end
7
+ end
8
+ 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,14 @@
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
+ class KeyValueMapping < Mapping
6
7
  attr_reader :mappings, :format
7
8
 
8
9
  def initialize(format = nil)
9
- @mappings = []
10
+ super()
11
+
10
12
  @format = format
11
13
  end
12
14
 
@@ -96,10 +98,12 @@ module Lutaml
96
98
  )
97
99
  end
98
100
 
99
- validate_with_options!(key, with)
101
+ validate_with_options!(to, key, with)
100
102
  end
101
103
 
102
- def validate_with_options!(key, with)
104
+ def validate_with_options!(to, key, with)
105
+ return true if to
106
+
103
107
  if !with.empty? && (with[:from].nil? || with[:to].nil?) && !@raw_mapping
104
108
  raise IncorrectMappingArgumentsError.new(
105
109
  ":with argument for mapping '#{key}' requires :to and :from keys",
@@ -0,0 +1,13 @@
1
+ module Lutaml
2
+ module Model
3
+ class Mapping
4
+ def initialize
5
+ @mappings = []
6
+ end
7
+
8
+ def mappings
9
+ raise NotImplementedError, "#{self.class.name} must implement `mappings`."
10
+ end
11
+ end
12
+ end
13
+ end
@@ -216,8 +216,12 @@ module Lutaml
216
216
  assign_value(model, value)
217
217
  end
218
218
 
219
- def using_custom_methods?
220
- !custom_methods.empty?
219
+ def has_custom_method_for_serialization?
220
+ !custom_methods.empty? && custom_methods[:to]
221
+ end
222
+
223
+ def has_custom_method_for_deserialization?
224
+ !custom_methods.empty? && custom_methods[:from]
221
225
  end
222
226
 
223
227
  def multiple_mappings?
@@ -284,10 +288,7 @@ module Lutaml
284
288
  end
285
289
 
286
290
  def handle_transform_method(model, value, attributes)
287
- transform_method = transform[:import] || attributes[to].transform_import_method
288
- return unless transform_method
289
-
290
- assign_value(model, transform_method.call(value))
291
+ assign_value(model, ImportTransformer.call(value, self, attributes[to]))
291
292
  true
292
293
  end
293
294
 
@@ -0,0 +1,22 @@
1
+ module Lutaml
2
+ module Model
3
+ class SerializationAdapter
4
+ def self.handles_format(format)
5
+ # Lutaml::Model::Config.register_format(format, self)
6
+ @handles = format
7
+ end
8
+
9
+ def self.document_class(klass = nil)
10
+ if klass
11
+ @document_class = klass
12
+ else
13
+ @document_class
14
+ end
15
+ end
16
+
17
+ def self.parse(data, _options = {})
18
+ document_class.parse(data, create_additions: false)
19
+ end
20
+ end
21
+ end
22
+ end