lutaml-model 0.3.10 → 0.3.12
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.
Potentially problematic release.
This version of lutaml-model might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +23 -23
- data/Gemfile +1 -0
- data/LICENSE.md +33 -0
- data/README.adoc +167 -13
- data/lib/lutaml/model/attribute.rb +28 -3
- data/lib/lutaml/model/error/incorrect_mapping_argument_error.rb +6 -0
- data/lib/lutaml/model/error/type_not_enabled_error.rb +9 -0
- data/lib/lutaml/model/error.rb +2 -0
- data/lib/lutaml/model/json_adapter/standard_json_adapter.rb +1 -2
- data/lib/lutaml/model/key_value_mapping.rb +15 -1
- data/lib/lutaml/model/mapping_hash.rb +14 -0
- data/lib/lutaml/model/mapping_rule.rb +50 -7
- data/lib/lutaml/model/serialize.rb +118 -62
- data/lib/lutaml/model/type.rb +10 -0
- data/lib/lutaml/model/utils.rb +16 -0
- data/lib/lutaml/model/version.rb +1 -1
- data/lib/lutaml/model/xml_adapter/builder/nokogiri.rb +14 -6
- data/lib/lutaml/model/xml_adapter/builder/ox.rb +4 -0
- data/lib/lutaml/model/xml_adapter/nokogiri_adapter.rb +20 -9
- data/lib/lutaml/model/xml_adapter/ox_adapter.rb +9 -1
- data/lib/lutaml/model/xml_adapter/xml_document.rb +82 -35
- data/lib/lutaml/model/xml_adapter/xml_element.rb +13 -3
- data/lib/lutaml/model/xml_adapter/xml_namespace.rb +1 -1
- data/lib/lutaml/model/xml_mapping.rb +38 -9
- data/lib/lutaml/model/xml_mapping_rule.rb +5 -1
- data/lib/lutaml/model/yaml_adapter/standard_yaml_adapter.rb +10 -5
- data/lutaml-model.gemspec +0 -1
- metadata +5 -16
@@ -66,24 +66,43 @@ module Lutaml
|
|
66
66
|
options[:tag_name] = rule.name
|
67
67
|
|
68
68
|
options[:mapper_class] = attribute&.type if attribute
|
69
|
+
options[:namespace_set] = set_namespace?(rule)
|
69
70
|
|
70
71
|
options
|
71
72
|
end
|
72
73
|
|
73
|
-
def parse_element(element)
|
74
|
+
def parse_element(element, klass = nil, format = nil)
|
74
75
|
result = Lutaml::Model::MappingHash.new
|
75
76
|
result.item_order = element.order
|
76
77
|
|
77
78
|
element.children.each_with_object(result) do |child, hash|
|
78
|
-
|
79
|
+
attr = klass.attribute_for_child(child.name, format) if klass&.<= Serialize
|
80
|
+
|
81
|
+
value = if child.text?
|
82
|
+
child.text
|
83
|
+
elsif attr&.raw?
|
84
|
+
child.children.map do |c|
|
85
|
+
next c.text if c.text?
|
86
|
+
|
87
|
+
c.to_xml.doc.root.to_xml({})
|
88
|
+
end.join
|
89
|
+
else
|
90
|
+
parse_element(child, attr&.type || klass, format)
|
91
|
+
end
|
79
92
|
|
80
|
-
hash[child.
|
81
|
-
[hash[child.
|
93
|
+
hash[child.namespaced_name] = if hash[child.namespaced_name]
|
94
|
+
[hash[child.namespaced_name], value].flatten
|
82
95
|
else
|
83
96
|
value
|
84
97
|
end
|
85
98
|
end
|
86
99
|
|
100
|
+
result.merge(attributes_hash(element))
|
101
|
+
end
|
102
|
+
|
103
|
+
def attributes_hash(element)
|
104
|
+
result = Lutaml::Model::MappingHash.new
|
105
|
+
|
87
106
|
element.attributes.each_value do |attr|
|
88
107
|
if attr.unprefixed_name == "schemaLocation"
|
89
108
|
result["__schema_location"] = {
|
@@ -92,7 +111,7 @@ module Lutaml
|
|
92
111
|
schema_location: attr.value,
|
93
112
|
}
|
94
113
|
else
|
95
|
-
result[attr.
|
114
|
+
result[attr.name] = attr.value
|
96
115
|
end
|
97
116
|
end
|
98
117
|
|
@@ -107,10 +126,10 @@ module Lutaml
|
|
107
126
|
end
|
108
127
|
end
|
109
128
|
|
110
|
-
def add_to_xml(xml, prefix, value, options = {})
|
129
|
+
def add_to_xml(xml, element, prefix, value, options = {})
|
111
130
|
if value.is_a?(Array)
|
112
131
|
value.each do |item|
|
113
|
-
add_to_xml(xml, prefix, item, options)
|
132
|
+
add_to_xml(xml, element, prefix, item, options)
|
114
133
|
end
|
115
134
|
|
116
135
|
return
|
@@ -120,7 +139,7 @@ module Lutaml
|
|
120
139
|
rule = options[:rule]
|
121
140
|
|
122
141
|
if rule.custom_methods[:to]
|
123
|
-
|
142
|
+
options[:mapper_class].new.send(rule.custom_methods[:to], element, xml.parent, xml)
|
124
143
|
return
|
125
144
|
end
|
126
145
|
|
@@ -130,21 +149,29 @@ module Lutaml
|
|
130
149
|
value,
|
131
150
|
options.merge({ rule: rule, attribute: attribute }),
|
132
151
|
)
|
133
|
-
|
152
|
+
elsif rule.prefix_set?
|
134
153
|
xml.create_and_add_element(rule.name, prefix: prefix) do
|
135
|
-
|
136
|
-
|
154
|
+
add_value(xml, value, attribute)
|
155
|
+
end
|
156
|
+
else
|
157
|
+
xml.create_and_add_element(rule.name) do
|
158
|
+
add_value(xml, value, attribute)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
137
162
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
163
|
+
def add_value(xml, value, attribute)
|
164
|
+
if !value.nil?
|
165
|
+
serialized_value = attribute.type.serialize(value)
|
166
|
+
|
167
|
+
if attribute.type == Lutaml::Model::Type::Hash
|
168
|
+
serialized_value.each do |key, val|
|
169
|
+
xml.create_and_add_element(key) do |element|
|
170
|
+
element.text(val)
|
146
171
|
end
|
147
172
|
end
|
173
|
+
else
|
174
|
+
xml.add_text(xml, serialized_value)
|
148
175
|
end
|
149
176
|
end
|
150
177
|
end
|
@@ -176,21 +203,28 @@ module Lutaml
|
|
176
203
|
prefixed_xml.add_namespace_prefix(nil)
|
177
204
|
end
|
178
205
|
|
206
|
+
xml_mapping.attributes.each do |attribute_rule|
|
207
|
+
attribute_rule.serialize_attribute(element, prefixed_xml.parent, xml)
|
208
|
+
end
|
209
|
+
|
179
210
|
xml_mapping.elements.each do |element_rule|
|
180
211
|
attribute_def = attribute_definition_for(element, element_rule,
|
181
212
|
mapper_class: mapper_class)
|
182
213
|
|
183
|
-
|
214
|
+
if attribute_def
|
215
|
+
value = attribute_value_for(element, element_rule)
|
184
216
|
|
185
|
-
|
217
|
+
next if value.nil? && !element_rule.render_nil?
|
186
218
|
|
187
|
-
|
219
|
+
value = [value] if attribute_def.collection? && !value.is_a?(Array)
|
220
|
+
end
|
188
221
|
|
189
222
|
add_to_xml(
|
190
223
|
prefixed_xml,
|
224
|
+
element,
|
191
225
|
element_rule.prefix,
|
192
226
|
value,
|
193
|
-
options.merge({ attribute: attribute_def, rule: element_rule }),
|
227
|
+
options.merge({ attribute: attribute_def, rule: element_rule, mapper_class: mapper_class }),
|
194
228
|
)
|
195
229
|
end
|
196
230
|
|
@@ -199,7 +233,7 @@ module Lutaml
|
|
199
233
|
@root.send(content_rule.custom_methods[:to], element,
|
200
234
|
prefixed_xml.parent, prefixed_xml)
|
201
235
|
else
|
202
|
-
text =
|
236
|
+
text = content_rule.serialize(element)
|
203
237
|
text = text.join if text.is_a?(Array)
|
204
238
|
prefixed_xml.add_text(xml, text)
|
205
239
|
end
|
@@ -216,15 +250,21 @@ module Lutaml
|
|
216
250
|
mapper_class ? mapper_class.mappings_for(:xml).mixed_content? : false
|
217
251
|
end
|
218
252
|
|
219
|
-
def
|
253
|
+
def set_namespace?(rule)
|
254
|
+
rule.nil? || !rule.namespace_set? || !rule.namespace.nil?
|
255
|
+
end
|
256
|
+
|
257
|
+
def build_namespace_attributes(klass, processed = {}, options = {})
|
220
258
|
xml_mappings = klass.mappings_for(:xml)
|
221
259
|
attributes = klass.attributes
|
222
260
|
|
223
261
|
attrs = {}
|
224
262
|
|
225
|
-
if xml_mappings.namespace_uri
|
226
|
-
prefixed_name = [
|
227
|
-
|
263
|
+
if xml_mappings.namespace_uri && set_namespace?(options[:caller_rule])
|
264
|
+
prefixed_name = [
|
265
|
+
"xmlns",
|
266
|
+
xml_mappings.namespace_prefix,
|
267
|
+
].compact.join(":")
|
228
268
|
|
229
269
|
attrs[prefixed_name] = xml_mappings.namespace_uri
|
230
270
|
end
|
@@ -239,14 +279,16 @@ module Lutaml
|
|
239
279
|
type = if mapping_rule.delegate
|
240
280
|
attributes[mapping_rule.delegate].type.attributes[mapping_rule.to].type
|
241
281
|
else
|
242
|
-
attributes[mapping_rule.to]
|
282
|
+
attributes[mapping_rule.to]&.type
|
243
283
|
end
|
244
284
|
|
285
|
+
next unless type
|
286
|
+
|
245
287
|
if type <= Lutaml::Model::Serialize
|
246
|
-
attrs = attrs.merge(build_namespace_attributes(type, processed))
|
288
|
+
attrs = attrs.merge(build_namespace_attributes(type, processed, { caller_rule: mapping_rule }))
|
247
289
|
end
|
248
290
|
|
249
|
-
if mapping_rule.namespace
|
291
|
+
if mapping_rule.namespace && mapping_rule.prefix && mapping_rule.name != "lang"
|
250
292
|
attrs["xmlns:#{mapping_rule.prefix}"] = mapping_rule.namespace
|
251
293
|
end
|
252
294
|
end
|
@@ -255,22 +297,27 @@ module Lutaml
|
|
255
297
|
end
|
256
298
|
|
257
299
|
def build_attributes(element, xml_mapping, options = {})
|
258
|
-
attrs =
|
300
|
+
attrs = if options.fetch(:namespace_set, true)
|
301
|
+
namespace_attributes(xml_mapping)
|
302
|
+
else
|
303
|
+
{}
|
304
|
+
end
|
259
305
|
|
260
306
|
xml_mapping.attributes.each_with_object(attrs) do |mapping_rule, hash|
|
261
307
|
next if options[:except]&.include?(mapping_rule.to)
|
308
|
+
next if mapping_rule.custom_methods[:to]
|
262
309
|
|
263
|
-
if mapping_rule.namespace
|
310
|
+
if mapping_rule.namespace && mapping_rule.prefix && mapping_rule.name != "lang"
|
264
311
|
hash["xmlns:#{mapping_rule.prefix}"] = mapping_rule.namespace
|
265
312
|
end
|
266
313
|
|
267
|
-
hash[mapping_rule.prefixed_name] =
|
314
|
+
hash[mapping_rule.prefixed_name] = mapping_rule.to_value_for(element)
|
268
315
|
end
|
269
316
|
|
270
317
|
xml_mapping.elements.each_with_object(attrs) do |mapping_rule, hash|
|
271
318
|
next if options[:except]&.include?(mapping_rule.to)
|
272
319
|
|
273
|
-
if mapping_rule.namespace
|
320
|
+
if mapping_rule.namespace && mapping_rule.prefix
|
274
321
|
hash["xmlns:#{mapping_rule.prefix}"] = mapping_rule.namespace
|
275
322
|
end
|
276
323
|
end
|
@@ -16,7 +16,8 @@ module Lutaml
|
|
16
16
|
children = [],
|
17
17
|
text = nil,
|
18
18
|
parent_document: nil,
|
19
|
-
namespace_prefix: nil
|
19
|
+
namespace_prefix: nil,
|
20
|
+
default_namespace: nil
|
20
21
|
)
|
21
22
|
@name = extract_name(name)
|
22
23
|
@namespace_prefix = namespace_prefix || extract_namespace_prefix(name)
|
@@ -24,11 +25,20 @@ module Lutaml
|
|
24
25
|
@children = children
|
25
26
|
@text = text
|
26
27
|
@parent_document = parent_document
|
28
|
+
@default_namespace = default_namespace
|
27
29
|
end
|
28
30
|
|
29
31
|
def name
|
30
|
-
|
31
|
-
|
32
|
+
return @name unless namespace_prefix
|
33
|
+
|
34
|
+
"#{namespace_prefix}:#{@name}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def namespaced_name
|
38
|
+
if namespaces[namespace_prefix] && !text?
|
39
|
+
"#{namespaces[namespace_prefix].uri}:#{@name}"
|
40
|
+
elsif @default_namespace && !text?
|
41
|
+
"#{@default_namespace}:#{name}"
|
32
42
|
else
|
33
43
|
@name
|
34
44
|
end
|
@@ -6,7 +6,8 @@ module Lutaml
|
|
6
6
|
attr_reader :root_element,
|
7
7
|
:namespace_uri,
|
8
8
|
:namespace_prefix,
|
9
|
-
:mixed_content
|
9
|
+
:mixed_content,
|
10
|
+
:ordered
|
10
11
|
|
11
12
|
def initialize
|
12
13
|
@elements = {}
|
@@ -16,10 +17,12 @@ module Lutaml
|
|
16
17
|
end
|
17
18
|
|
18
19
|
alias mixed_content? mixed_content
|
20
|
+
alias ordered? ordered
|
19
21
|
|
20
|
-
def root(name, mixed: false)
|
22
|
+
def root(name, mixed: false, ordered: false)
|
21
23
|
@root_element = name
|
22
24
|
@mixed_content = mixed
|
25
|
+
@ordered = ordered || mixed # mixed contenet will always be ordered
|
23
26
|
end
|
24
27
|
|
25
28
|
def prefixed_root
|
@@ -38,37 +41,46 @@ module Lutaml
|
|
38
41
|
# rubocop:disable Metrics/ParameterLists
|
39
42
|
def map_element(
|
40
43
|
name,
|
41
|
-
to
|
44
|
+
to: nil,
|
42
45
|
render_nil: false,
|
43
46
|
with: {},
|
44
47
|
delegate: nil,
|
45
48
|
namespace: (namespace_set = false
|
46
49
|
nil),
|
47
|
-
prefix:
|
50
|
+
prefix: (prefix_set = false
|
51
|
+
nil)
|
48
52
|
)
|
49
|
-
|
53
|
+
validate!(name, to, with)
|
54
|
+
|
55
|
+
rule = XmlMappingRule.new(
|
50
56
|
name,
|
51
57
|
to: to,
|
52
58
|
render_nil: render_nil,
|
53
59
|
with: with,
|
54
60
|
delegate: delegate,
|
55
61
|
namespace: namespace,
|
62
|
+
default_namespace: namespace_uri,
|
56
63
|
prefix: prefix,
|
57
64
|
namespace_set: namespace_set != false,
|
65
|
+
prefix_set: prefix_set != false,
|
58
66
|
)
|
67
|
+
@elements[rule.namespaced_name] = rule
|
59
68
|
end
|
60
69
|
|
61
70
|
def map_attribute(
|
62
71
|
name,
|
63
|
-
to
|
72
|
+
to: nil,
|
64
73
|
render_nil: false,
|
65
74
|
with: {},
|
66
75
|
delegate: nil,
|
67
76
|
namespace: (namespace_set = false
|
68
77
|
nil),
|
69
|
-
prefix:
|
78
|
+
prefix: (prefix_set = false
|
79
|
+
nil)
|
70
80
|
)
|
71
|
-
|
81
|
+
validate!(name, to, with)
|
82
|
+
|
83
|
+
rule = XmlMappingRule.new(
|
72
84
|
name,
|
73
85
|
to: to,
|
74
86
|
render_nil: render_nil,
|
@@ -76,19 +88,24 @@ module Lutaml
|
|
76
88
|
delegate: delegate,
|
77
89
|
namespace: namespace,
|
78
90
|
prefix: prefix,
|
91
|
+
default_namespace: namespace_uri,
|
79
92
|
namespace_set: namespace_set != false,
|
93
|
+
prefix_set: prefix_set != false,
|
80
94
|
)
|
95
|
+
@attributes[rule.namespaced_name] = rule
|
81
96
|
end
|
82
97
|
|
83
98
|
# rubocop:enable Metrics/ParameterLists
|
84
99
|
|
85
100
|
def map_content(
|
86
|
-
to
|
101
|
+
to: nil,
|
87
102
|
render_nil: false,
|
88
103
|
with: {},
|
89
104
|
delegate: nil,
|
90
105
|
mixed: false
|
91
106
|
)
|
107
|
+
validate!("content", to, with)
|
108
|
+
|
92
109
|
@content_mapping = XmlMappingRule.new(
|
93
110
|
nil,
|
94
111
|
to: to,
|
@@ -99,6 +116,18 @@ module Lutaml
|
|
99
116
|
)
|
100
117
|
end
|
101
118
|
|
119
|
+
def validate!(key, to, with)
|
120
|
+
if to.nil? && with.empty?
|
121
|
+
msg = ":to or :with argument is required for mapping '#{key}'"
|
122
|
+
raise IncorrectMappingArgumentsError.new(msg)
|
123
|
+
end
|
124
|
+
|
125
|
+
if !with.empty? && (with[:from].nil? || with[:to].nil?)
|
126
|
+
msg = ":with argument for mapping '#{key}' requires :to and :from keys"
|
127
|
+
raise IncorrectMappingArgumentsError.new(msg)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
102
131
|
def elements
|
103
132
|
@elements.values
|
104
133
|
end
|
@@ -14,7 +14,9 @@ module Lutaml
|
|
14
14
|
namespace: nil,
|
15
15
|
prefix: nil,
|
16
16
|
mixed_content: false,
|
17
|
-
namespace_set: false
|
17
|
+
namespace_set: false,
|
18
|
+
prefix_set: false,
|
19
|
+
default_namespace: nil
|
18
20
|
)
|
19
21
|
super(
|
20
22
|
name,
|
@@ -24,6 +26,8 @@ module Lutaml
|
|
24
26
|
delegate: delegate,
|
25
27
|
mixed_content: mixed_content,
|
26
28
|
namespace_set: namespace_set,
|
29
|
+
prefix_set: prefix_set,
|
30
|
+
default_namespace: default_namespace
|
27
31
|
)
|
28
32
|
|
29
33
|
@namespace = if namespace.to_s == "inherit"
|
@@ -5,12 +5,17 @@ module Lutaml
|
|
5
5
|
module Model
|
6
6
|
module YamlAdapter
|
7
7
|
class StandardYamlAdapter < YamlDocument
|
8
|
+
PERMITTED_CLASSES_BASE = [Date, Time, DateTime, Symbol, Hash,
|
9
|
+
Array].freeze
|
10
|
+
|
11
|
+
PERMITTED_CLASSES = if defined?(BigDecimal)
|
12
|
+
PERMITTED_CLASSES_BASE + [BigDecimal]
|
13
|
+
else
|
14
|
+
PERMITTED_CLASSES_BASE
|
15
|
+
end.freeze
|
16
|
+
|
8
17
|
def self.parse(yaml)
|
9
|
-
YAML.safe_load(
|
10
|
-
yaml,
|
11
|
-
permitted_classes: [Date, Time, DateTime, Symbol,
|
12
|
-
BigDecimal, Hash, Array],
|
13
|
-
)
|
18
|
+
YAML.safe_load(yaml, permitted_classes: PERMITTED_CLASSES)
|
14
19
|
end
|
15
20
|
|
16
21
|
def to_yaml(options = {})
|
data/lutaml-model.gemspec
CHANGED
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lutaml-model
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ribose Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-10-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: bigdecimal
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: thor
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -56,6 +42,7 @@ files:
|
|
56
42
|
- ".rubocop_todo.yml"
|
57
43
|
- CODE_OF_CONDUCT.md
|
58
44
|
- Gemfile
|
45
|
+
- LICENSE.md
|
59
46
|
- README.adoc
|
60
47
|
- Rakefile
|
61
48
|
- bin/console
|
@@ -70,7 +57,9 @@ files:
|
|
70
57
|
- lib/lutaml/model/config.rb
|
71
58
|
- lib/lutaml/model/error.rb
|
72
59
|
- lib/lutaml/model/error/collection_count_out_of_range_error.rb
|
60
|
+
- lib/lutaml/model/error/incorrect_mapping_argument_error.rb
|
73
61
|
- lib/lutaml/model/error/invalid_value_error.rb
|
62
|
+
- lib/lutaml/model/error/type_not_enabled_error.rb
|
74
63
|
- lib/lutaml/model/error/unknown_adapter_type_error.rb
|
75
64
|
- lib/lutaml/model/error/validation_error.rb
|
76
65
|
- lib/lutaml/model/json_adapter.rb
|