lutaml-model 0.8.0 → 0.8.2
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-repos.json +9 -0
- data/.github/workflows/downstream-performance.yml +0 -3
- data/.rubocop_todo.yml +18 -186
- data/README.adoc +212 -15
- data/bench/bench_xmi.rb +6 -6
- data/bench/gate_config.rb +2 -9
- data/docs/_pages/configuration.adoc +155 -41
- data/docs/_pages/serialization_adapters.adoc +65 -14
- data/docs/index.adoc +3 -1
- data/docs/yamls_sequence.adoc +335 -0
- data/lib/lutaml/hash_format.rb +4 -0
- data/lib/lutaml/json/adapter/multi_json_adapter.rb +4 -2
- data/lib/lutaml/json/adapter/oj_adapter.rb +4 -2
- data/lib/lutaml/json.rb +4 -0
- data/lib/lutaml/key_value/adapter/json/multi_json_adapter.rb +4 -2
- data/lib/lutaml/key_value/adapter/json/oj_adapter.rb +4 -2
- data/lib/lutaml/model/adapter_resolver.rb +410 -0
- data/lib/lutaml/model/adapter_scope.rb +64 -0
- data/lib/lutaml/model/config.rb +84 -21
- data/lib/lutaml/model/configuration.rb +17 -249
- data/lib/lutaml/model/format_registry.rb +44 -117
- data/lib/lutaml/model/mapping/listener.rb +4 -2
- data/lib/lutaml/model/serialize/format_conversion.rb +42 -3
- data/lib/lutaml/model/serialize.rb +4 -2
- data/lib/lutaml/model/services/base.rb +4 -2
- data/lib/lutaml/model/version.rb +1 -1
- data/lib/lutaml/model.rb +2 -0
- data/lib/lutaml/toml.rb +10 -3
- data/lib/lutaml/xml/serialization/instance_methods.rb +6 -0
- data/lib/lutaml/xml.rb +3 -4
- data/lib/lutaml/yaml.rb +4 -0
- data/lib/lutaml/yamls/adapter/mapping.rb +7 -0
- data/lib/lutaml/yamls/adapter/standard_adapter.rb +23 -2
- data/lib/lutaml/yamls/adapter/transform.rb +105 -7
- data/lib/lutaml/yamls/adapter/yamls_sequence.rb +20 -0
- data/lib/lutaml/yamls/adapter/yamls_sequence_rule.rb +48 -0
- data/lib/lutaml/yamls/adapter.rb +2 -0
- data/spec/fixtures/geolexica_v2_concept.rb +136 -0
- data/spec/fixtures/geolexica_v2_sample.yaml +36 -0
- data/spec/fixtures/geolexica_v2_sample2.yaml +38 -0
- data/spec/fixtures/yamls_range_concept.rb +139 -0
- data/spec/lutaml/model/xml_decoupling_spec.rb +5 -4
- data/spec/lutaml/model/yamls_range_spec.rb +393 -0
- data/spec/lutaml/model/yamls_sequence_spec.rb +245 -0
- data/spec/spec_helper.rb +5 -0
- metadata +13 -3
- data/bench/bench_uniword.rb +0 -69
|
@@ -41,7 +41,7 @@ module Lutaml
|
|
|
41
41
|
# @return [Object] The deserialized model instance
|
|
42
42
|
def from(format, data, options = {})
|
|
43
43
|
Instrumentation.instrument(:from, model: name, format: format) do
|
|
44
|
-
adapter =
|
|
44
|
+
adapter = resolve_adapter(format, options.delete(:adapter))
|
|
45
45
|
|
|
46
46
|
raise Lutaml::Model::FormatAdapterNotSpecifiedError.new(format) if adapter.nil?
|
|
47
47
|
|
|
@@ -130,7 +130,7 @@ module Lutaml
|
|
|
130
130
|
# @param options [Hash] Additional options
|
|
131
131
|
# @return [Object] The model instance
|
|
132
132
|
def of(format, doc, options = {})
|
|
133
|
-
if doc.is_a?(Array) && format
|
|
133
|
+
if doc.is_a?(Array) && !array_passthrough_format?(format)
|
|
134
134
|
return doc.map { |item| send(:"of_#{format}", item) }
|
|
135
135
|
end
|
|
136
136
|
|
|
@@ -156,6 +156,23 @@ module Lutaml
|
|
|
156
156
|
# No-op by default; XML overrides via prepend
|
|
157
157
|
end
|
|
158
158
|
|
|
159
|
+
# Whether this format+model combination requires the parsed array
|
|
160
|
+
# to pass through to the transformer as a whole (not split per element).
|
|
161
|
+
# YAMLS with sequence definitions needs the full document array.
|
|
162
|
+
#
|
|
163
|
+
# @param format [Symbol] The format
|
|
164
|
+
# @return [Boolean]
|
|
165
|
+
def array_passthrough_format?(format)
|
|
166
|
+
return true if format == :jsonl
|
|
167
|
+
|
|
168
|
+
if format == :yamls
|
|
169
|
+
mapping = mappings[format]
|
|
170
|
+
return true if mapping.respond_to?(:yamls_sequence) && mapping.yamls_sequence
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
false
|
|
174
|
+
end
|
|
175
|
+
|
|
159
176
|
# Serialize a model instance to a format
|
|
160
177
|
#
|
|
161
178
|
# @param format [Symbol] The format to serialize to
|
|
@@ -171,8 +188,13 @@ module Lutaml
|
|
|
171
188
|
# @return [String] The serialized output
|
|
172
189
|
def to(format, instance, options = {})
|
|
173
190
|
Instrumentation.instrument(:to, model: name, format: format) do
|
|
191
|
+
adapter_override = options.is_a?(Hash) && options.delete(:adapter)
|
|
192
|
+
if adapter_override && options.is_a?(Hash)
|
|
193
|
+
options[:_adapter_override] =
|
|
194
|
+
true
|
|
195
|
+
end
|
|
174
196
|
value = public_send(:"as_#{format}", instance, options)
|
|
175
|
-
adapter =
|
|
197
|
+
adapter = resolve_adapter(format, adapter_override)
|
|
176
198
|
|
|
177
199
|
# Hook for format-specific options preparation (e.g., XML prefix/namespace/declaration)
|
|
178
200
|
options = prepare_to_options(format, instance, options)
|
|
@@ -292,6 +314,23 @@ module Lutaml
|
|
|
292
314
|
# If a root element is needed, declare it explicitly in xml block
|
|
293
315
|
end
|
|
294
316
|
end
|
|
317
|
+
|
|
318
|
+
private
|
|
319
|
+
|
|
320
|
+
# Resolve adapter class for a format operation.
|
|
321
|
+
#
|
|
322
|
+
# @param format [Symbol] the format name
|
|
323
|
+
# @param adapter_override [Symbol, Class, nil] per-operation adapter override
|
|
324
|
+
# @return [Class, nil] the adapter class
|
|
325
|
+
def resolve_adapter(format, adapter_override)
|
|
326
|
+
if adapter_override.is_a?(Class)
|
|
327
|
+
adapter_override
|
|
328
|
+
elsif adapter_override
|
|
329
|
+
AdapterResolver.resolved_adapter_class(format, adapter_override)
|
|
330
|
+
else
|
|
331
|
+
AdapterResolver.adapter_for(format)
|
|
332
|
+
end
|
|
333
|
+
end
|
|
295
334
|
end
|
|
296
335
|
end
|
|
297
336
|
end
|
|
@@ -159,16 +159,18 @@ module Lutaml
|
|
|
159
159
|
@using_default[attribute_name]
|
|
160
160
|
end
|
|
161
161
|
|
|
162
|
-
|
|
162
|
+
# rubocop:disable Style/ArgumentsForwarding -- anonymous * requires Ruby 3.2+, but required_ruby_version >= 3.0
|
|
163
|
+
def method_missing(method_name, *args)
|
|
163
164
|
if method_name.to_s.end_with?("=") && attribute_exist?(method_name)
|
|
164
165
|
define_singleton_method(method_name) do |value|
|
|
165
166
|
instance_variable_set(:"@#{method_name.to_s.chomp('=')}", value)
|
|
166
167
|
end
|
|
167
|
-
send(method_name, *)
|
|
168
|
+
send(method_name, *args)
|
|
168
169
|
else
|
|
169
170
|
super
|
|
170
171
|
end
|
|
171
172
|
end
|
|
173
|
+
# rubocop:enable Style/ArgumentsForwarding
|
|
172
174
|
|
|
173
175
|
def respond_to_missing?(method_name, include_private = false)
|
|
174
176
|
(method_name.to_s.end_with?("=") && attribute_exist?(method_name)) ||
|
|
@@ -2,8 +2,10 @@ module Lutaml
|
|
|
2
2
|
module Model
|
|
3
3
|
module Services
|
|
4
4
|
class Base
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
# rubocop:disable Style/ArgumentsForwarding -- anonymous * requires Ruby 3.2+
|
|
6
|
+
def self.call(*args)
|
|
7
|
+
new(*args).call
|
|
8
|
+
# rubocop:enable Style/ArgumentsForwarding
|
|
7
9
|
end
|
|
8
10
|
end
|
|
9
11
|
end
|
data/lib/lutaml/model/version.rb
CHANGED
data/lib/lutaml/model.rb
CHANGED
|
@@ -28,6 +28,8 @@ module Lutaml
|
|
|
28
28
|
autoload :ContextRegistry, "#{__dir__}/model/context_registry"
|
|
29
29
|
autoload :ImportRegistry, "#{__dir__}/model/import_registry"
|
|
30
30
|
autoload :GlobalContext, "#{__dir__}/model/global_context"
|
|
31
|
+
autoload :AdapterResolver, "#{__dir__}/model/adapter_resolver"
|
|
32
|
+
autoload :AdapterScope, "#{__dir__}/model/adapter_scope"
|
|
31
33
|
autoload :Utils, "#{__dir__}/model/utils"
|
|
32
34
|
autoload :Serializable, "#{__dir__}/model/serializable"
|
|
33
35
|
autoload :Error, "#{__dir__}/model/error"
|
data/lib/lutaml/toml.rb
CHANGED
|
@@ -30,12 +30,19 @@ Lutaml::Model::FormatRegistry.register(
|
|
|
30
30
|
adapter_class: nil,
|
|
31
31
|
transformer: Lutaml::Toml::Adapter::Transform,
|
|
32
32
|
key_value: true,
|
|
33
|
+
adapter_options: if Lutaml::Model::RuntimeCompatibility.opal?
|
|
34
|
+
nil
|
|
35
|
+
else
|
|
36
|
+
{
|
|
37
|
+
available: %i[tomlib toml_rb],
|
|
38
|
+
default: Lutaml::Model::RuntimeCompatibility.windows? ? :toml_rb : :tomlib,
|
|
39
|
+
}
|
|
40
|
+
end,
|
|
33
41
|
)
|
|
34
42
|
|
|
35
43
|
# Register TOML type serializers
|
|
36
44
|
require_relative "toml/type/serializers"
|
|
37
45
|
Lutaml::Toml::Type::Serializers.register_all!
|
|
38
46
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
end
|
|
47
|
+
# Auto-detection is now handled lazily by AdapterResolver on first use.
|
|
48
|
+
# No eager adapter selection at require time.
|
|
@@ -203,6 +203,12 @@ module Lutaml
|
|
|
203
203
|
def prepare_instance_format_options(format, options)
|
|
204
204
|
return super unless format == :xml
|
|
205
205
|
|
|
206
|
+
# Force eager plan building when adapter is being overridden,
|
|
207
|
+
# to dereference adapter-specific native nodes before the switch.
|
|
208
|
+
if @pending_plan_root_element && options[:_adapter_override]
|
|
209
|
+
import_declaration_plan
|
|
210
|
+
end
|
|
211
|
+
|
|
206
212
|
# Handle prefix option (converts to use_prefix for transformation phase)
|
|
207
213
|
if options.key?(:prefix)
|
|
208
214
|
prefix_option = options[:prefix]
|
data/lib/lutaml/xml.rb
CHANGED
|
@@ -279,10 +279,9 @@ Lutaml::Model::GlobalContext.register_format_registry(
|
|
|
279
279
|
# Eagerly load W3C namespace definitions (has registration side effects)
|
|
280
280
|
require_relative "xml/w3c"
|
|
281
281
|
|
|
282
|
-
# Auto-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
end
|
|
282
|
+
# Auto-detection is now handled lazily by AdapterResolver on first use.
|
|
283
|
+
# No eager adapter selection at require time — libraries can configure
|
|
284
|
+
# their preferred adapter before any XML operations occur.
|
|
286
285
|
|
|
287
286
|
# Namespace identifier validation:
|
|
288
287
|
# - URIs (http://..., urn:...) are valid namespace names per W3C XML
|
data/lib/lutaml/yaml.rb
CHANGED
|
@@ -19,6 +19,10 @@ Lutaml::Model::FormatRegistry.register(
|
|
|
19
19
|
adapter_class: Lutaml::Yaml::Adapter::StandardAdapter,
|
|
20
20
|
transformer: Lutaml::Yaml::Adapter::Transform,
|
|
21
21
|
key_value: true,
|
|
22
|
+
adapter_options: {
|
|
23
|
+
available: %i[standard standard_yaml],
|
|
24
|
+
default: :standard,
|
|
25
|
+
},
|
|
22
26
|
)
|
|
23
27
|
|
|
24
28
|
# Register YAML type serializers
|
|
@@ -4,10 +4,17 @@ module Lutaml
|
|
|
4
4
|
module Yamls
|
|
5
5
|
module Adapter
|
|
6
6
|
class Mapping < Lutaml::KeyValue::Mapping
|
|
7
|
+
attr_reader :yamls_sequence
|
|
8
|
+
|
|
7
9
|
def initialize
|
|
8
10
|
super(:yaml)
|
|
9
11
|
end
|
|
10
12
|
|
|
13
|
+
def sequence(&)
|
|
14
|
+
@yamls_sequence = YamlsSequence.new
|
|
15
|
+
@yamls_sequence.instance_eval(&)
|
|
16
|
+
end
|
|
17
|
+
|
|
11
18
|
def deep_dup
|
|
12
19
|
self.class.new.tap do |new_mapping|
|
|
13
20
|
new_mapping.mappings = duplicate_mappings
|
|
@@ -9,13 +9,33 @@ module Lutaml
|
|
|
9
9
|
FORMAT_SYMBOL = :yamls
|
|
10
10
|
|
|
11
11
|
def self.parse(yamls, _options = {})
|
|
12
|
+
parse_with_stream(yamls)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.parse_with_stream(yamls)
|
|
16
|
+
results = []
|
|
17
|
+
|
|
18
|
+
YAML.load_stream(yamls) do |doc|
|
|
19
|
+
next if doc.nil?
|
|
20
|
+
|
|
21
|
+
results << doc
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
results
|
|
25
|
+
rescue Psych::SyntaxError => e
|
|
26
|
+
warn "Skipping invalid yaml: #{e.message}"
|
|
27
|
+
parse_with_split(yamls)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.parse_with_split(yamls)
|
|
12
31
|
results = []
|
|
13
32
|
|
|
14
|
-
yamls.split(/^---\
|
|
33
|
+
yamls.split(/^---\s*$/).each do |yaml|
|
|
15
34
|
next if yaml.strip.empty?
|
|
16
35
|
|
|
17
36
|
begin
|
|
18
|
-
|
|
37
|
+
doc = YAML.safe_load(yaml, aliases: true)
|
|
38
|
+
results << doc unless doc.nil?
|
|
19
39
|
rescue Psych::SyntaxError => e
|
|
20
40
|
warn "Skipping invalid yaml: #{e.message}"
|
|
21
41
|
end
|
|
@@ -23,6 +43,7 @@ module Lutaml
|
|
|
23
43
|
|
|
24
44
|
results
|
|
25
45
|
end
|
|
46
|
+
private_class_method :parse_with_stream, :parse_with_split
|
|
26
47
|
|
|
27
48
|
def to_yamls(*_args)
|
|
28
49
|
(@yamls || []).map do |yaml|
|
|
@@ -8,17 +8,115 @@ module Lutaml
|
|
|
8
8
|
mappings = defined_mappings_for(:yamls) || mappings_for(:yaml,
|
|
9
9
|
lutaml_register)
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
if mappings.is_a?(Mapping) && mappings.yamls_sequence
|
|
12
|
+
data_to_model_with_sequence(data, format, mappings.yamls_sequence,
|
|
13
|
+
options)
|
|
14
|
+
else
|
|
15
|
+
super(data, format, options.merge(mappings: mappings))
|
|
16
|
+
end
|
|
12
17
|
end
|
|
13
18
|
|
|
14
19
|
def model_to_data(instance, _format, options = {})
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
mappings = defined_mappings_for(:yamls) || mappings_for(:yaml,
|
|
21
|
+
lutaml_register)
|
|
22
|
+
|
|
23
|
+
if mappings.is_a?(Mapping) && mappings.yamls_sequence
|
|
24
|
+
model_to_data_with_sequence(instance, mappings.yamls_sequence)
|
|
25
|
+
else
|
|
26
|
+
defined = defined_mappings_for(:yamls) || mappings_for(:yaml,
|
|
27
|
+
lutaml_register)
|
|
28
|
+
super(instance, :yaml, options.merge(mappings: defined))
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def data_to_model_with_sequence(data_array, format, sequence, options)
|
|
35
|
+
register = lutaml_register
|
|
36
|
+
child_register = Lutaml::Model::Register.resolve_for_child(
|
|
37
|
+
model_class, register
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
instance = if model_class.include?(Lutaml::Model::Serialize)
|
|
41
|
+
model_class.new(lutaml_register: child_register)
|
|
42
|
+
else
|
|
43
|
+
model_class.new
|
|
44
|
+
end
|
|
45
|
+
root_and_parent_assignment(instance, options)
|
|
46
|
+
|
|
47
|
+
sequence.rules.each do |rule|
|
|
48
|
+
docs = extract_docs_for_rule(data_array, rule)
|
|
49
|
+
next if docs.nil?
|
|
50
|
+
next if docs.is_a?(Array) && docs.empty?
|
|
51
|
+
|
|
52
|
+
if rule.singular?
|
|
53
|
+
doc = docs.is_a?(Array) ? docs.first : docs
|
|
54
|
+
value = deserialize_single_doc(doc, rule.type, format,
|
|
55
|
+
register, instance)
|
|
56
|
+
rule.assign_value(instance, value)
|
|
57
|
+
else
|
|
58
|
+
values = docs.map do |doc|
|
|
59
|
+
deserialize_single_doc(doc, rule.type, format, register,
|
|
60
|
+
instance)
|
|
61
|
+
end
|
|
62
|
+
rule.assign_value(instance, values)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
instance
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def extract_docs_for_rule(data_array, rule)
|
|
70
|
+
size = data_array.size
|
|
71
|
+
return nil if size.zero?
|
|
72
|
+
|
|
73
|
+
case rule.position
|
|
74
|
+
when Integer
|
|
75
|
+
idx = rule.position.negative? ? rule.position + size : rule.position
|
|
76
|
+
data_array[idx]
|
|
77
|
+
when Range
|
|
78
|
+
start_idx = rule.position.begin.negative? ? rule.position.begin + size : rule.position.begin
|
|
79
|
+
end_idx = rule.position.end
|
|
80
|
+
end_idx = size - 1 if end_idx.nil?
|
|
81
|
+
end_idx = end_idx + size if end_idx.negative?
|
|
82
|
+
end_idx = size - 1 if end_idx > size - 1
|
|
83
|
+
start_idx = 0 if start_idx.negative?
|
|
84
|
+
return nil if start_idx > end_idx
|
|
85
|
+
|
|
86
|
+
data_array[start_idx..end_idx]
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def deserialize_single_doc(doc, type, _format, register, parent)
|
|
91
|
+
transformer = Lutaml::Model::Config.transformer_for(:yaml)
|
|
92
|
+
transformer.data_to_model(
|
|
93
|
+
type, doc, :yaml,
|
|
94
|
+
register: register,
|
|
95
|
+
lutaml_parent: parent,
|
|
96
|
+
lutaml_root: parent.lutaml_root || parent
|
|
97
|
+
)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def model_to_data_with_sequence(instance, sequence)
|
|
101
|
+
results = []
|
|
102
|
+
|
|
103
|
+
sequence.rules.each do |rule|
|
|
104
|
+
value = rule.read_value(instance)
|
|
105
|
+
next if value.nil?
|
|
106
|
+
|
|
107
|
+
if rule.singular?
|
|
108
|
+
results << serialize_single_model(value)
|
|
109
|
+
else
|
|
110
|
+
value.each { |item| results << serialize_single_model(item) }
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
results
|
|
115
|
+
end
|
|
19
116
|
|
|
20
|
-
|
|
21
|
-
|
|
117
|
+
def serialize_single_model(item)
|
|
118
|
+
transformer = Lutaml::Model::Config.transformer_for(:yaml)
|
|
119
|
+
transformer.model_to_data(item.class, item, :yaml)
|
|
22
120
|
end
|
|
23
121
|
end
|
|
24
122
|
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Lutaml
|
|
4
|
+
module Yamls
|
|
5
|
+
module Adapter
|
|
6
|
+
class YamlsSequence
|
|
7
|
+
attr_reader :rules
|
|
8
|
+
|
|
9
|
+
def initialize
|
|
10
|
+
@rules = []
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def map_document(position, to:, type:, collection: false)
|
|
14
|
+
@rules << YamlsSequenceRule.new(position, to: to, type: type,
|
|
15
|
+
collection: collection)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Lutaml
|
|
4
|
+
module Yamls
|
|
5
|
+
module Adapter
|
|
6
|
+
class YamlsSequenceRule
|
|
7
|
+
attr_reader :position, :to, :type, :collection
|
|
8
|
+
|
|
9
|
+
def initialize(position, to:, type:, collection: false)
|
|
10
|
+
@position = position
|
|
11
|
+
@to = to
|
|
12
|
+
@type = type
|
|
13
|
+
@collection = collection
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def resolve_range(doc_count)
|
|
17
|
+
return nil unless doc_count.positive?
|
|
18
|
+
|
|
19
|
+
case position
|
|
20
|
+
when Integer
|
|
21
|
+
idx = position.negative? ? position + doc_count : position
|
|
22
|
+
idx..idx
|
|
23
|
+
when Range
|
|
24
|
+
start_idx = position.begin.negative? ? position.begin + doc_count : position.begin
|
|
25
|
+
end_idx = position.end
|
|
26
|
+
end_idx = doc_count - 1 if end_idx.nil?
|
|
27
|
+
end_idx = end_idx + doc_count if end_idx.negative?
|
|
28
|
+
end_idx = doc_count - 1 if end_idx > doc_count - 1
|
|
29
|
+
start_idx = 0 if start_idx.negative?
|
|
30
|
+
start_idx..end_idx
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def singular?
|
|
35
|
+
!collection
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def assign_value(instance, value)
|
|
39
|
+
instance.public_send(:"#{to}=", value)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def read_value(instance)
|
|
43
|
+
instance.public_send(to)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
data/lib/lutaml/yamls/adapter.rb
CHANGED
|
@@ -7,6 +7,8 @@ module Lutaml
|
|
|
7
7
|
autoload :Mapping, "#{__dir__}/adapter/mapping"
|
|
8
8
|
autoload :MappingRule, "#{__dir__}/adapter/mapping_rule"
|
|
9
9
|
autoload :Transform, "#{__dir__}/adapter/transform"
|
|
10
|
+
autoload :YamlsSequence, "#{__dir__}/adapter/yamls_sequence"
|
|
11
|
+
autoload :YamlsSequenceRule, "#{__dir__}/adapter/yamls_sequence_rule"
|
|
10
12
|
autoload :StandardAdapter, "#{__dir__}/adapter/standard_adapter"
|
|
11
13
|
end
|
|
12
14
|
end
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
require_relative "../../lib/lutaml/model"
|
|
2
|
+
|
|
3
|
+
module GeolexicaV2
|
|
4
|
+
# --- Leaf types ---
|
|
5
|
+
|
|
6
|
+
class ContentBlock < Lutaml::Model::Serializable
|
|
7
|
+
attribute :content, :string
|
|
8
|
+
|
|
9
|
+
yaml do
|
|
10
|
+
map "content", to: :content
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class TermDesignation < Lutaml::Model::Serializable
|
|
15
|
+
attribute :type, :string
|
|
16
|
+
attribute :normative_status, :string
|
|
17
|
+
attribute :designation, :string
|
|
18
|
+
|
|
19
|
+
yaml do
|
|
20
|
+
map "type", to: :type
|
|
21
|
+
map "normative_status", to: :normative_status
|
|
22
|
+
map "designation", to: :designation
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class Locality < Lutaml::Model::Serializable
|
|
27
|
+
attribute :type, :string
|
|
28
|
+
attribute :reference_from, :string
|
|
29
|
+
|
|
30
|
+
yaml do
|
|
31
|
+
map "type", to: :type
|
|
32
|
+
map "reference_from", to: :reference_from
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
class SourceOrigin < Lutaml::Model::Serializable
|
|
37
|
+
attribute :ref, :string
|
|
38
|
+
attribute :locality, Locality
|
|
39
|
+
attribute :link, :string
|
|
40
|
+
|
|
41
|
+
yaml do
|
|
42
|
+
map "ref", to: :ref
|
|
43
|
+
map "locality", to: :locality
|
|
44
|
+
map "link", to: :link
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
class Source < Lutaml::Model::Serializable
|
|
49
|
+
attribute :origin, SourceOrigin
|
|
50
|
+
attribute :type, :string
|
|
51
|
+
|
|
52
|
+
yaml do
|
|
53
|
+
map "origin", to: :origin
|
|
54
|
+
map "type", to: :type
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# --- Document 0: Concept Index ---
|
|
59
|
+
|
|
60
|
+
class ConceptIndexData < Lutaml::Model::Serializable
|
|
61
|
+
attribute :identifier, :string
|
|
62
|
+
attribute :localized_concepts, :hash
|
|
63
|
+
|
|
64
|
+
yaml do
|
|
65
|
+
map "identifier", to: :identifier
|
|
66
|
+
map "localized_concepts", to: :localized_concepts
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
class ConceptIndex < Lutaml::Model::Serializable
|
|
71
|
+
attribute :data, ConceptIndexData
|
|
72
|
+
attribute :id, :string
|
|
73
|
+
|
|
74
|
+
yaml do
|
|
75
|
+
map "data", to: :data
|
|
76
|
+
map "id", to: :id
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# --- Document 1: Localized Concept ---
|
|
81
|
+
|
|
82
|
+
class LocalizedConceptData < Lutaml::Model::Serializable
|
|
83
|
+
attribute :definition, ContentBlock, collection: true
|
|
84
|
+
attribute :examples, ContentBlock, collection: true
|
|
85
|
+
attribute :notes, ContentBlock, collection: true
|
|
86
|
+
attribute :sources, Source, collection: true
|
|
87
|
+
attribute :terms, TermDesignation, collection: true
|
|
88
|
+
attribute :language_code, :string
|
|
89
|
+
attribute :entry_status, :string
|
|
90
|
+
|
|
91
|
+
yaml do
|
|
92
|
+
map "definition", to: :definition, render_empty: true
|
|
93
|
+
map "examples", to: :examples, render_empty: true
|
|
94
|
+
map "notes", to: :notes, render_empty: true
|
|
95
|
+
map "sources", to: :sources, render_empty: true
|
|
96
|
+
map "terms", to: :terms
|
|
97
|
+
map "language_code", to: :language_code
|
|
98
|
+
map "entry_status", to: :entry_status
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
class LocalizedConcept < Lutaml::Model::Serializable
|
|
103
|
+
attribute :data, LocalizedConceptData
|
|
104
|
+
attribute :id, :string
|
|
105
|
+
|
|
106
|
+
yaml do
|
|
107
|
+
map "data", to: :data
|
|
108
|
+
map "id", to: :id
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# --- Managed Concept: YAMLS sequence of ConceptIndex + LocalizedConcept ---
|
|
113
|
+
|
|
114
|
+
class ManagedConcept < Lutaml::Model::Serializable
|
|
115
|
+
attribute :index, ConceptIndex
|
|
116
|
+
attribute :localized, LocalizedConcept, collection: true
|
|
117
|
+
|
|
118
|
+
yamls do
|
|
119
|
+
sequence do
|
|
120
|
+
map_document 0, to: :index, type: ConceptIndex
|
|
121
|
+
map_document 1.., to: :localized, type: LocalizedConcept,
|
|
122
|
+
collection: true
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# --- Collection of ManagedConcepts (directory of v2 files) ---
|
|
128
|
+
|
|
129
|
+
class ManagedConceptCollection < Lutaml::Model::Collection
|
|
130
|
+
instances :concepts, ManagedConcept
|
|
131
|
+
|
|
132
|
+
yamls do
|
|
133
|
+
map_instances to: :concepts
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
data:
|
|
3
|
+
identifier: 3.5.8.8
|
|
4
|
+
localized_concepts:
|
|
5
|
+
eng: fbe1444a-7c11-555e-bb1b-680a4e6f2502
|
|
6
|
+
id: 0171b198-d068-53d9-8741-fb87e6755d62
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
data:
|
|
10
|
+
definition:
|
|
11
|
+
- content: characteristic of a {{urn:iso:std:iso:14812:3.5.8.1,financial model}}
|
|
12
|
+
that requires {{urn:iso:std:iso:14812:3.5.3.4,user,users}} to enter into an
|
|
13
|
+
agreement prior to receiving {{urn:iso:std:iso:14812:3.5.2.1,service,services}}
|
|
14
|
+
examples: []
|
|
15
|
+
notes:
|
|
16
|
+
- content: The agreement can be associated with fees.
|
|
17
|
+
- content: The agreement can be minimal, such as collecting user information for
|
|
18
|
+
business purposes.
|
|
19
|
+
- content: The membership can be granted as a part of a broader agreement. For example,
|
|
20
|
+
a university bus {{urn:iso:std:iso:14812:3.1.2.1,system}} can restrict access
|
|
21
|
+
to students and faculty.
|
|
22
|
+
sources:
|
|
23
|
+
- origin:
|
|
24
|
+
ref: ISO/TS 14812:2022
|
|
25
|
+
locality:
|
|
26
|
+
type: clause
|
|
27
|
+
reference_from: 3.5.8.8
|
|
28
|
+
link: https://www.iso.org/standard/79779.html
|
|
29
|
+
type: authoritative
|
|
30
|
+
terms:
|
|
31
|
+
- type: expression
|
|
32
|
+
normative_status: preferred
|
|
33
|
+
designation: membership-based
|
|
34
|
+
language_code: eng
|
|
35
|
+
entry_status: valid
|
|
36
|
+
id: fbe1444a-7c11-555e-bb1b-680a4e6f2502
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
data:
|
|
3
|
+
identifier: 3.7.1.5
|
|
4
|
+
localized_concepts:
|
|
5
|
+
eng: 0e4dd58e-d197-57af-a4fb-55653e46540d
|
|
6
|
+
id: 01da7814-e090-5c79-8e88-04a40532da50
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
data:
|
|
10
|
+
definition:
|
|
11
|
+
- content: "{{urn:iso:std:iso:14812:3.7.1.4,vehicle input device,input device}}
|
|
12
|
+
designed to be physically {{urn:iso:std:iso:14812:3.2.3.6,connected}} to a {{urn:iso:std:iso:14812:3.7.1.1,vehicle}}
|
|
13
|
+
and to remain connected even when the vehicle is not in use"
|
|
14
|
+
examples: []
|
|
15
|
+
notes:
|
|
16
|
+
- content: Built-in input devices include devices that can be temporarily {{urn:iso:std:iso:14812:3.7.4.3,disconnected}}
|
|
17
|
+
for security reasons (e.g. some radios are equipped with detachable front panels).
|
|
18
|
+
- content: Built-in input devices are typically considered to be a part of the vehicle.
|
|
19
|
+
- content: Built-in input devices require a maintenance operation to connect or
|
|
20
|
+
disconnect.
|
|
21
|
+
sources:
|
|
22
|
+
- origin:
|
|
23
|
+
ref: ISO/TS 14812:2022
|
|
24
|
+
locality:
|
|
25
|
+
type: clause
|
|
26
|
+
reference_from: 3.7.1.5
|
|
27
|
+
link: https://www.iso.org/standard/79779.html
|
|
28
|
+
type: authoritative
|
|
29
|
+
terms:
|
|
30
|
+
- type: expression
|
|
31
|
+
normative_status: preferred
|
|
32
|
+
designation: built-in vehicle input device
|
|
33
|
+
- type: expression
|
|
34
|
+
normative_status: preferred
|
|
35
|
+
designation: built-in input device
|
|
36
|
+
language_code: eng
|
|
37
|
+
entry_status: valid
|
|
38
|
+
id: 0e4dd58e-d197-57af-a4fb-55653e46540d
|