lutaml-model 0.7.3 → 0.7.5

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.
Files changed (184) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +1 -0
  3. data/.github/workflows/release.yml +3 -0
  4. data/.gitignore +6 -1
  5. data/.irbrc +1 -0
  6. data/.pryrc +1 -0
  7. data/.rubocop_todo.yml +25 -52
  8. data/README.adoc +2177 -192
  9. data/docs/custom_registers.adoc +228 -0
  10. data/docs/schema_generation.adoc +898 -0
  11. data/docs/schema_import.adoc +364 -0
  12. data/flake.lock +114 -0
  13. data/flake.nix +103 -0
  14. data/lib/lutaml/model/attribute.rb +230 -94
  15. data/lib/lutaml/model/choice.rb +30 -0
  16. data/lib/lutaml/model/collection.rb +194 -0
  17. data/lib/lutaml/model/comparable_model.rb +3 -3
  18. data/lib/lutaml/model/config.rb +26 -3
  19. data/lib/lutaml/model/constants.rb +2 -0
  20. data/lib/lutaml/model/error/element_count_out_of_range_error.rb +29 -0
  21. data/lib/lutaml/model/error/invalid_attribute_name_error.rb +15 -0
  22. data/lib/lutaml/model/error/invalid_attribute_options_error.rb +16 -0
  23. data/lib/lutaml/model/error/invalid_choice_range_error.rb +3 -5
  24. data/lib/lutaml/model/error/register/not_registrable_class_error.rb +11 -0
  25. data/lib/lutaml/model/error/type/invalid_value_error.rb +5 -3
  26. data/lib/lutaml/model/error/type/max_bound_error.rb +20 -0
  27. data/lib/lutaml/model/error/type/max_length_error.rb +20 -0
  28. data/lib/lutaml/model/error/type/min_bound_error.rb +20 -0
  29. data/lib/lutaml/model/error/type/min_length_error.rb +20 -0
  30. data/lib/lutaml/model/error/type/pattern_not_matched_error.rb +18 -0
  31. data/lib/lutaml/model/error/validation_failed_error.rb +9 -0
  32. data/lib/lutaml/model/error.rb +10 -0
  33. data/lib/lutaml/model/errors.rb +36 -0
  34. data/lib/lutaml/model/format_registry.rb +5 -2
  35. data/lib/lutaml/model/global_register.rb +41 -0
  36. data/lib/lutaml/model/{hash.rb → hash_adapter.rb} +5 -5
  37. data/lib/lutaml/model/jsonl/document.rb +14 -0
  38. data/lib/lutaml/model/jsonl/mapping.rb +19 -0
  39. data/lib/lutaml/model/jsonl/mapping_rule.rb +9 -0
  40. data/lib/lutaml/model/jsonl/standard_adapter.rb +33 -0
  41. data/lib/lutaml/model/jsonl/transform.rb +19 -0
  42. data/lib/lutaml/model/jsonl.rb +21 -0
  43. data/lib/lutaml/model/key_value_document.rb +3 -2
  44. data/lib/lutaml/model/mapping/key_value_mapping.rb +64 -4
  45. data/lib/lutaml/model/mapping/key_value_mapping_rule.rb +4 -0
  46. data/lib/lutaml/model/mapping/mapping_rule.rb +8 -3
  47. data/lib/lutaml/model/register.rb +105 -0
  48. data/lib/lutaml/model/registrable.rb +6 -0
  49. data/lib/lutaml/model/schema/base_schema.rb +64 -0
  50. data/lib/lutaml/model/schema/decorators/attribute.rb +114 -0
  51. data/lib/lutaml/model/schema/decorators/choices.rb +31 -0
  52. data/lib/lutaml/model/schema/decorators/class_definition.rb +85 -0
  53. data/lib/lutaml/model/schema/decorators/definition_collection.rb +97 -0
  54. data/lib/lutaml/model/schema/generator/definition.rb +53 -0
  55. data/lib/lutaml/model/schema/generator/definitions_collection.rb +81 -0
  56. data/lib/lutaml/model/schema/generator/properties_collection.rb +63 -0
  57. data/lib/lutaml/model/schema/generator/property.rb +110 -0
  58. data/lib/lutaml/model/schema/generator/ref.rb +24 -0
  59. data/lib/lutaml/model/schema/helpers/template_helper.rb +49 -0
  60. data/lib/lutaml/model/schema/json_schema.rb +42 -49
  61. data/lib/lutaml/model/schema/relaxng_schema.rb +14 -10
  62. data/lib/lutaml/model/schema/renderer.rb +36 -0
  63. data/lib/lutaml/model/schema/shared_methods.rb +24 -0
  64. data/lib/lutaml/model/schema/templates/model.erb +9 -0
  65. data/lib/lutaml/model/schema/xml_compiler/attribute.rb +85 -0
  66. data/lib/lutaml/model/schema/xml_compiler/attribute_group.rb +45 -0
  67. data/lib/lutaml/model/schema/xml_compiler/choice.rb +65 -0
  68. data/lib/lutaml/model/schema/xml_compiler/complex_content.rb +27 -0
  69. data/lib/lutaml/model/schema/xml_compiler/complex_content_restriction.rb +34 -0
  70. data/lib/lutaml/model/schema/xml_compiler/complex_type.rb +136 -0
  71. data/lib/lutaml/model/schema/xml_compiler/element.rb +104 -0
  72. data/lib/lutaml/model/schema/xml_compiler/group.rb +97 -0
  73. data/lib/lutaml/model/schema/xml_compiler/restriction.rb +101 -0
  74. data/lib/lutaml/model/schema/xml_compiler/sequence.rb +50 -0
  75. data/lib/lutaml/model/schema/xml_compiler/simple_content.rb +36 -0
  76. data/lib/lutaml/model/schema/xml_compiler/simple_type.rb +189 -0
  77. data/lib/lutaml/model/schema/xml_compiler.rb +231 -587
  78. data/lib/lutaml/model/schema/xsd_schema.rb +12 -8
  79. data/lib/lutaml/model/schema/yaml_schema.rb +41 -35
  80. data/lib/lutaml/model/schema.rb +1 -0
  81. data/lib/lutaml/model/sequence.rb +60 -30
  82. data/lib/lutaml/model/serialize.rb +175 -53
  83. data/lib/lutaml/model/services/base.rb +11 -0
  84. data/lib/lutaml/model/services/logger.rb +2 -2
  85. data/lib/lutaml/model/services/rule_value_extractor.rb +92 -0
  86. data/lib/lutaml/model/services/type/validator/number.rb +25 -0
  87. data/lib/lutaml/model/services/type/validator/string.rb +52 -0
  88. data/lib/lutaml/model/services/type/validator.rb +43 -0
  89. data/lib/lutaml/model/services/validator.rb +145 -0
  90. data/lib/lutaml/model/services.rb +3 -0
  91. data/lib/lutaml/model/transform/key_value_transform.rb +60 -50
  92. data/lib/lutaml/model/transform/xml_transform.rb +46 -57
  93. data/lib/lutaml/model/transform.rb +22 -8
  94. data/lib/lutaml/model/type/boolean.rb +1 -1
  95. data/lib/lutaml/model/type/date.rb +1 -1
  96. data/lib/lutaml/model/type/date_time.rb +1 -1
  97. data/lib/lutaml/model/type/decimal.rb +11 -9
  98. data/lib/lutaml/model/type/float.rb +2 -1
  99. data/lib/lutaml/model/type/integer.rb +24 -21
  100. data/lib/lutaml/model/type/string.rb +4 -2
  101. data/lib/lutaml/model/type/time.rb +1 -1
  102. data/lib/lutaml/model/type/time_without_date.rb +1 -1
  103. data/lib/lutaml/model/type/value.rb +5 -1
  104. data/lib/lutaml/model/type.rb +5 -2
  105. data/lib/lutaml/model/utils.rb +30 -8
  106. data/lib/lutaml/model/validation.rb +6 -4
  107. data/lib/lutaml/model/version.rb +1 -1
  108. data/lib/lutaml/model/xml/document.rb +37 -19
  109. data/lib/lutaml/model/xml/mapping.rb +74 -13
  110. data/lib/lutaml/model/xml/mapping_rule.rb +10 -2
  111. data/lib/lutaml/model/xml/nokogiri_adapter.rb +5 -3
  112. data/lib/lutaml/model/xml/oga/element.rb +4 -1
  113. data/lib/lutaml/model/xml/oga_adapter.rb +4 -3
  114. data/lib/lutaml/model/xml/ox_adapter.rb +20 -6
  115. data/lib/lutaml/model/xml/xml_element.rb +3 -28
  116. data/lib/lutaml/model/xml_adapter/element.rb +1 -1
  117. data/lib/lutaml/model/xml_adapter/nokogiri_adapter.rb +1 -1
  118. data/lib/lutaml/model/xml_adapter/oga_adapter.rb +1 -1
  119. data/lib/lutaml/model/xml_adapter/ox_adapter.rb +1 -1
  120. data/lib/lutaml/model/yamls/document.rb +14 -0
  121. data/lib/lutaml/model/yamls/mapping.rb +19 -0
  122. data/lib/lutaml/model/yamls/mapping_rule.rb +9 -0
  123. data/lib/lutaml/model/yamls/standard_adapter.rb +34 -0
  124. data/lib/lutaml/model/yamls/transform.rb +19 -0
  125. data/lib/lutaml/model/yamls.rb +21 -0
  126. data/lib/lutaml/model.rb +7 -31
  127. data/spec/benchmarks/xml_parsing_benchmark_spec.rb +4 -5
  128. data/spec/fixtures/xml/advanced_test_schema.xsd +134 -0
  129. data/spec/fixtures/xml/examples/nested_categories.xml +55 -0
  130. data/spec/fixtures/xml/examples/valid_catalog.xml +43 -0
  131. data/spec/fixtures/xml/product_catalog.xsd +151 -0
  132. data/spec/fixtures/xml/specifications_schema.xsd +38 -0
  133. data/spec/lutaml/model/attribute_collection_spec.rb +101 -0
  134. data/spec/lutaml/model/attribute_spec.rb +41 -44
  135. data/spec/lutaml/model/choice_spec.rb +44 -0
  136. data/spec/lutaml/model/custom_collection_spec.rb +830 -0
  137. data/spec/lutaml/model/custom_model_spec.rb +15 -3
  138. data/spec/lutaml/model/defaults_spec.rb +5 -1
  139. data/spec/lutaml/model/global_register_spec.rb +108 -0
  140. data/spec/lutaml/model/group_spec.rb +9 -3
  141. data/spec/lutaml/model/jsonl/standard_adapter_spec.rb +91 -0
  142. data/spec/lutaml/model/jsonl_spec.rb +229 -0
  143. data/spec/lutaml/model/multiple_mapping_spec.rb +1 -1
  144. data/spec/lutaml/model/register/key_value_spec.rb +275 -0
  145. data/spec/lutaml/model/register/xml_spec.rb +187 -0
  146. data/spec/lutaml/model/register_spec.rb +147 -0
  147. data/spec/lutaml/model/rule_value_extractor_spec.rb +162 -0
  148. data/spec/lutaml/model/schema/generator/definitions_collection_spec.rb +120 -0
  149. data/spec/lutaml/model/schema/json_schema_spec.rb +412 -51
  150. data/spec/lutaml/model/schema/json_schema_to_models_spec.rb +383 -0
  151. data/spec/lutaml/model/schema/xml_compiler/attribute_group_spec.rb +65 -0
  152. data/spec/lutaml/model/schema/xml_compiler/attribute_spec.rb +63 -0
  153. data/spec/lutaml/model/schema/xml_compiler/choice_spec.rb +71 -0
  154. data/spec/lutaml/model/schema/xml_compiler/complex_content_restriction_spec.rb +55 -0
  155. data/spec/lutaml/model/schema/xml_compiler/complex_content_spec.rb +37 -0
  156. data/spec/lutaml/model/schema/xml_compiler/complex_type_spec.rb +173 -0
  157. data/spec/lutaml/model/schema/xml_compiler/element_spec.rb +63 -0
  158. data/spec/lutaml/model/schema/xml_compiler/group_spec.rb +86 -0
  159. data/spec/lutaml/model/schema/xml_compiler/restriction_spec.rb +76 -0
  160. data/spec/lutaml/model/schema/xml_compiler/sequence_spec.rb +59 -0
  161. data/spec/lutaml/model/schema/xml_compiler/simple_content_spec.rb +55 -0
  162. data/spec/lutaml/model/schema/xml_compiler/simple_type_spec.rb +181 -0
  163. data/spec/lutaml/model/schema/xml_compiler_spec.rb +503 -1804
  164. data/spec/lutaml/model/schema/yaml_schema_spec.rb +249 -26
  165. data/spec/lutaml/model/sequence_spec.rb +36 -0
  166. data/spec/lutaml/model/serializable_spec.rb +31 -0
  167. data/spec/lutaml/model/type_spec.rb +8 -4
  168. data/spec/lutaml/model/utils_spec.rb +3 -3
  169. data/spec/lutaml/model/xml/derived_attributes_spec.rb +1 -1
  170. data/spec/lutaml/model/xml/xml_element_spec.rb +7 -1
  171. data/spec/lutaml/model/xml_adapter/xml_namespace_spec.rb +6 -6
  172. data/spec/lutaml/model/xml_adapter_spec.rb +24 -0
  173. data/spec/lutaml/model/xml_mapping_rule_spec.rb +11 -4
  174. data/spec/lutaml/model/xml_mapping_spec.rb +1 -1
  175. data/spec/lutaml/model/yamls/standard_adapter_spec.rb +183 -0
  176. data/spec/lutaml/model/yamls_spec.rb +294 -0
  177. data/spec/spec_helper.rb +1 -0
  178. metadata +105 -9
  179. data/lib/lutaml/model/schema/templates/simple_type.rb +0 -247
  180. /data/lib/lutaml/model/{hash → hash_adapter}/document.rb +0 -0
  181. /data/lib/lutaml/model/{hash → hash_adapter}/mapping.rb +0 -0
  182. /data/lib/lutaml/model/{hash → hash_adapter}/mapping_rule.rb +0 -0
  183. /data/lib/lutaml/model/{hash → hash_adapter}/standard_adapter.rb +0 -0
  184. /data/lib/lutaml/model/{hash → hash_adapter}/transform.rb +0 -0
