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,7 +1,7 @@
|
|
|
1
1
|
module Lutaml
|
|
2
2
|
module Model
|
|
3
3
|
class Attribute
|
|
4
|
-
attr_reader :name, :
|
|
4
|
+
attr_reader :name, :options
|
|
5
5
|
|
|
6
6
|
ALLOWED_OPTIONS = %i[
|
|
7
7
|
raw
|
|
@@ -17,23 +17,88 @@ module Lutaml
|
|
|
17
17
|
polymorphic
|
|
18
18
|
polymorphic_class
|
|
19
19
|
initialize_empty
|
|
20
|
+
validations
|
|
20
21
|
].freeze
|
|
21
22
|
|
|
23
|
+
MODEL_STRINGS = [
|
|
24
|
+
Lutaml::Model::Type::String,
|
|
25
|
+
"String",
|
|
26
|
+
:string,
|
|
27
|
+
].freeze
|
|
28
|
+
|
|
29
|
+
# Safe methods than can be overriden without any crashing
|
|
30
|
+
ALLOW_OVERRIDING = %i[
|
|
31
|
+
display
|
|
32
|
+
validate
|
|
33
|
+
hash
|
|
34
|
+
itself
|
|
35
|
+
taint
|
|
36
|
+
untaint
|
|
37
|
+
trust
|
|
38
|
+
untrust
|
|
39
|
+
methods
|
|
40
|
+
instance_variables
|
|
41
|
+
tap
|
|
42
|
+
extend
|
|
43
|
+
freeze
|
|
44
|
+
encoding
|
|
45
|
+
method
|
|
46
|
+
object_id
|
|
47
|
+
].freeze
|
|
48
|
+
|
|
49
|
+
def self.cast_type!(type)
|
|
50
|
+
case type
|
|
51
|
+
when Symbol then cast_from_symbol!(type)
|
|
52
|
+
when String then cast_from_string!(type)
|
|
53
|
+
when Class then type
|
|
54
|
+
else
|
|
55
|
+
raise ArgumentError, "Unknown Lutaml::Model::Type: #{type}"
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def self.cast_from_symbol!(type)
|
|
60
|
+
Type.lookup(type)
|
|
61
|
+
rescue UnknownTypeError
|
|
62
|
+
raise ArgumentError, "Unknown Lutaml::Model::Type: #{type}"
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def self.cast_from_string!(type)
|
|
66
|
+
Type.const_get(type)
|
|
67
|
+
rescue NameError
|
|
68
|
+
raise ArgumentError, "Unknown Lutaml::Model::Type: #{type}"
|
|
69
|
+
end
|
|
70
|
+
|
|
22
71
|
def initialize(name, type, options = {})
|
|
72
|
+
validate_name!(
|
|
73
|
+
name, reserved_methods: Lutaml::Model::Serializable.instance_methods
|
|
74
|
+
)
|
|
75
|
+
|
|
23
76
|
@name = name
|
|
24
77
|
@options = options
|
|
25
78
|
|
|
26
79
|
validate_presence!(type, options[:method_name])
|
|
27
|
-
|
|
80
|
+
@type = type
|
|
28
81
|
process_options!
|
|
29
82
|
end
|
|
30
83
|
|
|
84
|
+
def type(register_id = nil)
|
|
85
|
+
return if unresolved_type.nil?
|
|
86
|
+
|
|
87
|
+
register_id ||= Lutaml::Model::Config.default_register
|
|
88
|
+
register = Lutaml::Model::GlobalRegister.lookup(register_id)
|
|
89
|
+
register.get_class_without_register(unresolved_type)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def unresolved_type
|
|
93
|
+
@type
|
|
94
|
+
end
|
|
95
|
+
|
|
31
96
|
def polymorphic?
|
|
32
97
|
@options[:polymorphic_class]
|
|
33
98
|
end
|
|
34
99
|
|
|
35
100
|
def derived?
|
|
36
|
-
|
|
101
|
+
unresolved_type.nil?
|
|
37
102
|
end
|
|
38
103
|
|
|
39
104
|
def delegate
|
|
@@ -52,45 +117,61 @@ module Lutaml
|
|
|
52
117
|
@options[:initialize_empty]
|
|
53
118
|
end
|
|
54
119
|
|
|
120
|
+
def validations
|
|
121
|
+
@options[:validations]
|
|
122
|
+
end
|
|
123
|
+
|
|
55
124
|
def cast_type!(type)
|
|
56
|
-
|
|
57
|
-
when Symbol
|
|
58
|
-
begin
|
|
59
|
-
Type.lookup(type)
|
|
60
|
-
rescue UnknownTypeError
|
|
61
|
-
raise ArgumentError, "Unknown Lutaml::Model::Type: #{type}"
|
|
62
|
-
end
|
|
63
|
-
when String
|
|
64
|
-
begin
|
|
65
|
-
Type.const_get(type)
|
|
66
|
-
rescue NameError
|
|
67
|
-
raise ArgumentError, "Unknown Lutaml::Model::Type: #{type}"
|
|
68
|
-
end
|
|
69
|
-
when Class
|
|
70
|
-
type
|
|
71
|
-
else
|
|
72
|
-
raise ArgumentError, "Unknown Lutaml::Model::Type: #{type}"
|
|
73
|
-
end
|
|
125
|
+
self.class.cast_type!(type)
|
|
74
126
|
end
|
|
75
127
|
|
|
76
|
-
def cast_value(value)
|
|
77
|
-
return
|
|
128
|
+
def cast_value(value, register)
|
|
129
|
+
return cast_element(value, register) unless collection_instance?(value)
|
|
130
|
+
|
|
131
|
+
build_collection(value.map { |v| cast_element(v, register) })
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def cast_element(value, register)
|
|
135
|
+
resolved_type = type(register)
|
|
136
|
+
return resolved_type.new(value) if value.is_a?(Hash) && !hash_type?
|
|
137
|
+
|
|
138
|
+
resolved_type.cast(value)
|
|
139
|
+
end
|
|
78
140
|
|
|
79
|
-
|
|
141
|
+
def hash_type?
|
|
142
|
+
type == Lutaml::Model::Type::Hash
|
|
80
143
|
end
|
|
81
144
|
|
|
82
145
|
def setter
|
|
83
146
|
:"#{@name}="
|
|
84
147
|
end
|
|
85
148
|
|
|
149
|
+
def collection
|
|
150
|
+
@options[:collection]
|
|
151
|
+
end
|
|
152
|
+
|
|
86
153
|
def collection?
|
|
87
|
-
|
|
154
|
+
collection || false
|
|
88
155
|
end
|
|
89
156
|
|
|
90
157
|
def singular?
|
|
91
158
|
!collection?
|
|
92
159
|
end
|
|
93
160
|
|
|
161
|
+
def collection_class
|
|
162
|
+
return Array unless custom_collection?
|
|
163
|
+
|
|
164
|
+
collection
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def collection_instance?(value)
|
|
168
|
+
value.is_a?(collection_class)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def build_collection(*args)
|
|
172
|
+
collection_class.new(args.flatten)
|
|
173
|
+
end
|
|
174
|
+
|
|
94
175
|
def raw?
|
|
95
176
|
@raw
|
|
96
177
|
end
|
|
@@ -99,13 +180,13 @@ module Lutaml
|
|
|
99
180
|
!enum_values.empty?
|
|
100
181
|
end
|
|
101
182
|
|
|
102
|
-
def default
|
|
103
|
-
cast_value(default_value)
|
|
183
|
+
def default(register = Lutaml::Model::Config.default_register)
|
|
184
|
+
cast_value(default_value(register), register)
|
|
104
185
|
end
|
|
105
186
|
|
|
106
|
-
def default_value
|
|
187
|
+
def default_value(register)
|
|
107
188
|
if delegate
|
|
108
|
-
type.attributes[to].default
|
|
189
|
+
type(register).attributes[to].default(register)
|
|
109
190
|
elsif options[:default].is_a?(Proc)
|
|
110
191
|
options[:default].call
|
|
111
192
|
elsif options.key?(:default)
|
|
@@ -115,8 +196,8 @@ module Lutaml
|
|
|
115
196
|
end
|
|
116
197
|
end
|
|
117
198
|
|
|
118
|
-
def default_set?
|
|
119
|
-
!Utils.uninitialized?(default_value)
|
|
199
|
+
def default_set?(register)
|
|
200
|
+
!Utils.uninitialized?(default_value(register))
|
|
120
201
|
end
|
|
121
202
|
|
|
122
203
|
def pattern
|
|
@@ -153,8 +234,8 @@ module Lutaml
|
|
|
153
234
|
options[:values].include?(value)
|
|
154
235
|
end
|
|
155
236
|
|
|
156
|
-
def valid_pattern!(value)
|
|
157
|
-
return true unless
|
|
237
|
+
def valid_pattern!(value, resolved_type)
|
|
238
|
+
return true unless resolved_type == Lutaml::Model::Type::String
|
|
158
239
|
return true unless pattern
|
|
159
240
|
|
|
160
241
|
unless pattern.match?(value)
|
|
@@ -174,32 +255,48 @@ module Lutaml
|
|
|
174
255
|
# 2. Value count should be between the collection range if defined
|
|
175
256
|
# e.g if collection: 0..5 is set then the value greater then 5
|
|
176
257
|
# will raise `Lutaml::Model::CollectionCountOutOfRangeError`
|
|
177
|
-
def validate_value!(value)
|
|
258
|
+
def validate_value!(value, register)
|
|
178
259
|
# Use the default value if the value is nil
|
|
179
|
-
value = default if value.nil?
|
|
260
|
+
value = default(register) if value.nil?
|
|
261
|
+
resolved_type = type(register)
|
|
180
262
|
|
|
181
263
|
valid_value!(value) &&
|
|
182
264
|
valid_collection!(value, self) &&
|
|
183
|
-
valid_pattern!(value) &&
|
|
184
|
-
validate_polymorphic!(value)
|
|
265
|
+
valid_pattern!(value, resolved_type) &&
|
|
266
|
+
validate_polymorphic!(value, resolved_type) &&
|
|
267
|
+
execute_validations!(value)
|
|
185
268
|
end
|
|
186
269
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
270
|
+
# execute custom validations on the attribute value
|
|
271
|
+
# i.e presence: true, numericality: true, etc
|
|
272
|
+
def execute_validations!(value)
|
|
273
|
+
return true if Utils.blank?(value)
|
|
274
|
+
|
|
275
|
+
memoization_container = {}
|
|
276
|
+
errors = Lutaml::Model::Validator.call(value, validations, memoization_container)
|
|
190
277
|
|
|
191
|
-
|
|
278
|
+
return if errors.empty?
|
|
279
|
+
|
|
280
|
+
raise Lutaml::Model::ValidationFailedError.new(errors)
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
def validate_polymorphic(value, resolved_type)
|
|
284
|
+
return value.all? { |v| validate_polymorphic!(v, resolved_type) } if value.is_a?(Array)
|
|
285
|
+
return true unless options[:polymorphic]
|
|
286
|
+
|
|
287
|
+
valid_polymorphic_type?(value, resolved_type)
|
|
192
288
|
end
|
|
193
289
|
|
|
194
|
-
def validate_polymorphic!(value)
|
|
195
|
-
return true if validate_polymorphic(value)
|
|
290
|
+
def validate_polymorphic!(value, resolved_type)
|
|
291
|
+
return true if validate_polymorphic(value, resolved_type)
|
|
196
292
|
|
|
197
|
-
raise Lutaml::Model::PolymorphicError.new(value, options)
|
|
293
|
+
raise Lutaml::Model::PolymorphicError.new(value, options, resolved_type)
|
|
198
294
|
end
|
|
199
295
|
|
|
200
296
|
def validate_collection_range
|
|
201
297
|
range = @options[:collection]
|
|
202
298
|
return if range == true
|
|
299
|
+
return if custom_collection?
|
|
203
300
|
|
|
204
301
|
unless range.is_a?(Range)
|
|
205
302
|
raise ArgumentError, "Invalid collection range: #{range}"
|
|
@@ -228,14 +325,14 @@ module Lutaml
|
|
|
228
325
|
end
|
|
229
326
|
|
|
230
327
|
def valid_collection!(value, caller)
|
|
231
|
-
raise Lutaml::Model::CollectionTrueMissingError.new(name, caller) if
|
|
328
|
+
raise Lutaml::Model::CollectionTrueMissingError.new(name, caller) if collection_instance?(value) && !collection?
|
|
232
329
|
|
|
233
330
|
return true unless collection?
|
|
234
331
|
|
|
235
332
|
# Allow any value for unbounded collections
|
|
236
333
|
return true if options[:collection] == true
|
|
237
334
|
|
|
238
|
-
unless
|
|
335
|
+
unless collection_instance?(value)
|
|
239
336
|
raise Lutaml::Model::CollectionCountOutOfRangeError.new(
|
|
240
337
|
name,
|
|
241
338
|
value,
|
|
@@ -246,7 +343,7 @@ module Lutaml
|
|
|
246
343
|
range = options[:collection]
|
|
247
344
|
return true unless range.is_a?(Range)
|
|
248
345
|
|
|
249
|
-
if range.end.nil?
|
|
346
|
+
if range.is_a?(Range) && range.end.nil?
|
|
250
347
|
if value.size < range.begin
|
|
251
348
|
raise Lutaml::Model::CollectionCountOutOfRangeError.new(
|
|
252
349
|
name,
|
|
@@ -254,7 +351,7 @@ module Lutaml
|
|
|
254
351
|
range,
|
|
255
352
|
)
|
|
256
353
|
end
|
|
257
|
-
elsif !range.cover?(value.size)
|
|
354
|
+
elsif range.is_a?(Range) && !range.cover?(value.size)
|
|
258
355
|
raise Lutaml::Model::CollectionCountOutOfRangeError.new(
|
|
259
356
|
name,
|
|
260
357
|
value,
|
|
@@ -263,39 +360,86 @@ module Lutaml
|
|
|
263
360
|
end
|
|
264
361
|
end
|
|
265
362
|
|
|
266
|
-
def serialize(value, format, options = {})
|
|
267
|
-
value ||=
|
|
363
|
+
def serialize(value, format, register, options = {})
|
|
364
|
+
value ||= build_collection if collection? && initialize_empty?
|
|
268
365
|
return value if value.nil? || Utils.uninitialized?(value)
|
|
269
366
|
return value if derived?
|
|
270
|
-
return serialize_array(value, format, options) if value.is_a?(Array)
|
|
271
|
-
return serialize_model(value, format, options) if type <= Serialize
|
|
272
367
|
|
|
273
|
-
|
|
274
|
-
|
|
368
|
+
resolved_type = options[:resolved_type] || type(register)
|
|
369
|
+
serialize_options = options.merge(resolved_type: resolved_type)
|
|
370
|
+
return serialize_array(value, format, register, serialize_options) if collection_instance?(value)
|
|
371
|
+
return serialize_model(value, format, register, options) if resolved_type <= Serialize
|
|
275
372
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
return value.map { |v| cast(v, format, options) } if value.is_a?(Array)
|
|
373
|
+
serialize_value(value, format, resolved_type)
|
|
374
|
+
end
|
|
279
375
|
|
|
280
|
-
|
|
376
|
+
def cast(value, format, register, options = {})
|
|
377
|
+
resolved_type = options[:resolved_type] || type(register)
|
|
378
|
+
return build_collection(value.map { |v| cast(v, format, register, options.merge(resolved_type: resolved_type)) }) if collection_instance?(value) || value.is_a?(Array)
|
|
281
379
|
|
|
282
|
-
|
|
380
|
+
return value if already_serialized?(resolved_type, value)
|
|
283
381
|
|
|
382
|
+
klass = resolve_polymorphic_class(resolved_type, value, options)
|
|
284
383
|
if can_serialize?(klass, value, format)
|
|
285
|
-
klass.apply_mappings(value, format, options)
|
|
384
|
+
klass.apply_mappings(value, format, options.merge(register: register))
|
|
286
385
|
elsif needs_conversion?(klass, value)
|
|
287
386
|
klass.send(:"from_#{format}", value)
|
|
288
387
|
else
|
|
289
|
-
|
|
388
|
+
# No need to use register#get_class,
|
|
389
|
+
# can_serialize? method already checks if type is Serializable or not.
|
|
390
|
+
Type.lookup(klass).cast(value)
|
|
290
391
|
end
|
|
291
392
|
end
|
|
292
393
|
|
|
394
|
+
def serializable?(register)
|
|
395
|
+
type(register) <= Serialize
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
def collection_range
|
|
399
|
+
return unless collection?
|
|
400
|
+
|
|
401
|
+
collection.is_a?(Range) ? collection : 0..Float::INFINITY
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
def sequenced_appearance_count(element_order, mapped_name, current_index)
|
|
405
|
+
elements = element_order[current_index..]
|
|
406
|
+
element_count = elements.take_while { |element| element == mapped_name }.count
|
|
407
|
+
return element_count if element_count.between?(*collection_range.minmax)
|
|
408
|
+
|
|
409
|
+
raise Lutaml::Model::ElementCountOutOfRangeError.new(
|
|
410
|
+
mapped_name,
|
|
411
|
+
element_count,
|
|
412
|
+
collection_range,
|
|
413
|
+
)
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
def process_options!
|
|
417
|
+
validate_options!(@options)
|
|
418
|
+
@raw = !!@options[:raw]
|
|
419
|
+
@validations = @options[:validations]
|
|
420
|
+
set_default_for_collection if collection?
|
|
421
|
+
end
|
|
422
|
+
|
|
293
423
|
def deep_dup
|
|
294
|
-
self.class.new(name,
|
|
424
|
+
self.class.new(name, unresolved_type, Utils.deep_dup(options))
|
|
295
425
|
end
|
|
296
426
|
|
|
297
427
|
private
|
|
298
428
|
|
|
429
|
+
def validate_name!(name, reserved_methods:)
|
|
430
|
+
return unless reserved_methods.include?(name.to_sym)
|
|
431
|
+
|
|
432
|
+
if ALLOW_OVERRIDING.include?(name.to_sym)
|
|
433
|
+
warn_name_conflict(name)
|
|
434
|
+
else
|
|
435
|
+
raise Lutaml::Model::InvalidAttributeNameError.new(name)
|
|
436
|
+
end
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
def warn_name_conflict(name)
|
|
440
|
+
Logger.warn("Attribute name `#{name}` conflicts with a built-in method")
|
|
441
|
+
end
|
|
442
|
+
|
|
299
443
|
def resolve_polymorphic_class(type, value, options)
|
|
300
444
|
return type unless polymorphic_map_defined?(options, value)
|
|
301
445
|
|
|
@@ -304,47 +448,54 @@ module Lutaml
|
|
|
304
448
|
Object.const_get(klass_name)
|
|
305
449
|
end
|
|
306
450
|
|
|
307
|
-
def polymorphic_map_defined?(
|
|
451
|
+
def polymorphic_map_defined?(polymorphic_options, value)
|
|
308
452
|
!value.nil? &&
|
|
309
|
-
|
|
310
|
-
!
|
|
311
|
-
value[
|
|
453
|
+
polymorphic_options[:polymorphic] &&
|
|
454
|
+
!polymorphic_options[:polymorphic].empty? &&
|
|
455
|
+
value[polymorphic_options[:polymorphic][:attribute]]
|
|
312
456
|
end
|
|
313
457
|
|
|
314
458
|
def castable?(value, format)
|
|
315
459
|
value.is_a?(Hash) ||
|
|
316
|
-
(format == :xml && value.is_a?(Lutaml::Model::
|
|
317
|
-
end
|
|
318
|
-
|
|
319
|
-
def castable_serialized_type?(value)
|
|
320
|
-
type <= Serialize && value.is_a?(type.model)
|
|
460
|
+
(format == :xml && value.is_a?(Lutaml::Model::Xml::XmlElement))
|
|
321
461
|
end
|
|
322
462
|
|
|
323
463
|
def can_serialize?(klass, value, format)
|
|
324
464
|
klass <= Serialize && castable?(value, format)
|
|
325
465
|
end
|
|
326
466
|
|
|
467
|
+
def custom_collection?
|
|
468
|
+
return false if singular?
|
|
469
|
+
return false if collection == true
|
|
470
|
+
return false if collection.is_a?(Range)
|
|
471
|
+
|
|
472
|
+
collection <= Lutaml::Model::Collection
|
|
473
|
+
end
|
|
474
|
+
|
|
327
475
|
def needs_conversion?(klass, value)
|
|
328
|
-
!value.nil? && !value.is_a?(klass)
|
|
476
|
+
!value.nil? && !value.is_a?(klass) && Utils.initialized?(value)
|
|
329
477
|
end
|
|
330
478
|
|
|
331
479
|
def already_serialized?(klass, value)
|
|
332
480
|
klass <= Serialize && value.is_a?(klass.model)
|
|
333
481
|
end
|
|
334
482
|
|
|
335
|
-
def serialize_array(value, format, options)
|
|
336
|
-
value.map { |v| serialize(v, format, options) }
|
|
483
|
+
def serialize_array(value, format, register, options)
|
|
484
|
+
value.map { |v| serialize(v, format, register, options) }
|
|
337
485
|
end
|
|
338
486
|
|
|
339
|
-
def serialize_model(value, format, options)
|
|
487
|
+
def serialize_model(value, format, register, options)
|
|
488
|
+
as_options = options.merge(register: register)
|
|
340
489
|
return unless Utils.present?(value)
|
|
341
|
-
return value.class.as(format, value, options) if value.is_a?(type)
|
|
342
490
|
|
|
343
|
-
|
|
491
|
+
resolved_type = as_options.delete(:resolved_type) || type(register)
|
|
492
|
+
return value.class.as(format, value, as_options) if value.is_a?(resolved_type)
|
|
493
|
+
|
|
494
|
+
resolved_type.as(format, value, as_options)
|
|
344
495
|
end
|
|
345
496
|
|
|
346
|
-
def serialize_value(value, format)
|
|
347
|
-
value =
|
|
497
|
+
def serialize_value(value, format, resolved_type)
|
|
498
|
+
value = resolved_type.new(value) unless value.is_a?(Type::Value)
|
|
348
499
|
value.send(:"to_#{format}")
|
|
349
500
|
end
|
|
350
501
|
|
|
@@ -354,29 +505,19 @@ module Lutaml
|
|
|
354
505
|
raise ArgumentError, "method or type must be set for an attribute"
|
|
355
506
|
end
|
|
356
507
|
|
|
357
|
-
def process_type!(type)
|
|
358
|
-
validate_type!(type)
|
|
359
|
-
@type = cast_type!(type)
|
|
360
|
-
end
|
|
361
|
-
|
|
362
|
-
def process_options!
|
|
363
|
-
validate_options!(@options)
|
|
364
|
-
@raw = !!@options[:raw]
|
|
365
|
-
set_default_for_collection if collection?
|
|
366
|
-
end
|
|
367
|
-
|
|
368
508
|
def set_default_for_collection
|
|
369
509
|
validate_collection_range
|
|
370
|
-
@options[:default] ||= -> {
|
|
510
|
+
@options[:default] ||= -> { build_collection } if initialize_empty?
|
|
371
511
|
end
|
|
372
512
|
|
|
373
513
|
def validate_options!(options)
|
|
374
514
|
if (invalid_opts = options.keys - ALLOWED_OPTIONS).any?
|
|
375
|
-
raise
|
|
376
|
-
"Invalid options given for `#{name}` #{invalid_opts}"
|
|
515
|
+
raise Lutaml::Model::InvalidAttributeOptionsError.new(name, invalid_opts)
|
|
377
516
|
end
|
|
378
517
|
|
|
379
|
-
|
|
518
|
+
# No need to change user register#get_class, only checks if type is LutaML-Model string.
|
|
519
|
+
# Using MODEL_STRINGS since pattern is only supported for String type.
|
|
520
|
+
if options.key?(:pattern) && !MODEL_STRINGS.include?(type)
|
|
380
521
|
raise StandardError,
|
|
381
522
|
"Invalid option `pattern` given for `#{name}`, " \
|
|
382
523
|
"`pattern` is only allowed for :string type"
|
|
@@ -390,19 +531,20 @@ module Lutaml
|
|
|
390
531
|
end
|
|
391
532
|
|
|
392
533
|
def validate_type!(type)
|
|
393
|
-
return true if type.is_a?(Class)
|
|
394
|
-
return true if [Symbol, String].include?(type.class) && cast_type!(type)
|
|
534
|
+
return true if [Symbol, String].include?(type.class) || type.is_a?(Class)
|
|
395
535
|
|
|
396
536
|
raise ArgumentError,
|
|
397
537
|
"Invalid type: #{type}, must be a Symbol, String or a Class"
|
|
398
538
|
end
|
|
399
539
|
|
|
400
|
-
def
|
|
401
|
-
|
|
540
|
+
def valid_polymorphic_type?(value, resolved_type)
|
|
541
|
+
return value.is_a?(type) unless has_polymorphic_list?
|
|
542
|
+
|
|
543
|
+
options[:polymorphic].include?(value.class) && value.is_a?(resolved_type)
|
|
402
544
|
end
|
|
403
545
|
|
|
404
|
-
def
|
|
405
|
-
|
|
546
|
+
def has_polymorphic_list?
|
|
547
|
+
options[:polymorphic]&.is_a?(Array)
|
|
406
548
|
end
|
|
407
549
|
end
|
|
408
550
|
end
|
data/lib/lutaml/model/choice.rb
CHANGED
|
@@ -41,8 +41,28 @@ module Lutaml
|
|
|
41
41
|
raise Lutaml::Model::ChoiceLowerBoundError.new(validated_attributes, @min) if valid.count < @min
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
+
def import_model_attributes(model)
|
|
45
|
+
return import_model_later(model, :import_model_attributes) if later_importable?(model)
|
|
46
|
+
|
|
47
|
+
root_model_error(model)
|
|
48
|
+
imported_attributes = Utils.deep_dup(model.attributes.values)
|
|
49
|
+
imported_attributes.each do |attr|
|
|
50
|
+
attr.options[:choice] = self
|
|
51
|
+
@model.define_attribute_methods(attr)
|
|
52
|
+
end
|
|
53
|
+
@attributes.concat(imported_attributes)
|
|
54
|
+
attrs_hash = imported_attributes.to_h { |attr| [attr.name, attr] }
|
|
55
|
+
@model.attributes.merge!(attrs_hash)
|
|
56
|
+
end
|
|
57
|
+
|
|
44
58
|
private
|
|
45
59
|
|
|
60
|
+
def root_model_error(model)
|
|
61
|
+
return unless model.root?
|
|
62
|
+
|
|
63
|
+
raise Lutaml::Model::ImportModelWithRootError.new(model)
|
|
64
|
+
end
|
|
65
|
+
|
|
46
66
|
def valid_attributes(object, validated_attributes)
|
|
47
67
|
@attributes.each do |attribute|
|
|
48
68
|
if attribute.is_a?(Choice)
|
|
@@ -58,6 +78,16 @@ module Lutaml
|
|
|
58
78
|
|
|
59
79
|
validated_attributes
|
|
60
80
|
end
|
|
81
|
+
|
|
82
|
+
def later_importable?(model)
|
|
83
|
+
model.is_a?(Symbol) || model.is_a?(String)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def import_model_later(model, method)
|
|
87
|
+
@model.importable_choices[self][method] << model.to_sym
|
|
88
|
+
@model.instance_variable_set(:@choices_imported, false)
|
|
89
|
+
@model.setup_trace_point
|
|
90
|
+
end
|
|
61
91
|
end
|
|
62
92
|
end
|
|
63
93
|
end
|