lutaml-model 0.5.4 → 0.6.0
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 +58 -21
- data/Gemfile +1 -0
- data/README.adoc +1112 -264
- data/lib/lutaml/model/attribute.rb +33 -10
- data/lib/lutaml/model/choice.rb +56 -0
- data/lib/lutaml/model/config.rb +1 -0
- data/lib/lutaml/model/error/choice_lower_bound_error.rb +9 -0
- data/lib/lutaml/model/error/choice_upper_bound_error.rb +9 -0
- data/lib/lutaml/model/error/import_model_with_root_error.rb +9 -0
- data/lib/lutaml/model/error/incorrect_sequence_error.rb +9 -0
- data/lib/lutaml/model/error/invalid_choice_range_error.rb +20 -0
- data/lib/lutaml/model/error/no_root_mapping_error.rb +9 -0
- data/lib/lutaml/model/error/no_root_namespace_error.rb +9 -0
- data/lib/lutaml/model/error/unknown_sequence_mapping_error.rb +9 -0
- data/lib/lutaml/model/error.rb +8 -0
- data/lib/lutaml/model/json_adapter/standard_json_adapter.rb +6 -1
- data/lib/lutaml/model/key_value_mapping.rb +3 -1
- data/lib/lutaml/model/key_value_mapping_rule.rb +4 -2
- data/lib/lutaml/model/liquefiable.rb +59 -0
- data/lib/lutaml/model/mapping_hash.rb +1 -1
- data/lib/lutaml/model/mapping_rule.rb +15 -2
- data/lib/lutaml/model/schema/xml_compiler.rb +68 -26
- data/lib/lutaml/model/schema_location.rb +7 -0
- data/lib/lutaml/model/sequence.rb +71 -0
- data/lib/lutaml/model/serialize.rb +125 -35
- data/lib/lutaml/model/type/decimal.rb +0 -4
- data/lib/lutaml/model/type/time.rb +3 -3
- data/lib/lutaml/model/utils.rb +19 -15
- data/lib/lutaml/model/validation.rb +12 -1
- data/lib/lutaml/model/version.rb +1 -1
- data/lib/lutaml/model/xml_adapter/builder/oga.rb +10 -7
- data/lib/lutaml/model/xml_adapter/builder/ox.rb +20 -13
- data/lib/lutaml/model/xml_adapter/element.rb +32 -0
- data/lib/lutaml/model/xml_adapter/nokogiri_adapter.rb +8 -8
- data/lib/lutaml/model/xml_adapter/oga/element.rb +14 -13
- data/lib/lutaml/model/xml_adapter/oga_adapter.rb +86 -19
- data/lib/lutaml/model/xml_adapter/ox_adapter.rb +19 -15
- data/lib/lutaml/model/xml_adapter/xml_document.rb +74 -13
- data/lib/lutaml/model/xml_adapter/xml_element.rb +57 -3
- data/lib/lutaml/model/xml_mapping.rb +49 -7
- data/lib/lutaml/model/xml_mapping_rule.rb +8 -3
- data/lib/lutaml/model.rb +1 -0
- data/lutaml-model.gemspec +5 -0
- data/spec/benchmarks/xml_parsing_benchmark_spec.rb +75 -0
- data/spec/ceramic_spec.rb +39 -0
- data/spec/fixtures/ceramic.rb +23 -0
- data/spec/fixtures/xml/address_example_260.xsd +9 -0
- data/spec/fixtures/xml/user.xsd +10 -0
- data/spec/lutaml/model/cdata_spec.rb +4 -5
- data/spec/lutaml/model/choice_spec.rb +168 -0
- data/spec/lutaml/model/collection_spec.rb +1 -1
- data/spec/lutaml/model/custom_model_spec.rb +6 -7
- data/spec/lutaml/model/custom_serialization_spec.rb +74 -2
- data/spec/lutaml/model/defaults_spec.rb +3 -1
- data/spec/lutaml/model/delegation_spec.rb +7 -5
- data/spec/lutaml/model/enum_spec.rb +35 -0
- data/spec/lutaml/model/group_spec.rb +160 -0
- data/spec/lutaml/model/inheritance_spec.rb +25 -0
- data/spec/lutaml/model/liquefiable_spec.rb +121 -0
- data/spec/lutaml/model/mixed_content_spec.rb +80 -41
- data/spec/lutaml/model/multiple_mapping_spec.rb +22 -10
- data/spec/lutaml/model/schema/xml_compiler_spec.rb +218 -25
- data/spec/lutaml/model/sequence_spec.rb +216 -0
- data/spec/lutaml/model/transformation_spec.rb +230 -0
- data/spec/lutaml/model/type_spec.rb +138 -31
- data/spec/lutaml/model/utils_spec.rb +32 -0
- data/spec/lutaml/model/xml_adapter/oga_adapter_spec.rb +11 -7
- data/spec/lutaml/model/xml_mapping_rule_spec.rb +51 -0
- data/spec/lutaml/model/xml_mapping_spec.rb +143 -112
- metadata +67 -2
@@ -1,7 +1,6 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
require "lutaml/model/schema"
|
3
3
|
require "lutaml/xsd"
|
4
|
-
require "tmpdir"
|
5
4
|
|
6
5
|
RSpec.describe Lutaml::Model::Schema::XmlCompiler do
|
7
6
|
describe ".to_models" do
|
@@ -25,8 +24,8 @@ RSpec.describe Lutaml::Model::Schema::XmlCompiler do
|
|
25
24
|
end
|
26
25
|
|
27
26
|
Dir.mktmpdir do |dir|
|
28
|
-
it "
|
29
|
-
described_class.to_models(File.read("spec/fixtures/xml/test_schema.xsd"), output_dir: dir)
|
27
|
+
it "creates the model files, requires them, and tests them with valid and invalid xml" do
|
28
|
+
described_class.to_models(File.read("spec/fixtures/xml/test_schema.xsd"), output_dir: dir, create_files: true)
|
30
29
|
expect(File).to exist("#{dir}/ct_math_test.rb")
|
31
30
|
expect(File).to exist("#{dir}/st_integer255.rb")
|
32
31
|
expect(File).to exist("#{dir}/long.rb")
|
@@ -38,20 +37,25 @@ RSpec.describe Lutaml::Model::Schema::XmlCompiler do
|
|
38
37
|
end
|
39
38
|
end
|
40
39
|
|
41
|
-
context "when processing examples from classes generated by valid xml schema" do
|
40
|
+
context "when processing examples from classes/files generated by valid xml schema" do
|
42
41
|
Dir.mktmpdir do |dir|
|
43
42
|
before do
|
44
43
|
described_class.to_models(
|
45
44
|
File.read("spec/fixtures/xml/math_document_schema.xsd"),
|
46
45
|
output_dir: dir,
|
46
|
+
create_files: true,
|
47
47
|
)
|
48
48
|
require_relative "#{dir}/math_document"
|
49
49
|
end
|
50
50
|
|
51
|
-
let(:valid_example)
|
52
|
-
|
51
|
+
let(:valid_example) do
|
52
|
+
File.read("spec/fixtures/xml/valid_math_document.xml")
|
53
|
+
end
|
54
|
+
let(:invalid_example) do
|
55
|
+
File.read("spec/fixtures/xml/invalid_math_document.xml")
|
56
|
+
end
|
53
57
|
|
54
|
-
it "does not raise error with valid example" do
|
58
|
+
it "does not raise error with valid example and creates files" do
|
55
59
|
expect(defined?(MathDocument)).to eq("constant")
|
56
60
|
parsed = MathDocument.from_xml(valid_example)
|
57
61
|
expect(parsed.title).to eql("Example Title")
|
@@ -65,6 +69,100 @@ RSpec.describe Lutaml::Model::Schema::XmlCompiler do
|
|
65
69
|
end
|
66
70
|
end
|
67
71
|
end
|
72
|
+
|
73
|
+
context "when processing example from lutaml-model#260" do
|
74
|
+
Dir.mktmpdir do |dir|
|
75
|
+
before do
|
76
|
+
described_class.to_models(
|
77
|
+
File.read("spec/fixtures/xml/address_example_260.xsd"),
|
78
|
+
output_dir: dir,
|
79
|
+
create_files: true,
|
80
|
+
)
|
81
|
+
require_relative "#{dir}/address"
|
82
|
+
end
|
83
|
+
|
84
|
+
let(:address) do
|
85
|
+
<<~ADD
|
86
|
+
<Address>
|
87
|
+
Oxford Street
|
88
|
+
<City>London</City>
|
89
|
+
<ZIP>E1 6AN</ZIP>
|
90
|
+
</Address>
|
91
|
+
ADD
|
92
|
+
end
|
93
|
+
|
94
|
+
it "matches parsed xml with input" do
|
95
|
+
expect(defined?(Address)).to eq("constant")
|
96
|
+
expect(Address.from_xml(address).to_xml).to be_equivalent_to(address)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context "when classes are generated but files are not created" do
|
102
|
+
let(:schema_classes_hash) do
|
103
|
+
described_class.to_models(
|
104
|
+
File.read("spec/fixtures/xml/user.xsd"),
|
105
|
+
)
|
106
|
+
end
|
107
|
+
|
108
|
+
let(:expected_classes) do
|
109
|
+
[
|
110
|
+
"NonNegativeInteger",
|
111
|
+
"PositiveInteger",
|
112
|
+
"Base64Binary",
|
113
|
+
"UnsignedLong",
|
114
|
+
"UnsignedInt",
|
115
|
+
"HexBinary",
|
116
|
+
"Token",
|
117
|
+
"Long",
|
118
|
+
"User",
|
119
|
+
]
|
120
|
+
end
|
121
|
+
|
122
|
+
it "matches the expected class names of the schema" do
|
123
|
+
expect(schema_classes_hash.keys).to eql(expected_classes)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
context "when classes are generated and loaded but files are not created" do
|
128
|
+
before do
|
129
|
+
described_class.to_models(
|
130
|
+
File.read("spec/fixtures/xml/user.xsd"),
|
131
|
+
load_classes: true,
|
132
|
+
)
|
133
|
+
end
|
134
|
+
|
135
|
+
let(:expected_classes) do
|
136
|
+
%w[
|
137
|
+
NonNegativeInteger
|
138
|
+
PositiveInteger
|
139
|
+
Base64Binary
|
140
|
+
UnsignedLong
|
141
|
+
UnsignedInt
|
142
|
+
HexBinary
|
143
|
+
Token
|
144
|
+
Long
|
145
|
+
User
|
146
|
+
]
|
147
|
+
end
|
148
|
+
|
149
|
+
let(:xml) do
|
150
|
+
<<~XML
|
151
|
+
<User>
|
152
|
+
<id>1112</id>
|
153
|
+
<age>29</age>
|
154
|
+
<token>u9dId901dp13f</token>
|
155
|
+
</User>
|
156
|
+
XML
|
157
|
+
end
|
158
|
+
|
159
|
+
it "matches the expected class names of the schema" do
|
160
|
+
expected_classes.each do |klass|
|
161
|
+
expect(be_const_defined(klass)).to be_truthy
|
162
|
+
end
|
163
|
+
expect(User.from_xml(xml).to_xml).to be_equivalent_to(xml)
|
164
|
+
end
|
165
|
+
end
|
68
166
|
end
|
69
167
|
|
70
168
|
describe "structure setup methods" do
|
@@ -136,7 +234,7 @@ RSpec.describe Lutaml::Model::Schema::XmlCompiler do
|
|
136
234
|
<xsd:attribute name="test_attribute" type="xsd:string"/>
|
137
235
|
<xsd:group name="test_group"/>
|
138
236
|
<xsd:simpleType name="test_simple_type"/>
|
139
|
-
<xsd:complexType name="test_complex_type"/>
|
237
|
+
<xsd:complexType name="test_complex_type" mixed="true"/>
|
140
238
|
<xsd:attributeGroup name="test_attribute_group"/>
|
141
239
|
</xsd:schema>
|
142
240
|
XSD
|
@@ -148,7 +246,7 @@ RSpec.describe Lutaml::Model::Schema::XmlCompiler do
|
|
148
246
|
attributes: { "test_attribute" => { name: "test_attribute", base_class: "xsd:string" } },
|
149
247
|
group_types: { "test_group" => {} },
|
150
248
|
simple_types: { "test_simple_type" => {} },
|
151
|
-
complex_types: { "test_complex_type" => {} },
|
249
|
+
complex_types: { "test_complex_type" => { mixed: true } },
|
152
250
|
attribute_groups: { "test_attribute_group" => {} },
|
153
251
|
}
|
154
252
|
end
|
@@ -260,7 +358,15 @@ RSpec.describe Lutaml::Model::Schema::XmlCompiler do
|
|
260
358
|
ct.attribute_group = [Lutaml::Xsd::AttributeGroup.new(name: "test_attribute_group")]
|
261
359
|
ct.group = [Lutaml::Xsd::Group.new(name: "test_group")]
|
262
360
|
ct.simple_content = [Lutaml::Xsd::SimpleContent.new(name: "test_simple_content")]
|
263
|
-
ct.element_order = [
|
361
|
+
ct.element_order = create_pattern_mapping([
|
362
|
+
["Element", "attribute"],
|
363
|
+
["Element", "sequence"],
|
364
|
+
["Element", "choice"],
|
365
|
+
["Element", "complex_content"],
|
366
|
+
["Element", "attribute_group"],
|
367
|
+
["Element", "group"],
|
368
|
+
["Element", "simple_content"],
|
369
|
+
])
|
264
370
|
end
|
265
371
|
end
|
266
372
|
|
@@ -272,6 +378,7 @@ RSpec.describe Lutaml::Model::Schema::XmlCompiler do
|
|
272
378
|
complex_content: {},
|
273
379
|
attribute_groups: [{}],
|
274
380
|
group: {},
|
381
|
+
mixed: false,
|
275
382
|
simple_content: nil,
|
276
383
|
}
|
277
384
|
end
|
@@ -289,7 +396,7 @@ RSpec.describe Lutaml::Model::Schema::XmlCompiler do
|
|
289
396
|
end
|
290
397
|
|
291
398
|
it "initializes the instance variables with empty MappingHash" do
|
292
|
-
expect(described_class.send(:setup_complex_type, complex_type)).to
|
399
|
+
expect(described_class.send(:setup_complex_type, complex_type)).to eq({ mixed: false })
|
293
400
|
end
|
294
401
|
end
|
295
402
|
end
|
@@ -299,7 +406,7 @@ RSpec.describe Lutaml::Model::Schema::XmlCompiler do
|
|
299
406
|
let(:complex_type) do
|
300
407
|
Lutaml::Xsd::SimpleContent.new.tap do |ct|
|
301
408
|
ct.extension = Lutaml::Xsd::ExtensionSimpleContent.new(base: "test_extension")
|
302
|
-
ct.element_order = ["extension"]
|
409
|
+
ct.element_order = [Lutaml::Model::XmlAdapter::Element.new("Element", "extension")]
|
303
410
|
end
|
304
411
|
end
|
305
412
|
|
@@ -314,7 +421,7 @@ RSpec.describe Lutaml::Model::Schema::XmlCompiler do
|
|
314
421
|
let(:complex_type) do
|
315
422
|
Lutaml::Xsd::SimpleContent.new.tap do |ct|
|
316
423
|
ct.restriction = Lutaml::Xsd::RestrictionSimpleContent.new(base: "test_restriction")
|
317
|
-
ct.element_order = ["restriction"]
|
424
|
+
ct.element_order = [Lutaml::Model::XmlAdapter::Element.new("Element", "restriction")]
|
318
425
|
end
|
319
426
|
end
|
320
427
|
|
@@ -338,7 +445,14 @@ RSpec.describe Lutaml::Model::Schema::XmlCompiler do
|
|
338
445
|
Lutaml::Xsd::Group.new(name: "test_group"),
|
339
446
|
Lutaml::Xsd::Group.new(ref: "test_ref"),
|
340
447
|
]
|
341
|
-
ct.element_order = [
|
448
|
+
ct.element_order = create_pattern_mapping([
|
449
|
+
["Element", "sequence"],
|
450
|
+
["Element", "group"],
|
451
|
+
["Element", "element"],
|
452
|
+
["Element", "choice"],
|
453
|
+
["Element", "element"],
|
454
|
+
["Element", "group"],
|
455
|
+
])
|
342
456
|
end
|
343
457
|
end
|
344
458
|
|
@@ -375,7 +489,10 @@ RSpec.describe Lutaml::Model::Schema::XmlCompiler do
|
|
375
489
|
Lutaml::Xsd::Group.new.tap do |ct|
|
376
490
|
ct.sequence = [Lutaml::Xsd::Sequence.new(name: "test_sequence")]
|
377
491
|
ct.choice = [Lutaml::Xsd::Choice.new(name: "test_choice")]
|
378
|
-
ct.element_order = [
|
492
|
+
ct.element_order = create_pattern_mapping([
|
493
|
+
["Element", "sequence"],
|
494
|
+
["Element", "choice"],
|
495
|
+
])
|
379
496
|
end
|
380
497
|
end
|
381
498
|
|
@@ -407,7 +524,12 @@ RSpec.describe Lutaml::Model::Schema::XmlCompiler do
|
|
407
524
|
ct.sequence = [Lutaml::Xsd::Sequence.new(name: "test_sequence")]
|
408
525
|
ct.choice = [Lutaml::Xsd::Choice.new(name: "test_choice")]
|
409
526
|
ct.group = [Lutaml::Xsd::Group.new(name: "test_group")]
|
410
|
-
ct.element_order = [
|
527
|
+
ct.element_order = create_pattern_mapping([
|
528
|
+
["Element", "sequence"],
|
529
|
+
["Element", "choice"],
|
530
|
+
["Element", "group"],
|
531
|
+
["Element", "element"],
|
532
|
+
])
|
411
533
|
end
|
412
534
|
end
|
413
535
|
|
@@ -516,7 +638,10 @@ RSpec.describe Lutaml::Model::Schema::XmlCompiler do
|
|
516
638
|
Lutaml::Xsd::AttributeGroup.new.tap do |attr_group|
|
517
639
|
attr_group.attribute = [Lutaml::Xsd::Attribute.new(name: "test_name", type: "test_type")]
|
518
640
|
attr_group.attribute_group = [Lutaml::Xsd::AttributeGroup.new(name: "test_name", type: "test_type")]
|
519
|
-
attr_group.element_order = [
|
641
|
+
attr_group.element_order = create_pattern_mapping([
|
642
|
+
["Element", "attribute"],
|
643
|
+
["Element", "attribute_group"],
|
644
|
+
])
|
520
645
|
end
|
521
646
|
end
|
522
647
|
|
@@ -622,7 +747,7 @@ RSpec.describe Lutaml::Model::Schema::XmlCompiler do
|
|
622
747
|
element.min_occurs = 0
|
623
748
|
element.max_occurs = 1
|
624
749
|
element.complex_type = Lutaml::Xsd::ComplexType.new(name: "test_complex_type")
|
625
|
-
element.element_order = ["complex_type"]
|
750
|
+
element.element_order = [Lutaml::Model::XmlAdapter::Element.new("Element", "complex_type")]
|
626
751
|
end
|
627
752
|
end
|
628
753
|
|
@@ -656,11 +781,11 @@ RSpec.describe Lutaml::Model::Schema::XmlCompiler do
|
|
656
781
|
element.type = "test_type"
|
657
782
|
element.name = "test_name"
|
658
783
|
element.complex_type = Lutaml::Xsd::ComplexType.new(name: "test_complex_type")
|
659
|
-
element.element_order = ["complex_type"]
|
784
|
+
element.element_order = [Lutaml::Model::XmlAdapter::Element.new("Element", "complex_type")]
|
660
785
|
end
|
661
786
|
end
|
662
787
|
|
663
|
-
let(:expected_hash) { { type_name: "test_type", element_name: "test_name", complex_type: {} } }
|
788
|
+
let(:expected_hash) { { type_name: "test_type", element_name: "test_name", complex_type: { mixed: false } } }
|
664
789
|
|
665
790
|
it "returns the expected hash" do
|
666
791
|
expect(described_class.send(:setup_element, element)).to eql(expected_hash)
|
@@ -776,7 +901,12 @@ RSpec.describe Lutaml::Model::Schema::XmlCompiler do
|
|
776
901
|
]
|
777
902
|
extension.sequence = Lutaml::Xsd::Sequence.new
|
778
903
|
extension.choice = Lutaml::Xsd::Choice.new
|
779
|
-
extension.element_order = [
|
904
|
+
extension.element_order = create_pattern_mapping([
|
905
|
+
["Element", "attribute"],
|
906
|
+
["Element", "sequence"],
|
907
|
+
["Element", "choice"],
|
908
|
+
["Element", "attribute"],
|
909
|
+
])
|
780
910
|
end
|
781
911
|
end
|
782
912
|
|
@@ -832,12 +962,17 @@ RSpec.describe Lutaml::Model::Schema::XmlCompiler do
|
|
832
962
|
context "when given element contains element_order but no instance relevant elements/instances" do
|
833
963
|
let(:element) do
|
834
964
|
Lutaml::Xsd::Element.new.tap do |element|
|
835
|
-
element.element_order = [
|
965
|
+
element.element_order = create_pattern_mapping([
|
966
|
+
["Element", "annotation"],
|
967
|
+
["Element", "simple_type"],
|
968
|
+
["Element", "complex_type"],
|
969
|
+
["Element", "key"],
|
970
|
+
])
|
836
971
|
end
|
837
972
|
end
|
838
973
|
|
839
974
|
it "raises an error when element_order contains elements that isn't an attribute of the instance" do
|
840
|
-
element.element_order << "test_element"
|
975
|
+
element.element_order << Lutaml::Model::XmlAdapter::Element.new("Element", "test_element")
|
841
976
|
expect { described_class.send(:resolved_element_order, element) }.to raise_error(NoMethodError)
|
842
977
|
end
|
843
978
|
|
@@ -854,7 +989,12 @@ RSpec.describe Lutaml::Model::Schema::XmlCompiler do
|
|
854
989
|
element.simple_type = Lutaml::Xsd::SimpleType.new
|
855
990
|
element.complex_type = Lutaml::Xsd::ComplexType.new
|
856
991
|
element.key = Lutaml::Xsd::Key.new
|
857
|
-
element.element_order = [
|
992
|
+
element.element_order = create_pattern_mapping([
|
993
|
+
["Element", "annotation"],
|
994
|
+
["Element", "simple_type"],
|
995
|
+
["Element", "complex_type"],
|
996
|
+
["Element", "key"],
|
997
|
+
])
|
858
998
|
end
|
859
999
|
end
|
860
1000
|
|
@@ -913,6 +1053,24 @@ RSpec.describe Lutaml::Model::Schema::XmlCompiler do
|
|
913
1053
|
end
|
914
1054
|
end
|
915
1055
|
|
1056
|
+
describe ".resolve_element_class" do
|
1057
|
+
context "when element.type_name is one of the standard classes" do
|
1058
|
+
described_class::DEFAULT_CLASSES.each do |standard_class|
|
1059
|
+
it "returns the element_class value for #{standard_class.capitalize}" do
|
1060
|
+
type_name_hash = to_mapping_hash({ type_name: "xsd:#{standard_class}" })
|
1061
|
+
expect(described_class.send(:resolve_element_class, type_name_hash)).to eql(":#{standard_class}")
|
1062
|
+
end
|
1063
|
+
end
|
1064
|
+
end
|
1065
|
+
|
1066
|
+
context "when element.type_name is not one of the standard classes" do
|
1067
|
+
it "returns the element_class value" do
|
1068
|
+
type_name_hash = to_mapping_hash({ type_name: "test_st_element1" })
|
1069
|
+
expect(described_class.send(:resolve_element_class, type_name_hash)).to eql("TestStElement1")
|
1070
|
+
end
|
1071
|
+
end
|
1072
|
+
end
|
1073
|
+
|
916
1074
|
describe ".resolve_occurs" do
|
917
1075
|
context "when min_occurs and max_occurs are present" do
|
918
1076
|
it "returns the collection: true" do
|
@@ -1392,7 +1550,7 @@ RSpec.describe Lutaml::Model::Schema::XmlCompiler do
|
|
1392
1550
|
end
|
1393
1551
|
|
1394
1552
|
describe ".required_files_elements" do
|
1395
|
-
context "when
|
1553
|
+
context "when given element's data type is not one of standard class" do
|
1396
1554
|
before do
|
1397
1555
|
described_class.instance_variable_set(:@required_files, [])
|
1398
1556
|
described_class.instance_variable_set(:@elements, elements)
|
@@ -1421,10 +1579,45 @@ RSpec.describe Lutaml::Model::Schema::XmlCompiler do
|
|
1421
1579
|
expect(described_class.instance_variable_get(:@required_files)).to eql(["ct_element1", "ct_element2"])
|
1422
1580
|
end
|
1423
1581
|
end
|
1582
|
+
|
1583
|
+
context "when given element's data type is one of standard class" do
|
1584
|
+
before do
|
1585
|
+
described_class.instance_variable_set(:@required_files, [])
|
1586
|
+
described_class.instance_variable_set(:@elements, elements)
|
1587
|
+
end
|
1588
|
+
|
1589
|
+
after do
|
1590
|
+
described_class.instance_variable_set(:@required_files, nil)
|
1591
|
+
described_class.instance_variable_set(:@elements, nil)
|
1592
|
+
end
|
1593
|
+
|
1594
|
+
let(:elements) do
|
1595
|
+
{
|
1596
|
+
"CT_Element1" => to_mapping_hash({ type_name: "w:CT_Element1" }),
|
1597
|
+
"CT_Element2" => to_mapping_hash({ type_name: "xsd:string" }),
|
1598
|
+
}
|
1599
|
+
end
|
1600
|
+
|
1601
|
+
let(:content) do
|
1602
|
+
[
|
1603
|
+
to_mapping_hash({ type_name: "CT_Element1" }),
|
1604
|
+
to_mapping_hash({ ref_class: "CT_Element2" }),
|
1605
|
+
]
|
1606
|
+
end
|
1607
|
+
|
1608
|
+
it "populates @required_files variable with the names of the required files excluding default classes" do
|
1609
|
+
described_class.send(:required_files_elements, content)
|
1610
|
+
expect(described_class.instance_variable_get(:@required_files)).to eql(["ct_element1"])
|
1611
|
+
end
|
1612
|
+
end
|
1424
1613
|
end
|
1425
1614
|
end
|
1426
1615
|
end
|
1427
1616
|
|
1617
|
+
def create_pattern_mapping(array)
|
1618
|
+
array.map { |type, text| Lutaml::Model::XmlAdapter::Element.new(type, text) }
|
1619
|
+
end
|
1620
|
+
|
1428
1621
|
def to_mapping_hash(content)
|
1429
1622
|
@hash ||= Lutaml::Model::MappingHash.new
|
1430
1623
|
@hash.merge(content)
|
@@ -0,0 +1,216 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "lutaml/model"
|
3
|
+
|
4
|
+
module SequenceSpec
|
5
|
+
class Ceramic < Lutaml::Model::Serializable
|
6
|
+
attribute :id, :string
|
7
|
+
attribute :name, :string
|
8
|
+
attribute :type, :string
|
9
|
+
attribute :color, :string
|
10
|
+
attribute :bold, :string
|
11
|
+
attribute :text, :string
|
12
|
+
attribute :usage, :string
|
13
|
+
attribute :size, :string
|
14
|
+
attribute :first_name, :string
|
15
|
+
attribute :last_name, :string
|
16
|
+
attribute :tag, :string
|
17
|
+
attribute :temperature, :string
|
18
|
+
|
19
|
+
xml do
|
20
|
+
root "Ceramic"
|
21
|
+
map_element :tag, to: :tag
|
22
|
+
|
23
|
+
sequence do
|
24
|
+
map_element :id, to: :id
|
25
|
+
map_element :name, to: :name
|
26
|
+
map_element :type, to: :type
|
27
|
+
map_element :color, to: :color
|
28
|
+
map_element :bold, to: :bold
|
29
|
+
map_element :text, to: :text
|
30
|
+
sequence do
|
31
|
+
map_element :usage, to: :usage
|
32
|
+
map_element :size, to: :size
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
sequence do
|
37
|
+
map_element :first_name, to: :first_name
|
38
|
+
map_element :last_name, to: :last_name
|
39
|
+
end
|
40
|
+
|
41
|
+
map_element :temperature, to: :temperature
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class CeramicCollection < Lutaml::Model::Serializable
|
46
|
+
attribute :ceramic, Ceramic, collection: 1..2
|
47
|
+
|
48
|
+
xml do
|
49
|
+
root "collection"
|
50
|
+
map_element "ceramic", to: :ceramic
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
RSpec.describe "Sequence" do
|
56
|
+
context "with nesting sequence" do
|
57
|
+
let(:mapper) { SequenceSpec::Ceramic }
|
58
|
+
|
59
|
+
it "don't raise error for a valid instance, if given attribute for sequence has correct order" do
|
60
|
+
xml = <<~XML
|
61
|
+
<Ceramic>
|
62
|
+
<tag>Nik</tag>
|
63
|
+
<id>1</id>
|
64
|
+
<name>Vase</name>
|
65
|
+
<type>Decorative</type>
|
66
|
+
<color>Blue</color>
|
67
|
+
<bold>Heading</bold>
|
68
|
+
<text>Header</text>
|
69
|
+
<usage>Indoor</usage>
|
70
|
+
<size>Medium</size>
|
71
|
+
<first_name>Dale</first_name>
|
72
|
+
<last_name>Steyn</last_name>
|
73
|
+
<temperature>Normal</temperature>
|
74
|
+
</Ceramic>
|
75
|
+
XML
|
76
|
+
|
77
|
+
expect { mapper.from_xml(xml) }.not_to raise_error
|
78
|
+
end
|
79
|
+
|
80
|
+
it "don't raise error for a valid instance with sequence range, if given attribute for sequence has correct order" do
|
81
|
+
xml = <<~XML
|
82
|
+
<collection>
|
83
|
+
<ceramic>
|
84
|
+
<tag>Nik</tag>
|
85
|
+
<id>1</id>
|
86
|
+
<name>Vase</name>
|
87
|
+
<type>Decorative</type>
|
88
|
+
<color>Blue</color>
|
89
|
+
<bold>Heading</bold>
|
90
|
+
<text>Header</text>
|
91
|
+
<usage>Indoor</usage>
|
92
|
+
<size>Medium</size>
|
93
|
+
<first_name>Dale</first_name>
|
94
|
+
<last_name>Steyn</last_name>
|
95
|
+
<temperature>Normal</temperature>
|
96
|
+
</ceramic>
|
97
|
+
<ceramic>
|
98
|
+
<tag>Nik</tag>
|
99
|
+
<id>1</id>
|
100
|
+
<name>Vase</name>
|
101
|
+
<type>Decorative</type>
|
102
|
+
<color>Blue</color>
|
103
|
+
<bold>Heading</bold>
|
104
|
+
<text>Header</text>
|
105
|
+
<usage>Indoor</usage>
|
106
|
+
<size>Medium</size>
|
107
|
+
<first_name>Dale</first_name>
|
108
|
+
<last_name>Steyn</last_name>
|
109
|
+
<temperature>Normal</temperature>
|
110
|
+
</ceramic>
|
111
|
+
</collection>
|
112
|
+
XML
|
113
|
+
|
114
|
+
expect do
|
115
|
+
SequenceSpec::CeramicCollection.from_xml(xml)
|
116
|
+
end.not_to raise_error
|
117
|
+
end
|
118
|
+
|
119
|
+
it "raises error, if given attributes order is incorrect in sequence" do
|
120
|
+
xml = <<~XML
|
121
|
+
<Ceramic>
|
122
|
+
<tag>Nik</tag>
|
123
|
+
<temperature>High</temperature>
|
124
|
+
<first_name>Micheal</first_name>
|
125
|
+
<id>1</id>
|
126
|
+
<name>Vase</name>
|
127
|
+
<type>Decorative</type>
|
128
|
+
<color>Blue</color>
|
129
|
+
<bold>Heading</bold>
|
130
|
+
<usage>Indoor</usage>
|
131
|
+
<size>Medium</size>
|
132
|
+
<last_name>Johnson</last_name>
|
133
|
+
<text>Header</text>
|
134
|
+
</Ceramic>
|
135
|
+
XML
|
136
|
+
|
137
|
+
expect do
|
138
|
+
mapper.from_xml(xml)
|
139
|
+
end.to raise_error(Lutaml::Model::IncorrectSequenceError) do |error|
|
140
|
+
expect(error.message).to eq("Element `usage` does not match the expected sequence order element `text`")
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
it "raises error with sequence range, if given attributes order is incorrect in sequence" do
|
145
|
+
invalid_xml = <<~XML
|
146
|
+
<collection>
|
147
|
+
<ceramic>
|
148
|
+
<id>1</id>
|
149
|
+
<name>Vase</name>
|
150
|
+
<type>Decorative</type>
|
151
|
+
<color>Blue</color>
|
152
|
+
<bold>Heading</bold>
|
153
|
+
<text>Header</text>
|
154
|
+
<usage>Indoor</usage>
|
155
|
+
<size>Medium</size>
|
156
|
+
<first_name>Dale</first_name>
|
157
|
+
<last_name>Steyn</last_name>
|
158
|
+
<temperature>Normal</temperature>
|
159
|
+
<tag>Nik</tag>
|
160
|
+
</ceramic>
|
161
|
+
|
162
|
+
<ceramic>
|
163
|
+
<id>2</id>
|
164
|
+
<name>Nick</name>
|
165
|
+
<type>Unique</type>
|
166
|
+
<color>Red</color>
|
167
|
+
<bold>Name</bold>
|
168
|
+
<text>Body</text>
|
169
|
+
<usage>Outdoor</usage>
|
170
|
+
<size>Small</size>
|
171
|
+
<first_name>Smith</first_name>
|
172
|
+
<last_name>Ash</last_name>
|
173
|
+
<temperature>High</temperature>
|
174
|
+
<tag>Adid</tag>
|
175
|
+
</ceramic>
|
176
|
+
|
177
|
+
<ceramic>
|
178
|
+
<id>3</id>
|
179
|
+
<name>Starc</name>
|
180
|
+
<type>Int</type>
|
181
|
+
<color>White</color>
|
182
|
+
<bold>Act</bold>
|
183
|
+
<text>Footer</text>
|
184
|
+
<usage>Nothing</usage>
|
185
|
+
<size>Large</size>
|
186
|
+
<first_name>Dale</first_name>
|
187
|
+
<last_name>Steyn</last_name>
|
188
|
+
<temperature>Normal</temperature>
|
189
|
+
<tag>Bet</tag>
|
190
|
+
</ceramic>
|
191
|
+
</collection>
|
192
|
+
XML
|
193
|
+
|
194
|
+
expect do
|
195
|
+
SequenceSpec::CeramicCollection.from_xml(invalid_xml).validate!
|
196
|
+
end.to raise_error(Lutaml::Model::ValidationError) do |error|
|
197
|
+
expect(error).to include(Lutaml::Model::CollectionCountOutOfRangeError)
|
198
|
+
expect(error.error_messages).to eq(["ceramic count is 3, must be between 1 and 2"])
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
it "raises error, if mapping other map_element are defined in sequence" do
|
203
|
+
expect do
|
204
|
+
Class.new(Lutaml::Model::Serializable) do
|
205
|
+
attribute :type, :string
|
206
|
+
|
207
|
+
xml do
|
208
|
+
sequence do
|
209
|
+
map_attribute :type, to: :type
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end.to raise_error(Lutaml::Model::UnknownSequenceMappingError, "map_attribute is not allowed in sequence")
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|