lutaml-model 0.5.4 → 0.6.1
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/.rubocop_todo.yml +58 -21
- data/Gemfile +1 -0
- data/README.adoc +1112 -264
- data/lib/lutaml/model/attribute.rb +37 -15
- 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 +126 -38
- 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 +55 -8
- 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 +167 -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
|