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
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
module Lutaml
|
|
2
|
+
module Model
|
|
3
|
+
class Logger
|
|
4
|
+
def self.warn(message)
|
|
5
|
+
new.call(message, :warn)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
# @param [String] old: The name of the deprecated class or method
|
|
9
|
+
# @param [String] replacement: The name of the replacement class or method
|
|
10
|
+
#
|
|
11
|
+
# Outputs a warning message that
|
|
12
|
+
# Usage of `old` name is deprecated will be removed in the next major
|
|
13
|
+
# release. Please use the `replacement`` instead.
|
|
14
|
+
def self.warn_future_deprecation(old:, replacement:)
|
|
15
|
+
warn("Usage of `#{old}` is deprecated and will be removed in the next major release. Please use `#{replacement}` instead.")
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# @param [String] name
|
|
19
|
+
# @param [String] caller_file
|
|
20
|
+
# @param [Integer] caller_line
|
|
21
|
+
#
|
|
22
|
+
# Outputs a warning message that
|
|
23
|
+
# `<name>` is handled by default. No need to explicitly
|
|
24
|
+
# define at `<caller_file>:<caller_line>`.
|
|
25
|
+
def self.warn_auto_handling(name:, caller_file:, caller_line:)
|
|
26
|
+
warn("`#{name}` is handled by default. No need to explicitly define at `#{caller_file}:#{caller_line}`")
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def call(message, type)
|
|
30
|
+
Warning.warn format_message(message, type)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def colorize(message, type)
|
|
36
|
+
type_color = {
|
|
37
|
+
error: 31, # Red: 31
|
|
38
|
+
success: 32, # Green: 32
|
|
39
|
+
warn: 33, # Yellow: 33
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
io = type == :warn ? $stderr : $stdout
|
|
43
|
+
return message unless io.tty?
|
|
44
|
+
|
|
45
|
+
color = type_color[type]
|
|
46
|
+
"\e[#{color}m#{message}\e[0m"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def format_message(message, type)
|
|
50
|
+
colorize("\n[Lutaml::Model] #{type.upcase}: #{message}\n", type)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
require_relative "base"
|
|
2
|
+
|
|
3
|
+
module Lutaml
|
|
4
|
+
module Model
|
|
5
|
+
class RuleValueExtractor < Services::Base
|
|
6
|
+
def initialize(rule, doc, format, attr, register, options)
|
|
7
|
+
super()
|
|
8
|
+
|
|
9
|
+
@rule = rule
|
|
10
|
+
@doc = doc
|
|
11
|
+
@format = format
|
|
12
|
+
@attr = attr
|
|
13
|
+
@register = register
|
|
14
|
+
@options = options
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def call
|
|
18
|
+
rule_names.each do |rule_name|
|
|
19
|
+
value = rule_value_for(rule_name)
|
|
20
|
+
value = transform_mapped_value(value) if should_transform_value?(value)
|
|
21
|
+
return value if Utils.initialized?(value)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
uninitialized_value
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
attr_reader :rule, :doc, :format, :attr, :register, :options
|
|
30
|
+
|
|
31
|
+
def rule_names
|
|
32
|
+
rule.multiple_mappings? ? rule.name : [rule.name]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def rule_value_for(name)
|
|
36
|
+
return doc if root_or_nil?(name)
|
|
37
|
+
return convert_to_format(doc, format) if rule.raw_mapping?
|
|
38
|
+
return fetch_value(name) if Utils.string_or_symbol_key?(doc, name)
|
|
39
|
+
return attr.default(register) if attr&.default_set?(register)
|
|
40
|
+
|
|
41
|
+
uninitialized_value
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def root_or_nil?(name)
|
|
45
|
+
name.nil? || rule.root_mapping?
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def fetch_value(name)
|
|
49
|
+
Utils.fetch_str_or_sym(doc, name)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def transform_mapped_value(value)
|
|
53
|
+
value.map do |k, v|
|
|
54
|
+
if v.is_a?(Hash)
|
|
55
|
+
transform_hash_value(v, k, options)
|
|
56
|
+
else
|
|
57
|
+
transform_simple_value(k, v, options)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def transform_hash_value(hash_value, key, options)
|
|
63
|
+
hash_value.merge(
|
|
64
|
+
{
|
|
65
|
+
options[:key_mappings].to_instance.to_s => key,
|
|
66
|
+
},
|
|
67
|
+
)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def transform_simple_value(key, value, options)
|
|
71
|
+
{
|
|
72
|
+
options[:key_mappings].to_instance.to_s => key,
|
|
73
|
+
options[:value_mappings].as_attribute.to_s => value,
|
|
74
|
+
}
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def should_transform_value?(value)
|
|
78
|
+
(options[:key_mappings] || options[:value_mappings]) &&
|
|
79
|
+
value.is_a?(Hash)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def convert_to_format(doc, format)
|
|
83
|
+
adapter = Lutaml::Model::Config.adapter_for(format)
|
|
84
|
+
adapter.new(doc).public_send(:"to_#{format}")
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def uninitialized_value
|
|
88
|
+
Lutaml::Model::UninitializedClass.instance
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
module Lutaml
|
|
2
|
+
module Model
|
|
3
|
+
class Transformer
|
|
4
|
+
class << self
|
|
5
|
+
def call(value, rule, attribute)
|
|
6
|
+
new(rule, attribute).call(value)
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
attr_reader :rule, :attribute
|
|
11
|
+
|
|
12
|
+
def initialize(rule, attribute)
|
|
13
|
+
@rule = rule
|
|
14
|
+
@attribute = attribute
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def call(value)
|
|
18
|
+
transformation_methods.reduce(value) do |transformed_value, method|
|
|
19
|
+
method.call(transformed_value)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
class ImportTransformer < Transformer
|
|
25
|
+
# Precedene of transformations:
|
|
26
|
+
# 1. Rule transform
|
|
27
|
+
# 2. Attribute transform
|
|
28
|
+
def transformation_methods
|
|
29
|
+
[
|
|
30
|
+
rule.transform[:import],
|
|
31
|
+
attribute&.transform&.[](:import),
|
|
32
|
+
].compact
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
class ExportTransformer < Transformer
|
|
37
|
+
# Precedene of transformations (reverse order):
|
|
38
|
+
# 1. Attribute transform
|
|
39
|
+
# 2. Rule transform
|
|
40
|
+
def transformation_methods
|
|
41
|
+
[
|
|
42
|
+
attribute&.transform&.[](:export),
|
|
43
|
+
rule.transform[:export],
|
|
44
|
+
].compact
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Lutaml
|
|
4
|
+
module Model
|
|
5
|
+
module Services
|
|
6
|
+
module Type
|
|
7
|
+
class Validator
|
|
8
|
+
class Number < Validator
|
|
9
|
+
module ClassMethods
|
|
10
|
+
def validate!(value, options)
|
|
11
|
+
return if Utils.blank?(options)
|
|
12
|
+
|
|
13
|
+
validate_values!(value, options[:values])
|
|
14
|
+
validate_min_max_bounds!(value, options)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
extend ClassMethods
|
|
19
|
+
include ClassMethods
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
module Lutaml
|
|
2
|
+
module Model
|
|
3
|
+
module Services
|
|
4
|
+
module Type
|
|
5
|
+
class Validator
|
|
6
|
+
class String < Validator
|
|
7
|
+
module ClassMethods
|
|
8
|
+
def validate!(value, options)
|
|
9
|
+
return if Utils.blank?(value)
|
|
10
|
+
|
|
11
|
+
validate_values!(value, options[:values])
|
|
12
|
+
validate_length!(value, options)
|
|
13
|
+
validate_pattern!(value, options)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def validate_length!(value, options)
|
|
17
|
+
min, max = options&.values_at(:min, :max)
|
|
18
|
+
return if min.nil? || max.nil?
|
|
19
|
+
|
|
20
|
+
validate_min_length!(value, min) if min
|
|
21
|
+
validate_max_length!(value, max) if max
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def validate_pattern!(value, options)
|
|
25
|
+
pattern = options[:pattern]
|
|
26
|
+
return if Utils.blank?(pattern)
|
|
27
|
+
return if value.match?(pattern)
|
|
28
|
+
|
|
29
|
+
raise Lutaml::Model::Type::PatternNotMatchedError.new(value, pattern)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def validate_min_length!(value, min)
|
|
33
|
+
return if value.length >= min
|
|
34
|
+
|
|
35
|
+
raise Lutaml::Model::Type::MinLengthError.new(value, min)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def validate_max_length!(value, max)
|
|
39
|
+
return if value.length <= max
|
|
40
|
+
|
|
41
|
+
raise Lutaml::Model::Type::MaxLengthError.new(value, max)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
extend ClassMethods
|
|
46
|
+
include ClassMethods
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
require_relative "validator/string"
|
|
2
|
+
require_relative "validator/number"
|
|
3
|
+
|
|
4
|
+
module Lutaml
|
|
5
|
+
module Model
|
|
6
|
+
module Services
|
|
7
|
+
module Type
|
|
8
|
+
class Validator
|
|
9
|
+
module ClassMethods
|
|
10
|
+
def validate_values!(value, values)
|
|
11
|
+
return if Utils.blank?(values) || values.include?(value)
|
|
12
|
+
|
|
13
|
+
raise Lutaml::Model::Type::InvalidValueError.new(value, values)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def validate_min_max_bounds!(value, options)
|
|
17
|
+
min, max = options&.values_at(:min, :max)
|
|
18
|
+
return if min.nil? && max.nil?
|
|
19
|
+
|
|
20
|
+
validate_min_bound!(value, min) if min
|
|
21
|
+
validate_max_bound!(value, max) if max
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def validate_min_bound!(value, min)
|
|
25
|
+
return if value >= min
|
|
26
|
+
|
|
27
|
+
raise Lutaml::Model::Type::MinBoundError.new(value, min)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def validate_max_bound!(value, max)
|
|
31
|
+
return if value <= max
|
|
32
|
+
|
|
33
|
+
raise Lutaml::Model::Type::MaxBoundError.new(value, max)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
extend ClassMethods
|
|
38
|
+
include ClassMethods
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
require_relative "base"
|
|
2
|
+
|
|
3
|
+
module Lutaml
|
|
4
|
+
module Model
|
|
5
|
+
class ValidationRule
|
|
6
|
+
attr_reader :attribute, :options, :custom_method
|
|
7
|
+
|
|
8
|
+
def initialize(attribute: nil, custom_method: nil, options: {})
|
|
9
|
+
if Utils.blank?(attribute) && Utils.blank?(custom_method)
|
|
10
|
+
raise ArgumentError, "Missing attribute or custom method"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
@attribute = attribute
|
|
14
|
+
@options = options
|
|
15
|
+
@custom_method = custom_method
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def custom?
|
|
19
|
+
Utils.present?(custom_method)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def has_options?
|
|
23
|
+
options.is_a?(Hash)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
class Validator < Services::Base
|
|
28
|
+
attr_reader :value, :validations, :errors, :memoization_container
|
|
29
|
+
|
|
30
|
+
def initialize(value, validations, memoization_container)
|
|
31
|
+
super()
|
|
32
|
+
|
|
33
|
+
@errors = Errors.new
|
|
34
|
+
@value = value
|
|
35
|
+
@memoization_container = memoization_container
|
|
36
|
+
|
|
37
|
+
resolve_validations(validations)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def call
|
|
41
|
+
return [] if Utils.blank?(validations)
|
|
42
|
+
|
|
43
|
+
@validations.each do |validation|
|
|
44
|
+
if validation.custom?
|
|
45
|
+
public_send(validation.custom_method, value)
|
|
46
|
+
else
|
|
47
|
+
validation.options.each do |key, rule|
|
|
48
|
+
send(:"validate_#{key}", value, validation.attribute, rule)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
errors.messages
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
def resolve_validations(validations_block)
|
|
59
|
+
@validations ||= []
|
|
60
|
+
return unless validations_block
|
|
61
|
+
|
|
62
|
+
instance_eval(&validations_block)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def validate(method_name)
|
|
66
|
+
@validations << ValidationRule.new(custom_method: method_name)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def validates(attribute, options)
|
|
70
|
+
@validations <<
|
|
71
|
+
ValidationRule.new(attribute: attribute, options: options)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def validate_presence(model, attr, rule)
|
|
75
|
+
return if rule.nil?
|
|
76
|
+
|
|
77
|
+
if model.is_a?(Array)
|
|
78
|
+
model.each { |v| validate_presence(v, attr, rule) }
|
|
79
|
+
return
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
value = model.public_send(attr)
|
|
83
|
+
return if Utils.present?(value)
|
|
84
|
+
|
|
85
|
+
errors.add(attr, "`#{attr}` is required")
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def validate_numericality(model, attr, rule)
|
|
89
|
+
return if rule.nil?
|
|
90
|
+
|
|
91
|
+
if model.is_a?(Array)
|
|
92
|
+
model.each { |v| validate_numericality(v, attr, rule) }
|
|
93
|
+
return
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
value = model.public_send(attr)
|
|
97
|
+
return unless validate_integer(attr, value)
|
|
98
|
+
|
|
99
|
+
validate_comparison_rules(attr, value, rule)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def validate_integer(attr, value)
|
|
103
|
+
return true if value.is_a?(Integer)
|
|
104
|
+
|
|
105
|
+
errors.add(
|
|
106
|
+
attr,
|
|
107
|
+
"`#{attr}` value is `#{value.class}`, but expected integer",
|
|
108
|
+
)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def validate_comparison_rules(attr, value, options)
|
|
112
|
+
validate_less_than(attr, value, options[:less_than])
|
|
113
|
+
validate_greater_than(attr, value, options[:greater_than])
|
|
114
|
+
validate_equal_to(attr, value, options[:equal_to])
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def validate_less_than(attr, value, limit)
|
|
118
|
+
return if !limit || value < limit
|
|
119
|
+
|
|
120
|
+
errors.add(
|
|
121
|
+
attr,
|
|
122
|
+
"#{attr} value is `#{value}`, which is not less than #{limit}",
|
|
123
|
+
)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def validate_greater_than(attr, value, limit)
|
|
127
|
+
return if !limit || value > limit
|
|
128
|
+
|
|
129
|
+
errors.add(
|
|
130
|
+
attr,
|
|
131
|
+
"#{attr} value is `#{value}`, which is not greater than #{limit}",
|
|
132
|
+
)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def validate_equal_to(attr, value, target)
|
|
136
|
+
return if !target || value == target
|
|
137
|
+
|
|
138
|
+
errors.add(
|
|
139
|
+
attr,
|
|
140
|
+
"#{attr} value is `#{value}`, which is not equal to #{target}",
|
|
141
|
+
)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require_relative "../mapping/key_value_mapping"
|
|
2
|
+
|
|
3
|
+
module Lutaml
|
|
4
|
+
module Model
|
|
5
|
+
module Toml
|
|
6
|
+
class Mapping < Lutaml::Model::KeyValueMapping
|
|
7
|
+
def initialize
|
|
8
|
+
super(:toml)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def deep_dup
|
|
12
|
+
self.class.new.tap do |new_mapping|
|
|
13
|
+
new_mapping.instance_variable_set(:@mappings, duplicate_mappings)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def validate!(key, to, with, render_nil, render_empty)
|
|
18
|
+
super
|
|
19
|
+
|
|
20
|
+
if [true, :as_nil].include?(render_nil) || render_empty == :as_nil
|
|
21
|
+
raise IncorrectMappingArgumentsError, "nil values are not supported in toml format"
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
require "toml-rb"
|
|
2
|
-
require_relative "
|
|
2
|
+
require_relative "document"
|
|
3
3
|
|
|
4
4
|
module Lutaml
|
|
5
5
|
module Model
|
|
6
|
-
module
|
|
7
|
-
class TomlRbAdapter <
|
|
6
|
+
module Toml
|
|
7
|
+
class TomlRbAdapter < Document
|
|
8
8
|
def self.parse(toml, _options = {})
|
|
9
9
|
TomlRB.parse(toml)
|
|
10
10
|
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require "tomlib"
|
|
2
|
+
require_relative "document"
|
|
3
|
+
|
|
4
|
+
module Lutaml
|
|
5
|
+
module Model
|
|
6
|
+
module Toml
|
|
7
|
+
class TomlibAdapter < Document
|
|
8
|
+
def self.parse(toml, _options = {})
|
|
9
|
+
Tomlib.load(toml)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def to_toml(*)
|
|
13
|
+
Tomlib.dump(to_h)
|
|
14
|
+
# Tomlib::Generator.new(to_h).toml_str
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Lutaml
|
|
4
|
+
module Model
|
|
5
|
+
module Toml
|
|
6
|
+
def self.detect_toml_adapter
|
|
7
|
+
return :tomlib if Object.const_defined?(:Tomlib)
|
|
8
|
+
return :toml_rb if Object.const_defined?(:TomlRb)
|
|
9
|
+
|
|
10
|
+
nil
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
require_relative "toml/document"
|
|
17
|
+
require_relative "toml/mapping"
|
|
18
|
+
require_relative "toml/mapping_rule"
|
|
19
|
+
require_relative "toml/transform"
|
|
20
|
+
|
|
21
|
+
Lutaml::Model::FormatRegistry.register(
|
|
22
|
+
:toml,
|
|
23
|
+
mapping_class: Lutaml::Model::Toml::Mapping,
|
|
24
|
+
adapter_class: nil,
|
|
25
|
+
transformer: Lutaml::Model::Toml::Transform,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
if (adapter = Lutaml::Model::Toml.detect_toml_adapter)
|
|
29
|
+
Lutaml::Model::Config.toml_adapter_type = adapter
|
|
30
|
+
end
|