lutaml-model 0.8.19 → 0.8.22
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/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/format.rb +61 -0
- data/lib/lutaml/json.rb +4 -59
- data/lib/lutaml/jsonl/format.rb +22 -0
- data/lib/lutaml/jsonl.rb +5 -19
- 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 +2 -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/serialize/attribute_definition.rb +1 -0
- data/lib/lutaml/model/serialize/format_conversion.rb +2 -2
- 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 +4 -3
- 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 +2 -2
- data/lib/lutaml/xml/mapping_rule.rb +62 -3
- data/lib/lutaml/xml/model_transform.rb +132 -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/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/model/attribute_apply_value_map_spec.rb +26 -13
- data/spec/lutaml/model/attribute_spec.rb +8 -3
- 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/json_spec.rb +1 -2
- 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/w3c_types_spec.rb +3 -6
- metadata +20 -4
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Internal Hash format implementation. Loaded from lib/lutaml/hash_format.rb
|
|
4
|
+
# (the public entrypoint) and from lib/lutaml/model.rb (so the model
|
|
5
|
+
# entrypoint triggers the registration side effects).
|
|
6
|
+
# No require_relative "model" here — keeps the require graph acyclic.
|
|
7
|
+
|
|
8
|
+
module Lutaml
|
|
9
|
+
module HashFormat
|
|
10
|
+
class Error < StandardError; end
|
|
11
|
+
|
|
12
|
+
autoload :Adapter, "#{__dir__}/adapter"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
Lutaml::Model::FormatRegistry.register(
|
|
17
|
+
:hash,
|
|
18
|
+
mapping_class: Lutaml::HashFormat::Adapter::Mapping,
|
|
19
|
+
adapter_class: Lutaml::HashFormat::Adapter::StandardAdapter,
|
|
20
|
+
transformer: Lutaml::HashFormat::Adapter::Transform,
|
|
21
|
+
key_value: true,
|
|
22
|
+
adapter_options: {
|
|
23
|
+
available: %i[standard standard_hash],
|
|
24
|
+
default: :standard,
|
|
25
|
+
},
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
require_relative "type/serializers"
|
|
29
|
+
Lutaml::HashFormat::Type::Serializers.register_all!
|
data/lib/lutaml/hash_format.rb
CHANGED
|
@@ -1,29 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# Hash format
|
|
4
|
-
#
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class Error < StandardError; end
|
|
9
|
-
|
|
10
|
-
autoload :Adapter, "#{__dir__}/hash_format/adapter"
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
# Register Hash format with the format registry
|
|
15
|
-
Lutaml::Model::FormatRegistry.register(
|
|
16
|
-
:hash,
|
|
17
|
-
mapping_class: Lutaml::HashFormat::Adapter::Mapping,
|
|
18
|
-
adapter_class: Lutaml::HashFormat::Adapter::StandardAdapter,
|
|
19
|
-
transformer: Lutaml::HashFormat::Adapter::Transform,
|
|
20
|
-
key_value: true,
|
|
21
|
-
adapter_options: {
|
|
22
|
-
available: %i[standard standard_hash],
|
|
23
|
-
default: :standard,
|
|
24
|
-
},
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
# Register Hash type serializers
|
|
28
|
-
require_relative "hash_format/type/serializers"
|
|
29
|
-
Lutaml::HashFormat::Type::Serializers.register_all!
|
|
3
|
+
# Public Hash format entrypoint. Loads the base model and the internal
|
|
4
|
+
# implementation. The internal file does not require the model back,
|
|
5
|
+
# which keeps the require graph acyclic.
|
|
6
|
+
require_relative "model"
|
|
7
|
+
require_relative "hash_format/format"
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Internal JSON format implementation. Loaded from lib/lutaml/json.rb
|
|
4
|
+
# (the public entrypoint) and from lib/lutaml/model.rb (so the model
|
|
5
|
+
# entrypoint triggers the registration side effects).
|
|
6
|
+
# No require_relative "model" here — keeps the require graph acyclic.
|
|
7
|
+
|
|
8
|
+
require "lutaml/model/runtime_compatibility"
|
|
9
|
+
require_relative "../key_value/format"
|
|
10
|
+
|
|
11
|
+
module Lutaml
|
|
12
|
+
module Json
|
|
13
|
+
class Error < StandardError; end
|
|
14
|
+
|
|
15
|
+
require_relative "adapter/document"
|
|
16
|
+
require_relative "adapter/mapping"
|
|
17
|
+
require_relative "adapter/mapping_rule"
|
|
18
|
+
require_relative "adapter/transform"
|
|
19
|
+
require_relative "adapter/standard_adapter"
|
|
20
|
+
Lutaml::Model::RuntimeCompatibility.require_native(
|
|
21
|
+
"#{__dir__}/adapter/oj_adapter",
|
|
22
|
+
"#{__dir__}/adapter/multi_json_adapter",
|
|
23
|
+
)
|
|
24
|
+
require_relative "schema"
|
|
25
|
+
|
|
26
|
+
# Convenience aliases for common classes at the module level
|
|
27
|
+
# Allows Lutaml::Json::Mapping to resolve to Lutaml::Json::Adapter::Mapping
|
|
28
|
+
def self.const_missing(name)
|
|
29
|
+
if Adapter.const_defined?(name, false)
|
|
30
|
+
Adapter.const_get(name, false)
|
|
31
|
+
else
|
|
32
|
+
super
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Detect available JSON adapters
|
|
37
|
+
def self.detect_adapter
|
|
38
|
+
return :standard if defined?(::JSON) && Lutaml::Model.opal?
|
|
39
|
+
return :oj if defined?(::Oj)
|
|
40
|
+
return :multi_json if defined?(::MultiJson)
|
|
41
|
+
return :standard if defined?(::JSON)
|
|
42
|
+
|
|
43
|
+
nil
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
Lutaml::Model::FormatRegistry.register(
|
|
49
|
+
:json,
|
|
50
|
+
mapping_class: Lutaml::Json::Adapter::Mapping,
|
|
51
|
+
adapter_class: Lutaml::Json::Adapter::StandardAdapter,
|
|
52
|
+
transformer: Lutaml::Json::Adapter::Transform,
|
|
53
|
+
key_value: true,
|
|
54
|
+
adapter_options: {
|
|
55
|
+
available: %i[standard standard_json multi_json oj],
|
|
56
|
+
default: :standard,
|
|
57
|
+
},
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
require_relative "type/serializers"
|
|
61
|
+
Lutaml::Json::Type::Serializers.register_all!
|
data/lib/lutaml/json.rb
CHANGED
|
@@ -1,62 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# JSON format
|
|
4
|
-
#
|
|
5
|
-
|
|
6
|
-
require "lutaml/model/runtime_compatibility"
|
|
3
|
+
# Public JSON format entrypoint. Loads the base model and the internal
|
|
4
|
+
# implementation. The internal file does not require the model back,
|
|
5
|
+
# which keeps the require graph acyclic.
|
|
7
6
|
require_relative "model"
|
|
8
|
-
require_relative "
|
|
9
|
-
|
|
10
|
-
module Lutaml
|
|
11
|
-
module Json
|
|
12
|
-
class Error < StandardError; end
|
|
13
|
-
|
|
14
|
-
require_relative "json/adapter/document"
|
|
15
|
-
require_relative "json/adapter/mapping"
|
|
16
|
-
require_relative "json/adapter/mapping_rule"
|
|
17
|
-
require_relative "json/adapter/transform"
|
|
18
|
-
require_relative "json/adapter/standard_adapter"
|
|
19
|
-
Lutaml::Model::RuntimeCompatibility.require_native(
|
|
20
|
-
"#{__dir__}/json/adapter/oj_adapter",
|
|
21
|
-
"#{__dir__}/json/adapter/multi_json_adapter",
|
|
22
|
-
)
|
|
23
|
-
require_relative "json/schema"
|
|
24
|
-
|
|
25
|
-
# Convenience aliases for common classes at the module level
|
|
26
|
-
# Allows Lutaml::Json::Mapping to resolve to Lutaml::Json::Adapter::Mapping
|
|
27
|
-
def self.const_missing(name)
|
|
28
|
-
if Adapter.const_defined?(name, false)
|
|
29
|
-
Adapter.const_get(name, false)
|
|
30
|
-
else
|
|
31
|
-
super
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
# Detect available JSON adapters
|
|
36
|
-
def self.detect_adapter
|
|
37
|
-
return :standard if defined?(::JSON) && Lutaml::Model.opal?
|
|
38
|
-
return :oj if defined?(::Oj)
|
|
39
|
-
return :multi_json if defined?(::MultiJson)
|
|
40
|
-
return :standard if defined?(::JSON)
|
|
41
|
-
|
|
42
|
-
nil
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
# Register JSON format with the format registry
|
|
48
|
-
Lutaml::Model::FormatRegistry.register(
|
|
49
|
-
:json,
|
|
50
|
-
mapping_class: Lutaml::Json::Adapter::Mapping,
|
|
51
|
-
adapter_class: Lutaml::Json::Adapter::StandardAdapter,
|
|
52
|
-
transformer: Lutaml::Json::Adapter::Transform,
|
|
53
|
-
key_value: true,
|
|
54
|
-
adapter_options: {
|
|
55
|
-
available: %i[standard standard_json multi_json oj],
|
|
56
|
-
default: :standard,
|
|
57
|
-
},
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
# Register JSON type serializers
|
|
61
|
-
require_relative "json/type/serializers"
|
|
62
|
-
Lutaml::Json::Type::Serializers.register_all!
|
|
7
|
+
require_relative "json/format"
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Internal JSONL format implementation. Loaded from lib/lutaml/jsonl.rb
|
|
4
|
+
# (the public entrypoint) and from lib/lutaml/model.rb (so the model
|
|
5
|
+
# entrypoint triggers the registration side effects).
|
|
6
|
+
# No require_relative "model" here — keeps the require graph acyclic.
|
|
7
|
+
|
|
8
|
+
module Lutaml
|
|
9
|
+
module Jsonl
|
|
10
|
+
class Error < StandardError; end
|
|
11
|
+
|
|
12
|
+
autoload :Adapter, "#{__dir__}/adapter"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
Lutaml::Model::FormatRegistry.register(
|
|
17
|
+
:jsonl,
|
|
18
|
+
mapping_class: Lutaml::Jsonl::Adapter::Mapping,
|
|
19
|
+
adapter_class: Lutaml::Jsonl::Adapter::StandardAdapter,
|
|
20
|
+
transformer: Lutaml::Jsonl::Adapter::Transform,
|
|
21
|
+
key_value: true,
|
|
22
|
+
)
|
data/lib/lutaml/jsonl.rb
CHANGED
|
@@ -1,21 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# JSONL format
|
|
4
|
-
#
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class Error < StandardError; end
|
|
9
|
-
|
|
10
|
-
autoload :Adapter, "#{__dir__}/jsonl/adapter"
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
# Register JSONL format with the format registry
|
|
15
|
-
Lutaml::Model::FormatRegistry.register(
|
|
16
|
-
:jsonl,
|
|
17
|
-
mapping_class: Lutaml::Jsonl::Adapter::Mapping,
|
|
18
|
-
adapter_class: Lutaml::Jsonl::Adapter::StandardAdapter,
|
|
19
|
-
transformer: Lutaml::Jsonl::Adapter::Transform,
|
|
20
|
-
key_value: true,
|
|
21
|
-
)
|
|
3
|
+
# Public JSONL format entrypoint. Loads the base model and the internal
|
|
4
|
+
# implementation. The internal file does not require the model back,
|
|
5
|
+
# which keeps the require graph acyclic.
|
|
6
|
+
require_relative "model"
|
|
7
|
+
require_relative "jsonl/format"
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Internal KeyValue implementation. Loaded from lib/lutaml/key_value.rb
|
|
4
|
+
# (the public entrypoint) and from lib/lutaml/model.rb (so the model
|
|
5
|
+
# entrypoint triggers the registration side effects).
|
|
6
|
+
# No require_relative "model" here — keeps the require graph acyclic.
|
|
7
|
+
|
|
8
|
+
module Lutaml
|
|
9
|
+
module KeyValue
|
|
10
|
+
autoload :DataModel, "#{__dir__}/data_model"
|
|
11
|
+
autoload :Document, "#{__dir__}/document"
|
|
12
|
+
autoload :Mapping, "#{__dir__}/mapping"
|
|
13
|
+
autoload :MappingRule, "#{__dir__}/mapping_rule"
|
|
14
|
+
autoload :Transform, "#{__dir__}/transform"
|
|
15
|
+
autoload :Transformation, "#{__dir__}/transformation"
|
|
16
|
+
autoload :TransformationBuilder, "#{__dir__}/transformation_builder"
|
|
17
|
+
autoload :Adapter, "#{__dir__}/adapter"
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Register KeyValue transformation builders for all key-value formats
|
|
22
|
+
%i[json yaml toml hash].each do |format|
|
|
23
|
+
Lutaml::Model::TransformationRegistry.register_builder(
|
|
24
|
+
format, Lutaml::KeyValue::TransformationBuilder
|
|
25
|
+
)
|
|
26
|
+
end
|
|
@@ -249,7 +249,10 @@ format)
|
|
|
249
249
|
value = apply_value_map(value, rule.value_map(:from, options), attr)
|
|
250
250
|
|
|
251
251
|
if rule.has_custom_method_for_deserialization?
|
|
252
|
-
|
|
252
|
+
# An empty value ("", [], {}) is a present value per the
|
|
253
|
+
# missing-values semantics and must reach the custom method;
|
|
254
|
+
# only nil (non-existent) skips it (lutaml-model#746).
|
|
255
|
+
return if value.nil?
|
|
253
256
|
|
|
254
257
|
return rule.deserialize(instance, value, attributes, model_class)
|
|
255
258
|
end
|
|
@@ -88,11 +88,9 @@ model_class: nil)
|
|
|
88
88
|
# @param rule [CompiledRule] The compiled rule
|
|
89
89
|
# @return [Boolean] true if the rule defines a nested model
|
|
90
90
|
def nested_model?(rule)
|
|
91
|
-
# rubocop:disable Style/IncludeOrExtend
|
|
92
91
|
# Use include? instead of < because < returns nil (not false) for non-subclasses
|
|
93
92
|
rule.attribute_type.is_a?(Class) &&
|
|
94
93
|
rule.attribute_type.include?(Lutaml::Model::Serialize)
|
|
95
|
-
# rubocop:enable Style/IncludeOrExtend
|
|
96
94
|
end
|
|
97
95
|
|
|
98
96
|
# Serialize a nested model to a hash representation.
|
data/lib/lutaml/key_value.rb
CHANGED
|
@@ -1,24 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
autoload :Document, "#{__dir__}/key_value/document"
|
|
7
|
-
autoload :Mapping, "#{__dir__}/key_value/mapping"
|
|
8
|
-
autoload :MappingRule, "#{__dir__}/key_value/mapping_rule"
|
|
9
|
-
autoload :Transform, "#{__dir__}/key_value/transform"
|
|
10
|
-
autoload :Transformation, "#{__dir__}/key_value/transformation"
|
|
11
|
-
autoload :TransformationBuilder,
|
|
12
|
-
"#{__dir__}/key_value/transformation_builder"
|
|
13
|
-
autoload :Adapter, "#{__dir__}/key_value/adapter"
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
|
|
3
|
+
# Public KeyValue entrypoint. Loads the base model and the internal
|
|
4
|
+
# implementation. The internal file does not require the model back,
|
|
5
|
+
# which keeps the require graph acyclic.
|
|
17
6
|
require_relative "model"
|
|
18
|
-
|
|
19
|
-
# Register KeyValue transformation builders for all key-value formats
|
|
20
|
-
%i[json yaml toml hash].each do |format|
|
|
21
|
-
Lutaml::Model::TransformationRegistry.register_builder(
|
|
22
|
-
format, Lutaml::KeyValue::TransformationBuilder
|
|
23
|
-
)
|
|
24
|
-
end
|
|
7
|
+
require_relative "key_value/format"
|
|
@@ -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|
|
|
@@ -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
|