lutaml-model 0.8.17 → 0.8.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/downstream-performance.yml +27 -1
- data/.github/workflows/js-pr-check.yml +102 -0
- data/.github/workflows/js-sync.yml +51 -0
- data/.github/workflows/opal.yml +26 -6
- data/.github/workflows/performance.yml +32 -7
- data/.github/workflows/rake.yml +78 -32
- data/.gitmodules +6 -0
- data/.rubocop_todo.yml +8 -0
- data/Gemfile +16 -1
- data/README.adoc +267 -0
- data/Rakefile +166 -4
- data/docs/_guides/schema-import.adoc +42 -0
- data/docs/_guides/xml-mapping.adoc +21 -0
- data/docs/_pages/validation.adoc +65 -0
- data/lib/compat/opal/generate_boot.rb +123 -0
- data/lib/compat/opal/js_bundle_entry.rb +42 -0
- data/lib/compat/opal/lutaml_model_boot.rb +497 -0
- data/lib/compat/opal/moxml_boot.rb +68 -0
- data/lib/compat/opal/yaml_compat.rb +32 -0
- data/lib/lutaml/json.rb +1 -1
- data/lib/lutaml/key_value/transform.rb +3 -8
- data/lib/lutaml/key_value/transformation/value_serializer.rb +14 -1
- data/lib/lutaml/key_value/transformation.rb +17 -5
- data/lib/lutaml/model/adapter_resolver.rb +2 -2
- data/lib/lutaml/model/attribute.rb +88 -11
- data/lib/lutaml/model/cached_type_resolver.rb +1 -1
- data/lib/lutaml/model/error/union_schema_unsupported_error.rb +11 -0
- data/lib/lutaml/model/global_context.rb +11 -8
- data/lib/lutaml/model/instrumentation.rb +2 -2
- data/lib/lutaml/model/mapping/mapping_rule.rb +0 -6
- data/lib/lutaml/model/register.rb +2 -2
- data/lib/lutaml/model/runtime_compatibility.rb +50 -0
- data/lib/lutaml/model/schema/class_loader.rb +58 -0
- data/lib/lutaml/model/schema/compiled_output.rb +83 -0
- data/lib/lutaml/model/schema/definitions/attribute.rb +32 -0
- data/lib/lutaml/model/schema/definitions/choice.rb +20 -0
- data/lib/lutaml/model/schema/definitions/facet.rb +40 -0
- data/lib/lutaml/model/schema/definitions/group_import.rb +22 -0
- data/lib/lutaml/model/schema/definitions/member_walk.rb +33 -0
- data/lib/lutaml/model/schema/definitions/model.rb +40 -0
- data/lib/lutaml/model/schema/definitions/namespace.rb +23 -0
- data/lib/lutaml/model/schema/definitions/restricted_type.rb +30 -0
- data/lib/lutaml/model/schema/definitions/sequence.rb +19 -0
- data/lib/lutaml/model/schema/definitions/simple_content.rb +22 -0
- data/lib/lutaml/model/schema/definitions/transform_facet.rb +21 -0
- data/lib/lutaml/model/schema/definitions/type_ref.rb +20 -0
- data/lib/lutaml/model/schema/definitions/union_type.rb +28 -0
- data/lib/lutaml/model/schema/definitions/xml_root.rb +20 -0
- data/lib/lutaml/model/schema/definitions.rb +24 -0
- data/lib/lutaml/model/schema/file_writer.rb +70 -0
- data/lib/lutaml/model/schema/generator/definitions_collection.rb +16 -2
- data/lib/lutaml/model/schema/generator/property.rb +21 -4
- data/lib/lutaml/model/schema/module_nesting.rb +31 -0
- data/lib/lutaml/model/schema/namespace_naming.rb +46 -0
- data/lib/lutaml/model/schema/registry_generator.rb +115 -0
- data/lib/lutaml/model/schema/renderers/base.rb +40 -0
- data/lib/lutaml/model/schema/renderers/mappings.rb +72 -0
- data/lib/lutaml/model/schema/renderers/member_decls.rb +115 -0
- data/lib/lutaml/model/schema/renderers/model.rb +121 -0
- data/lib/lutaml/model/schema/renderers/namespace.rb +30 -0
- data/lib/lutaml/model/schema/renderers/registration.rb +64 -0
- data/lib/lutaml/model/schema/renderers/required_files_calculator.rb +93 -0
- data/lib/lutaml/model/schema/renderers/restricted_type.rb +88 -0
- data/lib/lutaml/model/schema/renderers/union.rb +83 -0
- data/lib/lutaml/model/schema/renderers.rb +19 -0
- data/lib/lutaml/model/schema/rnc_compiler/source_resolver.rb +47 -0
- data/lib/lutaml/model/schema/rnc_compiler.rb +62 -0
- data/lib/lutaml/model/schema/rng_compiler/define_classifier.rb +91 -0
- data/lib/lutaml/model/schema/rng_compiler/element_visitor.rb +392 -0
- data/lib/lutaml/model/schema/rng_compiler/member_collector.rb +30 -0
- data/lib/lutaml/model/schema/rng_compiler/rng_helpers.rb +152 -0
- data/lib/lutaml/model/schema/rng_compiler/value_type_resolver.rb +125 -0
- data/lib/lutaml/model/schema/rng_compiler.rb +220 -0
- data/lib/lutaml/model/schema/templates.rb +162 -0
- data/lib/lutaml/model/schema/xml_compiler/element_order.rb +41 -0
- data/lib/lutaml/model/schema/xml_compiler/registry_generator.rb +31 -107
- data/lib/lutaml/model/schema/xml_compiler/spec_builder/complex_types.rb +191 -0
- data/lib/lutaml/model/schema/xml_compiler/spec_builder/members.rb +216 -0
- data/lib/lutaml/model/schema/xml_compiler/spec_builder/simple_types.rb +153 -0
- data/lib/lutaml/model/schema/xml_compiler/spec_builder.rb +167 -0
- data/lib/lutaml/model/schema/xml_compiler/supported_data_types.rb +87 -0
- data/lib/lutaml/model/schema/xml_compiler.rb +38 -517
- data/lib/lutaml/model/schema.rb +19 -0
- data/lib/lutaml/model/serialize/attribute_definition.rb +14 -2
- data/lib/lutaml/model/serialize/builder.rb +15 -2
- data/lib/lutaml/model/serialize/value_mapping.rb +9 -57
- data/lib/lutaml/model/serialize.rb +6 -9
- data/lib/lutaml/model/services/rule_value_extractor.rb +2 -3
- data/lib/lutaml/model/services.rb +0 -2
- data/lib/lutaml/model/store.rb +2 -1
- data/lib/lutaml/model/toml.rb +1 -1
- data/lib/lutaml/model/transform.rb +17 -39
- data/lib/lutaml/model/transformation_registry.rb +1 -1
- data/lib/lutaml/model/type.rb +1 -0
- data/lib/lutaml/model/union.rb +320 -0
- data/lib/lutaml/model/utils.rb +6 -0
- data/lib/lutaml/model/validation.rb +1 -4
- data/lib/lutaml/model/version.rb +1 -1
- data/lib/lutaml/model.rb +18 -0
- data/lib/lutaml/toml.rb +1 -1
- data/lib/lutaml/xml/adapter.rb +1 -1
- data/lib/lutaml/xml/adapter_loader.rb +1 -1
- data/lib/lutaml/xml/builder/base.rb +1 -1
- data/lib/lutaml/xml/builder.rb +1 -1
- data/lib/lutaml/xml/error/schema_validation_error.rb +25 -0
- data/lib/lutaml/xml/model_transform.rb +5 -1
- data/lib/lutaml/xml/schema/relaxng_schema.rb +5 -0
- data/lib/lutaml/xml/schema/xsd_schema.rb +4 -0
- data/lib/lutaml/xml/serialization/format_conversion.rb +48 -0
- data/lib/lutaml/xml/serialization/instance_methods.rb +13 -0
- data/lib/lutaml/xml/transformation/element_builder.rb +21 -8
- data/lib/lutaml/xml/transformation/ordered_applier.rb +6 -0
- data/lib/lutaml/xml/xsd_validator.rb +66 -0
- data/lib/lutaml/xml.rb +53 -12
- data/lutaml-model.gemspec +4 -2
- data/spec/fixtures/xml/schema/rnc/address_book.rnc +15 -0
- data/spec/fixtures/xml/schema/rnc/book_features.rnc +18 -0
- data/spec/fixtures/xml/schema/rnc/includes/book.rnc +6 -0
- data/spec/fixtures/xml/schema/rnc/includes/circular_a.rnc +8 -0
- data/spec/fixtures/xml/schema/rnc/includes/circular_b.rnc +8 -0
- data/spec/fixtures/xml/schema/rnc/includes/library.rnc +8 -0
- data/spec/fixtures/xml/schema/rng/address_book.rng +16 -0
- data/spec/fixtures/xml/schema/rng/book.rng +27 -0
- data/spec/fixtures/xml/schema/rng/fixed_value.rng +11 -0
- data/spec/fixtures/xml/schema/rng/fragment_in_choice.rng +30 -0
- data/spec/fixtures/xml/schema/rng/full_name.rng +39 -0
- data/spec/fixtures/xml/schema/rng/integer_range.rng +32 -0
- data/spec/fixtures/xml/schema/rng/list_type.rng +12 -0
- data/spec/fixtures/xml/schema/rng/namespaced.rng +9 -0
- data/spec/fixtures/xml/schema/rng/paragraph.rng +13 -0
- data/spec/fixtures/xml/schema/rng/person.rng +23 -0
- data/spec/fixtures/xml/schema/rng/union.rng +14 -0
- data/spec/fixtures/xml/validate_xml_with_address.xsd +13 -0
- data/spec/fixtures/xml/validate_xml_with_contact.xsd +11 -0
- data/spec/fixtures/xml/validate_xml_with_person.xsd +11 -0
- data/spec/fixtures/xml/validate_xml_with_person_strict.xsd +17 -0
- data/spec/fixtures/xml/validate_xml_with_product.xsd +37 -0
- data/spec/lutaml/model/attribute_apply_value_map_spec.rb +134 -0
- data/spec/lutaml/model/attribute_spec.rb +169 -12
- data/spec/lutaml/model/boot_manifest_spec.rb +30 -0
- data/spec/lutaml/model/collection_spec.rb +18 -0
- data/spec/lutaml/model/mixed_content_spec.rb +171 -0
- data/spec/lutaml/model/opal_smoke_spec.rb +67 -2
- data/spec/lutaml/model/ordered_content_spec.rb +30 -0
- data/spec/lutaml/model/raw_element_spec.rb +125 -0
- data/spec/lutaml/model/rule_value_extractor_spec.rb +7 -14
- data/spec/lutaml/model/runtime_compatibility_spec.rb +25 -0
- data/spec/lutaml/model/schema/renderers/model_spec.rb +149 -0
- data/spec/lutaml/model/schema/renderers/namespace_spec.rb +36 -0
- data/spec/lutaml/model/schema/renderers/restricted_type_spec.rb +75 -0
- data/spec/lutaml/model/schema/renderers/union_spec.rb +58 -0
- data/spec/lutaml/model/transform_apply_value_map_spec.rb +64 -0
- data/spec/lutaml/model/union_attribute_spec.rb +658 -0
- data/spec/lutaml/model/union_spec.rb +257 -0
- data/spec/lutaml/model/utils_spec.rb +14 -0
- data/spec/lutaml/xml/opal_xml_spec.rb +22 -20
- data/spec/lutaml/xml/schema/compiler_spec.rb +21 -4
- data/spec/lutaml/xml/schema/rnc_compiler_spec.rb +404 -0
- data/spec/lutaml/xml/schema/rng_compiler_spec.rb +893 -0
- data/spec/lutaml/xml/validate_xml_with_constructs_spec.rb +222 -0
- data/spec/lutaml/xml/validate_xml_with_spec.rb +186 -0
- data/spec/spec_helper.rb +28 -11
- data/spec/support/opal.rb +5 -2
- metadata +97 -31
- data/lib/lutaml/model/schema/xml_compiler/attribute.rb +0 -106
- data/lib/lutaml/model/schema/xml_compiler/attribute_group.rb +0 -47
- data/lib/lutaml/model/schema/xml_compiler/choice.rb +0 -67
- data/lib/lutaml/model/schema/xml_compiler/complex_content.rb +0 -27
- data/lib/lutaml/model/schema/xml_compiler/complex_content_restriction.rb +0 -34
- data/lib/lutaml/model/schema/xml_compiler/complex_type.rb +0 -173
- data/lib/lutaml/model/schema/xml_compiler/element.rb +0 -121
- data/lib/lutaml/model/schema/xml_compiler/group.rb +0 -113
- data/lib/lutaml/model/schema/xml_compiler/restriction.rb +0 -104
- data/lib/lutaml/model/schema/xml_compiler/sequence.rb +0 -52
- data/lib/lutaml/model/schema/xml_compiler/simple_content.rb +0 -40
- data/lib/lutaml/model/schema/xml_compiler/simple_type.rb +0 -265
- data/lib/lutaml/model/schema/xml_compiler/xml_namespace_class.rb +0 -110
- data/lib/lutaml/model/services/default_value_resolver.rb +0 -60
- data/spec/lutaml/model/services/default_value_resolver_spec.rb +0 -162
- data/spec/lutaml/xml/schema/compiler/attribute_group_spec.rb +0 -71
- data/spec/lutaml/xml/schema/compiler/attribute_spec.rb +0 -67
- data/spec/lutaml/xml/schema/compiler/choice_spec.rb +0 -74
- data/spec/lutaml/xml/schema/compiler/complex_content_restriction_spec.rb +0 -60
- data/spec/lutaml/xml/schema/compiler/complex_content_spec.rb +0 -41
- data/spec/lutaml/xml/schema/compiler/complex_type_spec.rb +0 -202
- data/spec/lutaml/xml/schema/compiler/element_spec.rb +0 -68
- data/spec/lutaml/xml/schema/compiler/group_spec.rb +0 -90
- data/spec/lutaml/xml/schema/compiler/restriction_spec.rb +0 -77
- data/spec/lutaml/xml/schema/compiler/sequence_spec.rb +0 -65
- data/spec/lutaml/xml/schema/compiler/simple_content_spec.rb +0 -61
- data/spec/lutaml/xml/schema/compiler/simple_type_spec.rb +0 -184
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "erb"
|
|
4
3
|
require "tmpdir"
|
|
5
|
-
|
|
6
|
-
# XSD schema compilation support - now integrated into lutaml-model
|
|
4
|
+
require "uri"
|
|
7
5
|
|
|
8
6
|
module Lutaml
|
|
9
7
|
module Model
|
|
@@ -11,32 +9,10 @@ module Lutaml
|
|
|
11
9
|
module XmlCompiler
|
|
12
10
|
extend self
|
|
13
11
|
|
|
14
|
-
#
|
|
15
|
-
autoload :
|
|
16
|
-
|
|
17
|
-
autoload :
|
|
18
|
-
autoload :ComplexContent, "#{__dir__}/xml_compiler/complex_content"
|
|
19
|
-
autoload :SimpleContent, "#{__dir__}/xml_compiler/simple_content"
|
|
20
|
-
autoload :ComplexType, "#{__dir__}/xml_compiler/complex_type"
|
|
21
|
-
autoload :Restriction, "#{__dir__}/xml_compiler/restriction"
|
|
22
|
-
autoload :SimpleType, "#{__dir__}/xml_compiler/simple_type"
|
|
23
|
-
autoload :Attribute, "#{__dir__}/xml_compiler/attribute"
|
|
24
|
-
autoload :Sequence, "#{__dir__}/xml_compiler/sequence"
|
|
25
|
-
autoload :Element, "#{__dir__}/xml_compiler/element"
|
|
26
|
-
autoload :Choice, "#{__dir__}/xml_compiler/choice"
|
|
27
|
-
autoload :Group, "#{__dir__}/xml_compiler/group"
|
|
28
|
-
autoload :XmlNamespaceClass,
|
|
29
|
-
"#{__dir__}/xml_compiler/xml_namespace_class"
|
|
30
|
-
autoload :RegistryGenerator,
|
|
31
|
-
"#{__dir__}/xml_compiler/registry_generator"
|
|
32
|
-
|
|
33
|
-
attr_reader :simple_types,
|
|
34
|
-
:group_types,
|
|
35
|
-
:complex_types,
|
|
36
|
-
:elements,
|
|
37
|
-
:attributes,
|
|
38
|
-
:attribute_groups,
|
|
39
|
-
:namespace_classes
|
|
12
|
+
autoload :SpecBuilder, "#{__dir__}/xml_compiler/spec_builder"
|
|
13
|
+
autoload :RegistryGenerator, "#{__dir__}/xml_compiler/registry_generator"
|
|
14
|
+
autoload :SupportedDataTypes, "#{__dir__}/xml_compiler/supported_data_types"
|
|
15
|
+
autoload :ElementOrder, "#{__dir__}/xml_compiler/element_order"
|
|
40
16
|
|
|
41
17
|
ELEMENT_ORDER_IGNORABLE = %w[import include].freeze
|
|
42
18
|
|
|
@@ -48,9 +24,6 @@ module Lutaml
|
|
|
48
24
|
Lutaml::Model::Config.xml_adapter = :nokogiri
|
|
49
25
|
MSG
|
|
50
26
|
|
|
51
|
-
# NOTE: These must be full class names (strings), not symbols like :xml_id.
|
|
52
|
-
# The type resolver looks up these strings directly in the type registry,
|
|
53
|
-
# and symbols would be interpreted as literal type names rather than W3C types.
|
|
54
27
|
XML_DEFINED_ATTRIBUTES = {
|
|
55
28
|
"id" => "Lutaml::Xml::W3c::XmlIdType",
|
|
56
29
|
"lang" => "Lutaml::Xml::W3c::XmlLangType",
|
|
@@ -59,522 +32,70 @@ module Lutaml
|
|
|
59
32
|
}.freeze
|
|
60
33
|
XML_NAMESPACE_URI = "http://www.w3.org/XML/1998/namespace"
|
|
61
34
|
|
|
35
|
+
# The SpecBuilder instance set up by `as_models`. Exposed so
|
|
36
|
+
# tests can introspect the walked Definitions::* hashes (e.g.
|
|
37
|
+
# `XmlCompiler.builder.attributes["id"]`) without re-walking.
|
|
38
|
+
attr_reader :builder
|
|
39
|
+
|
|
62
40
|
def to_models(schema, options = {})
|
|
63
41
|
as_models(schema, options: options)
|
|
64
42
|
options[:indent] = options[:indent] ? options[:indent].to_i : 2
|
|
65
43
|
|
|
66
|
-
# Auto-generate module namespace from output directory if not explicitly set
|
|
67
44
|
unless options.key?(:module_namespace)
|
|
68
45
|
output_dir = options.fetch(:output_dir,
|
|
69
46
|
"lutaml_models_#{Time.now.to_i}")
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
options[:module_namespace] = dir_name
|
|
47
|
+
options[:module_namespace] =
|
|
48
|
+
File.basename(output_dir).split("_").map(&:capitalize).join
|
|
73
49
|
end
|
|
74
50
|
|
|
75
|
-
|
|
76
|
-
# only set default register_id if module_namespace is present
|
|
77
|
-
if options[:module_namespace]
|
|
78
|
-
options[:register_id] ||= :default
|
|
79
|
-
end
|
|
51
|
+
options[:register_id] ||= :default if options[:module_namespace]
|
|
80
52
|
|
|
81
|
-
@
|
|
53
|
+
@builder.add_supported_types
|
|
54
|
+
@builder.finalize_required_files!
|
|
82
55
|
|
|
83
|
-
|
|
84
|
-
namespace_classes_hash = {}
|
|
85
|
-
@namespace_classes.each do |name, ns_class|
|
|
86
|
-
namespace_classes_hash[name] = ns_class.to_class(options: options)
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
classes_list = namespace_classes_hash.merge(@simple_types).merge(@complex_types).merge(@group_types)
|
|
90
|
-
classes_list = classes_list.transform_values do |type|
|
|
91
|
-
# Skip namespace classes (already strings) and only process model types
|
|
92
|
-
next type if type.is_a?(String)
|
|
56
|
+
output = build_output(options)
|
|
93
57
|
|
|
94
|
-
type.to_class(options: options.merge(
|
|
95
|
-
module_namespace: options[:module_namespace],
|
|
96
|
-
register_id: options[:register_id],
|
|
97
|
-
))
|
|
98
|
-
end
|
|
99
58
|
if options[:create_files]
|
|
100
59
|
dir = options.fetch(:output_dir, "lutaml_models_#{Time.now.to_i}")
|
|
101
|
-
|
|
102
|
-
# If module_namespace provided, create subdirectories
|
|
103
|
-
if options[:module_namespace]
|
|
104
|
-
module_path = options[:module_namespace].split("::").map(&:downcase).join("/")
|
|
105
|
-
full_dir = File.join(dir, module_path)
|
|
106
|
-
FileUtils.mkdir_p(full_dir)
|
|
107
|
-
|
|
108
|
-
# Generate central registry file with autoload
|
|
109
|
-
registry_content = RegistryGenerator.generate(classes_list,
|
|
110
|
-
options)
|
|
111
|
-
if registry_content
|
|
112
|
-
# Registry file goes in parent directory of module path
|
|
113
|
-
registry_name = module_path.split("/").last
|
|
114
|
-
registry_file = File.join(dir, "#{registry_name}_registry.rb")
|
|
115
|
-
File.write(registry_file, registry_content)
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
# Write class files
|
|
119
|
-
classes_list.each do |name, klass|
|
|
120
|
-
create_file(name, klass, full_dir)
|
|
121
|
-
end
|
|
122
|
-
else
|
|
123
|
-
# When no module_namespace, write files directly to output dir
|
|
124
|
-
# Generated files use require_relative for dependencies (traditional approach)
|
|
125
|
-
FileUtils.mkdir_p(dir)
|
|
126
|
-
|
|
127
|
-
# Write class files
|
|
128
|
-
classes_list.each do |name, klass|
|
|
129
|
-
create_file(name, klass, dir)
|
|
130
|
-
end
|
|
131
|
-
end
|
|
60
|
+
FileWriter.write(output, dir, registry_generator: RegistryGenerator)
|
|
132
61
|
true
|
|
133
62
|
else
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
end
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
def create_file(name, content, dir)
|
|
140
|
-
name = name.split(":").last
|
|
141
|
-
File.write("#{dir}/#{Utils.snake_case(name)}.rb", content)
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
def require_classes(classes_hash)
|
|
145
|
-
Dir.mktmpdir do |dir|
|
|
146
|
-
# Create subdirectory for class files (matches autoload path in registry)
|
|
147
|
-
module_subdir = "generatedmodels"
|
|
148
|
-
full_dir = File.join(dir, module_subdir)
|
|
149
|
-
FileUtils.mkdir_p(full_dir)
|
|
150
|
-
|
|
151
|
-
# Generate registry file first with autoload
|
|
152
|
-
registry_content = RegistryGenerator.generate(classes_hash,
|
|
153
|
-
module_namespace: "GeneratedModels",
|
|
154
|
-
register_id: :default)
|
|
155
|
-
if registry_content
|
|
156
|
-
registry_file = File.join(dir, "registry.rb")
|
|
157
|
-
File.write(registry_file, registry_content)
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
# Write class files to subdirectory
|
|
161
|
-
classes_hash.each do |name, klass|
|
|
162
|
-
create_file(name, klass, full_dir)
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
# Require the registry first to set up autoloads
|
|
166
|
-
require "#{dir}/registry"
|
|
167
|
-
|
|
168
|
-
# Call register_all to register all classes
|
|
169
|
-
GeneratedModels.register_all if defined?(GeneratedModels)
|
|
63
|
+
ClassLoader.load(output, registry_generator: RegistryGenerator) if options[:load_classes]
|
|
64
|
+
output.sources
|
|
170
65
|
end
|
|
171
66
|
end
|
|
172
67
|
|
|
173
68
|
def as_models(schema, options: {})
|
|
174
69
|
unless Config.xml_adapter.name.end_with?("NokogiriAdapter")
|
|
175
|
-
raise Error,
|
|
176
|
-
XML_ADAPTER_NOT_SET_MESSAGE
|
|
70
|
+
raise Error, XML_ADAPTER_NOT_SET_MESSAGE
|
|
177
71
|
end
|
|
178
72
|
|
|
179
|
-
parsed_schema = Lutaml::Xml::Schema::Xsd.parse(
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
@elements = MappingHash.new
|
|
183
|
-
@attributes = MappingHash.new
|
|
184
|
-
@group_types = MappingHash.new
|
|
185
|
-
@simple_types = MappingHash.new
|
|
186
|
-
@complex_types = MappingHash.new
|
|
187
|
-
@attribute_groups = MappingHash.new
|
|
188
|
-
@namespace_classes = MappingHash.new
|
|
189
|
-
|
|
190
|
-
populate_default_values
|
|
191
|
-
collect_namespaces(Array(parsed_schema), options)
|
|
192
|
-
schema_to_models(Array(parsed_schema))
|
|
193
|
-
end
|
|
194
|
-
|
|
195
|
-
def populate_default_values
|
|
196
|
-
XML_DEFINED_ATTRIBUTES.each do |name, value|
|
|
197
|
-
@attributes[name] = Attribute.new(name: name)
|
|
198
|
-
@attributes[name].type = value
|
|
199
|
-
end
|
|
200
|
-
|
|
201
|
-
# W3C XmlNamespace is now auto-loaded via lutaml/model.rb
|
|
202
|
-
# Reference: Lutaml::Xml::W3c::XmlNamespace
|
|
203
|
-
end
|
|
204
|
-
|
|
205
|
-
def schema_to_models(schemas)
|
|
206
|
-
return if schemas.empty?
|
|
207
|
-
|
|
208
|
-
schemas.each do |schema|
|
|
209
|
-
schema_to_models(schema.include) if schema.include&.any?
|
|
210
|
-
schema_to_models(schema.import) if schema.import&.any?
|
|
211
|
-
# Use schema's resolved_element_order which returns properly typed XSD objects
|
|
212
|
-
schema.resolved_element_order.each do |order_item|
|
|
213
|
-
item_name = order_item.name if order_item.is_a?(Lutaml::Xml::Schema::Xsd::SimpleType) ||
|
|
214
|
-
order_item.is_a?(Lutaml::Xml::Schema::Xsd::Group) ||
|
|
215
|
-
order_item.is_a?(Lutaml::Xml::Schema::Xsd::ComplexType) ||
|
|
216
|
-
order_item.is_a?(Lutaml::Xml::Schema::Xsd::Element) ||
|
|
217
|
-
order_item.is_a?(Lutaml::Xml::Schema::Xsd::Attribute) ||
|
|
218
|
-
order_item.is_a?(Lutaml::Xml::Schema::Xsd::AttributeGroup)
|
|
219
|
-
case order_item
|
|
220
|
-
when Lutaml::Xml::Schema::Xsd::SimpleType
|
|
221
|
-
@simple_types[item_name] = setup_simple_type(order_item)
|
|
222
|
-
when Lutaml::Xml::Schema::Xsd::Group
|
|
223
|
-
@group_types[item_name] =
|
|
224
|
-
setup_group_type(order_item, root_call: true)
|
|
225
|
-
when Lutaml::Xml::Schema::Xsd::ComplexType
|
|
226
|
-
@complex_types[item_name] = setup_complex_type(order_item)
|
|
227
|
-
when Lutaml::Xml::Schema::Xsd::Element
|
|
228
|
-
@elements[item_name] = setup_element(order_item)
|
|
229
|
-
when Lutaml::Xml::Schema::Xsd::Attribute
|
|
230
|
-
next if xml_defined_attribute?(schema, item_name)
|
|
231
|
-
|
|
232
|
-
@attributes[item_name] = setup_attribute(order_item)
|
|
233
|
-
when Lutaml::Xml::Schema::Xsd::AttributeGroup
|
|
234
|
-
@attribute_groups[item_name] =
|
|
235
|
-
setup_attribute_groups(order_item)
|
|
236
|
-
end
|
|
237
|
-
end
|
|
238
|
-
end
|
|
239
|
-
nil
|
|
240
|
-
end
|
|
241
|
-
|
|
242
|
-
def setup_simple_type(simple_type)
|
|
243
|
-
SimpleType.new(simple_type.name).tap do |type_object|
|
|
244
|
-
if union = simple_type.union
|
|
245
|
-
type_object.unions = union.member_types.split
|
|
246
|
-
elsif restriction = simple_type.restriction
|
|
247
|
-
type_object.base_class = restriction.base&.split(":")&.last
|
|
248
|
-
type_object.instance = setup_restriction(restriction)
|
|
249
|
-
end
|
|
250
|
-
end
|
|
251
|
-
end
|
|
252
|
-
|
|
253
|
-
def restriction_content(instance, restriction)
|
|
254
|
-
restriction_min_max(restriction, instance, field: :max_length,
|
|
255
|
-
value_method: :min)
|
|
256
|
-
restriction_min_max(restriction, instance, field: :min_length,
|
|
257
|
-
value_method: :max)
|
|
258
|
-
restriction_min_max(restriction, instance, field: :min_inclusive,
|
|
259
|
-
value_method: :max)
|
|
260
|
-
restriction_min_max(restriction, instance, field: :max_inclusive,
|
|
261
|
-
value_method: :min)
|
|
262
|
-
restriction_min_max(restriction, instance, field: :max_exclusive,
|
|
263
|
-
value_method: :max)
|
|
264
|
-
restriction_min_max(restriction, instance, field: :min_exclusive,
|
|
265
|
-
value_method: :min)
|
|
266
|
-
instance.length = restriction_length(restriction.length) if restriction.length&.any?
|
|
267
|
-
end
|
|
268
|
-
|
|
269
|
-
# Use min/max to get the value from the field_value array.
|
|
270
|
-
def restriction_min_max(restriction, instance, field:,
|
|
271
|
-
value_method: :min)
|
|
272
|
-
field_value = restriction.public_send(field)
|
|
273
|
-
return unless field_value&.any?
|
|
274
|
-
|
|
275
|
-
instance.public_send(
|
|
276
|
-
:"#{field}=",
|
|
277
|
-
field_value.map(&:value).public_send(value_method).to_s,
|
|
73
|
+
parsed_schema = Lutaml::Xml::Schema::Xsd.parse(
|
|
74
|
+
schema, location: options[:location]
|
|
278
75
|
)
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
def restriction_length(lengths)
|
|
282
|
-
lengths.map do |length|
|
|
283
|
-
MappingHash.new.tap do |hash|
|
|
284
|
-
hash[:value] = length.value
|
|
285
|
-
hash[:fixed] = length.fixed if length.fixed
|
|
286
|
-
end
|
|
287
|
-
end
|
|
288
|
-
end
|
|
289
|
-
|
|
290
|
-
def setup_complex_type(complex_type)
|
|
291
|
-
ComplexType.new.tap do |instance|
|
|
292
|
-
instance.id = complex_type.id
|
|
293
|
-
instance.name = complex_type.name
|
|
294
|
-
instance.mixed = complex_type.mixed
|
|
295
|
-
resolved_element_order(complex_type).each do |element|
|
|
296
|
-
case element
|
|
297
|
-
when Lutaml::Xml::Schema::Xsd::Attribute
|
|
298
|
-
instance << setup_attribute(element)
|
|
299
|
-
when Lutaml::Xml::Schema::Xsd::Sequence
|
|
300
|
-
instance << setup_sequence(element)
|
|
301
|
-
when Lutaml::Xml::Schema::Xsd::Choice
|
|
302
|
-
instance << setup_choice(element)
|
|
303
|
-
when Lutaml::Xml::Schema::Xsd::ComplexContent
|
|
304
|
-
instance << setup_complex_content(element, instance.name,
|
|
305
|
-
instance)
|
|
306
|
-
when Lutaml::Xml::Schema::Xsd::AttributeGroup
|
|
307
|
-
instance << setup_attribute_groups(element)
|
|
308
|
-
when Lutaml::Xml::Schema::Xsd::Group
|
|
309
|
-
instance << setup_group_type(element)
|
|
310
|
-
when Lutaml::Xml::Schema::Xsd::SimpleContent
|
|
311
|
-
instance.simple_content = setup_simple_content(element)
|
|
312
|
-
end
|
|
313
|
-
end
|
|
314
|
-
end
|
|
315
|
-
end
|
|
316
|
-
|
|
317
|
-
def setup_simple_content(simple_content)
|
|
318
|
-
SimpleContent.new.tap do |instance|
|
|
319
|
-
if simple_content.extension
|
|
320
|
-
instance.base_class = simple_content.extension.base
|
|
321
|
-
setup_extension(simple_content.extension, instance)
|
|
322
|
-
elsif simple_content.restriction
|
|
323
|
-
instance.base_class = simple_content.restriction.base
|
|
324
|
-
instance << setup_restriction(simple_content.restriction)
|
|
325
|
-
end
|
|
326
|
-
end
|
|
327
|
-
end
|
|
328
|
-
|
|
329
|
-
def setup_sequence(sequence)
|
|
330
|
-
Sequence.new.tap do |instance|
|
|
331
|
-
resolved_element_order(sequence).each do |object|
|
|
332
|
-
# No implementation yet for Lutaml::Xml::Schema::Xsd::Any!
|
|
333
|
-
next if object.is_a?(Lutaml::Xml::Schema::Xsd::Any)
|
|
334
|
-
|
|
335
|
-
instance << case object
|
|
336
|
-
when Lutaml::Xml::Schema::Xsd::Sequence
|
|
337
|
-
setup_sequence(object)
|
|
338
|
-
when Lutaml::Xml::Schema::Xsd::Element
|
|
339
|
-
setup_element(object)
|
|
340
|
-
when Lutaml::Xml::Schema::Xsd::Choice
|
|
341
|
-
setup_choice(object)
|
|
342
|
-
when Lutaml::Xml::Schema::Xsd::Group
|
|
343
|
-
setup_group_type(object)
|
|
344
|
-
end
|
|
345
|
-
end
|
|
346
|
-
end
|
|
347
|
-
end
|
|
76
|
+
schemas = Array(parsed_schema)
|
|
348
77
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
@
|
|
353
|
-
object
|
|
78
|
+
@builder = SpecBuilder.new
|
|
79
|
+
@builder.populate_default_attributes
|
|
80
|
+
@builder.collect_namespaces(schemas, options)
|
|
81
|
+
@builder.walk_schemas(schemas)
|
|
354
82
|
end
|
|
355
83
|
|
|
356
|
-
|
|
357
|
-
if sequence = group.sequence
|
|
358
|
-
setup_sequence(sequence)
|
|
359
|
-
elsif choice = group.choice
|
|
360
|
-
setup_choice(choice)
|
|
361
|
-
end
|
|
362
|
-
end
|
|
363
|
-
|
|
364
|
-
def setup_choice(choice)
|
|
365
|
-
Choice.new.tap do |instance|
|
|
366
|
-
instance.min_occurs = choice.min_occurs
|
|
367
|
-
instance.max_occurs = choice.max_occurs
|
|
368
|
-
resolved_element_order(choice).each do |element|
|
|
369
|
-
instance << case element
|
|
370
|
-
when Lutaml::Xml::Schema::Xsd::Element
|
|
371
|
-
setup_element(element)
|
|
372
|
-
when Lutaml::Xml::Schema::Xsd::Sequence
|
|
373
|
-
setup_sequence(element)
|
|
374
|
-
when Lutaml::Xml::Schema::Xsd::Group
|
|
375
|
-
setup_group_type(element)
|
|
376
|
-
when Lutaml::Xml::Schema::Xsd::Choice
|
|
377
|
-
setup_choice(element)
|
|
378
|
-
end
|
|
379
|
-
end
|
|
380
|
-
end
|
|
381
|
-
end
|
|
382
|
-
|
|
383
|
-
def setup_attribute(attribute)
|
|
384
|
-
instance = Attribute.new(name: attribute.name, ref: attribute.ref)
|
|
385
|
-
if attribute.name
|
|
386
|
-
instance.type = setup_attribute_type(attribute)
|
|
387
|
-
instance.default = attribute.default
|
|
388
|
-
end
|
|
389
|
-
instance
|
|
390
|
-
end
|
|
391
|
-
|
|
392
|
-
def setup_attribute_type(attribute)
|
|
393
|
-
return attribute.type if attribute.type
|
|
394
|
-
|
|
395
|
-
simple_type = attribute.simple_type
|
|
396
|
-
attr_name = "ST_#{attribute.name}"
|
|
397
|
-
simple_type.name = attr_name
|
|
398
|
-
@simple_types[attr_name] = setup_simple_type(simple_type)
|
|
399
|
-
attr_name
|
|
400
|
-
end
|
|
84
|
+
private
|
|
401
85
|
|
|
402
|
-
def
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
if attribute_group.name
|
|
406
|
-
resolved_element_order(attribute_group).each do |object|
|
|
407
|
-
group_attribute = case object
|
|
408
|
-
when Lutaml::Xml::Schema::Xsd::Attribute
|
|
409
|
-
setup_attribute(object)
|
|
410
|
-
when Lutaml::Xml::Schema::Xsd::AttributeGroup
|
|
411
|
-
setup_attribute_groups(object)
|
|
412
|
-
end
|
|
413
|
-
instance << group_attribute if group_attribute
|
|
414
|
-
end
|
|
86
|
+
def build_output(options)
|
|
87
|
+
model_entries = @builder.all_models.map do |name, spec|
|
|
88
|
+
CompiledOutput::Entry.new(name, spec, :model)
|
|
415
89
|
end
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
def setup_element(element)
|
|
420
|
-
element_name = element.name
|
|
421
|
-
instance = Element.new(name: element_name, ref: element.ref)
|
|
422
|
-
instance.min_occurs = element.min_occurs
|
|
423
|
-
instance.max_occurs = element.max_occurs
|
|
424
|
-
if element_name
|
|
425
|
-
instance.type = setup_element_type(element, instance)
|
|
426
|
-
instance.id = element.id
|
|
427
|
-
instance.fixed = element.fixed
|
|
428
|
-
instance.default = element.default
|
|
90
|
+
namespace_entries = @builder.namespace_classes.map do |name, spec|
|
|
91
|
+
CompiledOutput::Entry.new(name, spec, :namespace)
|
|
429
92
|
end
|
|
430
|
-
instance
|
|
431
|
-
end
|
|
432
|
-
|
|
433
|
-
# Populates @simple_types or @complex_types based on elements available value.
|
|
434
|
-
def setup_element_type(element, _instance)
|
|
435
|
-
return element.type if element.type
|
|
436
|
-
|
|
437
|
-
type, prefix = if element.simple_type
|
|
438
|
-
["simple",
|
|
439
|
-
"ST"]
|
|
440
|
-
else
|
|
441
|
-
["complex", "CT"]
|
|
442
|
-
end
|
|
443
|
-
type_instance = element.public_send(:"#{type}_type")
|
|
444
|
-
type_instance.name = [prefix, element.name].join("_")
|
|
445
|
-
instance_variable_get(:"@#{type}_types")[type_instance.name] =
|
|
446
|
-
public_send(:"setup_#{type}_type", type_instance)
|
|
447
|
-
type_instance.name
|
|
448
|
-
end
|
|
449
|
-
|
|
450
|
-
def setup_restriction(restriction)
|
|
451
|
-
Restriction.new.tap do |instance|
|
|
452
|
-
instance.base_class = restriction.base
|
|
453
|
-
restriction_patterns(restriction.pattern,
|
|
454
|
-
instance)
|
|
455
|
-
restriction_content(instance, restriction)
|
|
456
|
-
if restriction.enumeration&.any?
|
|
457
|
-
instance.enumerations = restriction.enumeration.map(&:value)
|
|
458
|
-
end
|
|
459
|
-
end
|
|
460
|
-
end
|
|
461
|
-
|
|
462
|
-
def setup_complex_content_restriction(restriction,
|
|
463
|
-
compiler_complex_type)
|
|
464
|
-
ComplexContentRestriction.new.tap do |instance|
|
|
465
|
-
compiler_complex_type.base_class = restriction.base
|
|
466
|
-
resolved_element_order(restriction).each do |element|
|
|
467
|
-
# For restrictions, only add attributes and attribute groups.
|
|
468
|
-
# Sequence/choice/group elements are inherited from the base class
|
|
469
|
-
# and adding them here causes duplicate mappings.
|
|
470
|
-
next if element.is_a?(Lutaml::Xml::Schema::Xsd::Sequence) || element.is_a?(Lutaml::Xml::Schema::Xsd::Choice) || element.is_a?(Lutaml::Xml::Schema::Xsd::Group)
|
|
471
|
-
|
|
472
|
-
instance << case element
|
|
473
|
-
when Lutaml::Xml::Schema::Xsd::Attribute
|
|
474
|
-
setup_attribute(element)
|
|
475
|
-
when Lutaml::Xml::Schema::Xsd::AttributeGroup
|
|
476
|
-
setup_attribute_groups(element)
|
|
477
|
-
when Lutaml::Xml::Schema::Xsd::Sequence
|
|
478
|
-
setup_sequence(element)
|
|
479
|
-
when Lutaml::Xml::Schema::Xsd::Choice
|
|
480
|
-
setup_choice(element)
|
|
481
|
-
when Lutaml::Xml::Schema::Xsd::Group
|
|
482
|
-
setup_group_type(element)
|
|
483
|
-
end
|
|
484
|
-
end
|
|
485
|
-
end
|
|
486
|
-
end
|
|
487
|
-
|
|
488
|
-
def restriction_patterns(patterns, instance)
|
|
489
|
-
return if Utils.blank?(patterns)
|
|
490
|
-
|
|
491
|
-
instance.pattern = patterns.map { |p| "(#{p.value})" }.join("|")
|
|
492
|
-
end
|
|
493
93
|
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
setup_extension(extension, compiler_complex_type)
|
|
500
|
-
elsif restriction = complex_content.restriction
|
|
501
|
-
instance.restriction = setup_complex_content_restriction(restriction, compiler_complex_type)
|
|
502
|
-
end
|
|
503
|
-
end
|
|
504
|
-
end
|
|
505
|
-
|
|
506
|
-
def setup_extension(extension, instance)
|
|
507
|
-
instance.base_class = extension.base
|
|
508
|
-
resolved_element_order(extension).each do |element|
|
|
509
|
-
instance << case element
|
|
510
|
-
when Lutaml::Xml::Schema::Xsd::Attribute
|
|
511
|
-
setup_attribute(element)
|
|
512
|
-
when Lutaml::Xml::Schema::Xsd::AttributeGroup
|
|
513
|
-
setup_attribute_groups(element)
|
|
514
|
-
when Lutaml::Xml::Schema::Xsd::Sequence
|
|
515
|
-
setup_sequence(element)
|
|
516
|
-
when Lutaml::Xml::Schema::Xsd::Choice
|
|
517
|
-
setup_choice(element)
|
|
518
|
-
when Lutaml::Xml::Schema::Xsd::Group
|
|
519
|
-
setup_group_type(element)
|
|
520
|
-
end
|
|
521
|
-
end
|
|
522
|
-
end
|
|
523
|
-
|
|
524
|
-
def resolved_element_order(object)
|
|
525
|
-
return [] if object.element_order.nil?
|
|
526
|
-
|
|
527
|
-
# If the object is an XSD type (which has its own resolved_element_order),
|
|
528
|
-
# use it instead of processing element_order which returns generic XML elements
|
|
529
|
-
if object.is_a?(Lutaml::Xml::Schema::Xsd::Base)
|
|
530
|
-
return object.resolved_element_order
|
|
531
|
-
end
|
|
532
|
-
|
|
533
|
-
object.element_order.each_with_object(object.element_order.dup) do |builder_instance, array|
|
|
534
|
-
next array.delete(builder_instance) if builder_instance.text? || ELEMENT_ORDER_IGNORABLE.include?(builder_instance.name)
|
|
535
|
-
|
|
536
|
-
index = 0
|
|
537
|
-
array.each_with_index do |element, i|
|
|
538
|
-
next unless element == builder_instance
|
|
539
|
-
|
|
540
|
-
array[i] =
|
|
541
|
-
Array(object.public_send(Utils.snake_case(builder_instance.name)))[index]
|
|
542
|
-
index += 1
|
|
543
|
-
end
|
|
544
|
-
end
|
|
545
|
-
|
|
546
|
-
object.element_order
|
|
547
|
-
end
|
|
548
|
-
|
|
549
|
-
def collect_namespaces(schemas, options)
|
|
550
|
-
# Collect unique namespace URIs from the schemas
|
|
551
|
-
namespace_uris = Set.new
|
|
552
|
-
|
|
553
|
-
# Add the main namespace from options if provided
|
|
554
|
-
if options[:namespace]
|
|
555
|
-
namespace_uris.add(options[:namespace])
|
|
556
|
-
end
|
|
557
|
-
|
|
558
|
-
# Extract namespaces from schema elements
|
|
559
|
-
schemas.each do |schema|
|
|
560
|
-
namespace_uris.add(schema.target_namespace) if schema.target_namespace
|
|
561
|
-
end
|
|
562
|
-
|
|
563
|
-
# Create XmlNamespaceClass for each unique namespace
|
|
564
|
-
namespace_uris.each do |uri|
|
|
565
|
-
next if uri.nil? || uri.empty?
|
|
566
|
-
|
|
567
|
-
# Use provided prefix if available
|
|
568
|
-
prefix = options[:prefix] if options[:namespace] == uri
|
|
569
|
-
|
|
570
|
-
ns_class = XmlNamespaceClass.new(uri: uri, prefix: prefix)
|
|
571
|
-
@namespace_classes[ns_class.class_name] = ns_class
|
|
572
|
-
end
|
|
573
|
-
end
|
|
574
|
-
|
|
575
|
-
def xml_defined_attribute?(schema, item_name)
|
|
576
|
-
schema.target_namespace == XML_NAMESPACE_URI &&
|
|
577
|
-
XML_DEFINED_ATTRIBUTES.key?(item_name)
|
|
94
|
+
CompiledOutput.new(
|
|
95
|
+
entries: model_entries + namespace_entries,
|
|
96
|
+
module_namespace: options[:module_namespace],
|
|
97
|
+
register_id: options[:register_id] || :default,
|
|
98
|
+
)
|
|
578
99
|
end
|
|
579
100
|
end
|
|
580
101
|
end
|
data/lib/lutaml/model/schema.rb
CHANGED
|
@@ -4,6 +4,13 @@ module Lutaml
|
|
|
4
4
|
module Model
|
|
5
5
|
module Schema
|
|
6
6
|
autoload :BaseSchema, "#{__dir__}/schema/base_schema"
|
|
7
|
+
autoload :ClassLoader, "#{__dir__}/schema/class_loader"
|
|
8
|
+
autoload :CompiledOutput, "#{__dir__}/schema/compiled_output"
|
|
9
|
+
autoload :FileWriter, "#{__dir__}/schema/file_writer"
|
|
10
|
+
autoload :ModuleNesting, "#{__dir__}/schema/module_nesting"
|
|
11
|
+
autoload :NamespaceNaming, "#{__dir__}/schema/namespace_naming"
|
|
12
|
+
autoload :RegistryGenerator, "#{__dir__}/schema/registry_generator"
|
|
13
|
+
autoload :Templates, "#{__dir__}/schema/templates"
|
|
7
14
|
autoload :SharedMethods, "#{__dir__}/schema/shared_methods"
|
|
8
15
|
autoload :Helpers, "#{__dir__}/schema/helpers"
|
|
9
16
|
autoload :JsonSchema, "#{__dir__}/schema/json_schema"
|
|
@@ -12,11 +19,15 @@ module Lutaml
|
|
|
12
19
|
self,
|
|
13
20
|
{
|
|
14
21
|
XmlCompiler: "#{__dir__}/schema/xml_compiler",
|
|
22
|
+
RngCompiler: "#{__dir__}/schema/rng_compiler",
|
|
23
|
+
RncCompiler: "#{__dir__}/schema/rnc_compiler",
|
|
15
24
|
},
|
|
16
25
|
)
|
|
17
26
|
autoload :Generator, "#{__dir__}/schema/generator"
|
|
18
27
|
autoload :Renderer, "#{__dir__}/schema/renderer"
|
|
19
28
|
autoload :Decorators, "#{__dir__}/schema/decorators"
|
|
29
|
+
autoload :Definitions, "#{__dir__}/schema/definitions"
|
|
30
|
+
autoload :Renderers, "#{__dir__}/schema/renderers"
|
|
20
31
|
|
|
21
32
|
# Registry for format-specific schema methods.
|
|
22
33
|
# Format plugins register their schema methods at load time.
|
|
@@ -62,6 +73,14 @@ module Lutaml
|
|
|
62
73
|
def self.from_xml(_xml, _options = {})
|
|
63
74
|
raise "XML schema compilation requires lutaml-xml. Add it to your Gemfile."
|
|
64
75
|
end
|
|
76
|
+
|
|
77
|
+
def self.from_relaxng(_rng, _options = {})
|
|
78
|
+
raise "RELAX NG schema compilation requires lutaml-xml. Add it to your Gemfile."
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def self.from_rnc(_rnc, _options = {})
|
|
82
|
+
raise "RNC schema compilation requires lutaml-xml. Add it to your Gemfile."
|
|
83
|
+
end
|
|
65
84
|
end
|
|
66
85
|
end
|
|
67
86
|
end
|
|
@@ -131,8 +131,15 @@ module Lutaml
|
|
|
131
131
|
end
|
|
132
132
|
|
|
133
133
|
enum_shorthand_names = instance_variable_get(:@__enum_shorthand_names__) || Set.new
|
|
134
|
-
|
|
135
|
-
|
|
134
|
+
# Opal's Module#method_defined? only accepts 1 arg (MRI accepts
|
|
135
|
+
# the optional `inherit` flag). Skip the flag there — the
|
|
136
|
+
# difference only matters for inherited-method filtering.
|
|
137
|
+
setter_defined = if Lutaml::Model.opal?
|
|
138
|
+
method_defined?(:"#{name}=")
|
|
139
|
+
else
|
|
140
|
+
method_defined?(:"#{name}=", false)
|
|
141
|
+
end
|
|
142
|
+
unless setter_defined && !enum_shorthand_names.include?(name.to_s)
|
|
136
143
|
if attr.collection?
|
|
137
144
|
define_method(:"#{name}=") do |value|
|
|
138
145
|
value_set_for(name)
|
|
@@ -169,6 +176,11 @@ module Lutaml
|
|
|
169
176
|
def attribute(name, type, options = {})
|
|
170
177
|
type, options = process_type_hash(type, options) if type.is_a?(::Hash)
|
|
171
178
|
|
|
179
|
+
if type.is_a?(::Array)
|
|
180
|
+
options = options.merge(union_member_types: type)
|
|
181
|
+
type = Lutaml::Model::Type::Union
|
|
182
|
+
end
|
|
183
|
+
|
|
172
184
|
# Handle direct method option in options hash
|
|
173
185
|
if options[:method]
|
|
174
186
|
options[:method_name] = options.delete(:method)
|