lutaml-model 0.8.18 → 0.9.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.
Potentially problematic release.
This version of lutaml-model might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.github/workflows/dependent-tests.yml +1 -1
- data/.github/workflows/rake.yml +1 -0
- data/.rubocop_todo.yml +133 -72
- data/bench/bench_common.rb +6 -3
- data/bench/bench_niso.rb +1 -2
- data/docs/_guides/builder-dsl.adoc +127 -0
- data/lib/compat/opal/generate_boot.rb +3 -1
- data/lib/lutaml/key_value/transform.rb +4 -1
- data/lib/lutaml/key_value/transformation/value_serializer.rb +0 -2
- data/lib/lutaml/model/attribute.rb +23 -2
- data/lib/lutaml/model/global_context.rb +4 -2
- data/lib/lutaml/model/schema/class_loader.rb +2 -1
- data/lib/lutaml/model/schema/definitions/namespace.rb +2 -1
- data/lib/lutaml/model/schema/file_writer.rb +5 -2
- data/lib/lutaml/model/schema/renderers/base.rb +2 -1
- data/lib/lutaml/model/schema/renderers/mappings.rb +9 -3
- data/lib/lutaml/model/schema/renderers/member_decls.rb +9 -3
- data/lib/lutaml/model/schema/renderers/model.rb +16 -4
- data/lib/lutaml/model/schema/renderers/required_files_calculator.rb +2 -1
- data/lib/lutaml/model/schema/renderers.rb +2 -1
- data/lib/lutaml/model/schema/rnc_compiler/source_resolver.rb +6 -2
- data/lib/lutaml/model/schema/rnc_compiler.rb +3 -1
- data/lib/lutaml/model/schema/rng_compiler/element_visitor.rb +35 -15
- data/lib/lutaml/model/schema/rng_compiler/value_type_resolver.rb +4 -2
- data/lib/lutaml/model/schema/rng_compiler.rb +10 -5
- data/lib/lutaml/model/schema/xml_compiler/element_order.rb +2 -1
- data/lib/lutaml/model/schema/xml_compiler/spec_builder/complex_types.rb +4 -2
- data/lib/lutaml/model/schema/xml_compiler/spec_builder/members.rb +39 -13
- data/lib/lutaml/model/schema/xml_compiler/spec_builder.rb +29 -10
- data/lib/lutaml/model/schema/xml_compiler.rb +10 -5
- data/lib/lutaml/model/serialize/attribute_definition.rb +10 -9
- data/lib/lutaml/model/serialize/builder.rb +55 -0
- data/lib/lutaml/model/serialize/initialization.rb +12 -3
- data/lib/lutaml/model/serialize/model_import.rb +1 -0
- data/lib/lutaml/model/serialize.rb +5 -4
- data/lib/lutaml/model/union.rb +5 -2
- data/lib/lutaml/model/version.rb +1 -1
- data/lib/lutaml/xml/mapping_rule.rb +55 -1
- data/lib/lutaml/xml/model_transform.rb +53 -5
- data/lib/lutaml/xml/schema/xsd.rb +0 -2
- data/lib/lutaml/xml/schema/xsd_schema.rb +2 -1
- data/lib/lutaml/xml/transformation/element_builder.rb +2 -1
- data/lib/lutaml/xml/transformation/ordered_applier.rb +99 -4
- data/lutaml-model.gemspec +4 -1
- data/spec/lutaml/model/attribute_apply_value_map_spec.rb +26 -13
- data/spec/lutaml/model/attribute_spec.rb +8 -3
- data/spec/lutaml/model/custom_from_empty_values_spec.rb +74 -0
- data/spec/lutaml/model/defaults_spec.rb +45 -0
- data/spec/lutaml/model/json_spec.rb +1 -2
- data/spec/lutaml/model/ordered_content_spec.rb +18 -7
- data/spec/lutaml/model/serialize/builder_spec.rb +361 -0
- data/spec/lutaml/model/transform_apply_value_map_spec.rb +6 -3
- data/spec/lutaml/model/union_attribute_spec.rb +4 -2
- data/spec/lutaml/xml/attribute_namespace_disjointness_spec.rb +125 -0
- data/spec/lutaml/xml/schema/rnc_compiler_spec.rb +17 -6
- data/spec/lutaml/xml/schema/rng_compiler_spec.rb +15 -6
- data/spec/lutaml/xml/w3c_types_spec.rb +3 -6
- metadata +7 -3
|
@@ -36,7 +36,8 @@ module Lutaml
|
|
|
36
36
|
|
|
37
37
|
def load
|
|
38
38
|
Dir.mktmpdir do |dir|
|
|
39
|
-
FileWriter.write(@output, dir,
|
|
39
|
+
FileWriter.write(@output, dir,
|
|
40
|
+
registry_generator: @registry_generator)
|
|
40
41
|
require File.join(dir, "#{registry_basename}_registry")
|
|
41
42
|
call_register_all
|
|
42
43
|
end
|
|
@@ -7,7 +7,8 @@ module Lutaml
|
|
|
7
7
|
# An XML namespace declaration (subclass of
|
|
8
8
|
# Lutaml::Xml::W3c::XmlNamespace).
|
|
9
9
|
class Namespace
|
|
10
|
-
attr_accessor :class_name, :uri, :prefix_default,
|
|
10
|
+
attr_accessor :class_name, :uri, :prefix_default,
|
|
11
|
+
:element_form_default
|
|
11
12
|
|
|
12
13
|
def initialize(class_name:, uri:, prefix_default: nil,
|
|
13
14
|
element_form_default: nil)
|
|
@@ -45,7 +45,8 @@ module Lutaml
|
|
|
45
45
|
)
|
|
46
46
|
if registry
|
|
47
47
|
registry_name = module_path.split("/").last
|
|
48
|
-
File.write(File.join(@dir, "#{registry_name}_registry.rb"),
|
|
48
|
+
File.write(File.join(@dir, "#{registry_name}_registry.rb"),
|
|
49
|
+
registry)
|
|
49
50
|
end
|
|
50
51
|
|
|
51
52
|
write_sources_to(full_dir)
|
|
@@ -57,7 +58,9 @@ module Lutaml
|
|
|
57
58
|
end
|
|
58
59
|
|
|
59
60
|
def write_sources_to(target_dir)
|
|
60
|
-
@output.sources.each
|
|
61
|
+
@output.sources.each do |name, src|
|
|
62
|
+
write_source(target_dir, name, src)
|
|
63
|
+
end
|
|
61
64
|
end
|
|
62
65
|
|
|
63
66
|
def write_source(target_dir, name, src)
|
|
@@ -14,7 +14,8 @@ module Lutaml
|
|
|
14
14
|
new(spec, **).render
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
def initialize(spec, indent: 2, module_namespace: nil,
|
|
17
|
+
def initialize(spec, indent: 2, module_namespace: nil,
|
|
18
|
+
register_id: :default)
|
|
18
19
|
@spec = spec
|
|
19
20
|
@indent = indent.is_a?(Integer) ? " " * indent : indent
|
|
20
21
|
@extended_indent = @indent * 2
|
|
@@ -29,7 +29,9 @@ module Lutaml
|
|
|
29
29
|
def render_one(member, indent)
|
|
30
30
|
case member
|
|
31
31
|
when Definitions::Sequence then render_sequence(member, indent)
|
|
32
|
-
when Definitions::Choice then member.alternatives.map
|
|
32
|
+
when Definitions::Choice then member.alternatives.map do |a|
|
|
33
|
+
render_one(a, indent)
|
|
34
|
+
end.join
|
|
33
35
|
when Definitions::Attribute then render_attribute(member, indent)
|
|
34
36
|
when Definitions::GroupImport then "#{indent}import_model_mappings :#{member.name}\n"
|
|
35
37
|
end
|
|
@@ -37,7 +39,9 @@ module Lutaml
|
|
|
37
39
|
|
|
38
40
|
def render_sequence(sequence, indent)
|
|
39
41
|
inner_indent = indent + @base_indent
|
|
40
|
-
inner = sequence.members.map
|
|
42
|
+
inner = sequence.members.map do |m|
|
|
43
|
+
render_one(m, inner_indent)
|
|
44
|
+
end.join
|
|
41
45
|
"#{indent}sequence do\n#{inner}#{indent}end\n"
|
|
42
46
|
end
|
|
43
47
|
|
|
@@ -63,7 +67,9 @@ module Lutaml
|
|
|
63
67
|
def simple_content_attribute_mappings
|
|
64
68
|
return "" unless @simple_content
|
|
65
69
|
|
|
66
|
-
@simple_content.additional_attributes.map
|
|
70
|
+
@simple_content.additional_attributes.map do |a|
|
|
71
|
+
render_one(a, @indent)
|
|
72
|
+
end.join
|
|
67
73
|
end
|
|
68
74
|
end
|
|
69
75
|
end
|
|
@@ -35,7 +35,9 @@ module Lutaml
|
|
|
35
35
|
def render_one(member, indent)
|
|
36
36
|
case member
|
|
37
37
|
when Definitions::Choice then render_choice(member, indent)
|
|
38
|
-
when Definitions::Sequence then member.members.map
|
|
38
|
+
when Definitions::Sequence then member.members.map do |m|
|
|
39
|
+
render_one(m, indent)
|
|
40
|
+
end.join
|
|
39
41
|
when Definitions::Attribute then render_attribute(member, indent)
|
|
40
42
|
when Definitions::GroupImport then "#{indent}import_model_attributes :#{member.name}\n"
|
|
41
43
|
end
|
|
@@ -43,7 +45,9 @@ module Lutaml
|
|
|
43
45
|
|
|
44
46
|
def render_choice(choice, indent)
|
|
45
47
|
inner_indent = indent + @base_indent
|
|
46
|
-
inner = choice.alternatives.map
|
|
48
|
+
inner = choice.alternatives.map do |alt|
|
|
49
|
+
render_one(alt, inner_indent)
|
|
50
|
+
end.join
|
|
47
51
|
"#{indent}#{choice.header} do\n#{inner}#{indent}end\n"
|
|
48
52
|
end
|
|
49
53
|
|
|
@@ -106,7 +110,9 @@ module Lutaml
|
|
|
106
110
|
def simple_content_extras
|
|
107
111
|
return "" unless @simple_content
|
|
108
112
|
|
|
109
|
-
@simple_content.additional_attributes.map
|
|
113
|
+
@simple_content.additional_attributes.map do |a|
|
|
114
|
+
render_attribute(a, @indent)
|
|
115
|
+
end.join
|
|
110
116
|
end
|
|
111
117
|
end
|
|
112
118
|
end
|
|
@@ -14,7 +14,8 @@ module Lutaml
|
|
|
14
14
|
new(spec, **).render
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
def initialize(spec, indent: 2, module_namespace: nil,
|
|
17
|
+
def initialize(spec, indent: 2, module_namespace: nil,
|
|
18
|
+
register_id: :default)
|
|
18
19
|
@spec = spec
|
|
19
20
|
@indent = indent.is_a?(Integer) ? " " * indent : indent
|
|
20
21
|
@extended_indent = @indent * 2
|
|
@@ -39,8 +40,15 @@ module Lutaml
|
|
|
39
40
|
|
|
40
41
|
def rendered_class_name = @spec.class_name
|
|
41
42
|
def serializable_class_parent = @spec.parent_class
|
|
42
|
-
|
|
43
|
-
def
|
|
43
|
+
|
|
44
|
+
def serializable_class_required_files
|
|
45
|
+
format_files(@spec.required_files)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def serializable_class_documentation
|
|
49
|
+
format_doc_block(@spec.documentation)
|
|
50
|
+
end
|
|
51
|
+
|
|
44
52
|
def serializable_class_imports = render_imports
|
|
45
53
|
|
|
46
54
|
def serializable_class_attributes
|
|
@@ -76,7 +84,11 @@ module Lutaml
|
|
|
76
84
|
end
|
|
77
85
|
|
|
78
86
|
def xml_mixed_content? = @spec.mixed
|
|
79
|
-
|
|
87
|
+
|
|
88
|
+
def xml_text_content?
|
|
89
|
+
@spec.text_content || !!@spec.simple_content || @spec.mixed
|
|
90
|
+
end
|
|
91
|
+
|
|
80
92
|
def xml_extra_mappings = ""
|
|
81
93
|
|
|
82
94
|
def module_opening = ModuleNesting.opening(modules)
|
|
@@ -34,7 +34,8 @@ module Lutaml
|
|
|
34
34
|
Definitions::MemberWalk.each_attribute(model.members) do |attr|
|
|
35
35
|
deps.concat(xml_attribute_requires(attr, skippable_type))
|
|
36
36
|
end
|
|
37
|
-
deps.concat(simple_content_requires(model.simple_content,
|
|
37
|
+
deps.concat(simple_content_requires(model.simple_content,
|
|
38
|
+
skippable_type))
|
|
38
39
|
deps << namespace_require(model.namespace_class_name) if model.namespace_class_name
|
|
39
40
|
deps.uniq
|
|
40
41
|
end
|
|
@@ -6,7 +6,8 @@ module Lutaml
|
|
|
6
6
|
module Renderers
|
|
7
7
|
autoload :Base, "#{__dir__}/renderers/base"
|
|
8
8
|
autoload :Registration, "#{__dir__}/renderers/registration"
|
|
9
|
-
autoload :RequiredFilesCalculator,
|
|
9
|
+
autoload :RequiredFilesCalculator,
|
|
10
|
+
"#{__dir__}/renderers/required_files_calculator"
|
|
10
11
|
autoload :MemberDecls, "#{__dir__}/renderers/member_decls"
|
|
11
12
|
autoload :Mappings, "#{__dir__}/renderers/mappings"
|
|
12
13
|
autoload :Model, "#{__dir__}/renderers/model"
|
|
@@ -20,9 +20,13 @@ module Lutaml
|
|
|
20
20
|
if File.file?(expanded)
|
|
21
21
|
return file_source(expanded) if input.nil? || input.to_s.empty?
|
|
22
22
|
|
|
23
|
-
return string_source(input, base_dir: File.dirname(expanded),
|
|
23
|
+
return string_source(input, base_dir: File.dirname(expanded),
|
|
24
|
+
path: expanded)
|
|
25
|
+
end
|
|
26
|
+
if File.directory?(expanded)
|
|
27
|
+
return string_source(input,
|
|
28
|
+
base_dir: expanded)
|
|
24
29
|
end
|
|
25
|
-
return string_source(input, base_dir: expanded) if File.directory?(expanded)
|
|
26
30
|
|
|
27
31
|
string_source(input)
|
|
28
32
|
end
|
|
@@ -47,7 +47,9 @@ module Lutaml
|
|
|
47
47
|
# the 0.3.7 release; the released parse_rnc takes only `(rnc)`.
|
|
48
48
|
def rnc_parser_available?
|
|
49
49
|
defined?(::Rng::Grammar) && ::Rng.respond_to?(:parse_rnc) &&
|
|
50
|
-
::Rng.method(:parse_rnc).parameters.any?
|
|
50
|
+
::Rng.method(:parse_rnc).parameters.any? do |_type, name|
|
|
51
|
+
name == :location
|
|
52
|
+
end
|
|
51
53
|
end
|
|
52
54
|
|
|
53
55
|
def default_output_dir
|
|
@@ -23,8 +23,10 @@ module Lutaml
|
|
|
23
23
|
].freeze
|
|
24
24
|
|
|
25
25
|
REPETITION_CTX = {
|
|
26
|
-
zeroOrMore: { collection: (0..Float::INFINITY),
|
|
27
|
-
|
|
26
|
+
zeroOrMore: { collection: (0..Float::INFINITY),
|
|
27
|
+
initialize_empty: true },
|
|
28
|
+
oneOrMore: { collection: (1..Float::INFINITY),
|
|
29
|
+
initialize_empty: true },
|
|
28
30
|
list: { collection: (0..Float::INFINITY), initialize_empty: true },
|
|
29
31
|
}.freeze
|
|
30
32
|
|
|
@@ -60,7 +62,8 @@ module Lutaml
|
|
|
60
62
|
class_name = Utils.camel_case(element.attr_name)
|
|
61
63
|
model = @classes[class_name] ||= Definitions::Model.new(
|
|
62
64
|
class_name: class_name,
|
|
63
|
-
xml_root: Definitions::XmlRoot.new(kind: :element,
|
|
65
|
+
xml_root: Definitions::XmlRoot.new(kind: :element,
|
|
66
|
+
name: element.attr_name),
|
|
64
67
|
documentation: documentation_text(element),
|
|
65
68
|
namespace_class_name: namespace_class_for(element),
|
|
66
69
|
)
|
|
@@ -90,7 +93,8 @@ module Lutaml
|
|
|
90
93
|
wrapping = define.element.size == 1 ? define.element.first : nil
|
|
91
94
|
|
|
92
95
|
xml_root = if wrapping
|
|
93
|
-
Definitions::XmlRoot.new(kind: :element,
|
|
96
|
+
Definitions::XmlRoot.new(kind: :element,
|
|
97
|
+
name: wrapping.attr_name)
|
|
94
98
|
else
|
|
95
99
|
Definitions::XmlRoot.new(kind: :fragment)
|
|
96
100
|
end
|
|
@@ -198,22 +202,30 @@ module Lutaml
|
|
|
198
202
|
doc = documentation_text(child)
|
|
199
203
|
value_type = @value_type_resolver.resolve(child)
|
|
200
204
|
type_ref = type_ref_for_element(child, value_type)
|
|
201
|
-
push_attribute(parent,
|
|
205
|
+
push_attribute(parent,
|
|
206
|
+
build_attribute(child, type_ref, :element, ctx, doc))
|
|
202
207
|
end
|
|
203
208
|
|
|
204
209
|
def type_ref_for_element(child, value_type)
|
|
205
|
-
|
|
210
|
+
if value_type
|
|
211
|
+
return Definitions::TypeRef.new(kind: :symbol,
|
|
212
|
+
value: value_type.to_s)
|
|
213
|
+
end
|
|
206
214
|
|
|
207
215
|
compiled = compile_element(child)
|
|
208
|
-
Definitions::TypeRef.new(kind: :class_ref,
|
|
216
|
+
Definitions::TypeRef.new(kind: :class_ref,
|
|
217
|
+
value: compiled.class_name)
|
|
209
218
|
end
|
|
210
219
|
|
|
211
220
|
def handle_attribute(_kind, child, parent, ctx)
|
|
212
221
|
doc = documentation_text(child)
|
|
213
222
|
symbol = attribute_type_symbol(child)
|
|
214
|
-
type_ref = Definitions::TypeRef.new(kind: :symbol,
|
|
223
|
+
type_ref = Definitions::TypeRef.new(kind: :symbol,
|
|
224
|
+
value: symbol.to_s)
|
|
215
225
|
fixed = fixed_value_default(child)
|
|
216
|
-
push_attribute(parent,
|
|
226
|
+
push_attribute(parent,
|
|
227
|
+
build_attribute(child, type_ref, :attribute, ctx,
|
|
228
|
+
doc, default: fixed))
|
|
217
229
|
end
|
|
218
230
|
|
|
219
231
|
# The attribute's value type, as a Symbol. An attribute in a foreign
|
|
@@ -225,7 +237,8 @@ module Lutaml
|
|
|
225
237
|
uri = foreign_namespace_uri(child)
|
|
226
238
|
return base unless uri
|
|
227
239
|
|
|
228
|
-
namespaced_attribute_type(child, base,
|
|
240
|
+
namespaced_attribute_type(child, base,
|
|
241
|
+
@register_namespace.call(uri))
|
|
229
242
|
end
|
|
230
243
|
|
|
231
244
|
# Give the attribute's value a namespace via a dedicated generated
|
|
@@ -300,19 +313,26 @@ module Lutaml
|
|
|
300
313
|
|
|
301
314
|
def handle_ref(_kind, ref, parent, ctx)
|
|
302
315
|
target_define = @defines[ref.name]
|
|
303
|
-
|
|
316
|
+
unless target_define
|
|
317
|
+
raise Lutaml::Model::Error,
|
|
318
|
+
"ref to unknown define: #{ref.name}"
|
|
319
|
+
end
|
|
304
320
|
|
|
305
321
|
target_class = compile_define(target_define)
|
|
306
322
|
|
|
307
323
|
if RngHelpers.simple_type?(target_class)
|
|
308
|
-
type_ref = Definitions::TypeRef.new(kind: :symbol,
|
|
309
|
-
|
|
324
|
+
type_ref = Definitions::TypeRef.new(kind: :symbol,
|
|
325
|
+
value: RngHelpers.type_symbol(target_class.class_name).to_s)
|
|
326
|
+
push_attribute(parent,
|
|
327
|
+
build_ref_attribute(ref, type_ref, ref.name, ctx))
|
|
310
328
|
elsif RngHelpers.fragment_model?(target_class) && ctx[:collection].nil?
|
|
311
329
|
push_import(parent, target_class.class_name)
|
|
312
330
|
else
|
|
313
|
-
type_ref = Definitions::TypeRef.new(kind: :class_ref,
|
|
331
|
+
type_ref = Definitions::TypeRef.new(kind: :class_ref,
|
|
332
|
+
value: target_class.class_name)
|
|
314
333
|
xml_name = target_class.xml_root.name || ref.name
|
|
315
|
-
push_attribute(parent,
|
|
334
|
+
push_attribute(parent,
|
|
335
|
+
build_ref_attribute(ref, type_ref, xml_name, ctx))
|
|
316
336
|
end
|
|
317
337
|
end
|
|
318
338
|
|
|
@@ -57,14 +57,16 @@ module Lutaml
|
|
|
57
57
|
base = RngCompiler::DATA_TYPE_MAP.fetch(
|
|
58
58
|
data.type, RngCompiler::DEFAULT_DATA_TYPE
|
|
59
59
|
)
|
|
60
|
-
anonymous_restricted_type(container, base,
|
|
60
|
+
anonymous_restricted_type(container, base,
|
|
61
|
+
RngHelpers.facet_from_data(data))
|
|
61
62
|
end
|
|
62
63
|
|
|
63
64
|
def anonymous_from_enum_choice(container)
|
|
64
65
|
choice = RngHelpers.single(container.choice)
|
|
65
66
|
return nil unless choice && RngHelpers.pure_value_choice?(choice)
|
|
66
67
|
|
|
67
|
-
anonymous_restricted_type(container, :string,
|
|
68
|
+
anonymous_restricted_type(container, :string,
|
|
69
|
+
RngHelpers.facet_from_values(choice.value))
|
|
68
70
|
end
|
|
69
71
|
|
|
70
72
|
def anonymous_restricted_type(container, base, facet)
|
|
@@ -20,8 +20,9 @@ module Lutaml
|
|
|
20
20
|
autoload :MemberCollector, "#{__dir__}/rng_compiler/member_collector"
|
|
21
21
|
autoload :ElementVisitor, "#{__dir__}/rng_compiler/element_visitor"
|
|
22
22
|
autoload :DefineClassifier, "#{__dir__}/rng_compiler/define_classifier"
|
|
23
|
-
autoload :ValueTypeResolver,
|
|
24
|
-
|
|
23
|
+
autoload :ValueTypeResolver,
|
|
24
|
+
"#{__dir__}/rng_compiler/value_type_resolver"
|
|
25
|
+
autoload :RngHelpers, "#{__dir__}/rng_compiler/rng_helpers"
|
|
25
26
|
|
|
26
27
|
# Map RNG <data type="..."/> values to Lutaml::Model attribute type
|
|
27
28
|
# symbols. Mirrors Lutaml::Xml::Schema::RelaxngSchema.get_relaxng_type
|
|
@@ -59,7 +60,9 @@ module Lutaml
|
|
|
59
60
|
classes, namespaces = compile_grammar(grammar)
|
|
60
61
|
|
|
61
62
|
entries =
|
|
62
|
-
classes.map
|
|
63
|
+
classes.map do |name, spec|
|
|
64
|
+
CompiledOutput::Entry.new(name, spec, :model)
|
|
65
|
+
end +
|
|
63
66
|
namespaces.map { |name, spec| CompiledOutput::Entry.new(name, spec, :namespace) }
|
|
64
67
|
|
|
65
68
|
CompiledOutput.new(
|
|
@@ -89,7 +92,8 @@ module Lutaml
|
|
|
89
92
|
return rng if rng.is_a?(::Rng::Grammar)
|
|
90
93
|
|
|
91
94
|
if options[:location]
|
|
92
|
-
::Rng.parse(rng, location: options[:location],
|
|
95
|
+
::Rng.parse(rng, location: options[:location],
|
|
96
|
+
resolve_external: true)
|
|
93
97
|
else
|
|
94
98
|
::Rng::Grammar.from_xml(rng)
|
|
95
99
|
end
|
|
@@ -165,7 +169,8 @@ module Lutaml
|
|
|
165
169
|
ns = Definitions::Namespace.new(
|
|
166
170
|
class_name: class_name,
|
|
167
171
|
uri: uri,
|
|
168
|
-
prefix_default: unique_prefix(namespaces,
|
|
172
|
+
prefix_default: unique_prefix(namespaces,
|
|
173
|
+
NamespaceNaming.prefix_for(uri)),
|
|
169
174
|
element_form_default: :qualified,
|
|
170
175
|
)
|
|
171
176
|
namespaces[class_name] = ns
|
|
@@ -29,7 +29,8 @@ module Lutaml
|
|
|
29
29
|
array.each_with_index do |element, i|
|
|
30
30
|
next unless element == builder
|
|
31
31
|
|
|
32
|
-
array[i] =
|
|
32
|
+
array[i] =
|
|
33
|
+
Array(object.public_send(Utils.snake_case(builder.name)))[index]
|
|
33
34
|
index += 1
|
|
34
35
|
end
|
|
35
36
|
end
|
|
@@ -25,7 +25,8 @@ module Lutaml
|
|
|
25
25
|
def build(complex_type)
|
|
26
26
|
model = Definitions::Model.new(
|
|
27
27
|
class_name: Utils.camel_case(complex_type.name),
|
|
28
|
-
xml_root: Definitions::XmlRoot.new(kind: :element,
|
|
28
|
+
xml_root: Definitions::XmlRoot.new(kind: :element,
|
|
29
|
+
name: complex_type.name),
|
|
29
30
|
mixed: !!complex_type.mixed,
|
|
30
31
|
namespace_class_name: @parent.namespace_class_name,
|
|
31
32
|
)
|
|
@@ -49,7 +50,8 @@ module Lutaml
|
|
|
49
50
|
base_name = group.name || Utils.last_of_split(group.ref)
|
|
50
51
|
Definitions::Model.new(
|
|
51
52
|
class_name: Utils.camel_case(base_name),
|
|
52
|
-
xml_root: Definitions::XmlRoot.new(kind: :type_name,
|
|
53
|
+
xml_root: Definitions::XmlRoot.new(kind: :type_name,
|
|
54
|
+
name: base_name),
|
|
53
55
|
members: inner_members,
|
|
54
56
|
module_wrappable: false,
|
|
55
57
|
lazy_register: true,
|
|
@@ -56,7 +56,8 @@ module Lutaml
|
|
|
56
56
|
type: build_type_ref(resolve_element_type(element)),
|
|
57
57
|
xml_name: element.name,
|
|
58
58
|
kind: :element,
|
|
59
|
-
collection: collection_from_occurs(element.min_occurs,
|
|
59
|
+
collection: collection_from_occurs(element.min_occurs,
|
|
60
|
+
element.max_occurs),
|
|
60
61
|
default: element.default,
|
|
61
62
|
render_default: !element.default.nil?,
|
|
62
63
|
render_empty: element_required?(element.min_occurs),
|
|
@@ -75,7 +76,9 @@ module Lutaml
|
|
|
75
76
|
end
|
|
76
77
|
|
|
77
78
|
def build_choice(choice)
|
|
78
|
-
alternatives = ElementOrder.resolved(choice).filter_map
|
|
79
|
+
alternatives = ElementOrder.resolved(choice).filter_map do |item|
|
|
80
|
+
build_member(item)
|
|
81
|
+
end
|
|
79
82
|
Definitions::Choice.new(
|
|
80
83
|
alternatives: alternatives,
|
|
81
84
|
header: choice_header(choice),
|
|
@@ -97,11 +100,18 @@ module Lutaml
|
|
|
97
100
|
# ----- TypeRef ---------------------------------------------------
|
|
98
101
|
|
|
99
102
|
def build_type_ref(raw_type)
|
|
100
|
-
|
|
101
|
-
|
|
103
|
+
if raw_type.nil?
|
|
104
|
+
return Definitions::TypeRef.new(kind: :symbol,
|
|
105
|
+
value: "string")
|
|
106
|
+
end
|
|
107
|
+
if w3c_type?(raw_type)
|
|
108
|
+
return Definitions::TypeRef.new(kind: :w3c,
|
|
109
|
+
value: raw_type)
|
|
110
|
+
end
|
|
102
111
|
|
|
103
112
|
local = Utils.last_of_split(raw_type)
|
|
104
|
-
Definitions::TypeRef.new(kind: :symbol,
|
|
113
|
+
Definitions::TypeRef.new(kind: :symbol,
|
|
114
|
+
value: Utils.snake_case(local))
|
|
105
115
|
end
|
|
106
116
|
|
|
107
117
|
private
|
|
@@ -131,7 +141,8 @@ module Lutaml
|
|
|
131
141
|
def resolve_attribute_type(attr)
|
|
132
142
|
return attr.type if attr.type
|
|
133
143
|
|
|
134
|
-
register_anonymous_simple_type("ST_#{attr.name}",
|
|
144
|
+
register_anonymous_simple_type("ST_#{attr.name}",
|
|
145
|
+
attr.simple_type)
|
|
135
146
|
end
|
|
136
147
|
|
|
137
148
|
def resolve_element_ref(element)
|
|
@@ -143,7 +154,8 @@ module Lutaml
|
|
|
143
154
|
type: target.type,
|
|
144
155
|
xml_name: target.xml_name,
|
|
145
156
|
kind: :element,
|
|
146
|
-
collection: collection_from_occurs(element.min_occurs,
|
|
157
|
+
collection: collection_from_occurs(element.min_occurs,
|
|
158
|
+
element.max_occurs),
|
|
147
159
|
default: target.default,
|
|
148
160
|
render_default: !target.default.nil?,
|
|
149
161
|
render_empty: element_required?(element.min_occurs),
|
|
@@ -152,28 +164,42 @@ module Lutaml
|
|
|
152
164
|
|
|
153
165
|
def resolve_element_type(element)
|
|
154
166
|
return element.type if element.type
|
|
155
|
-
|
|
156
|
-
|
|
167
|
+
if element.simple_type
|
|
168
|
+
return register_anonymous_simple_type("ST_#{element.name}",
|
|
169
|
+
element.simple_type)
|
|
170
|
+
end
|
|
171
|
+
if element.complex_type
|
|
172
|
+
return register_anonymous_complex_type("CT_#{element.name}",
|
|
173
|
+
element.complex_type)
|
|
174
|
+
end
|
|
157
175
|
|
|
158
176
|
"string"
|
|
159
177
|
end
|
|
160
178
|
|
|
161
179
|
def top_level_type_str(item)
|
|
162
180
|
return item.type if item.respond_to?(:type) && item.type
|
|
163
|
-
|
|
181
|
+
if item.respond_to?(:simple_type) && item.simple_type
|
|
182
|
+
return register_anonymous_simple_type("ST_#{item.name}",
|
|
183
|
+
item.simple_type)
|
|
184
|
+
end
|
|
164
185
|
|
|
165
|
-
|
|
186
|
+
if item.respond_to?(:complex_type) && item.complex_type
|
|
187
|
+
register_anonymous_complex_type("CT_#{item.name}",
|
|
188
|
+
item.complex_type)
|
|
189
|
+
end
|
|
166
190
|
end
|
|
167
191
|
|
|
168
192
|
def register_anonymous_simple_type(anon_name, anon_node)
|
|
169
193
|
anon_node.name = anon_name
|
|
170
|
-
@parent.simple_types[anon_name] =
|
|
194
|
+
@parent.simple_types[anon_name] =
|
|
195
|
+
@parent.build_simple_type(anon_node)
|
|
171
196
|
anon_name
|
|
172
197
|
end
|
|
173
198
|
|
|
174
199
|
def register_anonymous_complex_type(anon_name, anon_node)
|
|
175
200
|
anon_node.name = anon_name
|
|
176
|
-
@parent.complex_types[anon_name] =
|
|
201
|
+
@parent.complex_types[anon_name] =
|
|
202
|
+
@parent.build_complex_type(anon_node)
|
|
177
203
|
anon_name
|
|
178
204
|
end
|
|
179
205
|
|
|
@@ -65,7 +65,9 @@ module Lutaml
|
|
|
65
65
|
# passed :namespace, every generated complex type gets this
|
|
66
66
|
# name. Mirrors XmlCompiler::ComplexType#setup_options on main.
|
|
67
67
|
@namespace_class_name =
|
|
68
|
-
requested_uri && @namespace_classes.values.find
|
|
68
|
+
requested_uri && @namespace_classes.values.find do |ns|
|
|
69
|
+
ns.uri == requested_uri
|
|
70
|
+
end&.class_name
|
|
69
71
|
end
|
|
70
72
|
|
|
71
73
|
def walk_schemas(schemas)
|
|
@@ -79,11 +81,15 @@ module Lutaml
|
|
|
79
81
|
end
|
|
80
82
|
|
|
81
83
|
def collect_lookups(schemas)
|
|
82
|
-
each_schema_item(schemas)
|
|
84
|
+
each_schema_item(schemas) do |item, schema|
|
|
85
|
+
dispatch_lookup(item, schema)
|
|
86
|
+
end
|
|
83
87
|
end
|
|
84
88
|
|
|
85
89
|
def build_complex_types(schemas)
|
|
86
|
-
each_schema_item(schemas)
|
|
90
|
+
each_schema_item(schemas) do |item, schema|
|
|
91
|
+
dispatch_complex(item, schema)
|
|
92
|
+
end
|
|
87
93
|
end
|
|
88
94
|
|
|
89
95
|
def dispatch_lookup(item, schema)
|
|
@@ -91,13 +97,17 @@ module Lutaml
|
|
|
91
97
|
when Lutaml::Xml::Schema::Xsd::SimpleType
|
|
92
98
|
@simple_types[item.name] = build_simple_type(item)
|
|
93
99
|
when Lutaml::Xml::Schema::Xsd::Element
|
|
94
|
-
@elements[item.name] =
|
|
100
|
+
@elements[item.name] =
|
|
101
|
+
@members_builder.build_top_level_attribute(item, kind: :element)
|
|
95
102
|
when Lutaml::Xml::Schema::Xsd::Attribute
|
|
96
103
|
return if xml_defined_attribute?(schema, item.name)
|
|
97
104
|
|
|
98
|
-
@attributes[item.name] =
|
|
105
|
+
@attributes[item.name] =
|
|
106
|
+
@members_builder.build_top_level_attribute(item,
|
|
107
|
+
kind: :attribute)
|
|
99
108
|
when Lutaml::Xml::Schema::Xsd::AttributeGroup
|
|
100
|
-
@attribute_groups[item.name] =
|
|
109
|
+
@attribute_groups[item.name] =
|
|
110
|
+
@complex_types_builder.build_attribute_group(item)
|
|
101
111
|
end
|
|
102
112
|
end
|
|
103
113
|
|
|
@@ -117,7 +127,8 @@ module Lutaml
|
|
|
117
127
|
next if info[:skippable]
|
|
118
128
|
|
|
119
129
|
str_name = name.to_s
|
|
120
|
-
@simple_types[str_name] =
|
|
130
|
+
@simple_types[str_name] =
|
|
131
|
+
@simple_types_builder.build_supported(str_name, info)
|
|
121
132
|
end
|
|
122
133
|
end
|
|
123
134
|
|
|
@@ -141,8 +152,13 @@ module Lutaml
|
|
|
141
152
|
# Public surface used by the Members sub-builder to register
|
|
142
153
|
# nested anonymous types it encounters during attribute /
|
|
143
154
|
# element resolution.
|
|
144
|
-
def build_simple_type(simple_type)
|
|
145
|
-
|
|
155
|
+
def build_simple_type(simple_type)
|
|
156
|
+
@simple_types_builder.build(simple_type)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def build_complex_type(complex_type)
|
|
160
|
+
@complex_types_builder.build(complex_type)
|
|
161
|
+
end
|
|
146
162
|
|
|
147
163
|
private
|
|
148
164
|
|
|
@@ -150,7 +166,10 @@ module Lutaml
|
|
|
150
166
|
# yields each resolved element-order item with its owning schema.
|
|
151
167
|
def each_schema_item(schemas, &dispatch)
|
|
152
168
|
schemas.each do |schema|
|
|
153
|
-
|
|
169
|
+
if schema.include&.any?
|
|
170
|
+
each_schema_item(schema.include,
|
|
171
|
+
&dispatch)
|
|
172
|
+
end
|
|
154
173
|
each_schema_item(schema.import, &dispatch) if schema.import&.any?
|
|
155
174
|
schema.resolved_element_order.each { |item| yield(item, schema) }
|
|
156
175
|
end
|
|
@@ -9,10 +9,12 @@ module Lutaml
|
|
|
9
9
|
module XmlCompiler
|
|
10
10
|
extend self
|
|
11
11
|
|
|
12
|
-
autoload :SpecBuilder,
|
|
13
|
-
autoload :RegistryGenerator,
|
|
14
|
-
|
|
15
|
-
autoload :
|
|
12
|
+
autoload :SpecBuilder, "#{__dir__}/xml_compiler/spec_builder"
|
|
13
|
+
autoload :RegistryGenerator,
|
|
14
|
+
"#{__dir__}/xml_compiler/registry_generator"
|
|
15
|
+
autoload :SupportedDataTypes,
|
|
16
|
+
"#{__dir__}/xml_compiler/supported_data_types"
|
|
17
|
+
autoload :ElementOrder, "#{__dir__}/xml_compiler/element_order"
|
|
16
18
|
|
|
17
19
|
ELEMENT_ORDER_IGNORABLE = %w[import include].freeze
|
|
18
20
|
|
|
@@ -60,7 +62,10 @@ module Lutaml
|
|
|
60
62
|
FileWriter.write(output, dir, registry_generator: RegistryGenerator)
|
|
61
63
|
true
|
|
62
64
|
else
|
|
63
|
-
|
|
65
|
+
if options[:load_classes]
|
|
66
|
+
ClassLoader.load(output,
|
|
67
|
+
registry_generator: RegistryGenerator)
|
|
68
|
+
end
|
|
64
69
|
output.sources
|
|
65
70
|
end
|
|
66
71
|
end
|