lutaml-model 0.3.6 → 0.3.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 45fc67305626a2fe4d38db31804a618fd887a9855ff8ddb7ef2d0d0e8cc8b9b8
4
- data.tar.gz: 7ffbc1f1b1958d05ebbf82889b1b54f032df48a4ed9052f3a963b896bfb43238
3
+ metadata.gz: 30487a24277470ff7b3d12193e46262b0fc1cac85461224ed98749c8b6de5104
4
+ data.tar.gz: a161a8e5f83a10ec5db5b77a0d5a0abe72b629d0900a4ab040414c2a02c22725
5
5
  SHA512:
6
- metadata.gz: 37a4e64c1b61b6a1112329b18ea4bd9b544fe125859cd81a1054b162817e1ffb22e03f4168836ce8890e6f6cba6f137c78110522322c0a0fe6fde3e121c533d4
7
- data.tar.gz: bd3bfb6600103c25034c3604fcdc83947d8eb3a14b23ec54e93186f66d273a5270a923394bd5f00e5caf3d58c9ff7c65efce9cd5f7a874ac22f4582711622d27
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-19 03:44:26 UTC using RuboCop version 1.65.1.
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: 78
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: 31
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: 4
60
+ # Offense count: 5
60
61
  # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode.
61
62
  # AllowedMethods: refine
62
63
  Metrics/BlockLength:
63
- Max: 31
64
+ Max: 43
64
65
 
65
- # Offense count: 23
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: 38
78
+ # Offense count: 36
77
79
  # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
78
80
  Metrics/MethodLength:
79
- Max: 52
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: 20
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: 73
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: 15
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
- doc['name'].sub(/^Masterpiece: /, '')
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(_model, value)
1975
- "JSON Masterpiece: #{value}"
1974
+ def name_to_json(model, doc)
1975
+ doc["name"] = "JSON Masterpiece: #{model.name}"
1976
1976
  end
1977
1977
 
1978
- def name_from_json(_model, doc)
1979
- doc["name"].sub(/^JSON Masterpiece: /, "")
1978
+ def name_from_json(model, value)
1979
+ model.name = value.sub(/^JSON Masterpiece: /, "")
1980
1980
  end
1981
1981
 
1982
- def color_to_json(_model, value)
1983
- value.upcase
1982
+ def color_to_json(model, doc)
1983
+ doc["color"] = model.color.upcase
1984
1984
  end
1985
1985
 
1986
- def color_from_json(_model, doc)
1987
- doc["color"].downcase
1986
+ def color_from_json(model, value)
1987
+ model.color = value.downcase
1988
1988
  end
1989
1989
 
1990
- def description_to_json(_model, value)
1991
- "JSON Description: #{value}"
1990
+ def description_to_json(model, doc)
1991
+ doc["description"] = "JSON Description: #{model.description}"
1992
1992
  end
1993
1993
 
1994
- def description_from_json(_model, doc)
1995
- doc["description"].sub(/^JSON Description: /, "")
1994
+ def description_from_json(model, value)
1995
+ model.description = value.sub(/^JSON Description: /, "")
1996
1996
  end
1997
1997
 
1998
- def name_to_xml(_model, value)
1999
- "XML Masterpiece: #{value}"
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(_model, value)
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(_model, value)
2007
- value.upcase
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(_model, value)
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(_model, value)
2015
- "XML Description: #{value}"
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(_model, value)
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
- mapped_attrs = apply_mappings(doc.to_h, format)
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(:"to_#{format}") do |instance|
94
- unless instance.is_a?(model)
95
- msg = "argument is a '#{instance.class}' but should be a '#{model}'"
96
- raise Lutaml::Model::IncorrectModelError, msg
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
- hash = hash_representation(instance, format)
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
- value = if rule.custom_methods[:to]
124
- instance.send(rule.custom_methods[:to], instance, instance.send(name))
125
- else
126
- instance.send(name)
127
- end
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.type.serialize(value)
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] = case value
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
- return apply_xml_mapping(doc) if format == :xml
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.each_with_object(Lutaml::Model::MappingHash.new) do |rule, hash|
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.custom_methods[:from]
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
- value = apply_child_mappings(value, rule.child_mappings)
304
-
305
- if attr.collection?
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
- hash[rule.delegate] ||= {}
315
- hash[rule.delegate][rule.to] = value
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
- hash[rule.to] = value
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, caller_class: nil, mixed_content: false)
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
- mapping_hash = Lutaml::Model::MappingHash.new
333
- mapping_hash.item_order = doc.item_order
334
- mapping_hash.ordered = mappings_for(:xml).mixed_content? || mixed_content
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.each_with_object(mapping_hash) do |rule, hash|
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
- value = (value || []).map do |v|
355
- if attr.type <= Serialize
356
- attr.type.apply_xml_mapping(v, caller_class: self, mixed_content: rule.mixed_content)
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 = attr.type.apply_xml_mapping(value, caller_class: self, mixed_content: rule.mixed_content)
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
- mapping_from << rule if rule.custom_methods[:from]
374
-
375
- hash[rule.to] = value
376
- end
377
-
378
- mapping_from.each do |rule|
379
- value = if rule.name.nil?
380
- mapping_hash[rule.to].join("\n").strip
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
- mapping_hash[rule.to] = new.send(rule.custom_methods[:from], mapping_hash, value)
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
- mapping_hash
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, 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
- attr_reader :element_order
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, options)
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, attr.options[:values])
430
+ raise Lutaml::Model::InvalidValueError.new(name, value,
431
+ attr.options[:values])
459
432
  end
460
433
  end
461
434
  end
@@ -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