lutaml-model 0.8.19 → 0.8.23
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/dependent-tests.yml +1 -1
- data/.github/workflows/rake.yml +1 -0
- data/.rubocop.yml +1 -1
- data/.rubocop_todo.yml +133 -72
- data/bench/bench_common.rb +8 -5
- data/bench/bench_niso.rb +1 -2
- data/bench/gate_config.rb +4 -1
- data/benchmark/serialization_benchmark.rb +4 -4
- data/docs/_guides/value-transformations.adoc +27 -0
- data/docs/_guides/xml-mapping.adoc +31 -0
- data/lib/compat/opal/generate_boot.rb +3 -1
- data/lib/compat/opal/lutaml_model_boot.rb +10 -7
- data/lib/compat/opal/moxml_boot.rb +6 -1
- data/lib/lutaml/hash_format/format.rb +29 -0
- data/lib/lutaml/hash_format.rb +5 -27
- data/lib/lutaml/json/adapter/oj_adapter.rb +7 -0
- data/lib/lutaml/json/adapter/standard_adapter.rb +17 -5
- data/lib/lutaml/json/format.rb +61 -0
- data/lib/lutaml/json/generator_options.rb +62 -0
- data/lib/lutaml/json.rb +4 -59
- data/lib/lutaml/jsonl/adapter/standard_adapter.rb +1 -1
- data/lib/lutaml/jsonl/format.rb +22 -0
- data/lib/lutaml/jsonl.rb +5 -19
- data/lib/lutaml/jsonld/adapter.rb +12 -4
- data/lib/lutaml/key_value/adapter/json/oj_adapter.rb +7 -0
- data/lib/lutaml/key_value/adapter/json/standard_adapter.rb +17 -5
- data/lib/lutaml/key_value/adapter/jsonl/standard_adapter.rb +1 -1
- data/lib/lutaml/key_value/format.rb +26 -0
- data/lib/lutaml/key_value/transform.rb +4 -1
- data/lib/lutaml/key_value/transformation/value_serializer.rb +0 -2
- data/lib/lutaml/key_value.rb +4 -21
- data/lib/lutaml/model/attribute.rb +38 -4
- data/lib/lutaml/model/collection.rb +7 -2
- data/lib/lutaml/model/compiled_rule.rb +1 -1
- data/lib/lutaml/model/config.rb +2 -2
- data/lib/lutaml/model/consolidation_map.rb +2 -2
- data/lib/lutaml/model/consolidation_rule/dispatch_block.rb +2 -2
- data/lib/lutaml/model/errors.rb +2 -2
- data/lib/lutaml/model/global_context.rb +4 -2
- data/lib/lutaml/model/mapping/mapping_rule.rb +4 -1
- data/lib/lutaml/model/mapping/model_mapping.rb +2 -2
- data/lib/lutaml/model/runtime_compatibility.rb +2 -2
- data/lib/lutaml/model/schema/class_loader.rb +2 -1
- data/lib/lutaml/model/schema/decorators/definition_collection.rb +4 -4
- 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 +4 -3
- 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 +18 -6
- 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/supported_data_types.rb +2 -2
- data/lib/lutaml/model/schema/xml_compiler.rb +10 -5
- data/lib/lutaml/model/sequence.rb +4 -4
- data/lib/lutaml/model/serialization_adapter.rb +1 -1
- data/lib/lutaml/model/serialize/attribute_definition.rb +1 -0
- data/lib/lutaml/model/serialize/format_conversion.rb +40 -9
- data/lib/lutaml/model/serialize/initialization.rb +9 -1
- data/lib/lutaml/model/serialize/model_import.rb +1 -0
- data/lib/lutaml/model/serialize.rb +22 -3
- data/lib/lutaml/model/transformation.rb +5 -0
- data/lib/lutaml/model/type/uninitialized_class_guard.rb +1 -1
- data/lib/lutaml/model/type.rb +9 -0
- data/lib/lutaml/model/type_registry.rb +2 -2
- data/lib/lutaml/model/uninitialized_class.rb +1 -1
- data/lib/lutaml/model/union.rb +5 -2
- data/lib/lutaml/model/utils.rb +2 -2
- data/lib/lutaml/model/value_policy.rb +27 -0
- data/lib/lutaml/model/version.rb +1 -1
- data/lib/lutaml/model.rb +17 -16
- data/lib/lutaml/rdf/mapping.rb +2 -2
- data/lib/lutaml/rdf/namespace_set.rb +2 -2
- data/lib/lutaml/rdf/transform.rb +2 -2
- data/lib/lutaml/toml/format.rb +48 -0
- data/lib/lutaml/toml.rb +5 -46
- data/lib/lutaml/xml/adapter/base_adapter.rb +2 -2
- data/lib/lutaml/xml/builder/base.rb +2 -2
- data/lib/lutaml/xml/format.rb +331 -0
- data/lib/lutaml/xml/mapping.rb +26 -2
- data/lib/lutaml/xml/mapping_rule.rb +62 -3
- data/lib/lutaml/xml/model_transform.rb +183 -55
- data/lib/lutaml/xml/namespace_collector.rb +3 -3
- data/lib/lutaml/xml/parse_session.rb +59 -0
- data/lib/lutaml/xml/parsed_namespace_set.rb +2 -2
- data/lib/lutaml/xml/schema/builder.rb +5 -5
- data/lib/lutaml/xml/schema/xsd/schema_location_mapping.rb +2 -2
- data/lib/lutaml/xml/schema/xsd.rb +0 -2
- data/lib/lutaml/xml/schema/xsd_schema.rb +2 -1
- data/lib/lutaml/xml/serialization/format_conversion.rb +3 -3
- data/lib/lutaml/xml/transformation/element_builder.rb +2 -1
- data/lib/lutaml/xml/transformation/ordered_applier.rb +2 -1
- data/lib/lutaml/xml/transformation.rb +29 -0
- data/lib/lutaml/xml/xml_element.rb +2 -0
- data/lib/lutaml/xml.rb +4 -328
- data/lib/lutaml/yaml/format.rb +30 -0
- data/lib/lutaml/yaml.rb +5 -28
- data/lib/lutaml/yamls/adapter/mapping.rb +2 -2
- data/lib/lutaml/yamls/format.rb +22 -0
- data/lib/lutaml/yamls.rb +5 -19
- data/lib/tasks/benchmark_runner.rb +2 -2
- data/lutaml-model.gemspec +1 -1
- data/spec/lutaml/json/adapter/standard_adapter_spec.rb +159 -0
- data/spec/lutaml/jsonld/adapter_spec.rb +19 -0
- 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/collection_spec.rb +1 -1
- data/spec/lutaml/model/collection_state_nesting_spec.rb +44 -0
- data/spec/lutaml/model/custom_bibtex_adapter_spec.rb +2 -2
- data/spec/lutaml/model/custom_from_empty_values_spec.rb +74 -0
- data/spec/lutaml/model/custom_vobject_adapter_spec.rb +8 -8
- data/spec/lutaml/model/defaults_spec.rb +45 -0
- data/spec/lutaml/model/generator_defaults_spec.rb +101 -0
- data/spec/lutaml/model/json_spec.rb +1 -2
- data/spec/lutaml/model/json_state_nesting_spec.rb +82 -0
- data/spec/lutaml/model/serialize/builder_spec.rb +6 -3
- data/spec/lutaml/model/store_spec.rb +3 -1
- 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/model/value_policy_spec.rb +82 -0
- data/spec/lutaml/require_load_order_spec.rb +25 -0
- data/spec/lutaml/xml/attribute_element_namespace_disjoint_spec.rb +88 -0
- data/spec/lutaml/xml/attribute_namespace_disjointness_spec.rb +125 -0
- data/spec/lutaml/xml/out_of_namespace_parsing_spec.rb +123 -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/shared_element_rules_spec.rb +64 -0
- data/spec/lutaml/xml/w3c_types_spec.rb +3 -6
- metadata +26 -4
|
@@ -119,6 +119,17 @@ module Lutaml
|
|
|
119
119
|
@resolver ||= GlobalContext.resolver
|
|
120
120
|
end
|
|
121
121
|
|
|
122
|
+
# The value-shaping policy for this attribute. Constructed lazily so
|
|
123
|
+
# the collection/union/ref flags are settled; memoized because they
|
|
124
|
+
# are fixed after definition.
|
|
125
|
+
def value_policy
|
|
126
|
+
@value_policy ||= ValuePolicy.new(
|
|
127
|
+
collection: collection?,
|
|
128
|
+
union: union?,
|
|
129
|
+
reference: !@options[:ref_model_class].nil?,
|
|
130
|
+
)
|
|
131
|
+
end
|
|
132
|
+
|
|
122
133
|
def type(context_or_register = nil)
|
|
123
134
|
return if unresolved_type.nil?
|
|
124
135
|
|
|
@@ -394,7 +405,9 @@ instance_object = nil)
|
|
|
394
405
|
instance_object)
|
|
395
406
|
elsif options[:default].is_a?(Proc)
|
|
396
407
|
if instance_object
|
|
397
|
-
|
|
408
|
+
::Lutaml::Model::Attribute.evaluating_default do
|
|
409
|
+
instance_object.instance_exec(&options[:default])
|
|
410
|
+
end
|
|
398
411
|
else
|
|
399
412
|
options[:default].call
|
|
400
413
|
end
|
|
@@ -405,6 +418,22 @@ instance_object = nil)
|
|
|
405
418
|
end
|
|
406
419
|
end
|
|
407
420
|
|
|
421
|
+
# Marks the dynamic extent in which a default proc runs against a
|
|
422
|
+
# model instance, so Serialize#method_missing can fall back to the
|
|
423
|
+
# model class for methods the instance does not define (0.7.x
|
|
424
|
+
# compatibility, lutaml-model#745).
|
|
425
|
+
def self.evaluating_default
|
|
426
|
+
previous = Thread.current[:__lutaml_evaluating_default]
|
|
427
|
+
Thread.current[:__lutaml_evaluating_default] = true
|
|
428
|
+
yield
|
|
429
|
+
ensure
|
|
430
|
+
Thread.current[:__lutaml_evaluating_default] = previous
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
def self.default_evaluation?
|
|
434
|
+
Thread.current[:__lutaml_evaluating_default] == true
|
|
435
|
+
end
|
|
436
|
+
|
|
408
437
|
def default_set?(register, instance_object = nil)
|
|
409
438
|
!Utils.uninitialized?(default_value(register, instance_object))
|
|
410
439
|
end
|
|
@@ -478,7 +507,10 @@ instance_object = nil)
|
|
|
478
507
|
# Use the default value if the value is nil
|
|
479
508
|
validate_required!(value)
|
|
480
509
|
|
|
481
|
-
|
|
510
|
+
if value.nil?
|
|
511
|
+
value = cast_value(default_value(register, instance_object),
|
|
512
|
+
register)
|
|
513
|
+
end
|
|
482
514
|
resolved_type = type(register)
|
|
483
515
|
|
|
484
516
|
valid_value!(value) &&
|
|
@@ -551,7 +583,8 @@ instance_object = nil)
|
|
|
551
583
|
end
|
|
552
584
|
|
|
553
585
|
def valid_collection!(value, caller)
|
|
554
|
-
if collection_instance?(value) && !collection?
|
|
586
|
+
if collection_instance?(value) && !collection? &&
|
|
587
|
+
!value_policy.whole_value?(unresolved_type)
|
|
555
588
|
raise Lutaml::Model::CollectionTrueMissingError.new(name,
|
|
556
589
|
caller)
|
|
557
590
|
end
|
|
@@ -632,7 +665,8 @@ instance_object = nil)
|
|
|
632
665
|
else
|
|
633
666
|
type(register)
|
|
634
667
|
end
|
|
635
|
-
if collection_instance?(value) || value.is_a?(Array)
|
|
668
|
+
if (collection_instance?(value) || value.is_a?(Array)) &&
|
|
669
|
+
!value_policy.whole_value?(resolved_type)
|
|
636
670
|
merged_opts = options.merge(resolved_type: resolved_type,
|
|
637
671
|
converted: true)
|
|
638
672
|
return build_collection(value.map do |v|
|
|
@@ -308,6 +308,10 @@ module Lutaml
|
|
|
308
308
|
end
|
|
309
309
|
|
|
310
310
|
def to(format, instance, options = {})
|
|
311
|
+
# Wrap before the branch, not inside it: only XML reaches the
|
|
312
|
+
# unwrapped path today, but a raw JSON::State must never survive
|
|
313
|
+
# into either arm.
|
|
314
|
+
options = Lutaml::Model::Serialize.wrap_generator_state(options)
|
|
311
315
|
mappings = mappings_for(format)
|
|
312
316
|
|
|
313
317
|
if mappings.no_root? && collection_unwrapped_to?(format)
|
|
@@ -456,6 +460,7 @@ lutaml_register: Lutaml::Model::Config.default_register)
|
|
|
456
460
|
end
|
|
457
461
|
|
|
458
462
|
def to_format(format, options = {})
|
|
463
|
+
options = Lutaml::Model::Serialize.wrap_generator_state(options)
|
|
459
464
|
super(format, options.merge(collection: true))
|
|
460
465
|
end
|
|
461
466
|
|
|
@@ -481,8 +486,8 @@ lutaml_register: Lutaml::Model::Config.default_register)
|
|
|
481
486
|
self.class.new(items - other.items)
|
|
482
487
|
end
|
|
483
488
|
|
|
484
|
-
def each(&)
|
|
485
|
-
collection.each(&)
|
|
489
|
+
def each(&block)
|
|
490
|
+
collection.each(&block)
|
|
486
491
|
end
|
|
487
492
|
|
|
488
493
|
def size
|
|
@@ -192,7 +192,7 @@ module Lutaml
|
|
|
192
192
|
# @param args [Array] Arguments (ignored for options)
|
|
193
193
|
# @param block [Proc] Block (ignored for options)
|
|
194
194
|
# @return [Object] The option value or nil
|
|
195
|
-
def method_missing(method_name, *args, &)
|
|
195
|
+
def method_missing(method_name, *args, &block)
|
|
196
196
|
# Check if this is an option key
|
|
197
197
|
if options.key?(method_name)
|
|
198
198
|
return options[method_name]
|
data/lib/lutaml/model/config.rb
CHANGED
|
@@ -42,8 +42,8 @@ module Lutaml
|
|
|
42
42
|
# Config.with_adapter(xml: :nokogiri, toml: :tomlib) do
|
|
43
43
|
# MyModel.from_xml(data)
|
|
44
44
|
# end
|
|
45
|
-
def with_adapter(**overrides, &)
|
|
46
|
-
AdapterScope.with(overrides, &)
|
|
45
|
+
def with_adapter(**overrides, &block)
|
|
46
|
+
AdapterScope.with(overrides, &block)
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
# Delegate configure to Configuration
|
|
@@ -39,8 +39,8 @@ module Lutaml
|
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
# Pattern A: declare discriminator routing
|
|
42
|
-
def dispatch_by(discriminator, &)
|
|
43
|
-
routes = DispatchBuilder.new.evaluate(&)
|
|
42
|
+
def dispatch_by(discriminator, &block)
|
|
43
|
+
routes = DispatchBuilder.new.evaluate(&block)
|
|
44
44
|
@rules << DispatchBlock.new(discriminator, routes)
|
|
45
45
|
end
|
|
46
46
|
|
data/lib/lutaml/model/errors.rb
CHANGED
|
@@ -436,8 +436,10 @@ context_id = nil)
|
|
|
436
436
|
instance.register_for_namespace(namespace_uri)
|
|
437
437
|
end
|
|
438
438
|
|
|
439
|
-
def resolve_type_with_namespace(type_name, namespace_uri = nil,
|
|
440
|
-
|
|
439
|
+
def resolve_type_with_namespace(type_name, namespace_uri = nil,
|
|
440
|
+
context_id = nil)
|
|
441
|
+
instance.resolve_type_with_namespace(type_name, namespace_uri,
|
|
442
|
+
context_id)
|
|
441
443
|
end
|
|
442
444
|
|
|
443
445
|
def namespace_register_map
|
|
@@ -67,6 +67,9 @@ module Lutaml
|
|
|
67
67
|
)
|
|
68
68
|
@name = name
|
|
69
69
|
@to = to
|
|
70
|
+
# Dynamic symbol built per call allocated ~10% of parse objects on
|
|
71
|
+
# attribute-heavy documents; `to` is immutable, so build it once.
|
|
72
|
+
@setter_name = :"#{to}="
|
|
70
73
|
@to_instance = to_instance
|
|
71
74
|
@as_attribute = as_attribute
|
|
72
75
|
@render_nil = render_nil
|
|
@@ -457,7 +460,7 @@ module Lutaml
|
|
|
457
460
|
end
|
|
458
461
|
|
|
459
462
|
def assign_value(model, value)
|
|
460
|
-
model.public_send(
|
|
463
|
+
model.public_send(@setter_name, value)
|
|
461
464
|
end
|
|
462
465
|
end
|
|
463
466
|
end
|
|
@@ -43,7 +43,7 @@ module Lutaml
|
|
|
43
43
|
to: nil,
|
|
44
44
|
transform: nil,
|
|
45
45
|
reverse_transform: nil,
|
|
46
|
-
&
|
|
46
|
+
&block
|
|
47
47
|
)
|
|
48
48
|
map(
|
|
49
49
|
from: from,
|
|
@@ -51,7 +51,7 @@ module Lutaml
|
|
|
51
51
|
transform: transform,
|
|
52
52
|
reverse_transform: reverse_transform,
|
|
53
53
|
collection: true,
|
|
54
|
-
&
|
|
54
|
+
&block
|
|
55
55
|
)
|
|
56
56
|
end
|
|
57
57
|
|
|
@@ -114,8 +114,8 @@ if Lutaml::Model::RuntimeCompatibility.opal?
|
|
|
114
114
|
|
|
115
115
|
# Minimal method_missing so the WeakRef quacks like its target
|
|
116
116
|
# for the Store's index lookups.
|
|
117
|
-
def method_missing(name,
|
|
118
|
-
@__target__.public_send(name,
|
|
117
|
+
def method_missing(name, ...)
|
|
118
|
+
@__target__.public_send(name, ...)
|
|
119
119
|
end
|
|
120
120
|
|
|
121
121
|
def respond_to_missing?(name, include_private = false)
|
|
@@ -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
|
|
@@ -21,12 +21,12 @@ module Lutaml
|
|
|
21
21
|
resolve_polymorphic_base_types!
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
def each(&)
|
|
25
|
-
@definitions.each(&)
|
|
24
|
+
def each(&block)
|
|
25
|
+
@definitions.each(&block)
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
def transform_values(&)
|
|
29
|
-
@definitions.transform_values(&)
|
|
28
|
+
def transform_values(&block)
|
|
29
|
+
@definitions.transform_values(&block)
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
def [](name)
|
|
@@ -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)
|
|
@@ -10,11 +10,12 @@ module Lutaml
|
|
|
10
10
|
# (Union, RestrictedType, Namespace). Model has its own constructor
|
|
11
11
|
# because it computes an opt-out (module-wrappable) namespace.
|
|
12
12
|
class Base
|
|
13
|
-
def self.render(spec, **)
|
|
14
|
-
new(spec, **).render
|
|
13
|
+
def self.render(spec, **options)
|
|
14
|
+
new(spec, **options).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
|
|
@@ -10,11 +10,12 @@ module Lutaml
|
|
|
10
10
|
# subclass as Ruby source. Member-declaration and xml-mapping
|
|
11
11
|
# rendering is delegated to MemberDecls and Mappings.
|
|
12
12
|
class Model
|
|
13
|
-
def self.render(spec, **)
|
|
14
|
-
new(spec, **).render
|
|
13
|
+
def self.render(spec, **options)
|
|
14
|
+
new(spec, **options).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
|