lutaml-model 0.7.1 → 0.7.7
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/.envrc +1 -0
- data/.github/workflows/dependent-tests.yml +4 -0
- data/.github/workflows/rake.yml +12 -0
- data/.github/workflows/release.yml +3 -0
- data/.gitignore +6 -1
- data/.irbrc +1 -0
- data/.pryrc +1 -0
- data/.rubocop.yml +1 -1
- data/.rubocop_todo.yml +58 -84
- data/Gemfile +4 -1
- data/README.adoc +3115 -365
- data/RELEASE_NOTES.adoc +346 -0
- data/docs/custom_adapters.adoc +144 -0
- data/docs/custom_registers.adoc +228 -0
- data/docs/schema_generation.adoc +898 -0
- data/docs/schema_import.adoc +364 -0
- data/flake.lock +114 -0
- data/flake.nix +103 -0
- data/lib/lutaml/model/attribute.rb +242 -100
- data/lib/lutaml/model/choice.rb +30 -0
- data/lib/lutaml/model/collection.rb +212 -0
- data/lib/lutaml/model/comparable_model.rb +3 -3
- data/lib/lutaml/model/config.rb +71 -42
- data/lib/lutaml/model/constants.rb +2 -0
- data/lib/lutaml/model/error/element_count_out_of_range_error.rb +29 -0
- data/lib/lutaml/model/error/invalid_attribute_name_error.rb +15 -0
- data/lib/lutaml/model/error/invalid_attribute_options_error.rb +16 -0
- data/lib/lutaml/model/error/invalid_choice_range_error.rb +3 -5
- data/lib/lutaml/model/error/polymorphic_error.rb +7 -2
- data/lib/lutaml/model/error/register/not_registrable_class_error.rb +11 -0
- data/lib/lutaml/model/error/type/invalid_value_error.rb +5 -3
- data/lib/lutaml/model/error/type/max_bound_error.rb +20 -0
- data/lib/lutaml/model/error/type/max_length_error.rb +20 -0
- data/lib/lutaml/model/error/type/min_bound_error.rb +20 -0
- data/lib/lutaml/model/error/type/min_length_error.rb +20 -0
- data/lib/lutaml/model/error/type/pattern_not_matched_error.rb +18 -0
- data/lib/lutaml/model/error/validation_failed_error.rb +9 -0
- data/lib/lutaml/model/error.rb +10 -0
- data/lib/lutaml/model/errors.rb +36 -0
- data/lib/lutaml/model/format_registry.rb +44 -0
- data/lib/lutaml/model/global_register.rb +41 -0
- data/lib/lutaml/model/hash_adapter/document.rb +11 -0
- data/lib/lutaml/model/hash_adapter/mapping.rb +19 -0
- data/lib/lutaml/model/hash_adapter/mapping_rule.rb +9 -0
- data/lib/lutaml/model/hash_adapter/standard_adapter.rb +17 -0
- data/lib/lutaml/model/hash_adapter/transform.rb +8 -0
- data/lib/lutaml/model/hash_adapter.rb +21 -0
- data/lib/lutaml/model/json/document.rb +11 -0
- data/lib/lutaml/model/json/mapping.rb +19 -0
- data/lib/lutaml/model/json/mapping_rule.rb +9 -0
- data/lib/lutaml/model/{json_adapter → json}/multi_json_adapter.rb +4 -5
- data/lib/lutaml/model/{json_adapter/standard_json_adapter.rb → json/standard_adapter.rb} +5 -3
- data/lib/lutaml/model/json/transform.rb +8 -0
- data/lib/lutaml/model/json.rb +21 -0
- data/lib/lutaml/model/jsonl/document.rb +14 -0
- data/lib/lutaml/model/jsonl/mapping.rb +19 -0
- data/lib/lutaml/model/jsonl/mapping_rule.rb +9 -0
- data/lib/lutaml/model/jsonl/standard_adapter.rb +33 -0
- data/lib/lutaml/model/jsonl/transform.rb +19 -0
- data/lib/lutaml/model/jsonl.rb +21 -0
- data/lib/lutaml/model/key_value_document.rb +28 -0
- data/lib/lutaml/model/mapping/key_value_mapping.rb +85 -13
- data/lib/lutaml/model/mapping/key_value_mapping_rule.rb +5 -0
- data/lib/lutaml/model/mapping/mapping.rb +13 -0
- data/lib/lutaml/model/mapping/mapping_rule.rb +15 -9
- data/lib/lutaml/model/register.rb +105 -0
- data/lib/lutaml/model/{toml_adapter.rb → registrable.rb} +1 -1
- data/lib/lutaml/model/schema/base_schema.rb +64 -0
- data/lib/lutaml/model/schema/decorators/attribute.rb +114 -0
- data/lib/lutaml/model/schema/decorators/choices.rb +31 -0
- data/lib/lutaml/model/schema/decorators/class_definition.rb +85 -0
- data/lib/lutaml/model/schema/decorators/definition_collection.rb +97 -0
- data/lib/lutaml/model/schema/generator/definition.rb +53 -0
- data/lib/lutaml/model/schema/generator/definitions_collection.rb +81 -0
- data/lib/lutaml/model/schema/generator/properties_collection.rb +63 -0
- data/lib/lutaml/model/schema/generator/property.rb +110 -0
- data/lib/lutaml/model/schema/generator/ref.rb +24 -0
- data/lib/lutaml/model/schema/helpers/template_helper.rb +49 -0
- data/lib/lutaml/model/schema/json_schema.rb +42 -49
- data/lib/lutaml/model/schema/relaxng_schema.rb +14 -10
- data/lib/lutaml/model/schema/renderer.rb +36 -0
- data/lib/lutaml/model/schema/shared_methods.rb +24 -0
- data/lib/lutaml/model/schema/templates/model.erb +9 -0
- data/lib/lutaml/model/schema/xml_compiler/attribute.rb +85 -0
- data/lib/lutaml/model/schema/xml_compiler/attribute_group.rb +45 -0
- data/lib/lutaml/model/schema/xml_compiler/choice.rb +65 -0
- data/lib/lutaml/model/schema/xml_compiler/complex_content.rb +27 -0
- data/lib/lutaml/model/schema/xml_compiler/complex_content_restriction.rb +34 -0
- data/lib/lutaml/model/schema/xml_compiler/complex_type.rb +136 -0
- data/lib/lutaml/model/schema/xml_compiler/element.rb +104 -0
- data/lib/lutaml/model/schema/xml_compiler/group.rb +97 -0
- data/lib/lutaml/model/schema/xml_compiler/restriction.rb +101 -0
- data/lib/lutaml/model/schema/xml_compiler/sequence.rb +50 -0
- data/lib/lutaml/model/schema/xml_compiler/simple_content.rb +36 -0
- data/lib/lutaml/model/schema/xml_compiler/simple_type.rb +189 -0
- data/lib/lutaml/model/schema/xml_compiler.rb +231 -587
- data/lib/lutaml/model/schema/xsd_schema.rb +12 -8
- data/lib/lutaml/model/schema/yaml_schema.rb +41 -35
- data/lib/lutaml/model/schema.rb +1 -0
- data/lib/lutaml/model/sequence.rb +60 -30
- data/lib/lutaml/model/serialization_adapter.rb +22 -0
- data/lib/lutaml/model/serialize.rb +296 -548
- data/lib/lutaml/model/services/base.rb +11 -0
- data/lib/lutaml/model/services/logger.rb +54 -0
- data/lib/lutaml/model/services/rule_value_extractor.rb +92 -0
- data/lib/lutaml/model/services/transformer.rb +48 -0
- data/lib/lutaml/model/services/type/validator/number.rb +25 -0
- data/lib/lutaml/model/services/type/validator/string.rb +52 -0
- data/lib/lutaml/model/services/type/validator.rb +43 -0
- data/lib/lutaml/model/services/validator.rb +145 -0
- data/lib/lutaml/model/services.rb +5 -0
- data/lib/lutaml/model/toml/document.rb +11 -0
- data/lib/lutaml/model/toml/mapping.rb +27 -0
- data/lib/lutaml/model/toml/mapping_rule.rb +9 -0
- data/lib/lutaml/model/{toml_adapter → toml}/toml_rb_adapter.rb +3 -3
- data/lib/lutaml/model/toml/tomlib_adapter.rb +19 -0
- data/lib/lutaml/model/toml/transform.rb +8 -0
- data/lib/lutaml/model/toml.rb +30 -0
- data/lib/lutaml/model/transform/key_value_transform.rb +297 -0
- data/lib/lutaml/model/transform/xml_transform.rb +228 -0
- data/lib/lutaml/model/transform.rb +93 -0
- data/lib/lutaml/model/type/boolean.rb +1 -1
- data/lib/lutaml/model/type/date.rb +1 -1
- data/lib/lutaml/model/type/date_time.rb +1 -1
- data/lib/lutaml/model/type/decimal.rb +11 -9
- data/lib/lutaml/model/type/float.rb +2 -1
- data/lib/lutaml/model/type/integer.rb +24 -21
- data/lib/lutaml/model/type/string.rb +4 -2
- data/lib/lutaml/model/type/time.rb +1 -1
- data/lib/lutaml/model/type/time_without_date.rb +1 -1
- data/lib/lutaml/model/type/value.rb +11 -10
- data/lib/lutaml/model/type.rb +5 -2
- data/lib/lutaml/model/uninitialized_class.rb +1 -1
- data/lib/lutaml/model/utils.rb +56 -4
- data/lib/lutaml/model/validation.rb +6 -4
- data/lib/lutaml/model/version.rb +1 -1
- data/lib/lutaml/model/{xml_adapter → xml}/builder/nokogiri.rb +2 -2
- data/lib/lutaml/model/{xml_adapter → xml}/builder/oga.rb +10 -10
- data/lib/lutaml/model/{xml_adapter → xml}/builder/ox.rb +1 -1
- data/lib/lutaml/model/{xml_adapter/xml_document.rb → xml/document.rb} +42 -25
- data/lib/lutaml/model/xml/element.rb +32 -0
- data/lib/lutaml/model/xml/mapping.rb +471 -0
- data/lib/lutaml/model/xml/mapping_rule.rb +149 -0
- data/lib/lutaml/model/xml/nokogiri_adapter.rb +234 -0
- data/lib/lutaml/model/{xml_adapter → xml}/oga/document.rb +1 -1
- data/lib/lutaml/model/{xml_adapter → xml}/oga/element.rb +7 -2
- data/lib/lutaml/model/xml/oga_adapter.rb +172 -0
- data/lib/lutaml/model/xml/ox_adapter.rb +229 -0
- data/lib/lutaml/model/xml/transform.rb +8 -0
- data/lib/lutaml/model/{xml_adapter → xml}/xml_attribute.rb +1 -1
- data/lib/lutaml/model/{xml_adapter → xml}/xml_element.rb +9 -31
- data/lib/lutaml/model/{xml_adapter → xml}/xml_namespace.rb +1 -1
- data/lib/lutaml/model/xml.rb +31 -0
- data/lib/lutaml/model/xml_adapter/element.rb +11 -25
- data/lib/lutaml/model/xml_adapter/nokogiri_adapter.rb +6 -223
- data/lib/lutaml/model/xml_adapter/oga_adapter.rb +13 -163
- data/lib/lutaml/model/xml_adapter/ox_adapter.rb +10 -207
- data/lib/lutaml/model/yaml/document.rb +10 -0
- data/lib/lutaml/model/yaml/mapping.rb +19 -0
- data/lib/lutaml/model/yaml/mapping_rule.rb +9 -0
- data/lib/lutaml/model/{yaml_adapter/standard_yaml_adapter.rb → yaml/standard_adapter.rb} +4 -3
- data/lib/lutaml/model/yaml/transform.rb +8 -0
- data/lib/lutaml/model/yaml.rb +21 -0
- data/lib/lutaml/model/yamls/document.rb +14 -0
- data/lib/lutaml/model/yamls/mapping.rb +19 -0
- data/lib/lutaml/model/yamls/mapping_rule.rb +9 -0
- data/lib/lutaml/model/yamls/standard_adapter.rb +34 -0
- data/lib/lutaml/model/yamls/transform.rb +19 -0
- data/lib/lutaml/model/yamls.rb +21 -0
- data/lib/lutaml/model.rb +15 -4
- data/lutaml-model.gemspec +0 -4
- data/spec/benchmarks/xml_parsing_benchmark_spec.rb +5 -6
- data/spec/fixtures/xml/advanced_test_schema.xsd +134 -0
- data/spec/fixtures/xml/examples/nested_categories.xml +55 -0
- data/spec/fixtures/xml/examples/valid_catalog.xml +43 -0
- data/spec/fixtures/xml/product_catalog.xsd +151 -0
- data/spec/fixtures/xml/specifications_schema.xsd +38 -0
- data/spec/lutaml/model/attribute_collection_spec.rb +101 -0
- data/spec/lutaml/model/attribute_spec.rb +41 -44
- data/spec/lutaml/model/cdata_spec.rb +7 -7
- data/spec/lutaml/model/choice_spec.rb +44 -0
- data/spec/lutaml/model/custom_bibtex_adapter_spec.rb +598 -0
- data/spec/lutaml/model/custom_collection_spec.rb +830 -0
- data/spec/lutaml/model/custom_vobject_adapter_spec.rb +1226 -0
- data/spec/lutaml/model/global_register_spec.rb +108 -0
- data/spec/lutaml/model/group_spec.rb +27 -10
- data/spec/lutaml/model/hash/adapter_spec.rb +255 -0
- data/spec/lutaml/model/json_adapter_spec.rb +6 -6
- data/spec/lutaml/model/jsonl/standard_adapter_spec.rb +91 -0
- data/spec/lutaml/model/jsonl_spec.rb +229 -0
- data/spec/lutaml/model/key_value_mapping_spec.rb +25 -1
- data/spec/lutaml/model/mixed_content_spec.rb +24 -24
- data/spec/lutaml/model/multiple_mapping_spec.rb +6 -6
- data/spec/lutaml/model/ordered_content_spec.rb +6 -6
- data/spec/lutaml/model/polymorphic_spec.rb +178 -0
- data/spec/lutaml/model/register/key_value_spec.rb +275 -0
- data/spec/lutaml/model/register/xml_spec.rb +185 -0
- data/spec/lutaml/model/register_spec.rb +147 -0
- data/spec/lutaml/model/root_mappings_spec.rb +3 -3
- data/spec/lutaml/model/rule_value_extractor_spec.rb +162 -0
- data/spec/lutaml/model/schema/generator/definitions_collection_spec.rb +120 -0
- data/spec/lutaml/model/schema/json_schema_spec.rb +412 -51
- data/spec/lutaml/model/schema/json_schema_to_models_spec.rb +383 -0
- data/spec/lutaml/model/schema/xml_compiler/attribute_group_spec.rb +65 -0
- data/spec/lutaml/model/schema/xml_compiler/attribute_spec.rb +63 -0
- data/spec/lutaml/model/schema/xml_compiler/choice_spec.rb +71 -0
- data/spec/lutaml/model/schema/xml_compiler/complex_content_restriction_spec.rb +55 -0
- data/spec/lutaml/model/schema/xml_compiler/complex_content_spec.rb +37 -0
- data/spec/lutaml/model/schema/xml_compiler/complex_type_spec.rb +173 -0
- data/spec/lutaml/model/schema/xml_compiler/element_spec.rb +63 -0
- data/spec/lutaml/model/schema/xml_compiler/group_spec.rb +86 -0
- data/spec/lutaml/model/schema/xml_compiler/restriction_spec.rb +76 -0
- data/spec/lutaml/model/schema/xml_compiler/sequence_spec.rb +59 -0
- data/spec/lutaml/model/schema/xml_compiler/simple_content_spec.rb +55 -0
- data/spec/lutaml/model/schema/xml_compiler/simple_type_spec.rb +181 -0
- data/spec/lutaml/model/schema/xml_compiler_spec.rb +503 -1804
- data/spec/lutaml/model/schema/yaml_schema_spec.rb +249 -26
- data/spec/lutaml/model/sequence_spec.rb +36 -0
- data/spec/lutaml/model/serializable_spec.rb +201 -94
- data/spec/lutaml/model/toml_adapter_spec.rb +6 -6
- data/spec/lutaml/model/toml_spec.rb +51 -0
- data/spec/lutaml/model/transformation_spec.rb +72 -15
- data/spec/lutaml/model/type_spec.rb +8 -4
- data/spec/lutaml/model/uninitialized_class_spec.rb +96 -0
- data/spec/lutaml/model/utils_spec.rb +3 -3
- data/spec/lutaml/model/xml/derived_attributes_spec.rb +1 -1
- data/spec/lutaml/model/xml/namespace_spec.rb +57 -0
- data/spec/lutaml/model/xml/root_mappings/nested_child_mappings_spec.rb +217 -0
- data/spec/lutaml/model/xml/xml_element_spec.rb +7 -1
- data/spec/lutaml/model/xml_adapter/nokogiri_adapter_spec.rb +2 -2
- data/spec/lutaml/model/xml_adapter/oga_adapter_spec.rb +2 -2
- data/spec/lutaml/model/xml_adapter/ox_adapter_spec.rb +2 -2
- data/spec/lutaml/model/xml_adapter/xml_namespace_spec.rb +12 -12
- data/spec/lutaml/model/xml_adapter_spec.rb +30 -6
- data/spec/lutaml/model/xml_mapping_rule_spec.rb +14 -7
- data/spec/lutaml/model/xml_mapping_spec.rb +27 -15
- data/spec/lutaml/model/xml_spec.rb +63 -0
- data/spec/lutaml/model/yaml_adapter_spec.rb +3 -5
- data/spec/lutaml/model/yamls/standard_adapter_spec.rb +183 -0
- data/spec/lutaml/model/yamls_spec.rb +294 -0
- data/spec/spec_helper.rb +4 -3
- metadata +162 -60
- data/lib/lutaml/model/json_adapter/json_document.rb +0 -20
- data/lib/lutaml/model/json_adapter/json_object.rb +0 -28
- data/lib/lutaml/model/loggable.rb +0 -15
- data/lib/lutaml/model/mapping/json_mapping.rb +0 -17
- data/lib/lutaml/model/mapping/toml_mapping.rb +0 -25
- data/lib/lutaml/model/mapping/xml_mapping.rb +0 -389
- data/lib/lutaml/model/mapping/xml_mapping_rule.rb +0 -139
- data/lib/lutaml/model/mapping/yaml_mapping.rb +0 -17
- data/lib/lutaml/model/mapping.rb +0 -14
- data/lib/lutaml/model/schema/templates/simple_type.rb +0 -247
- data/lib/lutaml/model/toml_adapter/toml_document.rb +0 -20
- data/lib/lutaml/model/toml_adapter/toml_object.rb +0 -28
- data/lib/lutaml/model/toml_adapter/tomlib_adapter.rb +0 -20
- data/lib/lutaml/model/yaml_adapter/yaml_document.rb +0 -20
- data/lib/lutaml/model/yaml_adapter/yaml_object.rb +0 -28
- data/lib/lutaml/model/yaml_adapter.rb +0 -8
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
require_relative "yaml_adapter"
|
|
2
1
|
require_relative "xml_adapter"
|
|
3
2
|
require_relative "config"
|
|
4
3
|
require_relative "type"
|
|
5
4
|
require_relative "attribute"
|
|
6
5
|
require_relative "mapping_hash"
|
|
7
|
-
require_relative "mapping"
|
|
8
6
|
require_relative "json_adapter"
|
|
9
7
|
require_relative "comparable_model"
|
|
10
8
|
require_relative "schema_location"
|
|
@@ -13,6 +11,8 @@ require_relative "error"
|
|
|
13
11
|
require_relative "choice"
|
|
14
12
|
require_relative "sequence"
|
|
15
13
|
require_relative "liquefiable"
|
|
14
|
+
require_relative "transform"
|
|
15
|
+
require_relative "registrable"
|
|
16
16
|
|
|
17
17
|
module Lutaml
|
|
18
18
|
module Model
|
|
@@ -20,6 +20,7 @@ module Lutaml
|
|
|
20
20
|
include ComparableModel
|
|
21
21
|
include Validation
|
|
22
22
|
include Lutaml::Model::Liquefiable
|
|
23
|
+
include Lutaml::Model::Registrable
|
|
23
24
|
|
|
24
25
|
def self.included(base)
|
|
25
26
|
base.extend(ClassMethods)
|
|
@@ -29,7 +30,7 @@ module Lutaml
|
|
|
29
30
|
module ClassMethods
|
|
30
31
|
include Lutaml::Model::Liquefiable::ClassMethods
|
|
31
32
|
|
|
32
|
-
attr_accessor :
|
|
33
|
+
attr_accessor :choice_attributes, :mappings
|
|
33
34
|
|
|
34
35
|
def inherited(subclass)
|
|
35
36
|
super
|
|
@@ -48,6 +49,16 @@ module Lutaml
|
|
|
48
49
|
instance_variable_set(:@model, self)
|
|
49
50
|
end
|
|
50
51
|
|
|
52
|
+
def attributes(register = nil)
|
|
53
|
+
ensure_imports!(register) if finalized?
|
|
54
|
+
@attributes
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def ensure_imports!(register = nil)
|
|
58
|
+
ensure_model_imports!(register)
|
|
59
|
+
ensure_choice_imports!(register)
|
|
60
|
+
end
|
|
61
|
+
|
|
51
62
|
def model(klass = nil)
|
|
52
63
|
if klass
|
|
53
64
|
@model = klass
|
|
@@ -112,7 +123,7 @@ module Lutaml
|
|
|
112
123
|
end
|
|
113
124
|
define_method(:"#{name}=") do |value|
|
|
114
125
|
value_set_for(name)
|
|
115
|
-
instance_variable_set(:"@#{name}", attr.cast_value(value))
|
|
126
|
+
instance_variable_set(:"@#{name}", attr.cast_value(value, __register))
|
|
116
127
|
end
|
|
117
128
|
end
|
|
118
129
|
end
|
|
@@ -131,6 +142,25 @@ module Lutaml
|
|
|
131
142
|
attr
|
|
132
143
|
end
|
|
133
144
|
|
|
145
|
+
def restrict(name, options = {})
|
|
146
|
+
validate_attribute_options!(name, options)
|
|
147
|
+
attr = attributes[name]
|
|
148
|
+
attr.options.merge!(options)
|
|
149
|
+
attr.process_options!
|
|
150
|
+
name
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def validate_attribute_options!(name, options)
|
|
154
|
+
invalid_opts = options.keys - Attribute::ALLOWED_OPTIONS
|
|
155
|
+
return if invalid_opts.empty?
|
|
156
|
+
|
|
157
|
+
raise Lutaml::Model::InvalidAttributeOptionsError.new(name, invalid_opts)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def register(name)
|
|
161
|
+
name&.to_sym
|
|
162
|
+
end
|
|
163
|
+
|
|
134
164
|
def root?
|
|
135
165
|
mappings_for(:xml)&.root?
|
|
136
166
|
end
|
|
@@ -142,6 +172,14 @@ module Lutaml
|
|
|
142
172
|
end
|
|
143
173
|
|
|
144
174
|
def import_model_attributes(model)
|
|
175
|
+
if model.is_a?(Symbol) || model.is_a?(String)
|
|
176
|
+
importable_models[:import_model_attributes] << model.to_sym
|
|
177
|
+
@models_imported = false
|
|
178
|
+
@choices_imported = false
|
|
179
|
+
setup_trace_point
|
|
180
|
+
return
|
|
181
|
+
end
|
|
182
|
+
|
|
145
183
|
model.attributes.each_value do |attr|
|
|
146
184
|
define_attribute_methods(attr)
|
|
147
185
|
end
|
|
@@ -151,37 +189,60 @@ module Lutaml
|
|
|
151
189
|
end
|
|
152
190
|
|
|
153
191
|
def import_model_mappings(model)
|
|
154
|
-
|
|
192
|
+
if model.is_a?(Symbol) || model.is_a?(String)
|
|
193
|
+
importable_models[:import_model_mappings] << model.to_sym
|
|
194
|
+
@models_imported = false
|
|
195
|
+
setup_trace_point
|
|
196
|
+
return
|
|
197
|
+
end
|
|
155
198
|
|
|
199
|
+
import_model_with_root_error(model)
|
|
156
200
|
Lutaml::Model::Config::AVAILABLE_FORMATS.each do |format|
|
|
157
201
|
next unless model.mappings.key?(format)
|
|
158
202
|
|
|
159
203
|
mapping = model.mappings_for(format)
|
|
160
204
|
mapping = Utils.deep_dup(mapping)
|
|
161
205
|
|
|
162
|
-
|
|
206
|
+
klass = ::Lutaml::Model::Config.mappings_class_for(format)
|
|
207
|
+
@mappings[format] ||= klass.new
|
|
163
208
|
|
|
164
209
|
if format == :xml
|
|
165
210
|
@mappings[format].merge_mapping_attributes(mapping)
|
|
166
211
|
@mappings[format].merge_mapping_elements(mapping)
|
|
167
212
|
@mappings[format].merge_elements_sequence(mapping)
|
|
168
213
|
else
|
|
169
|
-
@mappings[format].
|
|
214
|
+
@mappings[format].mappings_hash.merge!(mapping.mappings_hash)
|
|
170
215
|
end
|
|
171
216
|
end
|
|
172
217
|
end
|
|
173
218
|
|
|
174
219
|
def handle_key_value_mappings(mapping, format)
|
|
175
220
|
@mappings[format] ||= KeyValueMapping.new
|
|
176
|
-
@mappings[format].
|
|
221
|
+
@mappings[format].mappings_hash.merge!(mapping.mappings_hash)
|
|
177
222
|
end
|
|
178
223
|
|
|
179
224
|
def import_model(model)
|
|
225
|
+
if model.is_a?(Symbol) || model.is_a?(String)
|
|
226
|
+
importable_models[:import_model] << model.to_sym
|
|
227
|
+
@models_imported = false
|
|
228
|
+
@choices_imported = false
|
|
229
|
+
setup_trace_point
|
|
230
|
+
return
|
|
231
|
+
end
|
|
232
|
+
|
|
180
233
|
import_model_with_root_error(model)
|
|
181
234
|
import_model_attributes(model)
|
|
182
235
|
import_model_mappings(model)
|
|
183
236
|
end
|
|
184
237
|
|
|
238
|
+
def importable_models
|
|
239
|
+
@importable_models ||= MappingHash.new { |h, k| h[k] = [] }
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def importable_choices
|
|
243
|
+
@importable_choices ||= MappingHash.new { |h, k| h[k] = MappingHash.new { |h1, k1| h1[k1] = [] } }
|
|
244
|
+
end
|
|
245
|
+
|
|
185
246
|
def add_enum_methods_to_model(klass, enum_name, values, collection: false)
|
|
186
247
|
add_enum_getter_if_not_defined(klass, enum_name, collection)
|
|
187
248
|
add_enum_setter_if_not_defined(klass, enum_name, values, collection)
|
|
@@ -262,71 +323,60 @@ module Lutaml
|
|
|
262
323
|
attributes.select { |_, attr| attr.enum? }
|
|
263
324
|
end
|
|
264
325
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
mappings[format].instance_eval(&block)
|
|
326
|
+
def process_mapping(format, &block)
|
|
327
|
+
klass = ::Lutaml::Model::Config.mappings_class_for(format)
|
|
328
|
+
mappings[format] ||= klass.new
|
|
329
|
+
mappings[format].instance_eval(&block)
|
|
270
330
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
end
|
|
331
|
+
if mappings[format].respond_to?(:finalize)
|
|
332
|
+
mappings[format].finalize(self)
|
|
274
333
|
end
|
|
334
|
+
end
|
|
275
335
|
|
|
276
|
-
|
|
277
|
-
|
|
336
|
+
def from(format, data, options = {})
|
|
337
|
+
adapter = Lutaml::Model::Config.adapter_for(format)
|
|
278
338
|
|
|
279
|
-
|
|
339
|
+
doc = adapter.parse(data, options)
|
|
340
|
+
send("of_#{format}", doc, options)
|
|
341
|
+
end
|
|
280
342
|
|
|
281
|
-
|
|
282
|
-
|
|
343
|
+
def of(format, doc, options = {})
|
|
344
|
+
if doc.is_a?(Array) && format != :jsonl
|
|
345
|
+
return doc.map { |item| send(:"of_#{format}", item) }
|
|
283
346
|
end
|
|
284
347
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
end
|
|
289
|
-
|
|
290
|
-
if format == :xml
|
|
291
|
-
raise Lutaml::Model::NoRootMappingError.new(self) unless root?
|
|
348
|
+
if format == :xml
|
|
349
|
+
valid = root? || options[:from_collection]
|
|
350
|
+
raise Lutaml::Model::NoRootMappingError.new(self) unless valid
|
|
292
351
|
|
|
293
|
-
|
|
294
|
-
apply_mappings(doc, format, options)
|
|
295
|
-
else
|
|
296
|
-
apply_mappings(doc.to_h, format, options)
|
|
297
|
-
end
|
|
352
|
+
options[:encoding] = doc.encoding
|
|
298
353
|
end
|
|
354
|
+
options[:register] = extract_register_id(options[:register])
|
|
299
355
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
if format == :xml
|
|
305
|
-
xml_options = { mapper_class: self }
|
|
306
|
-
adapter.new(value).public_send(:"to_#{format}", xml_options)
|
|
307
|
-
else
|
|
308
|
-
adapter.new(value).public_send(:"to_#{format}")
|
|
309
|
-
end
|
|
310
|
-
end
|
|
356
|
+
transformer = Lutaml::Model::Config.transformer_for(format)
|
|
357
|
+
transformer.data_to_model(self, doc, format, options)
|
|
358
|
+
end
|
|
311
359
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
end
|
|
360
|
+
def to(format, instance, options = {})
|
|
361
|
+
value = public_send(:"as_#{format}", instance, options)
|
|
362
|
+
adapter = Lutaml::Model::Config.adapter_for(format)
|
|
316
363
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
end
|
|
364
|
+
options[:mapper_class] = self if format == :xml
|
|
365
|
+
adapter.new(value).public_send(:"to_#{format}", options)
|
|
366
|
+
end
|
|
321
367
|
|
|
322
|
-
|
|
368
|
+
def as(format, instance, options = {})
|
|
369
|
+
if instance.is_a?(Array)
|
|
370
|
+
return instance.map { |item| public_send(:"as_#{format}", item) }
|
|
371
|
+
end
|
|
323
372
|
|
|
324
|
-
|
|
373
|
+
unless instance.is_a?(model)
|
|
374
|
+
msg = "argument is a '#{instance.class}' but should be a '#{model}'"
|
|
375
|
+
raise Lutaml::Model::IncorrectModelError, msg
|
|
325
376
|
end
|
|
326
|
-
end
|
|
327
377
|
|
|
328
|
-
|
|
329
|
-
|
|
378
|
+
transformer = Lutaml::Model::Config.transformer_for(format)
|
|
379
|
+
transformer.model_to_data(self, instance, format, options)
|
|
330
380
|
end
|
|
331
381
|
|
|
332
382
|
def key_value(&block)
|
|
@@ -336,93 +386,16 @@ module Lutaml
|
|
|
336
386
|
end
|
|
337
387
|
end
|
|
338
388
|
|
|
339
|
-
def hash_representation(instance, format, options = {})
|
|
340
|
-
only = options[:only]
|
|
341
|
-
except = options[:except]
|
|
342
|
-
mappings = mappings_for(format).mappings
|
|
343
|
-
|
|
344
|
-
mappings.each_with_object({}) do |rule, hash|
|
|
345
|
-
name = rule.to
|
|
346
|
-
attr = attributes[name]
|
|
347
|
-
|
|
348
|
-
next if except&.include?(name) || (only && !only.include?(name))
|
|
349
|
-
next handle_delegate(instance, rule, hash, format) if rule.delegate
|
|
350
|
-
|
|
351
|
-
if rule.custom_methods[:to]
|
|
352
|
-
next instance.send(rule.custom_methods[:to], instance, hash)
|
|
353
|
-
end
|
|
354
|
-
|
|
355
|
-
value = rule.serialize(instance)
|
|
356
|
-
|
|
357
|
-
if rule.raw_mapping?
|
|
358
|
-
adapter = Lutaml::Model::Config.send(:"#{format}_adapter")
|
|
359
|
-
return adapter.parse(value, options)
|
|
360
|
-
end
|
|
361
|
-
|
|
362
|
-
if export_method = rule.transform[:export] || attr.transform_export_method
|
|
363
|
-
value = export_method.call(value)
|
|
364
|
-
end
|
|
365
|
-
|
|
366
|
-
next hash.merge!(generate_hash_from_child_mappings(attr, value, format, rule.root_mappings)) if rule.root_mapping?
|
|
367
|
-
|
|
368
|
-
value = if rule.child_mappings
|
|
369
|
-
generate_hash_from_child_mappings(attr, value, format, rule.child_mappings)
|
|
370
|
-
else
|
|
371
|
-
attr.serialize(value, format, options)
|
|
372
|
-
end
|
|
373
|
-
|
|
374
|
-
next if !rule.render?(value, instance, options)
|
|
375
|
-
|
|
376
|
-
value = apply_value_map(value, rule.value_map(:to, options), attr)
|
|
377
|
-
|
|
378
|
-
rule_from_name = rule.multiple_mappings? ? rule.from.first.to_s : rule.from.to_s
|
|
379
|
-
hash[rule_from_name] = value
|
|
380
|
-
end
|
|
381
|
-
end
|
|
382
|
-
|
|
383
|
-
def apply_value_map(value, value_map, attr)
|
|
384
|
-
if value.nil?
|
|
385
|
-
value_for_option(value_map[:nil], attr)
|
|
386
|
-
elsif Utils.empty?(value)
|
|
387
|
-
value_for_option(value_map[:empty], attr, value)
|
|
388
|
-
elsif Utils.uninitialized?(value)
|
|
389
|
-
value_for_option(value_map[:omitted], attr)
|
|
390
|
-
else
|
|
391
|
-
value
|
|
392
|
-
end
|
|
393
|
-
end
|
|
394
|
-
|
|
395
|
-
def value_for_option(option, attr, empty_value = nil)
|
|
396
|
-
return nil if option == :nil
|
|
397
|
-
return empty_value || empty_object(attr) if option == :empty
|
|
398
|
-
|
|
399
|
-
Lutaml::Model::UninitializedClass.instance
|
|
400
|
-
end
|
|
401
|
-
|
|
402
|
-
def empty_object(attr)
|
|
403
|
-
return [] if attr.collection?
|
|
404
|
-
|
|
405
|
-
""
|
|
406
|
-
end
|
|
407
|
-
|
|
408
|
-
def handle_delegate(instance, rule, hash, format)
|
|
409
|
-
name = rule.to
|
|
410
|
-
value = instance.send(rule.delegate).send(name)
|
|
411
|
-
return if value.nil? && !rule.render_nil
|
|
412
|
-
|
|
413
|
-
attribute = instance.send(rule.delegate).class.attributes[name]
|
|
414
|
-
rule_from_name = rule.multiple_mappings? ? rule.from.first.to_s : rule.from.to_s
|
|
415
|
-
hash[rule_from_name] = attribute.serialize(value, format)
|
|
416
|
-
end
|
|
417
|
-
|
|
418
389
|
def mappings_for(format)
|
|
390
|
+
@mappings[:xml]&.ensure_mappings_imported! if @mappings&.dig(:xml)&.finalized?
|
|
419
391
|
mappings[format] || default_mappings(format)
|
|
420
392
|
end
|
|
421
393
|
|
|
422
394
|
def default_mappings(format)
|
|
423
|
-
|
|
395
|
+
klass = ::Lutaml::Model::Config.mappings_class_for(format)
|
|
396
|
+
mappings = klass.new
|
|
424
397
|
|
|
425
|
-
|
|
398
|
+
mappings.tap do |mapping|
|
|
426
399
|
attributes&.each_key do |name|
|
|
427
400
|
mapping.map_element(
|
|
428
401
|
name.to_s,
|
|
@@ -430,116 +403,21 @@ module Lutaml
|
|
|
430
403
|
)
|
|
431
404
|
end
|
|
432
405
|
|
|
433
|
-
mapping.root(
|
|
434
|
-
end
|
|
435
|
-
end
|
|
436
|
-
|
|
437
|
-
def translate_mappings(hash, child_mappings, attr, format)
|
|
438
|
-
return hash unless child_mappings
|
|
439
|
-
|
|
440
|
-
hash.map do |key, value|
|
|
441
|
-
child_hash = child_mappings.to_h do |attr_name, path|
|
|
442
|
-
attr_value = if path == :key
|
|
443
|
-
key
|
|
444
|
-
elsif path == :value
|
|
445
|
-
value
|
|
446
|
-
else
|
|
447
|
-
path = [path] unless path.is_a?(Array)
|
|
448
|
-
value.dig(*path.map(&:to_s))
|
|
449
|
-
end
|
|
450
|
-
|
|
451
|
-
attr_rule = attr.type.mappings_for(format).find_by_to(attr_name)
|
|
452
|
-
[attr_rule.from.to_s, attr_value]
|
|
453
|
-
end
|
|
454
|
-
|
|
455
|
-
if child_mappings.values == [:key] && hash.values.all?(Hash)
|
|
456
|
-
child_hash.merge!(value)
|
|
457
|
-
end
|
|
458
|
-
|
|
459
|
-
attr.type.apply_hash_mapping(
|
|
460
|
-
child_hash,
|
|
461
|
-
attr.type.model.new,
|
|
462
|
-
format,
|
|
463
|
-
{ mappings: attr.type.mappings_for(format).mappings },
|
|
464
|
-
)
|
|
465
|
-
end
|
|
466
|
-
end
|
|
467
|
-
|
|
468
|
-
def generate_hash_from_child_mappings(attr, value, format, child_mappings)
|
|
469
|
-
return value unless child_mappings
|
|
470
|
-
|
|
471
|
-
hash = {}
|
|
472
|
-
|
|
473
|
-
if child_mappings.values == [:key]
|
|
474
|
-
klass = value.first.class
|
|
475
|
-
mappings = klass.mappings_for(format)
|
|
476
|
-
|
|
477
|
-
klass.attributes.each_key do |name|
|
|
478
|
-
next if child_mappings.key?(name.to_sym) || child_mappings.key?(name.to_s)
|
|
479
|
-
|
|
480
|
-
child_mappings[name.to_sym] = mappings.find_by_to(name)&.name.to_s || name.to_s
|
|
481
|
-
end
|
|
482
|
-
end
|
|
483
|
-
|
|
484
|
-
value.each do |child_obj|
|
|
485
|
-
map_key = nil
|
|
486
|
-
map_value = {}
|
|
487
|
-
mapping_rules = attr.type.mappings_for(format)
|
|
488
|
-
|
|
489
|
-
child_mappings.each do |attr_name, path|
|
|
490
|
-
mapping_rule = mapping_rules.find_by_to(attr_name)
|
|
491
|
-
|
|
492
|
-
attr_value = child_obj.send(attr_name)
|
|
493
|
-
|
|
494
|
-
attr_value = if attr_value.is_a?(Lutaml::Model::Serialize)
|
|
495
|
-
attr_value.to_yaml_hash
|
|
496
|
-
elsif attr_value.is_a?(Array) && attr_value.first.is_a?(Lutaml::Model::Serialize)
|
|
497
|
-
attr_value.map(&:to_yaml_hash)
|
|
498
|
-
else
|
|
499
|
-
attr_value
|
|
500
|
-
end
|
|
501
|
-
|
|
502
|
-
next unless mapping_rule&.render?(attr_value, nil)
|
|
503
|
-
|
|
504
|
-
if path == :key
|
|
505
|
-
map_key = attr_value
|
|
506
|
-
elsif path == :value
|
|
507
|
-
map_value = attr_value
|
|
508
|
-
else
|
|
509
|
-
path = [path] unless path.is_a?(Array)
|
|
510
|
-
path[0...-1].inject(map_value) do |acc, k|
|
|
511
|
-
acc[k.to_s] ||= {}
|
|
512
|
-
end.public_send(:[]=, path.last.to_s, attr_value)
|
|
513
|
-
end
|
|
514
|
-
end
|
|
515
|
-
|
|
516
|
-
map_value = nil if map_value.empty?
|
|
517
|
-
hash[map_key] = map_value
|
|
406
|
+
mapping.root(Utils.base_class_name(self)) if format == :xml
|
|
518
407
|
end
|
|
519
|
-
|
|
520
|
-
hash
|
|
521
|
-
end
|
|
522
|
-
|
|
523
|
-
def valid_rule?(rule)
|
|
524
|
-
attribute = attribute_for_rule(rule)
|
|
525
|
-
|
|
526
|
-
!!attribute || rule.custom_methods[:from]
|
|
527
|
-
end
|
|
528
|
-
|
|
529
|
-
def attribute_for_rule(rule)
|
|
530
|
-
return attributes[rule.to] unless rule.delegate
|
|
531
|
-
|
|
532
|
-
attributes[rule.delegate].type.attributes[rule.to]
|
|
533
|
-
end
|
|
534
|
-
|
|
535
|
-
def attribute_for_child(child_name, format)
|
|
536
|
-
mapping_rule = mappings_for(format).find_by_name(child_name)
|
|
537
|
-
|
|
538
|
-
attribute_for_rule(mapping_rule) if mapping_rule
|
|
539
408
|
end
|
|
540
409
|
|
|
541
410
|
def apply_mappings(doc, format, options = {})
|
|
542
|
-
|
|
411
|
+
register = options[:register] || Lutaml::Model::Config.default_register
|
|
412
|
+
instance = if options.key?(:instance)
|
|
413
|
+
options[:instance]
|
|
414
|
+
elsif model.include?(Lutaml::Model::Serialize)
|
|
415
|
+
model.new({ __register: register })
|
|
416
|
+
else
|
|
417
|
+
object = model.new
|
|
418
|
+
register_accessor_methods_for(object, register)
|
|
419
|
+
object
|
|
420
|
+
end
|
|
543
421
|
return instance if Utils.blank?(doc)
|
|
544
422
|
|
|
545
423
|
mappings = mappings_for(format)
|
|
@@ -548,10 +426,8 @@ module Lutaml
|
|
|
548
426
|
return resolve_polymorphic(doc, format, mappings, instance, options)
|
|
549
427
|
end
|
|
550
428
|
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
apply_hash_mapping(doc, instance, format, options)
|
|
429
|
+
transformer = Lutaml::Model::Config.transformer_for(format)
|
|
430
|
+
transformer.data_to_model(self, doc, format, options)
|
|
555
431
|
end
|
|
556
432
|
|
|
557
433
|
def resolve_polymorphic(doc, format, mappings, instance, options = {})
|
|
@@ -562,321 +438,167 @@ module Lutaml
|
|
|
562
438
|
klass_name = polymorphic_mapping.polymorphic_map[klass_key]
|
|
563
439
|
klass = Object.const_get(klass_name)
|
|
564
440
|
|
|
565
|
-
klass.apply_mappings(doc, format, options)
|
|
441
|
+
klass.apply_mappings(doc, format, options.merge(register: instance.__register))
|
|
566
442
|
end
|
|
567
443
|
|
|
568
|
-
def
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
set_instance_ordering(instance, doc, options)
|
|
578
|
-
set_schema_location(instance, doc)
|
|
579
|
-
|
|
580
|
-
defaults_used = []
|
|
581
|
-
validate_sequence!(doc.root.order)
|
|
582
|
-
|
|
583
|
-
mappings.each do |rule|
|
|
584
|
-
raise "Attribute '#{rule.to}' not found in #{self}" unless valid_rule?(rule)
|
|
585
|
-
|
|
586
|
-
attr = attribute_for_rule(rule)
|
|
587
|
-
next if attr&.derived?
|
|
588
|
-
|
|
589
|
-
new_opts = options.dup
|
|
590
|
-
if rule.namespace_set?
|
|
591
|
-
new_opts[:default_namespace] = rule.namespace
|
|
592
|
-
end
|
|
593
|
-
|
|
594
|
-
value = if rule.raw_mapping?
|
|
595
|
-
doc.root.inner_xml
|
|
596
|
-
elsif rule.content_mapping?
|
|
597
|
-
rule.cdata ? doc.cdata : doc.text
|
|
598
|
-
else
|
|
599
|
-
val = value_for_rule(doc, rule, new_opts, instance)
|
|
600
|
-
|
|
601
|
-
if (Utils.uninitialized?(val) || val.nil?) && (instance.using_default?(rule.to) || rule.render_default)
|
|
602
|
-
defaults_used << rule.to
|
|
603
|
-
attr&.default || rule.to_value_for(instance)
|
|
604
|
-
else
|
|
605
|
-
val
|
|
606
|
-
end
|
|
607
|
-
end
|
|
608
|
-
|
|
609
|
-
value = apply_value_map(value, rule.value_map(:from, new_opts), attr)
|
|
610
|
-
value = normalize_xml_value(value, rule, attr, new_opts)
|
|
611
|
-
rule.deserialize(instance, value, attributes, self)
|
|
612
|
-
end
|
|
613
|
-
|
|
614
|
-
defaults_used.each do |attr_name|
|
|
615
|
-
instance.using_default_for(attr_name)
|
|
444
|
+
def apply_value_map(value, value_map, attr)
|
|
445
|
+
if value.nil?
|
|
446
|
+
value_for_option(value_map[:nil], attr)
|
|
447
|
+
elsif Utils.empty?(value)
|
|
448
|
+
value_for_option(value_map[:empty], attr, value)
|
|
449
|
+
elsif Utils.uninitialized?(value)
|
|
450
|
+
value_for_option(value_map[:omitted], attr)
|
|
451
|
+
else
|
|
452
|
+
value
|
|
616
453
|
end
|
|
617
|
-
|
|
618
|
-
instance
|
|
619
454
|
end
|
|
620
455
|
|
|
621
|
-
def
|
|
622
|
-
|
|
623
|
-
|
|
456
|
+
def value_for_option(option, attr, empty_value = nil)
|
|
457
|
+
return nil if option == :nil
|
|
458
|
+
return empty_value || empty_object(attr) if option == :empty
|
|
624
459
|
|
|
625
|
-
|
|
460
|
+
Lutaml::Model::UninitializedClass.instance
|
|
626
461
|
end
|
|
627
462
|
|
|
628
|
-
def
|
|
629
|
-
return
|
|
463
|
+
def empty_object(attr)
|
|
464
|
+
return attr.build_collection if attr.collection?
|
|
630
465
|
|
|
631
|
-
|
|
632
|
-
self,
|
|
633
|
-
options[:caller_class],
|
|
634
|
-
)
|
|
466
|
+
""
|
|
635
467
|
end
|
|
636
468
|
|
|
637
|
-
def
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
469
|
+
def ensure_utf8(value)
|
|
470
|
+
case value
|
|
471
|
+
when String
|
|
472
|
+
value.encode("UTF-8", invalid: :replace, undef: :replace,
|
|
473
|
+
replace: "")
|
|
474
|
+
when Array
|
|
475
|
+
value.map { |v| ensure_utf8(v) }
|
|
476
|
+
when Hash
|
|
477
|
+
value.transform_keys do |k|
|
|
478
|
+
ensure_utf8(k)
|
|
479
|
+
end.transform_values do |v|
|
|
480
|
+
ensure_utf8(v)
|
|
481
|
+
end
|
|
482
|
+
else
|
|
483
|
+
value
|
|
484
|
+
end
|
|
643
485
|
end
|
|
644
486
|
|
|
645
|
-
def
|
|
646
|
-
|
|
647
|
-
|
|
487
|
+
def register_accessor_methods_for(object, register)
|
|
488
|
+
Utils.add_singleton_method_if_not_defined(object, :__register) do
|
|
489
|
+
@__register
|
|
648
490
|
end
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
schema_location: schema_location.value,
|
|
654
|
-
prefix: schema_location.namespace_prefix,
|
|
655
|
-
namespace: schema_location.namespace,
|
|
656
|
-
)
|
|
491
|
+
Utils.add_singleton_method_if_not_defined(object, :__register=) do |value|
|
|
492
|
+
@__register = value
|
|
493
|
+
end
|
|
494
|
+
object.__register = register
|
|
657
495
|
end
|
|
658
496
|
|
|
659
|
-
def
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
497
|
+
def extract_register_id(register)
|
|
498
|
+
if register
|
|
499
|
+
register.is_a?(Lutaml::Model::Register) ? register.id : register
|
|
500
|
+
elsif class_variable_defined?(:@@__register)
|
|
501
|
+
class_variable_get(:@@__register)
|
|
664
502
|
else
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
end
|
|
669
|
-
|
|
670
|
-
if rule.using_custom_methods? || attr.type == Lutaml::Model::Type::Hash
|
|
671
|
-
return_child = attr.type == Lutaml::Model::Type::Hash || !attr.collection? if attr
|
|
672
|
-
return return_child ? children.first : children
|
|
673
|
-
end
|
|
503
|
+
Lutaml::Model::Config.default_register
|
|
504
|
+
end
|
|
505
|
+
end
|
|
674
506
|
|
|
675
|
-
|
|
507
|
+
def ensure_model_imports!(register_id = nil)
|
|
508
|
+
return if @models_imported
|
|
676
509
|
|
|
677
|
-
|
|
510
|
+
register_id ||= Lutaml::Model::Config.default_register
|
|
511
|
+
register = Lutaml::Model::GlobalRegister.lookup(register_id)
|
|
512
|
+
importable_models.each do |method, models|
|
|
513
|
+
models.uniq.each do |model|
|
|
514
|
+
model_class = register.get_class_without_register(model)
|
|
515
|
+
import_model_with_root_error(model_class)
|
|
678
516
|
|
|
679
|
-
|
|
680
|
-
instance.value_set_for(attr.name)
|
|
681
|
-
else
|
|
682
|
-
children = nil
|
|
683
|
-
values = Lutaml::Model::UninitializedClass.instance
|
|
517
|
+
@model.public_send(method, model_class)
|
|
684
518
|
end
|
|
519
|
+
end
|
|
685
520
|
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
cast_options = options.except(:mappings)
|
|
689
|
-
cast_options[:polymorphic] = rule.polymorphic if rule.polymorphic
|
|
521
|
+
@models_imported = true
|
|
522
|
+
end
|
|
690
523
|
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
values << inner_xml_of(child)
|
|
694
|
-
else
|
|
695
|
-
return nil if rule.render_nil_as_nil? && child.nil_element?
|
|
524
|
+
def ensure_choice_imports!(register_id = nil)
|
|
525
|
+
return if @choices_imported
|
|
696
526
|
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
527
|
+
register_id ||= Lutaml::Model::Config.default_register
|
|
528
|
+
register = Lutaml::Model::GlobalRegister.lookup(register_id)
|
|
529
|
+
importable_choices.each do |choice, choice_imports|
|
|
530
|
+
choice_imports.each do |method, models|
|
|
531
|
+
models.uniq!
|
|
532
|
+
choice.public_send(method, register.get_class_without_register(models.shift)) until models.empty?
|
|
700
533
|
end
|
|
701
|
-
|
|
702
|
-
normalized_value_for_attr(values, attr)
|
|
703
534
|
end
|
|
704
|
-
end
|
|
705
|
-
|
|
706
|
-
def handle_cdata(children)
|
|
707
|
-
values = children.map do |child|
|
|
708
|
-
child.cdata_children&.map(&:text)
|
|
709
|
-
end.flatten
|
|
710
|
-
|
|
711
|
-
children.count > 1 ? values : values.first
|
|
712
|
-
end
|
|
713
|
-
|
|
714
|
-
def normalized_value_for_attr(values, attr)
|
|
715
|
-
# for xml collection true cases like
|
|
716
|
-
# <store><items /></store>
|
|
717
|
-
# <store><items xsi:nil="true"/></store>
|
|
718
|
-
# <store><items></items></store>
|
|
719
|
-
#
|
|
720
|
-
# these are considered empty collection
|
|
721
|
-
return [] if attr&.collection? && [[nil], [""]].include?(values)
|
|
722
|
-
return values if attr&.collection?
|
|
723
535
|
|
|
724
|
-
|
|
536
|
+
@choices_imported = true
|
|
725
537
|
end
|
|
726
538
|
|
|
727
|
-
def
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
attr = attribute_for_rule(rule)
|
|
733
|
-
next if attr&.derived?
|
|
734
|
-
|
|
735
|
-
names = rule.multiple_mappings? ? rule.name : [rule.name]
|
|
736
|
-
|
|
737
|
-
values = names.collect do |rule_name|
|
|
738
|
-
if rule.root_mapping?
|
|
739
|
-
doc
|
|
740
|
-
elsif rule.raw_mapping?
|
|
741
|
-
adapter = Lutaml::Model::Config.public_send(:"#{format}_adapter")
|
|
742
|
-
adapter.new(doc).public_send(:"to_#{format}")
|
|
743
|
-
elsif doc.key?(rule_name.to_s)
|
|
744
|
-
doc[rule_name.to_s]
|
|
745
|
-
elsif doc.key?(rule_name.to_sym)
|
|
746
|
-
doc[rule_name.to_sym]
|
|
747
|
-
elsif attr&.default_set?
|
|
748
|
-
attr&.default
|
|
749
|
-
else
|
|
750
|
-
Lutaml::Model::UninitializedClass.instance
|
|
751
|
-
end
|
|
752
|
-
end.compact
|
|
753
|
-
|
|
754
|
-
value = values.find { |v| Utils.initialized?(v) } || values.first
|
|
755
|
-
|
|
756
|
-
value = apply_value_map(value, rule.value_map(:from, options), attr)
|
|
757
|
-
|
|
758
|
-
if rule.using_custom_methods?
|
|
759
|
-
if Utils.present?(value)
|
|
760
|
-
value = new.send(rule.custom_methods[:from], instance, value)
|
|
761
|
-
end
|
|
762
|
-
|
|
763
|
-
next
|
|
539
|
+
def setup_trace_point
|
|
540
|
+
@trace ||= TracePoint.new(:end) do |_tp|
|
|
541
|
+
if include?(Lutaml::Model::Serialize)
|
|
542
|
+
@finalized = true
|
|
543
|
+
@trace.disable
|
|
764
544
|
end
|
|
765
|
-
|
|
766
|
-
value = translate_mappings(value, rule.hash_mappings, attr, format)
|
|
767
|
-
|
|
768
|
-
cast_options = {}
|
|
769
|
-
cast_options[:polymorphic] = rule.polymorphic if rule.polymorphic
|
|
770
|
-
|
|
771
|
-
value = attr.cast(value, format, cast_options) unless rule.hash_mappings
|
|
772
|
-
attr.valid_collection!(value, self)
|
|
773
|
-
|
|
774
|
-
rule.deserialize(instance, value, attributes, self)
|
|
775
545
|
end
|
|
776
|
-
|
|
777
|
-
instance
|
|
546
|
+
@trace.enable unless @trace.enabled?
|
|
778
547
|
end
|
|
779
548
|
|
|
780
|
-
def
|
|
781
|
-
|
|
549
|
+
def finalized?
|
|
550
|
+
@finalized
|
|
551
|
+
end
|
|
552
|
+
end
|
|
782
553
|
|
|
783
|
-
|
|
554
|
+
def self.register_format_mapping_method(format)
|
|
555
|
+
method_name = format == :hash ? :hsh : format
|
|
784
556
|
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
value,
|
|
788
|
-
:xml,
|
|
789
|
-
options,
|
|
790
|
-
)
|
|
557
|
+
::Lutaml::Model::Serialize::ClassMethods.define_method(method_name) do |&block|
|
|
558
|
+
process_mapping(format, &block)
|
|
791
559
|
end
|
|
560
|
+
end
|
|
792
561
|
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
!rule.content_mapping? &&
|
|
797
|
-
!rule.custom_methods[:from]
|
|
562
|
+
def self.register_from_format_method(format)
|
|
563
|
+
ClassMethods.define_method(:"from_#{format}") do |data, options = {}|
|
|
564
|
+
from(format, data, options)
|
|
798
565
|
end
|
|
799
566
|
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
return value.one? && value.text? unless attr
|
|
803
|
-
|
|
804
|
-
!(attr.type <= Serialize) && attr.type != Lutaml::Model::Type::Hash
|
|
567
|
+
ClassMethods.define_method(:"of_#{format}") do |doc, options = {}|
|
|
568
|
+
of(format, doc, options)
|
|
805
569
|
end
|
|
570
|
+
end
|
|
806
571
|
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
value.encode("UTF-8", invalid: :replace, undef: :replace,
|
|
811
|
-
replace: "")
|
|
812
|
-
when Array
|
|
813
|
-
value.map { |v| ensure_utf8(v) }
|
|
814
|
-
when Hash
|
|
815
|
-
value.transform_keys do |k|
|
|
816
|
-
ensure_utf8(k)
|
|
817
|
-
end.transform_values do |v|
|
|
818
|
-
ensure_utf8(v)
|
|
819
|
-
end
|
|
820
|
-
else
|
|
821
|
-
value
|
|
822
|
-
end
|
|
572
|
+
def self.register_to_format_method(format)
|
|
573
|
+
ClassMethods.define_method(:"to_#{format}") do |instance, options = {}|
|
|
574
|
+
to(format, instance, options)
|
|
823
575
|
end
|
|
824
576
|
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
current_order = element_order.filter_map(&:element_tag)
|
|
828
|
-
|
|
829
|
-
mapping_sequence.each do |mapping|
|
|
830
|
-
mapping.validate_content!(current_order)
|
|
831
|
-
end
|
|
577
|
+
ClassMethods.define_method(:"as_#{format}") do |instance, options = {}|
|
|
578
|
+
as(format, instance, options)
|
|
832
579
|
end
|
|
833
580
|
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
def inner_xml_of(node)
|
|
837
|
-
case node
|
|
838
|
-
when XmlAdapter::XmlElement
|
|
839
|
-
node.inner_xml
|
|
840
|
-
else
|
|
841
|
-
node.children.map(&:to_xml).join
|
|
842
|
-
end
|
|
581
|
+
define_method(:"to_#{format}") do |options = {}|
|
|
582
|
+
to_format(format, options)
|
|
843
583
|
end
|
|
844
584
|
end
|
|
845
585
|
|
|
846
|
-
attr_accessor :element_order, :schema_location, :encoding
|
|
586
|
+
attr_accessor :element_order, :schema_location, :encoding, :__register
|
|
847
587
|
attr_writer :ordered, :mixed
|
|
848
588
|
|
|
849
589
|
def initialize(attrs = {}, options = {})
|
|
850
590
|
@using_default = {}
|
|
851
|
-
|
|
852
591
|
return unless self.class.attributes
|
|
853
592
|
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
if attrs.key?(:schema_location)
|
|
860
|
-
self.schema_location = attrs[:schema_location]
|
|
861
|
-
end
|
|
862
|
-
|
|
863
|
-
self.class.attributes.each do |name, attr|
|
|
864
|
-
next if attr.derived?
|
|
865
|
-
|
|
866
|
-
value = if attrs.key?(name) || attrs.key?(name.to_s)
|
|
867
|
-
attr_value(attrs, name, attr)
|
|
868
|
-
elsif attr.default_set?
|
|
869
|
-
using_default_for(name)
|
|
870
|
-
attr.default
|
|
871
|
-
else
|
|
872
|
-
Lutaml::Model::UninitializedClass.instance
|
|
873
|
-
end
|
|
593
|
+
@__register = extract_register_id(attrs, options)
|
|
594
|
+
set_ordering(attrs)
|
|
595
|
+
set_schema_location(attrs)
|
|
596
|
+
initialize_attributes(attrs, options)
|
|
597
|
+
end
|
|
874
598
|
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
using_default_for(name) if default
|
|
879
|
-
end
|
|
599
|
+
def extract_register_id(attrs, options)
|
|
600
|
+
register = attrs&.dig(:__register) || options&.dig(:register)
|
|
601
|
+
self.class.extract_register_id(register)
|
|
880
602
|
end
|
|
881
603
|
|
|
882
604
|
def value_map(options)
|
|
@@ -887,30 +609,9 @@ module Lutaml
|
|
|
887
609
|
}
|
|
888
610
|
end
|
|
889
611
|
|
|
890
|
-
def attr_value(attrs, name,
|
|
891
|
-
value =
|
|
892
|
-
|
|
893
|
-
elsif attrs.key?(name.to_s)
|
|
894
|
-
attrs[name.to_s]
|
|
895
|
-
else
|
|
896
|
-
attr_rule.default
|
|
897
|
-
end
|
|
898
|
-
|
|
899
|
-
if attr_rule.collection? || value.is_a?(Array)
|
|
900
|
-
value&.map do |v|
|
|
901
|
-
if v.is_a?(Hash)
|
|
902
|
-
attr_rule.type.new(v)
|
|
903
|
-
else
|
|
904
|
-
# TODO: This code is problematic because Type.cast does not know
|
|
905
|
-
# about all the types.
|
|
906
|
-
Lutaml::Model::Type.cast(v, attr_rule.type)
|
|
907
|
-
end
|
|
908
|
-
end
|
|
909
|
-
else
|
|
910
|
-
# TODO: This code is problematic because Type.cast does not know
|
|
911
|
-
# about all the types.
|
|
912
|
-
Lutaml::Model::Type.cast(value, attr_rule.type)
|
|
913
|
-
end
|
|
612
|
+
def attr_value(attrs, name, attribute)
|
|
613
|
+
value = Utils.fetch_str_or_sym(attrs, name, attribute.default(__register))
|
|
614
|
+
attribute.cast_value(value, __register)
|
|
914
615
|
end
|
|
915
616
|
|
|
916
617
|
def using_default_for(attribute_name)
|
|
@@ -926,7 +627,7 @@ module Lutaml
|
|
|
926
627
|
end
|
|
927
628
|
|
|
928
629
|
def method_missing(method_name, *args)
|
|
929
|
-
if method_name.to_s.end_with?("=") &&
|
|
630
|
+
if method_name.to_s.end_with?("=") && attribute_exist?(method_name)
|
|
930
631
|
define_singleton_method(method_name) do |value|
|
|
931
632
|
instance_variable_set(:"@#{method_name.to_s.chomp('=')}", value)
|
|
932
633
|
end
|
|
@@ -936,6 +637,17 @@ module Lutaml
|
|
|
936
637
|
end
|
|
937
638
|
end
|
|
938
639
|
|
|
640
|
+
def respond_to_missing?(method_name, include_private = false)
|
|
641
|
+
(method_name.to_s.end_with?("=") && attribute_exist?(method_name)) ||
|
|
642
|
+
super
|
|
643
|
+
end
|
|
644
|
+
|
|
645
|
+
def attribute_exist?(name)
|
|
646
|
+
name = name.to_s.chomp("=").to_sym if name.end_with?("=")
|
|
647
|
+
|
|
648
|
+
self.class.attributes.key?(name)
|
|
649
|
+
end
|
|
650
|
+
|
|
939
651
|
def validate_attribute!(attr_name)
|
|
940
652
|
attr = self.class.attributes[attr_name]
|
|
941
653
|
value = instance_variable_get(:"@#{attr_name}")
|
|
@@ -959,27 +671,63 @@ module Lutaml
|
|
|
959
671
|
end
|
|
960
672
|
|
|
961
673
|
def pretty_print_instance_variables
|
|
962
|
-
(instance_variables - %i[@using_default]).sort
|
|
674
|
+
(instance_variables - %i[@using_default @__register]).sort
|
|
963
675
|
end
|
|
964
676
|
|
|
965
677
|
def to_yaml_hash
|
|
966
678
|
self.class.as_yaml(self)
|
|
967
679
|
end
|
|
968
680
|
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
681
|
+
def to_format(format, options = {})
|
|
682
|
+
validate_root_mapping!(format, options)
|
|
683
|
+
|
|
684
|
+
options[:parse_encoding] = encoding if encoding
|
|
685
|
+
self.class.to(format, self, options)
|
|
686
|
+
end
|
|
687
|
+
|
|
688
|
+
private
|
|
689
|
+
|
|
690
|
+
def validate_root_mapping!(format, options)
|
|
691
|
+
return if format != :xml
|
|
692
|
+
return if options[:collection] || self.class.root?
|
|
693
|
+
|
|
694
|
+
raise Lutaml::Model::NoRootMappingError.new(self.class)
|
|
695
|
+
end
|
|
696
|
+
|
|
697
|
+
def set_ordering(attrs)
|
|
698
|
+
return unless attrs.respond_to?(:ordered?)
|
|
699
|
+
|
|
700
|
+
@ordered = attrs.ordered?
|
|
701
|
+
@element_order = attrs.item_order
|
|
702
|
+
end
|
|
703
|
+
|
|
704
|
+
def set_schema_location(attrs)
|
|
705
|
+
return unless attrs.key?(:schema_location)
|
|
706
|
+
|
|
707
|
+
self.schema_location = attrs[:schema_location]
|
|
708
|
+
end
|
|
709
|
+
|
|
710
|
+
def initialize_attributes(attrs, options = {})
|
|
711
|
+
self.class.attributes.each do |name, attr|
|
|
712
|
+
next if attr.derived?
|
|
713
|
+
|
|
714
|
+
value = determine_value(attrs, name, attr)
|
|
715
|
+
|
|
716
|
+
default = using_default?(name)
|
|
717
|
+
value = self.class.apply_value_map(value, value_map(options), attr)
|
|
718
|
+
public_send(:"#{name}=", self.class.ensure_utf8(value))
|
|
719
|
+
using_default_for(name) if default
|
|
720
|
+
end
|
|
721
|
+
end
|
|
722
|
+
|
|
723
|
+
def determine_value(attrs, name, attr)
|
|
724
|
+
if attrs.key?(name) || attrs.key?(name.to_s)
|
|
725
|
+
attr_value(attrs, name, attr)
|
|
726
|
+
elsif attr.default_set?(__register)
|
|
727
|
+
using_default_for(name)
|
|
728
|
+
attr.default(__register)
|
|
729
|
+
else
|
|
730
|
+
Lutaml::Model::UninitializedClass.instance
|
|
983
731
|
end
|
|
984
732
|
end
|
|
985
733
|
end
|