lutaml-model 0.3.6 → 0.3.8
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 +14 -12
- data/README.adoc +30 -26
- data/lib/lutaml/model/attribute.rb +27 -0
- data/lib/lutaml/model/serialize.rb +100 -127
- data/lib/lutaml/model/type.rb +2 -0
- data/lib/lutaml/model/utils.rb +45 -0
- data/lib/lutaml/model/version.rb +1 -1
- data/lib/lutaml/model/xml_adapter/builder/nokogiri.rb +73 -0
- data/lib/lutaml/model/xml_adapter/builder/ox.rb +89 -0
- data/lib/lutaml/model/xml_adapter/nokogiri_adapter.rb +19 -92
- data/lib/lutaml/model/xml_adapter/ox_adapter.rb +22 -94
- data/lib/lutaml/model/xml_adapter/xml_document.rb +111 -7
- data/lib/lutaml/model/yaml_adapter/standard_yaml_adapter.rb +0 -12
- data/lib/lutaml/model.rb +1 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 30487a24277470ff7b3d12193e46262b0fc1cac85461224ed98749c8b6de5104
|
4
|
+
data.tar.gz: a161a8e5f83a10ec5db5b77a0d5a0abe72b629d0900a4ab040414c2a02c22725
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2a805f81f93bc0dcb983d83e7f7fc870989f84fb25434de7edee18269c1b96b8572516132e17e3db2e188075e985cb8219ec84257fd380c7abfe4b65b32116af
|
7
|
+
data.tar.gz: 0243f89d6fb6c5466e29500e810a077096e260b51d53a8a23db7918c7b2d57dc30a9757dd00814a2c497dd552e39bd17e92729c509670dde555a0b508a77013b
|
data/.rubocop_todo.yml
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# This configuration was generated by
|
2
2
|
# `rubocop --auto-gen-config`
|
3
|
-
# on 2024-08-
|
3
|
+
# on 2024-08-27 06:48:03 UTC using RuboCop version 1.65.1.
|
4
4
|
# The point is for the user to remove these configuration records
|
5
5
|
# one by one as the offenses are removed from the code base.
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
@@ -14,7 +14,7 @@ Gemspec/RequireMFA:
|
|
14
14
|
Exclude:
|
15
15
|
- 'lutaml-model.gemspec'
|
16
16
|
|
17
|
-
# Offense count:
|
17
|
+
# Offense count: 57
|
18
18
|
# This cop supports safe autocorrection (--autocorrect).
|
19
19
|
# Configuration parameters: Max, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns.
|
20
20
|
# URISchemes: http, https
|
@@ -24,6 +24,7 @@ Layout/LineLength:
|
|
24
24
|
- 'lib/lutaml/model/comparable_model.rb'
|
25
25
|
- 'lib/lutaml/model/serialize.rb'
|
26
26
|
- 'lib/lutaml/model/type.rb'
|
27
|
+
- 'lib/lutaml/model/utils.rb'
|
27
28
|
- 'lib/lutaml/model/xml_adapter/nokogiri_adapter.rb'
|
28
29
|
- 'lib/lutaml/model/xml_adapter/ox_adapter.rb'
|
29
30
|
- 'lib/lutaml/model/xml_adapter/xml_document.rb'
|
@@ -43,7 +44,7 @@ Lint/ConstantDefinitionInBlock:
|
|
43
44
|
- 'spec/lutaml/model/schema/xsd_schema_spec.rb'
|
44
45
|
- 'spec/lutaml/model/schema/yaml_schema_spec.rb'
|
45
46
|
|
46
|
-
# Offense count:
|
47
|
+
# Offense count: 28
|
47
48
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
|
48
49
|
Metrics/AbcSize:
|
49
50
|
Exclude:
|
@@ -56,16 +57,17 @@ Metrics/AbcSize:
|
|
56
57
|
- 'lib/lutaml/model/xml_adapter/ox_adapter.rb'
|
57
58
|
- 'lib/lutaml/model/xml_adapter/xml_document.rb'
|
58
59
|
|
59
|
-
# Offense count:
|
60
|
+
# Offense count: 5
|
60
61
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode.
|
61
62
|
# AllowedMethods: refine
|
62
63
|
Metrics/BlockLength:
|
63
|
-
Max:
|
64
|
+
Max: 43
|
64
65
|
|
65
|
-
# Offense count:
|
66
|
+
# Offense count: 22
|
66
67
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
67
68
|
Metrics/CyclomaticComplexity:
|
68
69
|
Exclude:
|
70
|
+
- 'lib/lutaml/model/attribute.rb'
|
69
71
|
- 'lib/lutaml/model/comparable_model.rb'
|
70
72
|
- 'lib/lutaml/model/serialize.rb'
|
71
73
|
- 'lib/lutaml/model/type.rb'
|
@@ -73,23 +75,23 @@ Metrics/CyclomaticComplexity:
|
|
73
75
|
- 'lib/lutaml/model/xml_adapter/ox_adapter.rb'
|
74
76
|
- 'lib/lutaml/model/xml_adapter/xml_document.rb'
|
75
77
|
|
76
|
-
# Offense count:
|
78
|
+
# Offense count: 36
|
77
79
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
78
80
|
Metrics/MethodLength:
|
79
|
-
Max:
|
81
|
+
Max: 43
|
80
82
|
|
81
83
|
# Offense count: 4
|
82
84
|
# Configuration parameters: CountKeywordArgs, MaxOptionalParameters.
|
83
85
|
Metrics/ParameterLists:
|
84
86
|
Max: 9
|
85
87
|
|
86
|
-
# Offense count:
|
88
|
+
# Offense count: 18
|
87
89
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
88
90
|
Metrics/PerceivedComplexity:
|
89
91
|
Exclude:
|
92
|
+
- 'lib/lutaml/model/attribute.rb'
|
90
93
|
- 'lib/lutaml/model/comparable_model.rb'
|
91
94
|
- 'lib/lutaml/model/serialize.rb'
|
92
|
-
- 'lib/lutaml/model/type.rb'
|
93
95
|
- 'lib/lutaml/model/xml_adapter/nokogiri_adapter.rb'
|
94
96
|
- 'lib/lutaml/model/xml_adapter/ox_adapter.rb'
|
95
97
|
- 'lib/lutaml/model/xml_adapter/xml_document.rb'
|
@@ -103,7 +105,7 @@ RSpec/ContextWording:
|
|
103
105
|
- 'spec/lutaml/model/xml_adapter/oga_adapter_spec.rb'
|
104
106
|
- 'spec/lutaml/model/xml_adapter/ox_adapter_spec.rb'
|
105
107
|
|
106
|
-
# Offense count:
|
108
|
+
# Offense count: 76
|
107
109
|
# Configuration parameters: CountAsOne.
|
108
110
|
RSpec/ExampleLength:
|
109
111
|
Max: 57
|
@@ -132,7 +134,7 @@ RSpec/MultipleDescribes:
|
|
132
134
|
|
133
135
|
# Offense count: 70
|
134
136
|
RSpec/MultipleExpectations:
|
135
|
-
Max:
|
137
|
+
Max: 10
|
136
138
|
|
137
139
|
# Offense count: 11
|
138
140
|
# Configuration parameters: AllowSubject.
|
data/README.adoc
CHANGED
@@ -1338,11 +1338,11 @@ class CustomCeramic < Lutaml::Model::Serializable
|
|
1338
1338
|
end
|
1339
1339
|
|
1340
1340
|
def name_to_json(model, value)
|
1341
|
-
"Masterpiece: #{value}"
|
1341
|
+
doc["name"] = "Masterpiece: #{value}"
|
1342
1342
|
end
|
1343
1343
|
|
1344
1344
|
def name_from_json(model, doc)
|
1345
|
-
|
1345
|
+
model.name = value.sub(/^JSON Masterpiece: /, '')
|
1346
1346
|
end
|
1347
1347
|
end
|
1348
1348
|
----
|
@@ -1971,52 +1971,56 @@ class Example < Lutaml::Model::Serializable
|
|
1971
1971
|
from: :description_from_xml }
|
1972
1972
|
end
|
1973
1973
|
|
1974
|
-
def name_to_json(
|
1975
|
-
"JSON Masterpiece: #{
|
1974
|
+
def name_to_json(model, doc)
|
1975
|
+
doc["name"] = "JSON Masterpiece: #{model.name}"
|
1976
1976
|
end
|
1977
1977
|
|
1978
|
-
def name_from_json(
|
1979
|
-
|
1978
|
+
def name_from_json(model, value)
|
1979
|
+
model.name = value.sub(/^JSON Masterpiece: /, "")
|
1980
1980
|
end
|
1981
1981
|
|
1982
|
-
def color_to_json(
|
1983
|
-
|
1982
|
+
def color_to_json(model, doc)
|
1983
|
+
doc["color"] = model.color.upcase
|
1984
1984
|
end
|
1985
1985
|
|
1986
|
-
def color_from_json(
|
1987
|
-
|
1986
|
+
def color_from_json(model, value)
|
1987
|
+
model.color = value.downcase
|
1988
1988
|
end
|
1989
1989
|
|
1990
|
-
def description_to_json(
|
1991
|
-
"JSON Description: #{
|
1990
|
+
def description_to_json(model, doc)
|
1991
|
+
doc["description"] = "JSON Description: #{model.description}"
|
1992
1992
|
end
|
1993
1993
|
|
1994
|
-
def description_from_json(
|
1995
|
-
|
1994
|
+
def description_from_json(model, value)
|
1995
|
+
model.description = value.sub(/^JSON Description: /, "")
|
1996
1996
|
end
|
1997
1997
|
|
1998
|
-
def name_to_xml(
|
1999
|
-
|
1998
|
+
def name_to_xml(model, parent, doc)
|
1999
|
+
el = doc.create_element("Name")
|
2000
|
+
doc.add_text(el, "XML Masterpiece: #{model.name}")
|
2001
|
+
doc.add_element(parent, el)
|
2000
2002
|
end
|
2001
2003
|
|
2002
|
-
def name_from_xml(
|
2003
|
-
value.sub(/^XML Masterpiece: /, "")
|
2004
|
+
def name_from_xml(model, value)
|
2005
|
+
model.name = value.sub(/^XML Masterpiece: /, "")
|
2004
2006
|
end
|
2005
2007
|
|
2006
|
-
def color_to_xml(
|
2007
|
-
|
2008
|
+
def color_to_xml(model, parent, doc)
|
2009
|
+
color_element = doc.create_element("Color")
|
2010
|
+
doc.add_text(color_element, model.color.upcase)
|
2011
|
+
doc.add_element(parent, color_element)
|
2008
2012
|
end
|
2009
2013
|
|
2010
|
-
def color_from_xml(
|
2011
|
-
value.downcase
|
2014
|
+
def color_from_xml(model, value)
|
2015
|
+
model.color = value.downcase
|
2012
2016
|
end
|
2013
2017
|
|
2014
|
-
def description_to_xml(
|
2015
|
-
"XML Description: #{
|
2018
|
+
def description_to_xml(model, parent, doc)
|
2019
|
+
doc.add_text(parent, "XML Description: #{model.description}")
|
2016
2020
|
end
|
2017
2021
|
|
2018
|
-
def description_from_xml(
|
2019
|
-
value.sub(/^XML Description: /, "")
|
2022
|
+
def description_from_xml(model, value)
|
2023
|
+
model.description = value.join.strip.sub(/^XML Description: /, "")
|
2020
2024
|
end
|
2021
2025
|
end
|
2022
2026
|
----
|
@@ -40,6 +40,33 @@ module Lutaml
|
|
40
40
|
def render_nil?
|
41
41
|
options.fetch(:render_nil, false)
|
42
42
|
end
|
43
|
+
|
44
|
+
def serialize(value, format, options = {})
|
45
|
+
if value.is_a?(Array)
|
46
|
+
value.map do |v|
|
47
|
+
serialize(v, format, options)
|
48
|
+
end
|
49
|
+
elsif type <= Serialize
|
50
|
+
type.hash_representation(value, format, options)
|
51
|
+
else
|
52
|
+
type.serialize(value)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def cast(value, format, options = {})
|
57
|
+
value ||= [] if collection?
|
58
|
+
instance = options[:instance]
|
59
|
+
|
60
|
+
if value.is_a?(Array)
|
61
|
+
value.map do |v|
|
62
|
+
cast(v, format, instance: instance)
|
63
|
+
end
|
64
|
+
elsif type <= Serialize && value.is_a?(Hash)
|
65
|
+
type.apply_mappings(value, format, options)
|
66
|
+
else
|
67
|
+
Lutaml::Model::Type.cast(value, type)
|
68
|
+
end
|
69
|
+
end
|
43
70
|
end
|
44
71
|
end
|
45
72
|
end
|
@@ -84,29 +84,47 @@ module Lutaml
|
|
84
84
|
|
85
85
|
define_method(:"from_#{format}") do |data|
|
86
86
|
adapter = Lutaml::Model::Config.send(:"#{format}_adapter")
|
87
|
+
|
87
88
|
doc = adapter.parse(data)
|
88
|
-
|
89
|
-
# apply_content_mapping(doc, mapped_attrs) if format == :xml
|
90
|
-
generate_model_object(self, mapped_attrs)
|
89
|
+
public_send(:"of_#{format}", doc.to_h)
|
91
90
|
end
|
92
91
|
|
93
|
-
define_method(:"
|
94
|
-
|
95
|
-
|
96
|
-
|
92
|
+
define_method(:"of_#{format}") do |hash|
|
93
|
+
if hash.is_a?(Array)
|
94
|
+
return hash.map do |item|
|
95
|
+
apply_mappings(item, format)
|
96
|
+
end
|
97
97
|
end
|
98
98
|
|
99
|
+
apply_mappings(hash, format)
|
100
|
+
end
|
101
|
+
|
102
|
+
define_method(:"to_#{format}") do |instance|
|
103
|
+
value = public_send(:"as_#{format}", instance)
|
99
104
|
adapter = Lutaml::Model::Config.public_send(:"#{format}_adapter")
|
100
105
|
|
101
106
|
if format == :xml
|
102
107
|
xml_options = { mapper_class: self }
|
103
|
-
|
104
|
-
adapter.new(instance).public_send(:"to_#{format}", xml_options)
|
108
|
+
adapter.new(value).public_send(:"to_#{format}", xml_options)
|
105
109
|
else
|
106
|
-
|
107
|
-
adapter.new(hash).public_send(:"to_#{format}")
|
110
|
+
adapter.new(value).public_send(:"to_#{format}")
|
108
111
|
end
|
109
112
|
end
|
113
|
+
|
114
|
+
define_method(:"as_#{format}") do |instance|
|
115
|
+
if instance.is_a?(Array)
|
116
|
+
return instance.map { |item| public_send(:"as_#{format}", item) }
|
117
|
+
end
|
118
|
+
|
119
|
+
unless instance.is_a?(model)
|
120
|
+
msg = "argument is a '#{instance.class}' but should be a '#{model}'"
|
121
|
+
raise Lutaml::Model::IncorrectModelError, msg
|
122
|
+
end
|
123
|
+
|
124
|
+
return instance if format == :xml
|
125
|
+
|
126
|
+
hash_representation(instance, format)
|
127
|
+
end
|
110
128
|
end
|
111
129
|
|
112
130
|
def hash_representation(instance, format, options = {})
|
@@ -118,13 +136,13 @@ module Lutaml
|
|
118
136
|
name = rule.to
|
119
137
|
next if except&.include?(name) || (only && !only.include?(name))
|
120
138
|
|
121
|
-
next handle_delegate(instance, rule, hash) if rule.delegate
|
139
|
+
next handle_delegate(instance, rule, hash, format) if rule.delegate
|
122
140
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
141
|
+
if rule.custom_methods[:to]
|
142
|
+
next instance.send(rule.custom_methods[:to], instance, hash)
|
143
|
+
end
|
144
|
+
|
145
|
+
value = instance.send(name)
|
128
146
|
|
129
147
|
next if value.nil? && !rule.render_nil
|
130
148
|
|
@@ -132,68 +150,27 @@ module Lutaml
|
|
132
150
|
|
133
151
|
hash[rule.from] = if rule.child_mappings
|
134
152
|
generate_hash_from_child_mappings(value, rule.child_mappings)
|
135
|
-
elsif value.is_a?(Array)
|
136
|
-
value.map do |v|
|
137
|
-
if attribute.type <= Serialize
|
138
|
-
attribute.type.hash_representation(v, format, options)
|
139
|
-
else
|
140
|
-
attribute.type.serialize(v)
|
141
|
-
end
|
142
|
-
end
|
143
|
-
elsif attribute.type <= Serialize
|
144
|
-
attribute.type.hash_representation(value, format, options)
|
145
153
|
else
|
146
|
-
attribute.
|
154
|
+
attribute.serialize(value, format, options)
|
147
155
|
end
|
148
156
|
end
|
149
157
|
end
|
150
158
|
|
151
|
-
def handle_delegate(instance, rule, hash)
|
159
|
+
def handle_delegate(instance, rule, hash, format)
|
152
160
|
name = rule.to
|
153
161
|
value = instance.send(rule.delegate).send(name)
|
154
162
|
return if value.nil? && !rule.render_nil
|
155
163
|
|
156
164
|
attribute = instance.send(rule.delegate).class.attributes[name]
|
157
|
-
hash[rule.from] =
|
158
|
-
when Array
|
159
|
-
value.map do |v|
|
160
|
-
if v.is_a?(Serialize)
|
161
|
-
hash_representation(v, format, options)
|
162
|
-
else
|
163
|
-
attribute.type.serialize(v)
|
164
|
-
end
|
165
|
-
end
|
166
|
-
else
|
167
|
-
if value.is_a?(Serialize)
|
168
|
-
hash_representation(value, format, options)
|
169
|
-
else
|
170
|
-
attribute.type.serialize(value)
|
171
|
-
end
|
172
|
-
end
|
165
|
+
hash[rule.from] = attribute.serialize(value, format)
|
173
166
|
end
|
174
167
|
|
175
168
|
def mappings_for(format)
|
176
169
|
mappings[format] || default_mappings(format)
|
177
170
|
end
|
178
171
|
|
179
|
-
def generate_model_object(type, mapped_attrs)
|
180
|
-
return type.model.new(mapped_attrs) if self == model
|
181
|
-
|
182
|
-
instance = type.model.new
|
183
|
-
|
184
|
-
type.attributes.each do |name, attr|
|
185
|
-
value = attr_value(mapped_attrs, name, attr)
|
186
|
-
|
187
|
-
instance.send(:"#{name}=", ensure_utf8(value))
|
188
|
-
end
|
189
|
-
|
190
|
-
instance
|
191
|
-
end
|
192
|
-
|
193
172
|
def attr_value(attrs, name, attr_rule)
|
194
|
-
value = if attrs.key?(name)
|
195
|
-
attrs[name]
|
196
|
-
elsif attrs.key?(name.to_sym)
|
173
|
+
value = if attrs.key?(name.to_sym)
|
197
174
|
attrs[name.to_sym]
|
198
175
|
elsif attrs.key?(name.to_s)
|
199
176
|
attrs[name.to_s]
|
@@ -211,8 +188,6 @@ module Lutaml
|
|
211
188
|
Lutaml::Model::Type.cast(v, attr_rule.type)
|
212
189
|
end
|
213
190
|
end
|
214
|
-
elsif value.is_a?(Hash) && attr_rule.type != Lutaml::Model::Type::Hash
|
215
|
-
generate_model_object(attr_rule.type, value)
|
216
191
|
else
|
217
192
|
# TODO: This code is problematic because Type.cast does not know
|
218
193
|
# about all the types.
|
@@ -279,11 +254,13 @@ module Lutaml
|
|
279
254
|
hash
|
280
255
|
end
|
281
256
|
|
282
|
-
def apply_mappings(doc, format)
|
283
|
-
|
257
|
+
def apply_mappings(doc, format, options = {})
|
258
|
+
instance = options[:instance] || model.new
|
259
|
+
return instance if !doc || doc.empty?
|
260
|
+
return apply_xml_mapping(doc, instance, options) if format == :xml
|
284
261
|
|
285
262
|
mappings = mappings_for(format).mappings
|
286
|
-
mappings.
|
263
|
+
mappings.each do |rule|
|
287
264
|
attr = if rule.delegate
|
288
265
|
attributes[rule.delegate].type.attributes[rule.to]
|
289
266
|
else
|
@@ -292,106 +269,96 @@ module Lutaml
|
|
292
269
|
|
293
270
|
raise "Attribute '#{rule.to}' not found in #{self}" unless attr
|
294
271
|
|
295
|
-
value = if rule.
|
296
|
-
new.send(rule.custom_methods[:from], hash, doc)
|
297
|
-
elsif doc.key?(rule.name) || doc.key?(rule.name.to_sym)
|
272
|
+
value = if doc.key?(rule.name) || doc.key?(rule.name.to_sym)
|
298
273
|
doc[rule.name] || doc[rule.name.to_sym]
|
299
274
|
else
|
300
275
|
attr.default
|
301
276
|
end
|
302
277
|
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
value = (value || []).map do |v|
|
307
|
-
attr.type <= Serialize ? attr.type.apply_mappings(v, format) : v
|
308
|
-
end
|
309
|
-
elsif value.is_a?(Hash) && attr.type != Lutaml::Model::Type::Hash
|
310
|
-
value = attr.type.apply_mappings(value, format)
|
278
|
+
if rule.custom_methods[:from]
|
279
|
+
value = new.send(rule.custom_methods[:from], instance, value) if value && !value.empty?
|
280
|
+
next
|
311
281
|
end
|
312
282
|
|
283
|
+
value = apply_child_mappings(value, rule.child_mappings)
|
284
|
+
value = attr.cast(value, format)
|
285
|
+
|
313
286
|
if rule.delegate
|
314
|
-
|
315
|
-
|
287
|
+
if instance.public_send(rule.delegate).nil?
|
288
|
+
instance.public_send(:"#{rule.delegate}=",
|
289
|
+
attributes[rule.delegate].type.new)
|
290
|
+
end
|
291
|
+
instance.public_send(rule.delegate).public_send(:"#{rule.to}=",
|
292
|
+
value)
|
316
293
|
else
|
317
|
-
|
294
|
+
instance.public_send(:"#{rule.to}=", value)
|
318
295
|
end
|
319
296
|
end
|
297
|
+
|
298
|
+
instance
|
320
299
|
end
|
321
300
|
|
322
|
-
def apply_xml_mapping(doc,
|
323
|
-
return unless doc
|
301
|
+
def apply_xml_mapping(doc, instance, options = {})
|
302
|
+
return instance unless doc
|
324
303
|
|
325
304
|
mappings = mappings_for(:xml).mappings
|
326
305
|
|
327
306
|
if doc.is_a?(Array)
|
328
307
|
raise "May be `collection: true` is" \
|
329
|
-
"missing for #{self} in #{caller_class}"
|
308
|
+
"missing for #{self} in #{options[:caller_class]}"
|
330
309
|
end
|
331
310
|
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
mapping_from = []
|
311
|
+
if instance.respond_to?(:ordered=) && doc.is_a?(Lutaml::Model::MappingHash)
|
312
|
+
instance.element_order = doc.item_order
|
313
|
+
instance.ordered = mappings_for(:xml).mixed_content? || options[:mixed_content]
|
314
|
+
end
|
337
315
|
|
338
|
-
mappings.
|
316
|
+
mappings.each do |rule|
|
339
317
|
attr = attributes[rule.to]
|
340
318
|
raise "Attribute '#{rule.to}' not found in #{self}" unless attr
|
341
319
|
|
342
320
|
is_content_mapping = rule.name.nil?
|
321
|
+
|
343
322
|
value = if is_content_mapping
|
344
323
|
doc["text"]
|
345
324
|
else
|
346
325
|
doc[rule.name.to_s] || doc[rule.name.to_sym]
|
347
326
|
end
|
348
327
|
|
349
|
-
if attr.collection?
|
350
|
-
if value && !value.is_a?(Array)
|
351
|
-
value = [value]
|
352
|
-
end
|
328
|
+
value = [value].compact if attr.collection? && !value.is_a?(Array)
|
353
329
|
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
elsif v.is_a?(Hash)
|
358
|
-
v["text"]
|
359
|
-
else
|
360
|
-
v
|
361
|
-
end
|
330
|
+
if value.is_a?(Array)
|
331
|
+
value = value.map do |v|
|
332
|
+
v.is_a?(Hash) && !(attr.type <= Serialize) ? v["text"] : v
|
362
333
|
end
|
363
|
-
elsif attr.type <= Serialize
|
364
|
-
value =
|
365
|
-
else
|
366
|
-
if value.is_a?(Hash) && attr.type != Lutaml::Model::Type::Hash
|
367
|
-
value = value["text"]
|
368
|
-
end
|
369
|
-
|
370
|
-
value = attr.type.cast(value) unless is_content_mapping
|
334
|
+
elsif !(attr.type <= Serialize) && value.is_a?(Hash) && attr.type != Lutaml::Model::Type::Hash
|
335
|
+
value = value["text"]
|
371
336
|
end
|
372
337
|
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
else
|
382
|
-
mapping_hash[rule.to]
|
383
|
-
end
|
338
|
+
unless is_content_mapping
|
339
|
+
value = attr.cast(
|
340
|
+
value,
|
341
|
+
:xml,
|
342
|
+
caller_class: self,
|
343
|
+
mixed_content: rule.mixed_content,
|
344
|
+
)
|
345
|
+
end
|
384
346
|
|
385
|
-
|
347
|
+
if rule.custom_methods[:from]
|
348
|
+
new.send(rule.custom_methods[:from], instance, value)
|
349
|
+
else
|
350
|
+
instance.public_send(:"#{rule.to}=", value)
|
351
|
+
end
|
386
352
|
end
|
387
353
|
|
388
|
-
|
354
|
+
instance
|
389
355
|
end
|
390
356
|
|
391
357
|
def ensure_utf8(value)
|
392
358
|
case value
|
393
359
|
when String
|
394
|
-
value.encode("UTF-8", invalid: :replace, undef: :replace,
|
360
|
+
value.encode("UTF-8", invalid: :replace, undef: :replace,
|
361
|
+
replace: "")
|
395
362
|
when Array
|
396
363
|
value.map { |v| ensure_utf8(v) }
|
397
364
|
when Hash
|
@@ -406,7 +373,7 @@ module Lutaml
|
|
406
373
|
end
|
407
374
|
end
|
408
375
|
|
409
|
-
|
376
|
+
attr_accessor :element_order
|
410
377
|
|
411
378
|
def initialize(attrs = {})
|
412
379
|
return unless self.class.attributes
|
@@ -429,6 +396,10 @@ module Lutaml
|
|
429
396
|
@ordered
|
430
397
|
end
|
431
398
|
|
399
|
+
def ordered=(ordered)
|
400
|
+
@ordered = ordered
|
401
|
+
end
|
402
|
+
|
432
403
|
def key_exist?(hash, key)
|
433
404
|
hash.key?(key.to_sym) || hash.key?(key.to_s)
|
434
405
|
end
|
@@ -444,7 +415,8 @@ module Lutaml
|
|
444
415
|
representation = if format == :xml
|
445
416
|
self
|
446
417
|
else
|
447
|
-
self.class.hash_representation(self, format,
|
418
|
+
self.class.hash_representation(self, format,
|
419
|
+
options)
|
448
420
|
end
|
449
421
|
|
450
422
|
adapter.new(representation).public_send(:"to_#{format}", options)
|
@@ -455,7 +427,8 @@ module Lutaml
|
|
455
427
|
self.class.attributes.each do |name, attr|
|
456
428
|
value = send(name)
|
457
429
|
unless self.class.attr_value_valid?(name, value)
|
458
|
-
raise Lutaml::Model::InvalidValueError.new(name, value,
|
430
|
+
raise Lutaml::Model::InvalidValueError.new(name, value,
|
431
|
+
attr.options[:values])
|
459
432
|
end
|
460
433
|
end
|
461
434
|
end
|
data/lib/lutaml/model/type.rb
CHANGED
@@ -22,11 +22,13 @@ module Lutaml
|
|
22
22
|
class #{t} # class Integer
|
23
23
|
def self.cast(value) # def self.cast(value)
|
24
24
|
return if value.nil? # return if value.nil?
|
25
|
+
#
|
25
26
|
Type.cast(value, #{t}) # Type.cast(value, Integer)
|
26
27
|
end # end
|
27
28
|
|
28
29
|
def self.serialize(value) # def self.serialize(value)
|
29
30
|
return if value.nil? # return if value.nil?
|
31
|
+
#
|
30
32
|
Type.serialize(value, #{t}) # Type.serialize(value, Integer)
|
31
33
|
end # end
|
32
34
|
end # end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lutaml
|
4
|
+
module Model
|
5
|
+
module Utils
|
6
|
+
class << self
|
7
|
+
# Convert string to camel case
|
8
|
+
def camel_case(str)
|
9
|
+
return "" if str.nil? || str.empty?
|
10
|
+
|
11
|
+
str.split("/").map { |part| camelize_part(part) }.join("::")
|
12
|
+
end
|
13
|
+
|
14
|
+
# Convert string to class name
|
15
|
+
def classify(str)
|
16
|
+
str = str.to_s.delete(".")
|
17
|
+
str = str.sub(/^[a-z\d]*/) { |match| camel_case(match) || match }
|
18
|
+
|
19
|
+
str.gsub("::", "/").gsub(%r{(?:_|-|(/))([a-z\d]*)}i) do
|
20
|
+
word = Regexp.last_match(2)
|
21
|
+
substituted = camel_case(word) || word
|
22
|
+
Regexp.last_match(1) ? "::#{substituted}" : substituted
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Convert string to snake case
|
27
|
+
def snake_case(str)
|
28
|
+
str = str.to_s.tr(".", "_")
|
29
|
+
return str unless /[A-Z-]|::/.match?(str)
|
30
|
+
|
31
|
+
str.gsub("::", "/")
|
32
|
+
.gsub(/([A-Z]+)(?=[A-Z][a-z])|([a-z\d])(?=[A-Z])/) { "#{$1 || $2}_" }
|
33
|
+
.tr("-", "_")
|
34
|
+
.downcase
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def camelize_part(part)
|
40
|
+
part.gsub(/(?:_|-|^)([a-z\d])/i) { $1.upcase }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|