lutaml-model 0.3.10 → 0.3.12
Sign up to get free protection for your applications and to get access to all the features.
- 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
|