@@ -4,56 +4,72 @@ require "lutaml/xsd"
4
4
 
5
5
  RSpec.describe Lutaml::Model::Schema::XmlCompiler do
6
6
  describe ".to_models" do
7
- context "with valid xml schema, it should generate the models" do
8
- let(:valid_value_xml_example) do
9
- <<~VALID_XML_EXAMPLE
10
- <CT_MathTest>
11
- <MathTest val="1"/>
12
- <MathTest1 val="1"/>
13
- </CT_MathTest>
14
- VALID_XML_EXAMPLE
15
- end
7
+ describe "Testing the unofficial schemas" do
8
+ context "with valid xml schema, it generates the models" do
9
+ before do
10
+ described_class.to_models(schema, output_dir: dir, create_files: true)
11
+ Dir.each_child(dir) { |child| require_relative File.expand_path("#{dir}/#{child}") }
12
+ end
16
13
 
17
- let(:invalid_value_xml_example) do
18
- <<~INVALID_XML_EXAMPLE
19
- <CT_MathTest>
20
- <MathTest val="0"/>
21
- <MathTest1 val="-3"/>
22
- </CT_MathTest>
23
- INVALID_XML_EXAMPLE
24
- end
14
+ after do
15
+ FileUtils.rm_rf(dir)
16
+ end
25
17
 
26
- Dir.mktmpdir do |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)
18
+ let(:dir) { Dir.mktmpdir }
19
+
20
+ let(:schema) { File.read("spec/fixtures/xml/test_schema.xsd") }
21
+
22
+ let(:valid_value_xml_example) do
23
+ <<~VALID_XML_EXAMPLE
24
+ <CT_MathTest>
25
+ <MathTest val="1"/>
26
+ <MathTest1 val="1"/>
27
+ </CT_MathTest>
28
+ VALID_XML_EXAMPLE
29
+ end
30
+
31
+ let(:invalid_value_xml_example) do
32
+ <<~INVALID_XML_EXAMPLE
33
+ <CT_MathTest>
34
+ <MathTest val="0"/>
35
+ <MathTest1 val="-3"/>
36
+ </CT_MathTest>
37
+ INVALID_XML_EXAMPLE
38
+ end
39
+
40
+ it "validates if the files exist in the directory" do
29
41
  expect(File).to exist("#{dir}/ct_math_test.rb")
30
42
  expect(File).to exist("#{dir}/st_integer255.rb")
31
43
  expect(File).to exist("#{dir}/long.rb")
32
- Dir.each_child(dir) { |child| require_relative File.expand_path("#{dir}/#{child}") }
44
+ end
45
+
46
+ it "validates if the CTMathTest class is loaded" do
33
47
  expect(defined?(CTMathTest)).to eq("constant")
48
+ end
49
+
50
+ it "creates the model files, requires them, and tests them with valid and invalid xml" do
34
51
  expect(CTMathTest.from_xml(valid_value_xml_example).to_xml).to be_equivalent_to(valid_value_xml_example)
35
- expect { CTMathTest.from_xml(invalid_value_xml_example) }.to raise_error(Lutaml::Model::Type::InvalidValueError)
52
+ end
53
+
54
+ it "raises error when processing invalid example" do
55
+ expect { CTMathTest.from_xml(invalid_value_xml_example) }.to raise_error(Lutaml::Model::Type::MinBoundError)
36
56
  end
37
57
  end
38
- end
39
58
 
40
- context "when processing examples from classes/files generated by valid xml schema" do
41
- Dir.mktmpdir do |dir|
59
+ context "when processing examples from classes/files generated by valid xml schema" do
42
60
  before do
43
- described_class.to_models(
44
- File.read("spec/fixtures/xml/math_document_schema.xsd"),
45
- output_dir: dir,
46
- create_files: true,
47
- )
48
- require_relative "#{dir}/math_document"
61
+ Dir.mktmpdir do |dir|
62
+ described_class.to_models(
63
+ File.read("spec/fixtures/xml/math_document_schema.xsd"),
64
+ output_dir: dir,
65
+ create_files: true,
66
+ )
67
+ require_relative "#{dir}/math_document"
68
+ end
49
69
  end
50
70
 
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
71
+ let(:valid_example) { File.read("spec/fixtures/xml/valid_math_document.xml") }
72
+ let(:invalid_example) { File.read("spec/fixtures/xml/invalid_math_document.xml") }
57
73
 
58
74
  it "does not raise error with valid example and creates files" do
59
75
  expect(defined?(MathDocument)).to eq("constant")
@@ -63,23 +79,23 @@ RSpec.describe Lutaml::Model::Schema::XmlCompiler do
63
79
  expect(parsed.to_xml).to be_equivalent_to(valid_example)
64
80
  end
65
81
 
66
- it "raises InvalidValueError" do
82
+ it "raises PatternNotMatchedError" do
67
83
  expect(defined?(MathDocument)).to eq("constant")
68
84
  expect { MathDocument.from_xml(invalid_example) }
69
- .to raise_error(Lutaml::Model::Type::InvalidValueError)
85
+ .to raise_error(Lutaml::Model::Type::PatternNotMatchedError)
70
86
  end
71
87
  end
72
- end
73
88
 
74
- context "when processing example from lutaml-model#260" do
75
- Dir.mktmpdir do |dir|
89
+ context "when processing example from lutaml-model#260" do
76
90
  before do
77
- described_class.to_models(
78
- File.read("spec/fixtures/xml/address_example_260.xsd"),
79
- output_dir: dir,
80
- create_files: true,
81
- )
82
- require_relative "#{dir}/address"
91
+ Dir.mktmpdir do |dir|
92
+ described_class.to_models(
93
+ File.read("spec/fixtures/xml/address_example_260.xsd"),
94
+ output_dir: dir,
95
+ create_files: true,
96
+ )
97
+ require_relative "#{dir}/address"
98
+ end
83
99
  end
84
100
 
85
101
  let(:address) do
@@ -97,1828 +113,511 @@ RSpec.describe Lutaml::Model::Schema::XmlCompiler do
97
113
  expect(Address.from_xml(address).to_xml).to be_equivalent_to(address)
98
114
  end
99
115
  end
100
- end
101
-
102
- context "when classes are generated but files are not created" do
103
- let(:schema_classes_hash) do
104
- described_class.to_models(
105
- File.read("spec/fixtures/xml/user.xsd"),
106
- )
107
- end
108
-
109
- let(:expected_classes) do
110
- [
111
- "NonNegativeInteger",
112
- "PositiveInteger",
113
- "Base64Binary",
114
- "UnsignedLong",
115
- "UnsignedInt",
116
- "HexBinary",
117
- "Token",
118
- "Long",
119
- "User",
120
- ]
121
- end
122
-
123
- it "matches the expected class names of the schema" do
124
- expect(schema_classes_hash.keys).to eql(expected_classes)
125
- end
126
- end
127
-
128
- context "when classes are generated and loaded but files are not created" do
129
- before do
130
- described_class.to_models(
131
- File.read("spec/fixtures/xml/user.xsd"),
132
- load_classes: true,
133
- )
134
- end
135
-
136
- let(:expected_classes) do
137
- %w[
138
- NonNegativeInteger
139
- PositiveInteger
140
- Base64Binary
141
- UnsignedLong
142
- UnsignedInt
143
- HexBinary
144
- Token
145
- Long
146
- User
147
- ]
148
- end
149
-
150
- let(:xml) do
151
- <<~XML
152
- <User>
153
- <id>1112</id>
154
- <age>29</age>
155
- <token>u9dId901dp13f</token>
156
- </User>
157
- XML
158
- end
159
-
160
- it "matches the expected class names of the schema" do
161
- expected_classes.each do |klass|
162
- expect(be_const_defined(klass)).to be_truthy
163
- end
164
- expect(User.from_xml(xml).to_xml).to be_equivalent_to(xml)
165
- end
166
- end
167
- end
168
-
169
- describe "structure setup methods" do
170
- describe ".as_models" do
171
- let(:as_models) do
172
- described_class.send(:as_models, schema)
173
- end
174
-
175
- context "when the XML adapter is not set" do
176
- before do
177
- Lutaml::Model::Config.xml_adapter_type = :ox
178
- end
179
-
180
- after do
181
- Lutaml::Model::Config.xml_adapter_type = :nokogiri
182
- end
183
-
184
- let(:schema) do
185
- '<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"/>'
186
- end
187
-
188
- it "raises an error" do
189
- expect { as_models }.to raise_error(Lutaml::Model::Error)
190
- end
191
- end
192
-
193
- context "when the XML adapter is set and schema is given" do
194
- let(:schema) do
195
- '<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"/>'
196
- end
197
-
198
- let(:instance_variables) do
199
- %i[
200
- @elements
201
- @attributes
202
- @group_types
203
- @simple_types
204
- @complex_types
205
- @attribute_groups
206
- ]
207
- end
208
-
209
- it "initializes the instance variables with empty MappingHash" do
210
- as_models
211
- instance_variables.each do |variable|
212
- instance_variable = described_class.instance_variable_get(variable)
213
-
214
- expect(instance_variable)
215
- .to be_a(Lutaml::Model::MappingHash)
216
- .and be_empty
217
- end
218
- end
219
-
220
- it "parses the schema and populates the instance variables" do
221
- expect(described_class.send(:as_models, schema)).to be_nil
222
- end
223
- end
224
- end
225
-
226
- describe ".schema_to_models" do
227
- context "when given schema element is empty" do
228
- let(:schema) { [] }
229
-
230
- it "returns nil if schema array is empty" do
231
- expect(described_class.send(:schema_to_models, schema)).to be_nil
232
- end
233
-
234
- it "returns nil if schema array contains empty schema instance" do
235
- schema << Lutaml::Xsd::Schema.new
236
- expect(described_class.send(:schema_to_models, schema)).to be_nil
237
- end
238
- end
239
116
 
240
- context "when given schema contains all the elements" do
117
+ context "when processing example from files generated by schema -> product_catalog.xsd" do
241
118
  before do
