shale 0.4.0 → 0.7.0
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 +4 -4
- data/CHANGELOG.md +34 -0
- data/LICENSE.txt +1 -1
- data/README.md +449 -40
- data/exe/shaleb +30 -6
- data/lib/shale/adapter/json.rb +3 -3
- data/lib/shale/adapter/nokogiri/document.rb +97 -0
- data/lib/shale/adapter/nokogiri/node.rb +100 -0
- data/lib/shale/adapter/nokogiri.rb +17 -156
- data/lib/shale/adapter/ox/document.rb +90 -0
- data/lib/shale/adapter/ox/node.rb +97 -0
- data/lib/shale/adapter/ox.rb +14 -138
- data/lib/shale/adapter/rexml/document.rb +98 -0
- data/lib/shale/adapter/rexml/node.rb +99 -0
- data/lib/shale/adapter/rexml.rb +14 -154
- data/lib/shale/adapter/toml_rb.rb +34 -0
- data/lib/shale/error.rb +57 -2
- data/lib/shale/mapper.rb +61 -9
- data/lib/shale/mapping/descriptor/dict.rb +12 -1
- data/lib/shale/mapping/descriptor/xml.rb +12 -2
- data/lib/shale/mapping/dict.rb +26 -2
- data/lib/shale/mapping/xml.rb +52 -6
- data/lib/shale/schema/{json_compiler → compiler}/boolean.rb +1 -1
- data/lib/shale/schema/{json_compiler/object.rb → compiler/complex.rb} +11 -8
- data/lib/shale/schema/{json_compiler → compiler}/date.rb +1 -1
- data/lib/shale/schema/{json_compiler → compiler}/float.rb +1 -1
- data/lib/shale/schema/{json_compiler → compiler}/integer.rb +1 -1
- data/lib/shale/schema/{json_compiler → compiler}/property.rb +6 -6
- data/lib/shale/schema/{json_compiler → compiler}/string.rb +1 -1
- data/lib/shale/schema/{json_compiler → compiler}/time.rb +1 -1
- data/lib/shale/schema/compiler/value.rb +21 -0
- data/lib/shale/schema/compiler/xml_complex.rb +50 -0
- data/lib/shale/schema/compiler/xml_property.rb +73 -0
- data/lib/shale/schema/json_compiler.rb +32 -34
- data/lib/shale/schema/json_generator.rb +4 -6
- data/lib/shale/schema/xml_compiler.rb +919 -0
- data/lib/shale/schema/xml_generator/import.rb +2 -2
- data/lib/shale/schema/xml_generator.rb +11 -13
- data/lib/shale/schema.rb +16 -0
- data/lib/shale/type/complex.rb +763 -0
- data/lib/shale/type/value.rb +38 -9
- data/lib/shale/utils.rb +42 -7
- data/lib/shale/version.rb +1 -1
- data/lib/shale.rb +22 -19
- data/shale.gemspec +3 -3
- metadata +26 -17
- data/lib/shale/schema/json_compiler/utils.rb +0 -52
- data/lib/shale/schema/json_compiler/value.rb +0 -13
- data/lib/shale/type/composite.rb +0 -331
@@ -0,0 +1,763 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../error'
|
4
|
+
require_relative 'value'
|
5
|
+
|
6
|
+
module Shale
|
7
|
+
module Type
|
8
|
+
# Build complex object. Don't use it directly.
|
9
|
+
# It serves as a base type class for @see Shale::Mapper
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
class Complex < Value
|
13
|
+
class << self
|
14
|
+
%i[hash json yaml toml].each do |format|
|
15
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
16
|
+
# Convert Hash to Object using Hash/JSON/YAML/TOML mapping
|
17
|
+
#
|
18
|
+
# @param [Hash] hash Hash to convert
|
19
|
+
# @param [Array<Symbol>] only
|
20
|
+
# @param [Array<Symbol>] except
|
21
|
+
# @param [any] context
|
22
|
+
#
|
23
|
+
# @return [model instance]
|
24
|
+
#
|
25
|
+
# @api public
|
26
|
+
def of_#{format}(hash, only: nil, except: nil, context: nil)
|
27
|
+
instance = model.new
|
28
|
+
|
29
|
+
attributes
|
30
|
+
.values
|
31
|
+
.select { |attr| attr.default }
|
32
|
+
.each { |attr| instance.send(attr.setter, attr.default.call) }
|
33
|
+
|
34
|
+
mapping_keys = #{format}_mapping.keys
|
35
|
+
|
36
|
+
only = to_partial_render_attributes(only)
|
37
|
+
except = to_partial_render_attributes(except)
|
38
|
+
|
39
|
+
hash.each do |key, value|
|
40
|
+
mapping = mapping_keys[key]
|
41
|
+
next unless mapping
|
42
|
+
|
43
|
+
if mapping.method_from
|
44
|
+
mapper = new
|
45
|
+
|
46
|
+
if mapper.method(mapping.method_from).arity == 3
|
47
|
+
mapper.send(mapping.method_from, instance, value, context)
|
48
|
+
else
|
49
|
+
mapper.send(mapping.method_from, instance, value)
|
50
|
+
end
|
51
|
+
else
|
52
|
+
attribute = attributes[mapping.attribute]
|
53
|
+
next unless attribute
|
54
|
+
|
55
|
+
if only
|
56
|
+
attribute_only = only[attribute.name]
|
57
|
+
next unless only.key?(attribute.name)
|
58
|
+
end
|
59
|
+
|
60
|
+
if except
|
61
|
+
attribute_except = except[attribute.name]
|
62
|
+
next if except.key?(attribute.name) && attribute_except.nil?
|
63
|
+
end
|
64
|
+
|
65
|
+
if value.nil?
|
66
|
+
instance.send(attribute.setter, nil)
|
67
|
+
elsif attribute.collection?
|
68
|
+
[*value].each do |val|
|
69
|
+
if val
|
70
|
+
val = attribute.type.of_#{format}(
|
71
|
+
val,
|
72
|
+
only: attribute_only,
|
73
|
+
except: attribute_except,
|
74
|
+
context: context
|
75
|
+
)
|
76
|
+
end
|
77
|
+
|
78
|
+
instance.send(attribute.name) << attribute.type.cast(val)
|
79
|
+
end
|
80
|
+
else
|
81
|
+
val = attribute.type.of_#{format}(
|
82
|
+
value,
|
83
|
+
only: attribute_only,
|
84
|
+
except: attribute_except,
|
85
|
+
context: context
|
86
|
+
)
|
87
|
+
instance.send(attribute.setter, attribute.type.cast(val))
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
instance
|
93
|
+
end
|
94
|
+
|
95
|
+
# Convert Object to Hash using Hash/JSON/YAML/TOML mapping
|
96
|
+
#
|
97
|
+
# @param [any] instance Object to convert
|
98
|
+
# @param [Array<Symbol>] only
|
99
|
+
# @param [Array<Symbol>] except
|
100
|
+
# @param [any] context
|
101
|
+
#
|
102
|
+
# @raise [IncorrectModelError]
|
103
|
+
#
|
104
|
+
# @return [Hash]
|
105
|
+
#
|
106
|
+
# @api public
|
107
|
+
def as_#{format}(instance, only: nil, except: nil, context: nil)
|
108
|
+
unless instance.is_a?(model)
|
109
|
+
msg = "argument is a '\#{instance.class}' but should be a '\#{model}'"
|
110
|
+
raise IncorrectModelError, msg
|
111
|
+
end
|
112
|
+
|
113
|
+
hash = {}
|
114
|
+
|
115
|
+
only = to_partial_render_attributes(only)
|
116
|
+
except = to_partial_render_attributes(except)
|
117
|
+
|
118
|
+
#{format}_mapping.keys.each_value do |mapping|
|
119
|
+
if mapping.method_to
|
120
|
+
mapper = new
|
121
|
+
|
122
|
+
if mapper.method(mapping.method_to).arity == 3
|
123
|
+
mapper.send(mapping.method_to, instance, hash, context)
|
124
|
+
else
|
125
|
+
mapper.send(mapping.method_to, instance, hash)
|
126
|
+
end
|
127
|
+
else
|
128
|
+
attribute = attributes[mapping.attribute]
|
129
|
+
next unless attribute
|
130
|
+
|
131
|
+
if only
|
132
|
+
attribute_only = only[attribute.name]
|
133
|
+
next unless only.key?(attribute.name)
|
134
|
+
end
|
135
|
+
|
136
|
+
if except
|
137
|
+
attribute_except = except[attribute.name]
|
138
|
+
next if except.key?(attribute.name) && attribute_except.nil?
|
139
|
+
end
|
140
|
+
|
141
|
+
value = instance.send(attribute.name)
|
142
|
+
|
143
|
+
if value.nil?
|
144
|
+
hash[mapping.name] = nil if mapping.render_nil?
|
145
|
+
elsif attribute.collection?
|
146
|
+
hash[mapping.name] = [*value].map do |val|
|
147
|
+
if val
|
148
|
+
attribute.type.as_#{format}(
|
149
|
+
val,
|
150
|
+
only: attribute_only,
|
151
|
+
except: attribute_except,
|
152
|
+
context: context
|
153
|
+
)
|
154
|
+
else
|
155
|
+
val
|
156
|
+
end
|
157
|
+
end
|
158
|
+
else
|
159
|
+
hash[mapping.name] = attribute.type.as_#{format}(
|
160
|
+
value,
|
161
|
+
only: attribute_only,
|
162
|
+
except: attribute_except,
|
163
|
+
context: context
|
164
|
+
)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
hash
|
170
|
+
end
|
171
|
+
RUBY
|
172
|
+
end
|
173
|
+
|
174
|
+
alias from_hash of_hash
|
175
|
+
|
176
|
+
alias to_hash as_hash
|
177
|
+
|
178
|
+
# Convert JSON to Object
|
179
|
+
#
|
180
|
+
# @param [String] json JSON to convert
|
181
|
+
# @param [Array<Symbol>] only
|
182
|
+
# @param [Array<Symbol>] except
|
183
|
+
# @param [any] context
|
184
|
+
#
|
185
|
+
# @return [model instance]
|
186
|
+
#
|
187
|
+
# @api public
|
188
|
+
def from_json(json, only: nil, except: nil, context: nil)
|
189
|
+
of_json(
|
190
|
+
Shale.json_adapter.load(json),
|
191
|
+
only: only,
|
192
|
+
except: except,
|
193
|
+
context: context
|
194
|
+
)
|
195
|
+
end
|
196
|
+
|
197
|
+
# Convert Object to JSON
|
198
|
+
#
|
199
|
+
# @param [model instance] instance Object to convert
|
200
|
+
# @param [Array<Symbol>] only
|
201
|
+
# @param [Array<Symbol>] except
|
202
|
+
# @param [any] context
|
203
|
+
# @param [true, false] pretty
|
204
|
+
#
|
205
|
+
# @return [String]
|
206
|
+
#
|
207
|
+
# @api public
|
208
|
+
def to_json(instance, only: nil, except: nil, context: nil, pretty: false)
|
209
|
+
Shale.json_adapter.dump(
|
210
|
+
as_json(instance, only: only, except: except, context: context),
|
211
|
+
pretty: pretty
|
212
|
+
)
|
213
|
+
end
|
214
|
+
|
215
|
+
# Convert YAML to Object
|
216
|
+
#
|
217
|
+
# @param [String] yaml YAML to convert
|
218
|
+
# @param [Array<Symbol>] only
|
219
|
+
# @param [Array<Symbol>] except
|
220
|
+
# @param [any] context
|
221
|
+
#
|
222
|
+
# @return [model instance]
|
223
|
+
#
|
224
|
+
# @api public
|
225
|
+
def from_yaml(yaml, only: nil, except: nil, context: nil)
|
226
|
+
of_yaml(
|
227
|
+
Shale.yaml_adapter.load(yaml),
|
228
|
+
only: only,
|
229
|
+
except: except,
|
230
|
+
context: context
|
231
|
+
)
|
232
|
+
end
|
233
|
+
|
234
|
+
# Convert Object to YAML
|
235
|
+
#
|
236
|
+
# @param [model instance] instance Object to convert
|
237
|
+
# @param [Array<Symbol>] only
|
238
|
+
# @param [Array<Symbol>] except
|
239
|
+
# @param [any] context
|
240
|
+
#
|
241
|
+
# @return [String]
|
242
|
+
#
|
243
|
+
# @api public
|
244
|
+
def to_yaml(instance, only: nil, except: nil, context: nil)
|
245
|
+
Shale.yaml_adapter.dump(
|
246
|
+
as_yaml(instance, only: only, except: except, context: context)
|
247
|
+
)
|
248
|
+
end
|
249
|
+
|
250
|
+
# Convert TOML to Object
|
251
|
+
#
|
252
|
+
# @param [String] toml TOML to convert
|
253
|
+
# @param [Array<Symbol>] only
|
254
|
+
# @param [Array<Symbol>] except
|
255
|
+
# @param [any] context
|
256
|
+
#
|
257
|
+
# @return [model instance]
|
258
|
+
#
|
259
|
+
# @api public
|
260
|
+
def from_toml(toml, only: nil, except: nil, context: nil)
|
261
|
+
validate_toml_adapter
|
262
|
+
of_toml(
|
263
|
+
Shale.toml_adapter.load(toml),
|
264
|
+
only: only,
|
265
|
+
except: except,
|
266
|
+
context: context
|
267
|
+
)
|
268
|
+
end
|
269
|
+
|
270
|
+
# Convert Object to TOML
|
271
|
+
#
|
272
|
+
# @param [model instance] instance Object to convert
|
273
|
+
# @param [Array<Symbol>] only
|
274
|
+
# @param [Array<Symbol>] except
|
275
|
+
# @param [any] context
|
276
|
+
#
|
277
|
+
# @return [String]
|
278
|
+
#
|
279
|
+
# @api public
|
280
|
+
def to_toml(instance, only: nil, except: nil, context: nil)
|
281
|
+
validate_toml_adapter
|
282
|
+
Shale.toml_adapter.dump(
|
283
|
+
as_toml(instance, only: only, except: except, context: context)
|
284
|
+
)
|
285
|
+
end
|
286
|
+
|
287
|
+
# Convert XML document to Object
|
288
|
+
#
|
289
|
+
# @param [Shale::Adapter::<XML adapter>::Node] element
|
290
|
+
# @param [Array<Symbol>] only
|
291
|
+
# @param [Array<Symbol>] except
|
292
|
+
# @param [any] context
|
293
|
+
#
|
294
|
+
# @return [model instance]
|
295
|
+
#
|
296
|
+
# @api public
|
297
|
+
def of_xml(element, only: nil, except: nil, context: nil)
|
298
|
+
instance = model.new
|
299
|
+
|
300
|
+
attributes
|
301
|
+
.values
|
302
|
+
.select { |attr| attr.default }
|
303
|
+
.each { |attr| instance.send(attr.setter, attr.default.call) }
|
304
|
+
|
305
|
+
only = to_partial_render_attributes(only)
|
306
|
+
except = to_partial_render_attributes(except)
|
307
|
+
|
308
|
+
element.attributes.each do |key, value|
|
309
|
+
mapping = xml_mapping.attributes[key.to_s]
|
310
|
+
next unless mapping
|
311
|
+
|
312
|
+
if mapping.method_from
|
313
|
+
mapper = new
|
314
|
+
|
315
|
+
if mapper.method(mapping.method_from).arity == 3
|
316
|
+
mapper.send(mapping.method_from, instance, value, context)
|
317
|
+
else
|
318
|
+
mapper.send(mapping.method_from, instance, value)
|
319
|
+
end
|
320
|
+
else
|
321
|
+
attribute = attributes[mapping.attribute]
|
322
|
+
next unless attribute
|
323
|
+
|
324
|
+
next if only && !only.key?(attribute.name)
|
325
|
+
next if except&.key?(attribute.name)
|
326
|
+
|
327
|
+
if attribute.collection?
|
328
|
+
instance.send(attribute.name) << attribute.type.cast(value)
|
329
|
+
else
|
330
|
+
instance.send(attribute.setter, attribute.type.cast(value))
|
331
|
+
end
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
content_mapping = xml_mapping.content
|
336
|
+
|
337
|
+
if content_mapping
|
338
|
+
if content_mapping.method_from
|
339
|
+
mapper = new
|
340
|
+
|
341
|
+
if mapper.method(content_mapping.method_from).arity == 3
|
342
|
+
mapper.send(content_mapping.method_from, instance, element, context)
|
343
|
+
else
|
344
|
+
mapper.send(content_mapping.method_from, instance, element)
|
345
|
+
end
|
346
|
+
else
|
347
|
+
attribute = attributes[content_mapping.attribute]
|
348
|
+
|
349
|
+
if attribute
|
350
|
+
skip = false
|
351
|
+
|
352
|
+
# rubocop:disable Metrics/BlockNesting
|
353
|
+
skip = true if only && !only.key?(attribute.name)
|
354
|
+
skip = true if except&.key?(attribute.name)
|
355
|
+
|
356
|
+
unless skip
|
357
|
+
value = attribute.type.of_xml(element)
|
358
|
+
instance.send(attribute.setter, attribute.type.cast(value))
|
359
|
+
end
|
360
|
+
# rubocop:enable Metrics/BlockNesting
|
361
|
+
end
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
element.children.each do |node|
|
366
|
+
mapping = xml_mapping.elements[node.name]
|
367
|
+
next unless mapping
|
368
|
+
|
369
|
+
if mapping.method_from
|
370
|
+
mapper = new
|
371
|
+
|
372
|
+
if mapper.method(mapping.method_from).arity == 3
|
373
|
+
mapper.send(mapping.method_from, instance, node, context)
|
374
|
+
else
|
375
|
+
mapper.send(mapping.method_from, instance, node)
|
376
|
+
end
|
377
|
+
else
|
378
|
+
attribute = attributes[mapping.attribute]
|
379
|
+
next unless attribute
|
380
|
+
|
381
|
+
if only
|
382
|
+
attribute_only = only[attribute.name]
|
383
|
+
next unless only.key?(attribute.name)
|
384
|
+
end
|
385
|
+
|
386
|
+
if except
|
387
|
+
attribute_except = except[attribute.name]
|
388
|
+
next if except.key?(attribute.name) && attribute_except.nil?
|
389
|
+
end
|
390
|
+
|
391
|
+
value = attribute.type.of_xml(
|
392
|
+
node,
|
393
|
+
only: attribute_only,
|
394
|
+
except: attribute_except,
|
395
|
+
context: context
|
396
|
+
)
|
397
|
+
|
398
|
+
if attribute.collection?
|
399
|
+
instance.send(attribute.name) << attribute.type.cast(value)
|
400
|
+
else
|
401
|
+
instance.send(attribute.setter, attribute.type.cast(value))
|
402
|
+
end
|
403
|
+
end
|
404
|
+
end
|
405
|
+
|
406
|
+
instance
|
407
|
+
end
|
408
|
+
|
409
|
+
# Convert XML to Object
|
410
|
+
#
|
411
|
+
# @param [String] xml XML to convert
|
412
|
+
# @param [Array<Symbol>] only
|
413
|
+
# @param [Array<Symbol>] except
|
414
|
+
# @param [any] context
|
415
|
+
#
|
416
|
+
# @raise [AdapterError]
|
417
|
+
#
|
418
|
+
# @return [model instance]
|
419
|
+
#
|
420
|
+
# @api public
|
421
|
+
def from_xml(xml, only: nil, except: nil, context: nil)
|
422
|
+
validate_xml_adapter
|
423
|
+
of_xml(
|
424
|
+
Shale.xml_adapter.load(xml),
|
425
|
+
only: only,
|
426
|
+
except: except,
|
427
|
+
context: context
|
428
|
+
)
|
429
|
+
end
|
430
|
+
|
431
|
+
# Convert Object to XML document
|
432
|
+
#
|
433
|
+
# @param [any] instance Object to convert
|
434
|
+
# @param [String, nil] node_name XML node name
|
435
|
+
# @param [Shale::Adapter::<xml adapter>::Document, nil] doc Object to convert
|
436
|
+
# @param [Array<Symbol>] only
|
437
|
+
# @param [Array<Symbol>] except
|
438
|
+
# @param [any] context
|
439
|
+
#
|
440
|
+
# @raise [IncorrectModelError]
|
441
|
+
#
|
442
|
+
# @return [::REXML::Document, ::Nokogiri::Document, ::Ox::Document]
|
443
|
+
#
|
444
|
+
# @api public
|
445
|
+
def as_xml(
|
446
|
+
instance,
|
447
|
+
node_name = nil,
|
448
|
+
doc = nil,
|
449
|
+
_cdata = nil,
|
450
|
+
only: nil,
|
451
|
+
except: nil,
|
452
|
+
context: nil
|
453
|
+
)
|
454
|
+
unless instance.is_a?(model)
|
455
|
+
msg = "argument is a '#{instance.class}' but should be a '#{model}'"
|
456
|
+
raise IncorrectModelError, msg
|
457
|
+
end
|
458
|
+
|
459
|
+
unless doc
|
460
|
+
doc = Shale.xml_adapter.create_document
|
461
|
+
|
462
|
+
element = as_xml(
|
463
|
+
instance,
|
464
|
+
xml_mapping.prefixed_root,
|
465
|
+
doc,
|
466
|
+
only: only,
|
467
|
+
except: except,
|
468
|
+
context: context
|
469
|
+
)
|
470
|
+
doc.add_element(doc.doc, element)
|
471
|
+
|
472
|
+
return doc.doc
|
473
|
+
end
|
474
|
+
|
475
|
+
element = doc.create_element(node_name)
|
476
|
+
|
477
|
+
doc.add_namespace(
|
478
|
+
xml_mapping.default_namespace.prefix,
|
479
|
+
xml_mapping.default_namespace.name
|
480
|
+
)
|
481
|
+
|
482
|
+
only = to_partial_render_attributes(only)
|
483
|
+
except = to_partial_render_attributes(except)
|
484
|
+
|
485
|
+
xml_mapping.attributes.each_value do |mapping|
|
486
|
+
if mapping.method_to
|
487
|
+
mapper = new
|
488
|
+
|
489
|
+
if mapper.method(mapping.method_to).arity == 4
|
490
|
+
mapper.send(mapping.method_to, instance, element, doc, context)
|
491
|
+
else
|
492
|
+
mapper.send(mapping.method_to, instance, element, doc)
|
493
|
+
end
|
494
|
+
else
|
495
|
+
attribute = attributes[mapping.attribute]
|
496
|
+
next unless attribute
|
497
|
+
|
498
|
+
next if only && !only.key?(attribute.name)
|
499
|
+
next if except&.key?(attribute.name)
|
500
|
+
|
501
|
+
value = instance.send(attribute.name)
|
502
|
+
|
503
|
+
if mapping.render_nil? || !value.nil?
|
504
|
+
doc.add_namespace(mapping.namespace.prefix, mapping.namespace.name)
|
505
|
+
doc.add_attribute(element, mapping.prefixed_name, value)
|
506
|
+
end
|
507
|
+
end
|
508
|
+
end
|
509
|
+
|
510
|
+
content_mapping = xml_mapping.content
|
511
|
+
|
512
|
+
if content_mapping
|
513
|
+
if content_mapping.method_to
|
514
|
+
mapper = new
|
515
|
+
|
516
|
+
if mapper.method(content_mapping.method_to).arity == 4
|
517
|
+
mapper.send(content_mapping.method_to, instance, element, doc, context)
|
518
|
+
else
|
519
|
+
mapper.send(content_mapping.method_to, instance, element, doc)
|
520
|
+
end
|
521
|
+
else
|
522
|
+
attribute = attributes[content_mapping.attribute]
|
523
|
+
|
524
|
+
if attribute
|
525
|
+
skip = false
|
526
|
+
|
527
|
+
# rubocop:disable Metrics/BlockNesting
|
528
|
+
skip = true if only && !only.key?(attribute.name)
|
529
|
+
skip = true if except&.key?(attribute.name)
|
530
|
+
|
531
|
+
unless skip
|
532
|
+
value = instance.send(attribute.name)
|
533
|
+
|
534
|
+
if content_mapping.cdata
|
535
|
+
doc.create_cdata(value.to_s, element)
|
536
|
+
else
|
537
|
+
doc.add_text(element, value.to_s)
|
538
|
+
end
|
539
|
+
end
|
540
|
+
# rubocop:enable Metrics/BlockNesting
|
541
|
+
end
|
542
|
+
end
|
543
|
+
end
|
544
|
+
|
545
|
+
xml_mapping.elements.each_value do |mapping|
|
546
|
+
if mapping.method_to
|
547
|
+
mapper = new
|
548
|
+
|
549
|
+
if mapper.method(mapping.method_to).arity == 4
|
550
|
+
mapper.send(mapping.method_to, instance, element, doc, context)
|
551
|
+
else
|
552
|
+
mapper.send(mapping.method_to, instance, element, doc)
|
553
|
+
end
|
554
|
+
else
|
555
|
+
attribute = attributes[mapping.attribute]
|
556
|
+
next unless attribute
|
557
|
+
|
558
|
+
if only
|
559
|
+
attribute_only = only[attribute.name]
|
560
|
+
next unless only.key?(attribute.name)
|
561
|
+
end
|
562
|
+
|
563
|
+
if except
|
564
|
+
attribute_except = except[attribute.name]
|
565
|
+
next if except.key?(attribute.name) && attribute_except.nil?
|
566
|
+
end
|
567
|
+
|
568
|
+
value = instance.send(attribute.name)
|
569
|
+
|
570
|
+
if mapping.render_nil? || !value.nil?
|
571
|
+
doc.add_namespace(mapping.namespace.prefix, mapping.namespace.name)
|
572
|
+
end
|
573
|
+
|
574
|
+
if value.nil?
|
575
|
+
if mapping.render_nil?
|
576
|
+
child = doc.create_element(mapping.prefixed_name)
|
577
|
+
doc.add_element(element, child)
|
578
|
+
end
|
579
|
+
elsif attribute.collection?
|
580
|
+
[*value].each do |v|
|
581
|
+
next if v.nil?
|
582
|
+
child = attribute.type.as_xml(
|
583
|
+
v,
|
584
|
+
mapping.prefixed_name,
|
585
|
+
doc,
|
586
|
+
mapping.cdata,
|
587
|
+
only: attribute_only,
|
588
|
+
except: attribute_except,
|
589
|
+
context: context
|
590
|
+
)
|
591
|
+
doc.add_element(element, child)
|
592
|
+
end
|
593
|
+
else
|
594
|
+
child = attribute.type.as_xml(
|
595
|
+
value,
|
596
|
+
mapping.prefixed_name,
|
597
|
+
doc,
|
598
|
+
mapping.cdata,
|
599
|
+
only: attribute_only,
|
600
|
+
except: attribute_except,
|
601
|
+
context: context
|
602
|
+
)
|
603
|
+
doc.add_element(element, child)
|
604
|
+
end
|
605
|
+
end
|
606
|
+
end
|
607
|
+
|
608
|
+
element
|
609
|
+
end
|
610
|
+
|
611
|
+
# Convert Object to XML
|
612
|
+
#
|
613
|
+
# @param [model instance] instance Object to convert
|
614
|
+
# @param [Array<Symbol>] only
|
615
|
+
# @param [Array<Symbol>] except
|
616
|
+
# @param [any] context
|
617
|
+
# @param [true, false] pretty
|
618
|
+
# @param [true, false] declaration
|
619
|
+
#
|
620
|
+
# @raise [AdapterError]
|
621
|
+
#
|
622
|
+
# @return [String]
|
623
|
+
#
|
624
|
+
# @api public
|
625
|
+
def to_xml(
|
626
|
+
instance,
|
627
|
+
only: nil,
|
628
|
+
except: nil,
|
629
|
+
context: nil,
|
630
|
+
pretty: false,
|
631
|
+
declaration: false
|
632
|
+
)
|
633
|
+
validate_xml_adapter
|
634
|
+
Shale.xml_adapter.dump(
|
635
|
+
as_xml(instance, only: only, except: except, context: context),
|
636
|
+
pretty: pretty,
|
637
|
+
declaration: declaration
|
638
|
+
)
|
639
|
+
end
|
640
|
+
|
641
|
+
private
|
642
|
+
|
643
|
+
# Validate TOML adapter
|
644
|
+
#
|
645
|
+
# @raise [AdapterError]
|
646
|
+
#
|
647
|
+
# @api private
|
648
|
+
def validate_toml_adapter
|
649
|
+
raise AdapterError, TOML_ADAPTER_NOT_SET_MESSAGE unless Shale.toml_adapter
|
650
|
+
end
|
651
|
+
|
652
|
+
# Validate XML adapter
|
653
|
+
#
|
654
|
+
# @raise [AdapterError]
|
655
|
+
#
|
656
|
+
# @api private
|
657
|
+
def validate_xml_adapter
|
658
|
+
raise AdapterError, XML_ADAPTER_NOT_SET_MESSAGE unless Shale.xml_adapter
|
659
|
+
end
|
660
|
+
|
661
|
+
# Convert array with attributes to a hash
|
662
|
+
#
|
663
|
+
# @param [Array] ary
|
664
|
+
#
|
665
|
+
# @return [Hash, nil]
|
666
|
+
#
|
667
|
+
# @api private
|
668
|
+
def to_partial_render_attributes(ary)
|
669
|
+
return unless ary
|
670
|
+
|
671
|
+
ary.each_with_object([]) do |e, obj|
|
672
|
+
if e.is_a?(Hash)
|
673
|
+
obj.push(*e.to_a)
|
674
|
+
else
|
675
|
+
obj.push([e, nil])
|
676
|
+
end
|
677
|
+
end.to_h
|
678
|
+
end
|
679
|
+
end
|
680
|
+
|
681
|
+
# Convert Object to Hash
|
682
|
+
#
|
683
|
+
# @param [Array<Symbol>] only
|
684
|
+
# @param [Array<Symbol>] except
|
685
|
+
# @param [any] context
|
686
|
+
#
|
687
|
+
# @return [Hash]
|
688
|
+
#
|
689
|
+
# @api public
|
690
|
+
def to_hash(only: nil, except: nil, context: nil)
|
691
|
+
self.class.to_hash(self, only: only, except: except, context: context)
|
692
|
+
end
|
693
|
+
|
694
|
+
# Convert Object to JSON
|
695
|
+
#
|
696
|
+
# @param [Array<Symbol>] only
|
697
|
+
# @param [Array<Symbol>] except
|
698
|
+
# @param [any] context
|
699
|
+
# @param [true, false] pretty
|
700
|
+
#
|
701
|
+
# @return [String]
|
702
|
+
#
|
703
|
+
# @api public
|
704
|
+
def to_json(only: nil, except: nil, context: nil, pretty: false)
|
705
|
+
self.class.to_json(
|
706
|
+
self,
|
707
|
+
only: only,
|
708
|
+
except: except,
|
709
|
+
context: context,
|
710
|
+
pretty: pretty
|
711
|
+
)
|
712
|
+
end
|
713
|
+
|
714
|
+
# Convert Object to YAML
|
715
|
+
#
|
716
|
+
# @param [Array<Symbol>] only
|
717
|
+
# @param [Array<Symbol>] except
|
718
|
+
# @param [any] context
|
719
|
+
#
|
720
|
+
# @return [String]
|
721
|
+
#
|
722
|
+
# @api public
|
723
|
+
def to_yaml(only: nil, except: nil, context: nil)
|
724
|
+
self.class.to_yaml(self, only: only, except: except, context: context)
|
725
|
+
end
|
726
|
+
|
727
|
+
# Convert Object to TOML
|
728
|
+
#
|
729
|
+
# @param [Array<Symbol>] only
|
730
|
+
# @param [Array<Symbol>] except
|
731
|
+
# @param [any] context
|
732
|
+
#
|
733
|
+
# @return [String]
|
734
|
+
#
|
735
|
+
# @api public
|
736
|
+
def to_toml(only: nil, except: nil, context: nil)
|
737
|
+
self.class.to_toml(self, only: only, except: except, context: context)
|
738
|
+
end
|
739
|
+
|
740
|
+
# Convert Object to XML
|
741
|
+
#
|
742
|
+
# @param [Array<Symbol>] only
|
743
|
+
# @param [Array<Symbol>] except
|
744
|
+
# @param [any] context
|
745
|
+
# @param [true, false] pretty
|
746
|
+
# @param [true, false] declaration
|
747
|
+
#
|
748
|
+
# @return [String]
|
749
|
+
#
|
750
|
+
# @api public
|
751
|
+
def to_xml(only: nil, except: nil, context: nil, pretty: false, declaration: false)
|
752
|
+
self.class.to_xml(
|
753
|
+
self,
|
754
|
+
only: only,
|
755
|
+
except: except,
|
756
|
+
context: context,
|
757
|
+
pretty: pretty,
|
758
|
+
declaration: declaration
|
759
|
+
)
|
760
|
+
end
|
761
|
+
end
|
762
|
+
end
|
763
|
+
end
|