242
- variables.each_key do |key|
243
- described_class.instance_variable_set(
244
- :"@#{key}",
245
- to_mapping_hash({}),
119
+ Dir.mktmpdir do |dir|
120
+ described_class.to_models(
121
+ File.read("spec/fixtures/xml/product_catalog.xsd"),
122
+ output_dir: dir,
123
+ create_files: true,
246
124
  )
125
+ require_relative "#{dir}/product_catalog"
247
126
  end
248
127
  end
249
128
 
250
- after do
251
- variables.each_key do |key|
252
- described_class.instance_variable_set(:"@#{key}", nil)
253
- end
254
- end
255
-
256
- let(:schema) do
257
- Lutaml::Xsd.parse(<<~XSD)
258
- <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
259
- <xsd:element name="test_element"/>
260
- <xsd:attribute name="test_attribute" type="xsd:string"/>
261
- <xsd:group name="test_group"/>
262
- <xsd:simpleType name="test_simple_type"/>
263
- <xsd:complexType name="test_complex_type" mixed="true"/>
264
- <xsd:attributeGroup name="test_attribute_group"/>
265
- </xsd:schema>
266
- XSD
267
- end
268
-
269
- let(:variables) do
270
- {
271
- elements: {
272
- "test_element" => {
273
- element_name: "test_element",
274
- type_name: nil,
275
- },
276
- },
277
- attributes: {
278
- "test_attribute" => {
279
- name: "test_attribute",
280
- base_class: "xsd:string",
281
- },
282
- },
283
- group_types: { "test_group" => {} },
284
- simple_types: { "test_simple_type" => {} },
285
- complex_types: { "test_complex_type" => { mixed: true } },
286
- attribute_groups: { "test_attribute_group" => {} },
287
- }
129
+ let(:product_catalog) do
130
+ File.read("spec/fixtures/xml/examples/valid_catalog.xml")
288
131
  end
289
132
 
290
- it "initializes the instance variables with empty MappingHash" do
291
- described_class.send(:schema_to_models, [schema])
292
- variables.each do |variable, expected_value|
293
- value = described_class.instance_variable_get(:"@#{variable}")
294
-
295
- expect(value)
296
- .to be_a(Lutaml::Model::MappingHash)
297
- .and eql(expected_value)
298
- end
133
+ let(:nested_category) do
134
+ File.read("spec/fixtures/xml/examples/nested_categories.xml")
299
135
  end
300
- end
301
- end
302
136
 
303
- describe ".setup_simple_type" do
304
- let(:setup_simple_type) do
305
- described_class.send(:setup_simple_type, simple_type)
306
- end
307
-
308
- context "when given simple_type contains restriction and union" do
309
- let(:simple_type) do
310
- Lutaml::Xsd::SimpleType.new.tap do |st|
311
- st.restriction = Lutaml::Xsd::RestrictionSimpleType.new(base: "test_base")
312
- st.union = Lutaml::Xsd::Union.new(member_types: "")
313
- end
137
+ it "confirms the ProductCatalog class is required" do
138
+ expect(defined?(ProductCatalog)).to eq("constant")
314
139
  end
315
140
 
316
- let(:expected_output) { { base_class: "test_base", union: [] } }
317
-
318
- it "initializes the instance variables with empty MappingHash" do
319
- expect(setup_simple_type).to eql(expected_output)
141
+ it "confirms that the from_xml and to_xml methods successfully handles xml for valid_catalog.xml" do
142
+ expect(ProductCatalog.from_xml(product_catalog).to_xml).to be_a(String)
320
143
  end
321
- end
322
-
323
- context "when simple_type contains nothing" do
324
- let(:simple_type) { Lutaml::Xsd::SimpleType.new }
325
144
 
326
- it "initializes the instance variables with empty MappingHash" do
327
- expect(setup_simple_type).to eql({})
145
+ it "confirms that the from_xml and to_xml methods successfully handles xml for nested_categories.xml" do
146
+ expect(ProductCatalog.from_xml(nested_category).to_xml).to be_a(String)
328
147
  end
329
148
  end
330
- end
331
-
332
- describe ".restriction_content" do
333
- context "when given restriction contains max_length, min_length, min_inclusive, max_inclusive, length" do
334
- let(:restriction) do
335
- Lutaml::Xsd::RestrictionSimpleType.new.tap do |r|
336
- r.max_length = [Lutaml::Xsd::MaxLength.new(value: "10")]
337
- r.min_length = [Lutaml::Xsd::MinLength.new(value: "1")]
338
- r.min_inclusive = [Lutaml::Xsd::MinInclusive.new(value: "1")]
339
- r.max_inclusive = [Lutaml::Xsd::MaxInclusive.new(value: "10")]
340
- r.length = [Lutaml::Xsd::Length.new(value: "10")]
341
- end
342
- end
343
149
 
344
- let(:expected_output) do
345
- {
346
- max_length: 10,
347
- min_length: 1,
348
- min_inclusive: "1",
349
- max_inclusive: "10",
350
- length: [{ value: 10 }],
351
- }
150
+ context "when classes are generated but files are not created" do
151
+ let(:schema_classes_hash) do
152
+ described_class.to_models(File.read("spec/fixtures/xml/user.xsd"))
352
153
  end
353
154
 
354
- it "initializes the instance variables with empty MappingHash" do
355
- described_class.send(:restriction_content, hash = {}, restriction)
356
- expect(hash).to eql(expected_output)
155
+ let(:expected_classes) do
156
+ types = described_class::SimpleType::SUPPORTED_DATA_TYPES
157
+ types.filter_map { |name, value| name.to_s unless value[:skippable] } << "User"
357
158
  end
358
- end
359
-
360
- context "when restriction contains nothing" do
361
- let(:restriction) { Lutaml::Xsd::RestrictionSimpleType.new }
362
159
 
363
- it "initializes the instance variables with empty MappingHash" do
364
- described_class.send(:restriction_content, hash = {}, restriction)
365
- expect(hash).to be_empty
160
+ it "matches the expected class names of the schema" do
161
+ expect(schema_classes_hash.keys).to eql(expected_classes)
366
162
  end
367
163
  end
368
- end
369
-
370
- describe ".restriction_length" do
371
- let(:restriction_length) do
372
- described_class.send(:restriction_length, lengths)
373
- end
374
164
 
375
- context "when given restriction contains max_length, min_length, min_inclusive, max_inclusive, length" do
376
- let(:lengths) do
377
- [
378
- Lutaml::Xsd::Length.new(value: "10", fixed: true),
379
- Lutaml::Xsd::Length.new(value: "1"),
380
- Lutaml::Xsd::Length.new(value: "1", fixed: true),
381
- Lutaml::Xsd::Length.new(value: "10"),
382
- Lutaml::Xsd::Length.new(value: "10", fixed: true),
383
- ]
165
+ context "when classes are generated and loaded but files are not created" do
166
+ before do
167
+ described_class.to_models(
168
+ File.read("spec/fixtures/xml/user.xsd"),
169
+ load_classes: true,
170
+ )
384
171
  end
385
172
 
386
- let(:expected_content) do
387
- [
388
- { value: 10, fixed: true },
389
- { value: 1 },
390
- { value: 1, fixed: true },
391
- { value: 10 },
392
- { value: 10, fixed: true },
173
+ let(:expected_classes) do
174
+ %w[
175
+ NonNegativeInteger
176
+ PositiveInteger
177
+ Base64Binary
178
+ UnsignedLong
179
+ UnsignedInt
180
+ HexBinary
181
+ Token
182
+ Long
183
+ User
393
184
  ]
394
185
  end
395
186
 
396
- it "initializes the instance variables with empty MappingHash" do
397
- expect(restriction_length).to eql(expected_content)
398
- end
399
- end
400
-
401
- context "when restriction contains nothing" do
402
- let(:lengths) { [] }
403
-
404
- it "initializes the instance variables with empty MappingHash" do
405
- expect(restriction_length).to be_empty
406
- end
407
- end
408
- end
409
-
410
- describe ".setup_complex_type" do
411
- context "when given complex_type contains attribute, sequence, choice, complex_content, attribute_group, group, simple_content" do
412
- let(:complex_type) do
413
- Lutaml::Xsd::ComplexType.new.tap do |ct|
414
- ct.attribute = [Lutaml::Xsd::Attribute.new(type: "test_attribute", name: "test_attribute1")]
415
- ct.sequence = [Lutaml::Xsd::Sequence.new(name: "test_sequence")]
416
- ct.choice = [Lutaml::Xsd::Choice.new(name: "test_choice")]
417
- ct.complex_content = [Lutaml::Xsd::ComplexContent.new(name: "test_complex_content")]
418
- ct.attribute_group = [Lutaml::Xsd::AttributeGroup.new(name: "test_attribute_group")]
419
- ct.group = [Lutaml::Xsd::Group.new(name: "test_group")]
420
- ct.simple_content = [Lutaml::Xsd::SimpleContent.new(name: "test_simple_content")]
421
- ct.element_order = create_pattern_mapping([
422
- ["Element", "attribute"],
423
- ["Element", "sequence"],
424
- ["Element", "choice"],
425
- ["Element", "complex_content"],
426
- ["Element", "attribute_group"],
427
- ["Element", "group"],
428
- ["Element", "simple_content"],
429
- ])
430
- end
431
- end
432
-
433
- let(:expected_hash) do
434
- {
435
- attributes: [{ name: "test_attribute1", base_class: "test_attribute" }],
436
- sequence: {},
437
- choice: {},
438
- complex_content: {},
439
- attribute_groups: [{}],
440
- group: {},
441
- mixed: false,
442
- simple_content: nil,
443
- }
444
- end
445
-
446
- it "initializes the instance variables with empty MappingHash" do
447
- expect(described_class.send(:setup_complex_type, complex_type)).to eql(expected_hash)
187
+ let(:xml) do
188
+ <<~XML
189
+ <User>
190
+ <id>1112</id>
191
+ <age>29</age>
192
+ <token>u9dId901dp13f</token>
193
+ </User>
194
+ XML
448
195
  end
449
- end
450
-
451
- context "when restriction contains nothing" do
452
- let(:complex_type) do
453
- Lutaml::Xsd::ComplexType.new.tap do |ct|
454
- ct.element_order = []
455
- end
456
- end
457
-
458
- it "initializes the instance variables with empty MappingHash" do
459
- expect(described_class.send(:setup_complex_type, complex_type)).to eq({ mixed: false })
460
- end
461
- end
462
- end
463
-
464
- describe ".setup_simple_content" do
465
- let(:setup_simple_content) do
466
- described_class.send(:setup_simple_content, complex_type)
467
- end
468
-
469
- context "when given complex_type contains extension" do
470
- let(:complex_type) do
471
- Lutaml::Xsd::SimpleContent.new.tap do |ct|
472
- ct.extension = Lutaml::Xsd::ExtensionSimpleContent.new(base: "test_extension")
473
- ct.element_order = [
474
- Lutaml::Model::Xml::Element.new("Element", "extension"),
475
- ]
476
- end
477
- end
478
-
479
- let(:expected_hash) { { extension_base: "test_extension" } }
480
-
481
- it "initializes the instance variables with empty MappingHash" do
482
- expect(setup_simple_content).to eql(expected_hash)
483
- end
484
- end
485
-
486
- context "when complex_type contains restriction" do
487
- let(:complex_type) do
488
- Lutaml::Xsd::SimpleContent.new.tap do |ct|
489
- ct.restriction = Lutaml::Xsd::RestrictionSimpleContent.new(base: "test_restriction")
490
- ct.element_order = [
491
- Lutaml::Model::Xml::Element.new("Element", "restriction"),
492
- ]
493
- end
494
- end
495
-
496
- let(:expected_hash) { { base_class: "test_restriction" } }
497
-
498
- it "initializes the instance variables with empty MappingHash" do
499
- expect(setup_simple_content).to eql(expected_hash)
500
- end
501
- end
502
- end
503
-
504
- describe ".setup_sequence" do
505
- let(:setup_sequence) do
506
- described_class.send(:setup_sequence, sequence)
507
- end
508
196
 
509
- context "when given sequence contains sequence, element, choice, group" do
510
- let(:sequence) do
511
- Lutaml::Xsd::Sequence.new.tap do |ct|
512
- ct.sequence = [Lutaml::Xsd::Sequence.new(name: "test_sequence")]
513
- ct.element = [
514
- Lutaml::Xsd::Element.new(name: "test_element"),
515
- Lutaml::Xsd::Element.new(ref: "test_ref"),
516
- ]
517
- ct.choice = [Lutaml::Xsd::Choice.new(name: "test_choice")]
518
- ct.group = [
519
- Lutaml::Xsd::Group.new(name: "test_group"),
520
- Lutaml::Xsd::Group.new(ref: "test_ref"),
521
- ]
522
- ct.element_order = create_pattern_mapping([
523
- ["Element", "sequence"],
524
- ["Element", "group"],
525
- ["Element", "element"],
526
- ["Element", "choice"],
527
- ["Element", "element"],
528
- ["Element", "group"],
529
- ])
197
+ it "matches the expected class names of the schema" do
198
+ expected_classes.each do |klass|
199
+ expect(be_const_defined(klass)).to be_truthy
530
200
  end
531
- end
532
-
533
- let(:expected_hash) do
534
- {
535
- sequences: [{}],
536
- elements: [
537
- { element_name: "test_element", type_name: nil },
538
- { ref_class: "test_ref" },
539
- ],
540
- choice: [{}],
541
- groups: [{}, { ref_class: "test_ref" }],
542
- }
543
- end
544
-
545
- it "initializes the instance variables with empty MappingHash" do
546
- expect(setup_sequence).to eql(expected_hash)
201
+ expect(User.from_xml(xml).to_xml).to be_equivalent_to(xml)
547
202
  end
548
203
  end
549
204
 
550
- context "when sequence contains nothing" do
551
- let(:sequence) do
552
- Lutaml::Xsd::Sequence.new.tap do |ct|
553
- ct.element_order = []
554
- end
555
- end
556
-
557
- it "initializes the instance variables with empty MappingHash" do
558
- expect(setup_sequence).to be_empty
559
- end
560
- end
561
- end
205
+ context "when classes are generated and loaded but files are not created for specifications schema" do
206
+ before { described_class.to_models(schema, load_classes: true) }
562
207
 
563
- describe ".setup_group_type" do
564
- let(:setup_group_type) do
565
- described_class.send(:setup_group_type, group)
566
- end
208
+ let(:schema) { File.read("spec/fixtures/xml/specifications_schema.xsd") }
567
209
 
568
- context "when given group contains sequence, choice" do
569
- let(:group) do
570
- Lutaml::Xsd::Group.new.tap do |ct|
571
- ct.sequence = [Lutaml::Xsd::Sequence.new(name: "test_sequence")]
572
- ct.choice = [Lutaml::Xsd::Choice.new(name: "test_choice")]
573
- ct.element_order = create_pattern_mapping([
574
- ["Element", "sequence"],
575
- ["Element", "choice"],
576
- ])
577
- end
210
+ let(:spec_xml) do
211
+ <<~XML
212
+ <spec>
213
+ <title>Example Specification</title>
214
+ <version>1.0</version>
215
+ <status>draft</status>
216
+ </spec>
217
+ XML
578
218
  end
579
219
 
580
- let(:expected_hash) { { sequence: {}, choice: {} } }
581
-
582
- it "initializes the instance variables with empty MappingHash" do
583
- expect(setup_group_type).to eql(expected_hash)
220
+ let(:short_spec_xml) do
221
+ <<~XML
222
+ <shortSpec>
223
+ <title>Example Specification</title>
224
+ <version>1.0</version>
225
+ <status>draft</status>
226
+ </shortSpec>
227
+ XML
584
228
  end
585
- end
586
229
 
587
- context "when sequence contains nothing" do
588
- let(:group) do
589
- Lutaml::Xsd::Group.new.tap do |ct|
590
- ct.element_order = []
591
- end
230
+ it "successfully processes the Spec example" do
231
+ expect(Spec.from_xml(spec_xml).to_xml).to be_equivalent_to(spec_xml)
592
232
  end
593
233
 
594
- it "initializes the instance variables with empty MappingHash" do
595
- expect(setup_group_type).to be_empty
234
+ it "successfully processes the ShortSpec example" do
235
+ expect(ShortSpec.from_xml(short_spec_xml).to_xml).to be_equivalent_to(short_spec_xml)
596
236
  end
597
237
  end
598
238
  end
599
239
 
600
- describe ".setup_choice" do
601
- let(:setup_choice) do
602
- described_class.send(:setup_choice, choice)
240
+ describe "Testing the official schemas" do
241
+ before do
242
+ Lutaml::Model::GlobalRegister.register(Lutaml::Model::Register.new(register_id))
243
+ Lutaml::Model::Config.default_register = register_id
603
244
  end
604
245
 
605
- context "when given choice contains sequence, choice" do
606
- let(:choice) do
607
- Lutaml::Xsd::Choice.new.tap do |ct|
608
- ct.element = [Lutaml::Xsd::Element.new(name: "test_element")]
609
- ct.sequence = [Lutaml::Xsd::Sequence.new(name: "test_sequence")]
610
- ct.choice = [Lutaml::Xsd::Choice.new(name: "test_choice")]
611
- ct.group = [Lutaml::Xsd::Group.new(name: "test_group")]
612
- ct.element_order = create_pattern_mapping([
613
- ["Element", "sequence"],
614
- ["Element", "choice"],
615
- ["Element", "group"],
616
- ["Element", "element"],
617
- ])
618
- end
619
- end
620
-
621
- let(:expected_hash) do
622
- {
623
- sequence: {},
624
- choice: {},
625
- group: {},
626
- "test_element" => {
627
- element_name: "test_element",
628
- type_name: nil,
629
- },
630
- }
631
- end
632
-
633
- it "initializes the instance variables with empty MappingHash" do
634
- expect(setup_choice).to eql(expected_hash)
635
- end
246
+ after do
247
+ Lutaml::Model::Config.default_register = :default
636
248
  end
637
249
 
638
- context "when choice contains nothing" do
639
- let(:choice) do
640
- Lutaml::Xsd::Choice.new.tap do |ct|
641
- ct.element_order = []
250
+ let(:namespaced_classes) do
251
+ Dir.mktmpdir do |dir|
252
+ loaded_classes.each do |name, klass|
253
+ content = "module #{module_name}\n#{klass}\nend\n"
254
+ File.write(File.join(dir, "#{Lutaml::Model::Utils.snake_case(name)}.rb"), content)
642
255
  end
643
- end
644
-
645
- it "initializes the instance variables with empty MappingHash" do
646
- expect(setup_choice).to be_empty
256
+ loaded_classes.each_key { |name| require File.join(dir, "#{Lutaml::Model::Utils.snake_case(name)}.rb") }
647
257
  end
648
258
  end
649
- end
650
-
651
- describe ".setup_union" do
652
- let(:setup_union) do
653
- described_class.send(:setup_union, union)
654
- end
655
259
 
656
- context "when given union contains member_types" do
260
+ context "when classes are generated and loaded but files are not created for OOXML schema" do
657
261
  before do
658
- described_class.instance_variable_set(:@simple_types, simple_types)
659
- end
660
-
661
- after do
662
- described_class.instance_variable_set(:@simple_types, nil)
663
- end
664
-
665
- let(:simple_types) do
666
- {
667
- "test_member_type" => { name: "test_member_type" },
668
- "test_member_type1" => { name: "test_member_type1" },
669
- }
670
- end
671
-
672
- let(:union) do
673
- Lutaml::Xsd::Union.new.tap do |ct|
674
- ct.member_types = "test_member_type test_member_type1"
675
- end
676
- end
677
-
678
- let(:expected_output) do
679
- [
680
- { name: "test_member_type" },
681
- { name: "test_member_type1" },
682
- ]
683
- end
684
-
685
- it "returns the expected hash" do
686
- expect(setup_union).to eql(expected_output)
687
- end
688
- end
689
-
690
- context "when union contains nothing" do
691
- let(:union) { Lutaml::Xsd::Union.new }
692
-
693
- it "returns the empty hash" do
694
- expect(setup_union).to be_empty
695
- end
696
- end
697
- end
698
-
699
- describe ".setup_attribute" do
700
- let(:setup_attribute) do
701
- described_class.send(:setup_attribute, attribute)
702
- end
703
-
704
- context "when given attribute contains name and type" do
705
- let(:attribute) do
706
- Lutaml::Xsd::Attribute.new.tap do |attr|
707
- attr.name = "test_name"
708
- attr.type = "test_type"
709
- end
710
- end
711
-
712
- let(:expected_hash) { { name: "test_name", base_class: "test_type" } }
713
-
714
- it "returns the expected hash" do
715
- expect(setup_attribute).to eql(expected_hash)
716
- end
717
- end
718
-
719
- context "when given attribute contains ref" do
720
- let(:attribute) do
721
- Lutaml::Xsd::Attribute.new.tap do |attr|
722
- attr.ref = "test_ref"
723
- end
724
- end
725
-
726
- let(:expected_hash) { { ref_class: "test_ref" } }
727
-
728
- it "returns the expected hash" do
729
- expect(setup_attribute).to eql(expected_hash)
730
- end
731
- end
732
-
733
- context "when attribute contains nothing" do
734
- let(:attribute) { Lutaml::Xsd::Attribute.new }
735
- let(:expected_hash) { { name: nil, base_class: nil } }
736
-
737
- it "returns the empty hash" do
738
- expect(setup_attribute).to eql(expected_hash)
739
- end
740
- end
741
- end
742
-
743
- describe ".setup_attribute_groups" do
744
- let(:setup_attribute_groups) do
745
- described_class.send(:setup_attribute_groups, attribute_group)
746
- end
747
-
748
- context "when given attribute_group contains attribute and attribute_group" do
749
- let(:attribute_group) do
750
- Lutaml::Xsd::AttributeGroup.new.tap do |attr_group|
751
- attr_group.attribute = [Lutaml::Xsd::Attribute.new(name: "test_name", type: "test_type")]
752
- attr_group.attribute_group = [Lutaml::Xsd::AttributeGroup.new(name: "test_name", type: "test_type")]
753
- attr_group.element_order = create_pattern_mapping([
754
- ["Element", "attribute"],
755
- ["Element", "attribute_group"],
756
- ])
757
- end
758
- end
759
-
760
- let(:expected_hash) do
761
- {
762
- attributes: [
763
- { name: "test_name", base_class: "test_type" },
764
- ],
765
- attribute_groups: [{}],
766
- }
262
+ loaded_classes.merge!(
263
+ described_class.to_models(
264
+ Net::HTTP.get(URI("#{schema_location}/shared-math.xsd")),
265
+ location: schema_location,
266
+ namespace: "http://schemas.openxmlformats.org/officeDocument/2006/math",
267
+ prefix: "m",
268
+ ),
269
+ )
270
+ namespaced_classes
767
271
  end
768
272
 
769
- it "returns the expected hash" do
770
- expect(setup_attribute_groups).to eql(expected_hash)
273
+ let(:register_id) { :ooxml }
274
+ let(:loaded_classes) { {} }
275
+ let(:module_name) { "OOXML" }
276
+ let(:schema_location) { "https://raw.githubusercontent.com/t-yuki/ooxml-xsd/refs/heads/master" }
277
+ let(:xml) do
278
+ <<~XML
279
+ <m:CT_F xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math">
280
+ <m:fPr>
281
+ <m:type val="noBar"/>
282
+ </m:fPr>
283
+ <m:num>
284
+ <m:r/>
285
+ </m:num>
286
+ <m:den>
287
+ <m:r/>
288
+ </m:den>
289
+ </m:CT_F>
290
+ XML
771
291
  end
772
- end
773
292
 
774
- context "when given attribute_group contains ref" do
775
- let(:attribute_group) do
776
- Lutaml::Xsd::AttributeGroup.new.tap do |attr_group|
777
- attr_group.ref = "test_ref"
293
+ it "matches the expected class names of the schema" do
294
+ expect(defined?(OOXML::CTOMath)).to eq("constant")
295
+ # TODO: The error is not expected once the issue#359 is implemented.
296
+ expect(OOXML::CTOMath.instance_variable_get(:@attributes)).to be_empty
297
+ expect { OOXML::CTF.from_xml(xml) }.to raise_error(Lutaml::Model::IncorrectSequenceError) do |error|
298
+ expect(error.message).to match(/does not match the expected sequence/)
778
299
  end
779
- end
780
-
781
- let(:expected_hash) { { ref_class: "test_ref" } }
782
-
783
- it "returns the expected hash" do
784
- expect(setup_attribute_groups).to eql(expected_hash)
300
+ expect(OOXML::CTF.instance_variable_get(:@attributes)).not_to be_empty
785
301
  end
786
302
  end
787
303
 
788
- context "when attribute_group contains nothing" do
789
- let(:attribute_group) { Lutaml::Xsd::AttributeGroup.new }
790
-
791
- it "returns the empty hash" do
792
- expect(setup_attribute_groups).to be_empty
793
- end
794
- end
795
- end
796
-
797
- describe ".create_mapping_hash" do
798
- context "when given value is a string and hash_key is :class_name" do
799
- let(:value) { "test_value" }
800
- let(:expected_hash) { { class_name: "test_value" } }
801
-
802
- it "returns the expected hash" do
803
- expect(described_class.send(:create_mapping_hash, value, hash_key: :class_name)).to eql(expected_hash)
804
- end
805
- end
806
-
807
- context "when given value is a string and hash_key is :element_name" do
808
- let(:value) { "test_value" }
809
- let(:expected_hash) { { element_name: "test_value" } }
810
-
811
- it "returns the expected hash" do
812
- expect(described_class.send(:create_mapping_hash, value, hash_key: :element_name)).to eql(expected_hash)
813
- end
814
- end
815
-
816
- context "when given value is a array and hash_key is :ref_class" do
817
- let(:value) { ["test_value"] }
818
- let(:expected_hash) { { ref_class: ["test_value"] } }
819
-
820
- it "returns the expected hash" do
821
- expect(described_class.send(:create_mapping_hash, value, hash_key: :ref_class)).to eql(expected_hash)
822
- end
823
- end
824
-
825
- context "when given value is a string and hash_key is not given" do
826
- let(:value) { "test_value" }
827
- let(:expected_hash) { { class_name: "test_value" } }
828
-
829
- it "returns the expected hash" do
830
- expect(described_class.send(:create_mapping_hash, value)).to eql(expected_hash)
831
- end
832
- end
833
- end
834
-
835
- describe ".setup_element" do
836
- before do
837
- described_class.instance_variable_set(:@complex_types, complex_types)
838
- end
839
-
840
- after do
841
- described_class.instance_variable_set(:@complex_types, nil)
842
- end
843
-
844
- let(:setup_element) do
845
- described_class.send(:setup_element, element)
846
- end
847
-
848
- let(:complex_types) { { "test_complex_type" => {} } }
849
-
850
- context "when given element contains ref" do
851
- let(:element) do
852
- Lutaml::Xsd::Element.new.tap do |element|
853
- element.ref = "test_ref"
854
- end
855
- end
856
-
857
- let(:expected_hash) { { ref_class: "test_ref" } }
858
-
859
- it "returns the expected hash" do
860
- expect(setup_element).to eql(expected_hash)
861
- end
862
- end
863
-
864
- context "when given element contains ref with other attributes/elements" do
865
- let(:element) do
866
- Lutaml::Xsd::Element.new.tap do |element|
867
- element.ref = "test_ref"
868
- element.type = "test_type"
869
- element.name = "test_name"
870
- element.min_occurs = 0
871
- element.max_occurs = 1
872
- element.complex_type = Lutaml::Xsd::ComplexType.new(name: "test_complex_type")
873
- element.element_order = [Lutaml::Model::Xml::Element.new("Element", "complex_type")]
874
- end
875
- end
876
-
877
- let(:expected_hash) { { ref_class: "test_ref" } }
878
-
879
- it "returns the expected hash" do
880
- expect(setup_element).to eql(expected_hash)
881
- end
882
- end
883
-
884
- context "when given element contains type, name and min/max_occurs" do
885
- let(:element) do
886
- Lutaml::Xsd::Element.new.tap do |element|
887
- element.type = "test_type"
888
- element.name = "test_name"
889
- element.min_occurs = 0
890
- element.max_occurs = 1
891
- end
892
- end
893
-
894
- let(:expected_hash) do
895
- {
896
- type_name: "test_type",
897
- element_name: "test_name",
898
- arguments: { min_occurs: "0", max_occurs: "1" },
899
- }
900
- end
901
-
902
- it "returns the expected hash" do
903
- expect(setup_element).to eql(expected_hash)
904
- end
905
- end
906
-
907
- context "when given element contains name, type, and complex_type and no min/max_occurs" do
908
- let(:element) do
909
- Lutaml::Xsd::Element.new.tap do |element|
910
- element.type = "test_type"
911
- element.name = "test_name"
912
- element.complex_type = Lutaml::Xsd::ComplexType.new(name: "test_complex_type")
913
- element.element_order = [Lutaml::Model::Xml::Element.new("Element", "complex_type")]
914
- end
915
- end
916
-
917
- let(:expected_hash) do
918
- {
919
- type_name: "test_type",
920
- element_name: "test_name",
921
- complex_type: { mixed: false },
922
- }
923
- end
924
-
925
- it "returns the expected hash" do
926
- expect(setup_element).to eql(expected_hash)
927
- end
928
- end
929
-
930
- context "when given element contains nothing" do
931
- let(:element) { Lutaml::Xsd::Element.new }
932
- let(:expected_hash) { { type_name: nil, element_name: nil } }
933
-
934
- it "returns the expected hash" do
935
- expect(setup_element).to eql(expected_hash)
936
- end
937
- end
938
- end
939
-
940
- describe ".setup_restriction" do
941
- let(:setup_restriction) do
942
- described_class.send(:setup_restriction, restriction, {})
943
- end
944
-
945
- context "when given restriction contains base and pattern" do
946
- let(:restriction) do
947
- Lutaml::Xsd::RestrictionSimpleType.new.tap do |restriction|
948
- restriction.base = "test_base"
949
- restriction.pattern = [
950
- Lutaml::Xsd::Pattern.new(value: /test_pattern/),
951
- Lutaml::Xsd::Pattern.new(value: /test_pattern1/),
952
- ]
953
- restriction.enumeration = [
954
- Lutaml::Xsd::Enumeration.new(value: "test_value"),
955
- Lutaml::Xsd::Enumeration.new(value: "test_value1"),
956
- ]
957
- end
958
- end
959
-
960
- let(:expected_hash) do
961
- {
962
- base_class: "test_base",
963
- pattern: "((?-mix:test_pattern))|((?-mix:test_pattern1))",
964
- values: ["test_value", "test_value1"],
965
- }
966
- end
967
-
968
- it "returns the expected hash" do
969
- expect(setup_restriction).to eql(expected_hash)
970
- end
971
- end
972
-
973
- context "when given restriction contains nothing" do
974
- let(:restriction) { Lutaml::Xsd::RestrictionSimpleType.new }
975
-
976
- it "returns the expected hash" do
977
- expect(setup_restriction).to eql({ base_class: nil })
978
- end
979
- end
980
- end
981
-
982
- describe ".restriction_patterns" do
983
- let(:restriction_patterns) do
984
- described_class.send(:restriction_patterns, patterns, {})
985
- end
986
-
987
- context "when given patterns are not empty" do
988
- let(:patterns) do
989
- [
990
- Lutaml::Xsd::Pattern.new(value: /test_pattern/),
991
- Lutaml::Xsd::Pattern.new(value: /test_pattern1/),
992
- ]
993
- end
994
-
995
- let(:expected_hash) do
996
- { pattern: "((?-mix:test_pattern))|((?-mix:test_pattern1))" }
997
- end
998
-
999
- it "returns the expected hash" do
1000
- expect(restriction_patterns).to eql(expected_hash)
1001
- end
1002
- end
1003
-
1004
- context "when given patterns are empty" do
1005
- let(:patterns) { [] }
1006
-
1007
- it "returns the expected hash" do
1008
- expect(restriction_patterns).to be_nil
1009
- end
1010
- end
1011
- end
1012
-
1013
- describe ".setup_complex_content" do
1014
- let(:setup_complex_content) do
1015
- described_class.send(:setup_complex_content, complex_content)
1016
- end
1017
-
1018
- context "when complex_content contains extension with mixed attribute" do
1019
- let(:complex_content) do
1020
- Lutaml::Xsd::ComplexContent.new.tap do |complex_content|
1021
- complex_content.mixed = true
1022
- complex_content.extension =
1023
- Lutaml::Xsd::ExtensionComplexContent.new(base: "test_base")
1024
- end
1025
- end
1026
-
1027
- let(:expected_hash) do
1028
- { mixed: true, extension: { extension_base: "test_base" } }
1029
- end
1030
-
1031
- it "returns the expected hash" do
1032
- expect(setup_complex_content).to eql(expected_hash)
1033
- end
1034
- end
1035
-
1036
- context "when complex_content contains restriction" do
1037
- let(:complex_content) do
1038
- Lutaml::Xsd::ComplexContent.new.tap do |complex_content|
1039
- complex_content.restriction =
1040
- Lutaml::Xsd::RestrictionComplexContent.new(base: "test_base")
1041
- end
1042
- end
1043
-
1044
- let(:expected_hash) { { base_class: "test_base" } }
1045
-
1046
- it "returns the expected hash" do
1047
- expect(setup_complex_content).to eql(expected_hash)
1048
- end
1049
- end
1050
- end
1051
-
1052
- describe ".setup_extension" do
1053
- let(:setup_extension) do
1054
- described_class.send(:setup_extension, extension)
1055
- end
1056
-
1057
- context "when given extension contains attributes" do
1058
- let(:extension) do
1059
- Lutaml::Xsd::ExtensionComplexContent.new.tap do |extension|
1060
- extension.base = "test_base"
1061
- extension.attribute = [
1062
- Lutaml::Xsd::Attribute.new(type: "ST_Attr1", name: "Attr1", default: "1"),
1063
- Lutaml::Xsd::Attribute.new(type: "ST_Attr2", name: "Attr2", default: "2"),
1064
- ]
1065
- extension.sequence = Lutaml::Xsd::Sequence.new
1066
- extension.choice = Lutaml::Xsd::Choice.new
1067
- extension.element_order = create_pattern_mapping([
1068
- ["Element", "attribute"],
1069
- ["Element", "sequence"],
1070
- ["Element", "choice"],
1071
- ["Element", "attribute"],
1072
- ])
1073
- end
1074
- end
1075
-
1076
- let(:expected_hash) do
1077
- {
1078
- extension_base: "test_base",
1079
- attributes: [{ base_class: "ST_Attr1", name: "Attr1", default: "1" }, { base_class: "ST_Attr2", name: "Attr2", default: "2" }],
1080
- sequence: {},
1081
- choice: {},
1082
- }
1083
- end
1084
-
1085
- it "returns the expected hash" do
1086
- expect(setup_extension).to eql(expected_hash)
1087
- end
1088
- end
1089
-
1090
- context "when given extension contains nothing" do
1091
- let(:extension) { Lutaml::Xsd::ExtensionComplexContent.new }
1092
-
1093
- it "returns the expected hash" do
1094
- expect(setup_extension).to eql({ extension_base: nil })
1095
- end
1096
- end
1097
- end
1098
-
1099
- describe ".element_arguments" do
1100
- let(:element_arguments) do
1101
- described_class.send(:element_arguments, element, {})
1102
- end
1103
-
1104
- context "when given element contains min_occurs and max_occurs" do
1105
- let(:element) do
1106
- Lutaml::Xsd::Element.new.tap do |element|
1107
- element.min_occurs = "0"
1108
- element.max_occurs = "1"
1109
- end
1110
- end
1111
-
1112
- let(:expected_hash) { { min_occurs: "0", max_occurs: "1" } }
1113
-
1114
- it "returns the expected hash" do
1115
- expect(element_arguments).to eql(expected_hash)
1116
- end
1117
- end
1118
-
1119
- context "when given element contains nothing" do
1120
- let(:element) { Lutaml::Xsd::Element.new }
1121
-
1122
- it "returns the expected hash" do
1123
- expect(element_arguments).to be_empty
1124
- end
1125
- end
1126
- end
1127
-
1128
- describe ".resolved_element_order" do
1129
- let(:resolved_element_order) do
1130
- described_class.send(:resolved_element_order, element)
1131
- end
1132
-
1133
- context "when given element contains element_order but no instance relevant elements/instances" do
1134
- let(:element) do
1135
- Lutaml::Xsd::Element.new.tap do |element|
1136
- element.element_order = create_pattern_mapping([
1137
- ["Element", "annotation"],
1138
- ["Element", "simple_type"],
1139
- ["Element", "complex_type"],
1140
- ["Element", "key"],
1141
- ])
1142
- end
1143
- end
1144
-
1145
- it "raises an error when element_order contains elements that isn't an attribute of the instance" do
1146
- element.element_order << Lutaml::Model::Xml::Element.new("Element", "test_element")
1147
- expect { resolved_element_order }.to raise_error(NoMethodError)
1148
- end
1149
-
1150
- it "returns the array with nil values" do
1151
- expected_hash = [nil, nil, nil, nil]
1152
- expect(resolved_element_order).to eql(expected_hash)
1153
- end
1154
- end
1155
-
1156
- context "when given element contains element_order but with relevant elements/instances" do
1157
- let(:element) do
1158
- Lutaml::Xsd::Element.new.tap do |element|
1159
- element.annotation = Lutaml::Xsd::Annotation.new
1160
- element.simple_type = Lutaml::Xsd::SimpleType.new
1161
- element.complex_type = Lutaml::Xsd::ComplexType.new
1162
- element.key = Lutaml::Xsd::Key.new
1163
- element.element_order = create_pattern_mapping([
1164
- ["Element", "annotation"],
1165
- ["Element", "simple_type"],
1166
- ["Element", "complex_type"],
1167
- ["Element", "key"],
1168
- ])
1169
- end
1170
- end
1171
-
1172
- let(:expected_hash) do
1173
- [
1174
- element.annotation,
1175
- element.simple_type,
1176
- element.complex_type,
1177
- element.key,
1178
- ]
1179
- end
1180
-
1181
- it "returns the expected hash" do
1182
- expect(resolved_element_order).to eql(expected_hash)
1183
- end
1184
- end
1185
-
1186
- context "when given element contains empty element_order with elements/instances" do
1187
- let(:element) do
1188
- Lutaml::Xsd::Element.new.tap do |element|
1189
- element.element_order = []
1190
- end
1191
- end
1192
-
1193
- it "returns the expected hash" do
1194
- expect(resolved_element_order).to be_empty
304
+ context "when classes are generated and loaded but files are not created for UnitsML-v0.9.19 schema" do
305
+ before do
306
+ loaded_classes.merge!(
307
+ described_class.to_models(
308
+ Net::HTTP.get(URI(schema_url)),
309
+ namespace: "http://unitsml.nist.gov/unitsml-v0.9.19",
310
+ ),
311
+ )
312
+ namespaced_classes
313
+ end
314
+
315
+ let(:register_id) { :unitsmlv0919 }
316
+ let(:loaded_classes) { {} }
317
+ let(:module_name) { "UnitsMLV0919" }
318
+ let(:schema_url) { "https://raw.githubusercontent.com/unitsml/schemas/refs/heads/main/unitsml/unitsml-v0.9.19.xsd" }
319
+ let(:xml) do
320
+ <<~XML
321
+ <UnitsMLType xmlns="http://unitsml.nist.gov/unitsml-v0.9.19">
322
+ <UnitSet>
323
+ <Unit>
324
+ <UnitSystem type="SI"/>
325
+ <UnitName xml:lang="en">meter</UnitName>
326
+ <UnitSymbol type="ASCII">m</UnitSymbol>
327
+ </Unit>
328
+ </UnitSet>
329
+ </UnitsMLType>
330
+ XML
331
+ end
332
+
333
+ let(:detailed_xml) do
334
+ <<~XML
335
+ <UnitsMLType xmlns="http://unitsml.nist.gov/unitsml-v0.9.19">
336
+ <!-- Units -->
337
+ <UnitSet>
338
+ <!-- Base unit: meter -->
339
+ <Unit xml:id="u1" timeStamp="2024-06-01T00:00:00+00:00" dimensionURL="http://unitsml.nist.gov/si/length">
340
+ <UnitSystem name="SI" type="SI_base"/>
341
+ <UnitName>meter</UnitName>
342
+ <UnitSymbol type="ASCII">m</UnitSymbol>
343
+ <UnitVersionHistory>Initial definition</UnitVersionHistory>
344
+ <CodeListValue unitCodeValue="MTR" codeListName="UN/ECE Rec 20" codeListVersion="10A" locationURL="https://unece.org/trade/cefact/UNLOCODE-Download" organizationName="UNECE"/>
345
+ <RootUnits>
346
+ <EnumeratedRootUnit unit="meter"/>
347
+ </RootUnits>
348
+ <UnitDefinition sourceName="SI Brochure" sourceURL="https://www.bipm.org/en/publications/si-brochure">The meter is the SI unit of length.</UnitDefinition>
349
+ <UnitHistory>Defined as the distance light travels in vacuum in 1/299792458 seconds.</UnitHistory>
350
+ <UnitRemark>Most common length unit</UnitRemark>
351
+ </Unit>
352
+
353
+ <!-- Derived unit: meter per second -->
354
+ <Unit xml:id="u2" timeStamp="2024-06-01T00:00:00+00:00" dimensionURL="http://unitsml.nist.gov/si/speed">
355
+ <UnitSystem name="SI" type="SI_derived"/>
356
+ <UnitName>meter per second</UnitName>
357
+ <UnitSymbol type="ASCII">m/s</UnitSymbol>
358
+ <RootUnits>
359
+ <EnumeratedRootUnit unit="meter"/>
360
+ <EnumeratedRootUnit unit="second" powerNumerator="-1"/>
361
+ </RootUnits>
362
+ <Conversions>
363
+ <Float64ConversionFrom xml:id="c1" initialUnit="http://example.com/units#u3" initialAddend="0.0" multiplicand="3.6" divisor="1.0" finalAddend="0.0" exact="true">
364
+ <ConversionNote>Convert from kilometers per hour to meters per second</ConversionNote>
365
+ </Float64ConversionFrom>
366
+ </Conversions>
367
+ <QuantityReference url="http://example.com/units#q2" name="speed"/>
368
+ <UnitDefinition>Speed unit in SI</UnitDefinition>
369
+ </Unit>
370
+
371
+ <!-- Non-SI unit: kilometer per hour -->
372
+ <Unit xml:id="u3" timeStamp="2024-06-01T00:00:00+00:00" dimensionURL="http://unitsml.nist.gov/si/speed">
373
+ <UnitSystem name="SI" type="non-SI_accepted"/>
374
+ <UnitName>kilometer per hour</UnitName>
375
+ <UnitSymbol type="ASCII">km/h</UnitSymbol>
376
+ <RootUnits>
377
+ <EnumeratedRootUnit unit="meter" prefix="k"/>
378
+ <EnumeratedRootUnit unit="second" powerNumerator="-1"/>
379
+ <EnumeratedRootUnit unit="hour" powerNumerator="-1"/>
380
+ </RootUnits>
381
+ <Conversions>
382
+ <Float64ConversionFrom xml:id="c2" initialUnit="http://example.com/units#u2" initialAddend="0.0" multiplicand="1.0" divisor="3.6" finalAddend="0.0" exact="true">
383
+ <ConversionNote>Convert from meters per second to kilometers per hour</ConversionNote>
384
+ </Float64ConversionFrom>
385
+ </Conversions>
386
+ <QuantityReference url="http://example.com/units#q2" name="speed"/>
387
+ <UnitDefinition>Common speed unit for vehicles</UnitDefinition>
388
+ </Unit>
389
+ </UnitSet>
390
+
391
+ <!-- Quantities -->
392
+ <QuantitySet>
393
+ <Quantity xml:id="q1" quantityType="base" dimensionURL="http://unitsml.nist.gov/si/length">
394
+ <QuantityName>length</QuantityName>
395
+ <QuantitySymbol type="ASCII">l</QuantitySymbol>
396
+ <UnitReference url="http://example.com/units#u1" name="meter"/>
397
+ <QuantityDefinition sourceName="SI Brochure" sourceURL="https://www.bipm.org/en/publications/si-brochure">Distance between two points</QuantityDefinition>
398
+ <QuantityRemark>SI base quantity</QuantityRemark>
399
+ </Quantity>
400
+ <Quantity xml:id="q2" quantityType="derived" dimensionURL="http://unitsml.nist.gov/si/speed">
401
+ <QuantityName>speed</QuantityName>
402
+ <QuantitySymbol type="ASCII">v</QuantitySymbol>
403
+ <UnitReference url="http://example.com/units#u2" name="meter per second"/>
404
+ <QuantityDefinition>Rate of change of position</QuantityDefinition>
405
+ </Quantity>
406
+ </QuantitySet>
407
+
408
+ <!-- Dimensions -->
409
+ <DimensionSet>
410
+ <Dimension xml:id="d1">
411
+ <Length powerNumerator="1"/>
412
+ </Dimension>
413
+ <Dimension xml:id="d2">
414
+ <Length powerNumerator="1"/>
415
+ <Time powerNumerator="-1"/>
416
+ </Dimension>
417
+ <Dimension xml:id="d3" dimensionless="true"/>
418
+ <Dimension xml:id="d4">
419
+ <Time powerNumerator="-1"/>
420
+ <Item itemURL="http://example.com/items#ci1" itemSymbol="e⁻" powerNumerator="1"/>
421
+ </Dimension>
422
+ </DimensionSet>
423
+
424
+ <!-- Prefixes -->
425
+ <PrefixSet>
426
+ <Prefix xml:id="p1" prefixBase="10" prefixPower="3">
427
+ <PrefixName>kilo</PrefixName>
428
+ <PrefixSymbol type="ASCII">k</PrefixSymbol>
429
+ </Prefix>
430
+ <Prefix xml:id="p2" prefixBase="2" prefixPower="10">
431
+ <PrefixName>kibi</PrefixName>
432
+ <PrefixSymbol type="ASCII">Ki</PrefixSymbol>
433
+ </Prefix>
434
+ </PrefixSet>
435
+ </UnitsMLType>
436
+ XML
437
+ end
438
+
439
+ it "matches the converted xml with the expected xml with a short example" do
440
+ expect(UnitsMLV0919::UnitsMLType.from_xml(xml).to_xml).to be_equivalent_to(xml)
441
+ end
442
+
443
+ it "matches the converted xml with the expected xml with a detailed example" do
444
+ expect(UnitsMLV0919::UnitsMLType.from_xml(detailed_xml).to_xml).to be_equivalent_to(detailed_xml)
445
+ end
446
+ end
447
+
448
+ context "when classes are generated and loaded but files are not created for UnitsML-v1.0-csd03 schema" do
449
+ before do
450
+ loaded_classes.merge!(
451
+ described_class.to_models(
452
+ Net::HTTP.get(
453
+ URI(schema_url),
454
+ ),
455
+ ),
456
+ )
457
+ namespaced_classes
458
+ end
459
+
460
+ let(:register_id) { :unitsml_v1_0_csd03 }
461
+ let(:loaded_classes) { {} }
462
+ let(:module_name) { "UnitsMLV10CSD03" }
463
+ let(:schema_url) { "https://raw.githubusercontent.com/unitsml/schemas/refs/heads/main/unitsml/unitsml-v1.0-csd03.xsd" }
464
+ let(:xml) do
465
+ <<~XML
466
+ <UnitsMLType>
467
+ <UnitSet>
468
+ <Unit xml:id="U_m">
469
+ <UnitSystem type="SI"/>
470
+ <UnitName xml:lang="en">meter</UnitName>
471
+ <UnitSymbol type="ASCII">m</UnitSymbol>
472
+ </Unit>
473
+ <Unit xml:id="U_km">
474
+ <UnitSystem type="SI"/>
475
+ <UnitName xml:lang="en">kilometer</UnitName>
476
+ <UnitSymbol type="ASCII">km</UnitSymbol>
477
+ </Unit>
478
+ </UnitSet>
479
+ </UnitsMLType>
480
+ XML
481
+ end
482
+
483
+ let(:detailed_xml) do
484
+ <<~XML
485
+ <UnitsMLType>
486
+ <UnitSet>
487
+ <Unit xml:id="u_meter" timeStamp="2024-06-01T12:00:00+00:00" dimensionURL="http://unitsml.nist.gov/si/meter">
488
+ <UnitSystem name="SI" type="SI_base"/>
489
+ <UnitName xml:lang="en">meter</UnitName>
490
+ <UnitSymbol type="ASCII">m</UnitSymbol>
491
+ <CodeListValue unitCodeValue="MTR" codeListName="UN/ECE Rec 20" codeListVersion="10A" locationURL="http://www.unece.org/cefact/codesfortrade/codes_index.html" organizationName="UNECE"/>
492
+ <RootUnits>
493
+ <EnumeratedRootUnit unit="meter"/>
494
+ </RootUnits>
495
+ <UnitVersionHistory>Initial definition of the meter.</UnitVersionHistory>
496
+ <UnitDefinition>The meter is the SI base unit of length.</UnitDefinition>
497
+ <UnitHistory>Defined as the distance light travels in vacuum in 1/299792458 seconds.</UnitHistory>
498
+ <UnitRemark>Commonly used in science and engineering.</UnitRemark>
499
+ </Unit>
500
+ <Unit xml:id="u_second" timeStamp="2024-06-01T12:00:00+00:00" dimensionURL="http://unitsml.nist.gov/si/second">
501
+ <UnitSystem name="SI" type="SI_base"/>
502
+ <UnitName xml:lang="en">second</UnitName>
503
+ <UnitSymbol type="ASCII">s</UnitSymbol>
504
+ <RootUnits>
505
+ <EnumeratedRootUnit unit="second"/>
506
+ </RootUnits>
507
+ </Unit>
508
+ <Unit xml:id="u_newton" timeStamp="2024-06-01T12:00:00+00:00" dimensionURL="http://unitsml.nist.gov/si/newton">
509
+ <UnitSystem name="SI" type="SI_derived"/>
510
+ <UnitName xml:lang="en">newton</UnitName>
511
+ <UnitSymbol type="ASCII">N</UnitSymbol>
512
+ <RootUnits>
513
+ <EnumeratedRootUnit unit="meter"/>
514
+ <EnumeratedRootUnit unit="gram"/>
515
+ <EnumeratedRootUnit unit="second" powerNumerator="-2"/>
516
+ </RootUnits>
517
+ <Conversions>
518
+ <Float64ConversionFrom xml:id="conv1" initialUnit="http://unitsml.nist.gov/si/meter#u_gram_meter_per_second_squared" multiplicand="1.0" divisor="1.0" exact="true"/>
519
+ </Conversions>
520
+ </Unit>
521
+ </UnitSet>
522
+ </UnitsMLType>
523
+ XML
524
+ end
525
+
526
+ it "matches the converted xml with the expected xml with a short example" do
527
+ expect(UnitsMLV10CSD03::UnitsMLType.from_xml(xml).to_xml).to be_equivalent_to(xml)
528
+ end
529
+
530
+ it "matches the converted xml with the expected xml with a detailed example" do
531
+ expect(UnitsMLV10CSD03::UnitsMLType.from_xml(detailed_xml).to_xml).to be_equivalent_to(detailed_xml)
532
+ end
533
+ end
534
+
535
+ context "when classes are generated and loaded but files are not created for UnitsML-v1.0-csd04 schema" do
536
+ before do
537
+ loaded_classes.merge!(
538
+ described_class.to_models(
539
+ Net::HTTP.get(
540
+ URI(schema_url),
541
+ ),
542
+ ),
543
+ )
544
+ namespaced_classes
545
+ end
546
+
547
+ let(:register_id) { :unitsml_v1_0_csd04 }
548
+ let(:loaded_classes) { {} }
549
+ let(:module_name) { "UnitsMLV10CSD04" }
550
+ let(:schema_url) { "https://raw.githubusercontent.com/unitsml/schemas/refs/heads/main/unitsml/unitsml-v1.0-csd04.xsd" }
551
+ let(:xml) do
552
+ <<~XML
553
+ <UnitsMLType>
554
+ <UnitSet>
555
+ <Unit xml:id="U_m">
556
+ <UnitSystem type="SI"/>
557
+ <UnitName xml:lang="en">meter</UnitName>
558
+ <UnitSymbol type="ASCII">m</UnitSymbol>
559
+ </Unit>
560
+ <Unit xml:id="U_km">
561
+ <UnitSystem type="SI"/>
562
+ <UnitName xml:lang="en">kilometer</UnitName>
563
+ <UnitSymbol type="ASCII">km</UnitSymbol>
564
+ </Unit>
565
+ </UnitSet>
566
+ </UnitsMLType>
567
+ XML
568
+ end
569
+
570
+ let(:detailed_xml) do
571
+ <<~XML
572
+ <UnitsMLType>
573
+ <UnitSet>
574
+ <Unit xml:id="u_meter" timeStamp="2024-06-01T12:00:00+00:00" dimensionURL="http://unitsml.nist.gov/si/meter">
575
+ <UnitSystem name="SI" type="SI_base"/>
576
+ <UnitName xml:lang="en">meter</UnitName>
577
+ <UnitSymbol type="ASCII">m</UnitSymbol>
578
+ <CodeListValue unitCodeValue="MTR" codeListName="UN/ECE Rec 20" codeListVersion="10A" locationURL="http://www.unece.org/cefact/codesfortrade/codes_index.html" organizationName="UNECE"/>
579
+ <RootUnits>
580
+ <EnumeratedRootUnit unit="meter"/>
581
+ </RootUnits>
582
+ <UnitVersionHistory>Initial definition of the meter.</UnitVersionHistory>
583
+ <UnitDefinition>The meter is the SI base unit of length.</UnitDefinition>
584
+ <UnitHistory>Defined as the distance light travels in vacuum in 1/299792458 seconds.</UnitHistory>
585
+ <UnitRemark>Commonly used in science and engineering.</UnitRemark>
586
+ </Unit>
587
+ <Unit xml:id="u_second" timeStamp="2024-06-01T12:00:00+00:00" dimensionURL="http://unitsml.nist.gov/si/second">
588
+ <UnitSystem name="SI" type="SI_base"/>
589
+ <UnitName xml:lang="en">second</UnitName>
590
+ <UnitSymbol type="ASCII">s</UnitSymbol>
591
+ <RootUnits>
592
+ <EnumeratedRootUnit unit="second"/>
593
+ </RootUnits>
594
+ </Unit>
595
+ <Unit xml:id="u_newton" timeStamp="2024-06-01T12:00:00+00:00" dimensionURL="http://unitsml.nist.gov/si/newton">
596
+ <UnitSystem name="SI" type="SI_derived"/>
597
+ <UnitName xml:lang="en">newton</UnitName>
598
+ <UnitSymbol type="ASCII">N</UnitSymbol>
599
+ <RootUnits>
600
+ <EnumeratedRootUnit unit="meter"/>
601
+ <EnumeratedRootUnit unit="gram"/>
602
+ <EnumeratedRootUnit unit="second" powerNumerator="-2"/>
603
+ </RootUnits>
604
+ <Conversions>
605
+ <Float64ConversionFrom xml:id="conv1" initialUnit="http://unitsml.nist.gov/si/meter#u_gram_meter_per_second_squared" multiplicand="1.0" divisor="1.0" exact="true"/>
606
+ </Conversions>
607
+ </Unit>
608
+ </UnitSet>
609
+ </UnitsMLType>
610
+ XML
611
+ end
612
+
613
+ it "matches the converted xml with the expected xml with a short example" do
614
+ expect(UnitsMLV10CSD04::UnitsMLType.from_xml(xml).to_xml).to be_equivalent_to(xml)
615
+ end
616
+
617
+ it "matches the converted xml with the expected xml with a detailed example" do
618
+ expect(UnitsMLV10CSD04::UnitsMLType.from_xml(detailed_xml).to_xml).to be_equivalent_to(detailed_xml)
1195
619
  end
1196
620
  end
1197
621
  end
1198
622
  end
1199
-
1200
- describe "structure to template content resolving methods" do
1201
- describe ".resolve_parent_class" do
1202
- let(:resolve_parent_class) do
1203
- described_class.send(:resolve_parent_class, content)
1204
- end
1205
-
1206
- context "when complex_content.extension is not present" do
1207
- let(:content) { {} }
1208
-
1209
- it "returns Lutaml::Model::Serializable" do
1210
- expect(resolve_parent_class).to eql("Lutaml::Model::Serializable")
1211
- end
1212
- end
1213
-
1214
- context "when complex_content.extension is present" do
1215
- let(:content) do
1216
- { complex_content: { extension: { extension_base: "ST_Parent" } } }
1217
- end
1218
-
1219
- it "returns the extension_base value" do
1220
- expect(resolve_parent_class).to eql("STParent")
1221
- end
1222
- end
1223
- end
1224
-
1225
- describe ".resolve_attribute_class" do
1226
- let(:resolve_attribute_class) do
1227
- described_class.send(:resolve_attribute_class, base_class_hash)
1228
- end
1229
-
1230
- described_class::DEFAULT_CLASSES.each do |standard_class|
1231
- context "when #{standard_class.capitalize}" do
1232
- let(:base_class_hash) do
1233
- to_mapping_hash({ base_class: "xsd:#{standard_class}" })
1234
- end
1235
-
1236
- it "returns :#{standard_class}" do
1237
- expect(resolve_attribute_class).to eql(":#{standard_class}")
1238
- end
1239
- end
1240
- end
1241
-
1242
- context "when attribute.base_class is not one of the standard classes" do
1243
- let(:base_class_hash) do
1244
- to_mapping_hash({ base_class: "test_st_attr1" })
1245
- end
1246
-
1247
- it "returns the attribute_class value" do
1248
- expect(resolve_attribute_class).to eql("TestStAttr1")
1249
- end
1250
- end
1251
- end
1252
-
1253
- describe ".resolve_element_class" do
1254
- let(:resolve_element_class) do
1255
- described_class.send(:resolve_element_class, type_name_hash)
1256
- end
1257
-
1258
- described_class::DEFAULT_CLASSES.each do |standard_class|
1259
- context "when #{standard_class.capitalize}" do
1260
- let(:type_name_hash) do
1261
- to_mapping_hash({ type_name: "xsd:#{standard_class}" })
1262
- end
1263
-
1264
- it "returns :#{standard_class}" do
1265
- expect(resolve_element_class).to eql(":#{standard_class}")
1266
- end
1267
- end
1268
- end
1269
-
1270
- context "when element.type_name is not one of the standard classes" do
1271
- let(:type_name_hash) do
1272
- to_mapping_hash({ type_name: "test_st_element1" })
1273
- end
1274
-
1275
- it "returns the element_class value" do
1276
- expect(resolve_element_class).to eql("TestStElement1")
1277
- end
1278
- end
1279
- end
1280
-
1281
- describe ".resolve_occurs" do
1282
- let(:resolve_occours) do
1283
- described_class.send(:resolve_occurs, base_class_hash)
1284
- end
1285
-
1286
- context "when max_occurs is unbounded" do
1287
- let(:base_class_hash) do
1288
- to_mapping_hash({ min_occurs: 0, max_occurs: "unbounded" })
1289
- end
1290
-
1291
- it "returns the collection: true" do
1292
- expect(resolve_occours).to eql(", collection: true")
1293
- end
1294
- end
1295
-
1296
- context "when max_occurs is 1" do
1297
- let(:base_class_hash) do
1298
- to_mapping_hash({ min_occurs: 0, max_occurs: 1 })
1299
- end
1300
-
1301
- it "returns the collection: 0..1" do
1302
- expect(resolve_occours).to eql(", collection: 0..1")
1303
- end
1304
- end
1305
-
1306
- context "when min_occurs/max_occurs are not present" do
1307
- let(:base_class_hash) { {} }
1308
-
1309
- it "returns the collection: 0.." do
1310
- expect(resolve_occours).to eql(", collection: true")
1311
- end
1312
- end
1313
- end
1314
-
1315
- describe ".resolve_elements" do
1316
- before do
1317
- described_class.instance_variable_set(:@elements, elements)
1318
- end
1319
-
1320
- after do
1321
- described_class.instance_variable_set(:@elements, nil)
1322
- end
1323
-
1324
- let(:resolve_elements) do
1325
- described_class.send(:resolve_elements, content)
1326
- end
1327
-
1328
- let(:elements) do
1329
- to_mapping_hash(
1330
- { "testRef" => to_mapping_hash({ element_name: "testElement" }) },
1331
- )
1332
- end
1333
-
1334
- context "when elements contain ref_class and base_class elements" do
1335
- let(:content) do
1336
- [
1337
- to_mapping_hash({ ref_class: "testRef" }),
1338
- to_mapping_hash({ element_name: "testElement1" }),
1339
- ]
1340
- end
1341
-
1342
- let(:expected_elements) do
1343
- {
1344
- "testElement" => { element_name: "testElement" },
1345
- "testElement1" => { element_name: "testElement1" },
1346
- }
1347
- end
1348
-
1349
- it "returns the elements hash" do
1350
- expect(resolve_elements).to eql(expected_elements)
1351
- end
1352
- end
1353
- end
1354
-
1355
- describe ".resolve_content" do
1356
- let(:content) do
1357
- {
1358
- sequence: [],
1359
- choice: [],
1360
- group: [],
1361
- }
1362
- end
1363
-
1364
- context "when content contain empty sequence, choice and group" do
1365
- it "returns the elements hash" do
1366
- expect(described_class.send(:resolve_content, content)).to be_empty
1367
- end
1368
- end
1369
- end
1370
-
1371
- describe ".resolve_sequence" do
1372
- let(:sequence) do
1373
- {
1374
- sequence: [],
1375
- elements: [],
1376
- groups: [],
1377
- choice: [],
1378
- }
1379
- end
1380
-
1381
- context "when sequence contain empty elements and empty attributes" do
1382
- it "returns the elements empty hash" do
1383
- expect(described_class.send(:resolve_sequence, sequence)).to be_empty
1384
- end
1385
- end
1386
- end
1387
-
1388
- describe ".resolve_choice" do
1389
- let(:resolve_choice) do
1390
- described_class.send(:resolve_choice, choice)
1391
- end
1392
-
1393
- let(:choice) do
1394
- {
1395
- "string" => to_mapping_hash({ element_name: "testElement" }),
1396
- sequence: [],
1397
- element: [],
1398
- group: [],
1399
- }
1400
- end
1401
-
1402
- context "when choice contain empty elements and other empty attributes" do
1403
- it "returns the one element hash" do
1404
- expect(resolve_choice)
1405
- .to eql({ "string" => { element_name: "testElement" } })
1406
- end
1407
- end
1408
- end
1409
-
1410
- describe ".resolve_group" do
1411
- before do
1412
- described_class.instance_variable_set(:@group_types, group_types)
1413
- end
1414
-
1415
- after do
1416
- described_class.instance_variable_set(:@group_types, nil)
1417
- end
1418
-
1419
- let(:group_types) { { "testRef" => {} } }
1420
-
1421
- let(:group) do
1422
- {
1423
- ref_class: "testRef",
1424
- sequence: [],
1425
- choice: [],
1426
- group: [],
1427
- }
1428
- end
1429
-
1430
- context "when group contain ref_class and other empty attributes" do
1431
- it "returns the one element hash" do
1432
- expect(described_class.send(:resolve_group, group)).to be_empty
1433
- end
1434
- end
1435
- end
1436
-
1437
- describe ".resolve_complex_content" do
1438
- let(:resolve_complex_content) do
1439
- described_class.send(:resolve_complex_content, complex_content)
1440
- end
1441
-
1442
- let(:complex_content) do
1443
- {
1444
- extension: {},
1445
- restriction: {},
1446
- }
1447
- end
1448
-
1449
- context "when complex_content contain extension and restriction" do
1450
- it "returns the one element hash" do
1451
- expect(resolve_complex_content).to be_empty
1452
- end
1453
- end
1454
- end
1455
-
1456
- describe ".resolve_extension" do
1457
- let(:resolve_extension) do
1458
- described_class.send(:resolve_extension, to_mapping_hash(extension))
1459
- end
1460
-
1461
- let(:extension) do
1462
- {
1463
- attributes: [
1464
- { base_class: "ST_Attr1", default: "1" },
1465
- { base_class: "ST_Attr2", default: "2" },
1466
- ],
1467
- sequence: {},
1468
- choice: {},
1469
- }
1470
- end
1471
-
1472
- context "when extension contain attributes, sequence and choice" do
1473
- it "returns the one element hash" do
1474
- expect(resolve_extension)
1475
- .to eql({ attributes: extension[:attributes] })
1476
- end
1477
- end
1478
- end
1479
-
1480
- describe ".resolve_attribute_default" do
1481
- let(:resolve_attribute_default) do
1482
- described_class.send(:resolve_attribute_default, attribute)
1483
- end
1484
-
1485
- context "when attribute contain default" do
1486
- let(:attribute) do
1487
- to_mapping_hash({ base_class: "ST_Attr1", default: "1" })
1488
- end
1489
-
1490
- it "returns the string with default value" do
1491
- expect(resolve_attribute_default).to eql(", default: \"1\"")
1492
- end
1493
- end
1494
-
1495
- context "when attribute contain no default" do
1496
- let(:attribute) { to_mapping_hash({ base_class: "ST_Attr1" }) }
1497
-
1498
- it "returns the string with nil as default value" do
1499
- expect(resolve_attribute_default).to eql(", default: nil")
1500
- end
1501
- end
1502
- end
1503
-
1504
- describe ".resolve_attribute_default_value" do
1505
- let(:resolve_attribute_default_value) do
1506
- described_class.send(
1507
- :resolve_attribute_default_value,
1508
- class_name,
1509
- input,
1510
- )
1511
- end
1512
-
1513
- let(:standard_class_value) do
1514
- {
1515
- "int" => { input: "1", output: 1 },
1516
- "integer" => { input: "12", output: 12 },
1517
- "string" => { input: "test_string", output: "test_string" },
1518
- "boolean" => { input: "false", output: false },
1519
- }
1520
- end
1521
-
1522
- described_class::DEFAULT_CLASSES.each do |standard_class|
1523
- describe "for #{standard_class.capitalize} class" do
1524
- let(:default_value) { standard_class_value[standard_class] }
1525
- let(:class_name) { standard_class }
1526
- let(:input) { default_value[:input] }
1527
-
1528
- it "returns an instance of #{standard_class.capitalize}" do
1529
- expect(resolve_attribute_default_value)
1530
- .to eql(default_value[:output])
1531
- end
1532
- end
1533
- end
1534
-
1535
- context "when attribute data type is not one of the standard classes" do
1536
- let(:class_name) { "BooleanTestClass" }
1537
- let(:input) { "1" }
1538
-
1539
- it "returns the string with default value" do
1540
- expect(resolve_attribute_default_value).to eql("\"1\"")
1541
- end
1542
- end
1543
- end
1544
-
1545
- describe ".resolve_namespace" do
1546
- let(:resolved_namespace) do
1547
- described_class.send(
1548
- :resolve_namespace,
1549
- namespace_attrs,
1550
- )
1551
- end
1552
-
1553
- context "when namespace is given" do
1554
- let(:namespace_attrs) { { namespace: "testNamespace" } }
1555
-
1556
- it "returns the string with namespace" do
1557
- expect(resolved_namespace)
1558
- .to eql("namespace \"testNamespace\"\n")
1559
- end
1560
- end
1561
-
1562
- context "when namespace and prefix are given" do
1563
- let(:namespace_attrs) do
1564
- {
1565
- namespace: "testNamespace",
1566
- prefix: "testPrefix",
1567
- }
1568
- end
1569
-
1570
- it "returns the string with namespace and prefix" do
1571
- expect(resolved_namespace)
1572
- .to eql("namespace \"testNamespace\", \"testPrefix\"\n")
1573
- end
1574
- end
1575
-
1576
- context "when namespace and prefix are not given" do
1577
- it "returns the string with nil" do
1578
- expect(described_class.send(:resolve_namespace, {})).to be_nil
1579
- end
1580
- end
1581
- end
1582
- end
1583
-
1584
- describe "required files list compiler methods" do
1585
- let(:required_files) do
1586
- described_class.instance_variable_get(:@required_files)
1587
- end
1588
-
1589
- describe ".resolve_required_files" do
1590
- context "when elements are given" do
1591
- before do
1592
- described_class.instance_variable_set(:@required_files, [])
1593
- end
1594
-
1595
- after do
1596
- described_class.instance_variable_set(:@required_files, nil)
1597
- end
1598
-
1599
- let(:content) do
1600
- {
1601
- attribute_groups: {},
1602
- complex_content: {},
1603
- simple_content: {},
1604
- attributes: {},
1605
- sequence: {},
1606
- choice: {},
1607
- group: {},
1608
- }
1609
- end
1610
-
1611
- it "populates @required_files" do
1612
- described_class.send(:resolve_required_files, content)
1613
- expect(required_files).to eql([])
1614
- end
1615
- end
1616
- end
1617
-
1618
- describe ".required_files_simple_content" do
1619
- context "when elements are given" do
1620
- before do
1621
- described_class.instance_variable_set(:@required_files, [])
1622
- end
1623
-
1624
- after do
1625
- described_class.instance_variable_set(:@required_files, nil)
1626
- end
1627
-
1628
- let(:content) do
1629
- {
1630
- extension_base: {},
1631
- attributes: {},
1632
- extension: {},
1633
- restriction: {},
1634
- }
1635
- end
1636
-
1637
- it "populates @required_files" do
1638
- described_class.send(:required_files_simple_content, content)
1639
- expect(required_files).to eql([])
1640
- end
1641
- end
1642
- end
1643
-
1644
- describe ".required_files_complex_content" do
1645
- context "when elements are given" do
1646
- before do
1647
- described_class.instance_variable_set(:@required_files, [])
1648
- end
1649
-
1650
- after do
1651
- described_class.instance_variable_set(:@required_files, nil)
1652
- end
1653
-
1654
- let(:content) do
1655
- {
1656
- extension: {},
1657
- restriction: {},
1658
- }
1659
- end
1660
-
1661
- it "populates @required_files" do
1662
- described_class.send(:required_files_complex_content, content)
1663
- expect(required_files).to eql([])
1664
- end
1665
- end
1666
- end
1667
-
1668
- describe ".required_files_extension" do
1669
- context "when elements are given" do
1670
- before do
1671
- described_class.instance_variable_set(:@required_files, [])
1672
- end
1673
-
1674
- after do
1675
- described_class.instance_variable_set(:@required_files, nil)
1676
- end
1677
-
1678
- let(:content) do
1679
- {
1680
- attribute_group: {},
1681
- extension_base: {},
1682
- attributes: {},
1683
- attribute: {},
1684
- sequence: {},
1685
- choice: {},
1686
- }
1687
- end
1688
-
1689
- it "populates @required_files" do
1690
- described_class.send(:required_files_extension, content)
1691
- expect(required_files).to eql([])
1692
- end
1693
- end
1694
- end
1695
-
1696
- describe ".required_files_restriction" do
1697
- context "when elements are given" do
1698
- before do
1699
- described_class.instance_variable_set(:@required_files, [])
1700
- end
1701
-
1702
- after do
1703
- described_class.instance_variable_set(:@required_files, nil)
1704
- end
1705
-
1706
- let(:content) { { base: "testId" } }
1707
-
1708
- it "populates @required_files" do
1709
- described_class.send(:required_files_restriction, content)
1710
- expect(required_files).to eql(["test_id"])
1711
- end
1712
- end
1713
- end
1714
-
1715
- describe ".required_files_attribute_groups" do
1716
- context "when elements are given" do
1717
- before do
1718
- described_class.instance_variable_set(:@required_files, [])
1719
- described_class.instance_variable_set(:@attribute_groups, attribute_groups)
1720
- end
1721
-
1722
- after do
1723
- described_class.instance_variable_set(:@required_files, nil)
1724
- described_class.instance_variable_set(:@attribute_groups, nil)
1725
- end
1726
-
1727
- let(:attribute_groups) { { "testId" => {} } }
1728
-
1729
- let(:content) do
1730
- {
1731
- ref_class: "testId",
1732
- attributes: {},
1733
- attribute: {},
1734
- }
1735
- end
1736
-
1737
- it "populates @required_files" do
1738
- described_class.send(:required_files_attribute_groups, content)
1739
- expect(required_files).to eql([])
1740
- end
1741
- end
1742
- end
1743
-
1744
- describe ".required_files_attribute" do
1745
- context "when elements are given" do
1746
- before do
1747
- described_class.instance_variable_set(:@required_files, [])
1748
- described_class.instance_variable_set(:@attributes, attributes)
1749
- end
1750
-
1751
- after do
1752
- described_class.instance_variable_set(:@required_files, nil)
1753
- described_class.instance_variable_set(:@attributes, nil)
1754
- end
1755
-
1756
- let(:attributes) do
1757
- {
1758
- "testRef" => to_mapping_hash({ base_class: "ST_Attr1" }),
1759
- }
1760
- end
1761
-
1762
- let(:content) do
1763
- [
1764
- to_mapping_hash({ ref_class: "testRef" }),
1765
- to_mapping_hash({ base_class: "ST_Attr2" }),
1766
- ]
1767
- end
1768
-
1769
- it "populates @required_files" do
1770
- described_class.send(:required_files_attribute, content)
1771
- expect(required_files).to eql(["st_attr1", "st_attr2"])
1772
- end
1773
- end
1774
- end
1775
-
1776
- describe ".required_files_choice" do
1777
- context "when elements are given" do
1778
- before { described_class.instance_variable_set(:@required_files, []) }
1779
- after { described_class.instance_variable_set(:@required_files, nil) }
1780
-
1781
- let(:content) do
1782
- {
1783
- "testRef" => to_mapping_hash({ type_name: "ST_Attr1" }),
1784
- sequence: {},
1785
- element: {},
1786
- choice: {},
1787
- group: {},
1788
- }
1789
- end
1790
-
1791
- it "populates @required_files" do
1792
- described_class.send(:required_files_choice, content)
1793
- expect(required_files).to eql(["st_attr1"])
1794
- end
1795
- end
1796
- end
1797
-
1798
- describe ".required_files_group" do
1799
- context "when elements are given" do
1800
- before do
1801
- described_class.instance_variable_set(:@required_files, [])
1802
- described_class.instance_variable_set(:@group_types, group_types)
1803
- end
1804
-
1805
- after do
1806
- described_class.instance_variable_set(:@required_files, nil)
1807
- described_class.instance_variable_set(:@group_types, nil)
1808
- end
1809
-
1810
- let(:group_types) { { "testRef" => {} } }
1811
- let(:content) do
1812
- {
1813
- ref_class: "testRef",
1814
- sequence: {},
1815
- choice: {},
1816
- }
1817
- end
1818
-
1819
- it "populates @required_files" do
1820
- described_class.send(:required_files_group, content)
1821
- expect(required_files).to eql([])
1822
- end
1823
- end
1824
- end
1825
-
1826
- describe ".required_files_sequence" do
1827
- context "when elements are given" do
1828
- before do
1829
- described_class.instance_variable_set(:@required_files, [])
1830
- end
1831
-
1832
- after do
1833
- described_class.instance_variable_set(:@required_files, nil)
1834
- end
1835
-
1836
- let(:content) do
1837
- {
1838
- elements: {},
1839
- sequence: {},
1840
- groups: {},
1841
- choice: {},
1842
- }
1843
- end
1844
-
1845
- it "populates @required_files" do
1846
- described_class.send(:required_files_sequence, content)
1847
- expect(required_files).to eql([])
1848
- end
1849
- end
1850
- end
1851
-
1852
- describe ".required_files_elements" do
1853
- context "when given element's data type is not one of standard class" do
1854
- before do
1855
- described_class.instance_variable_set(:@required_files, [])
1856
- described_class.instance_variable_set(:@elements, elements)
1857
- end
1858
-
1859
- after do
1860
- described_class.instance_variable_set(:@required_files, nil)
1861
- described_class.instance_variable_set(:@elements, nil)
1862
- end
1863
-
1864
- let(:elements) do
1865
- {
1866
- "CT_Element1" => to_mapping_hash({ type_name: "w:CT_Element1" }),
1867
- }
1868
- end
1869
-
1870
- let(:content) do
1871
- [
1872
- to_mapping_hash({ ref_class: "CT_Element1" }),
1873
- to_mapping_hash({ type_name: "CT_Element2" }),
1874
- ]
1875
- end
1876
-
1877
- it "populates @required_files" do
1878
- described_class.send(:required_files_elements, content)
1879
- expect(required_files).to eql(["ct_element1", "ct_element2"])
1880
- end
1881
- end
1882
-
1883
- context "when given element's data type is one of standard class" do
1884
- before do
1885
- described_class.instance_variable_set(:@required_files, [])
1886
- described_class.instance_variable_set(:@elements, elements)
1887
- end
1888
-
1889
- after do
1890
- described_class.instance_variable_set(:@required_files, nil)
1891
- described_class.instance_variable_set(:@elements, nil)
1892
- end
1893
-
1894
- let(:elements) do
1895
- {
1896
- "CT_Element1" => to_mapping_hash({ type_name: "w:CT_Element1" }),
1897
- "CT_Element2" => to_mapping_hash({ type_name: "xsd:string" }),
1898
- }
1899
- end
1900
-
1901
- let(:content) do
1902
- [
1903
- to_mapping_hash({ type_name: "CT_Element1" }),
1904
- to_mapping_hash({ ref_class: "CT_Element2" }),
1905
- ]
1906
- end
1907
-
1908
- it "populates @required_files excluding default classes" do
1909
- described_class.send(:required_files_elements, content)
1910
- expect(required_files).to eql(["ct_element1"])
1911
- end
1912
- end
1913
- end
1914
- end
1915
- end
1916
-
1917
- def create_pattern_mapping(array)
1918
- array.map { |type, text| Lutaml::Model::Xml::Element.new(type, text) }
1919
- end
1920
-
1921
- def to_mapping_hash(content)
1922
- @hash ||= Lutaml::Model::MappingHash.new
1923
- @hash.merge(content)
1924
623
  end