lutaml-model 0.7.3 → 0.7.5
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/release.yml +3 -0
- data/.gitignore +6 -1
- data/.irbrc +1 -0
- data/.pryrc +1 -0
- data/.rubocop_todo.yml +25 -52
- data/README.adoc +2177 -192
- 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 +230 -94
- data/lib/lutaml/model/choice.rb +30 -0
- data/lib/lutaml/model/collection.rb +194 -0
- data/lib/lutaml/model/comparable_model.rb +3 -3
- data/lib/lutaml/model/config.rb +26 -3
- 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/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 +5 -2
- data/lib/lutaml/model/global_register.rb +41 -0
- data/lib/lutaml/model/{hash.rb → hash_adapter.rb} +5 -5
- 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 +3 -2
- data/lib/lutaml/model/mapping/key_value_mapping.rb +64 -4
- data/lib/lutaml/model/mapping/key_value_mapping_rule.rb +4 -0
- data/lib/lutaml/model/mapping/mapping_rule.rb +8 -3
- data/lib/lutaml/model/register.rb +105 -0
- data/lib/lutaml/model/registrable.rb +6 -0
- 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/serialize.rb +175 -53
- data/lib/lutaml/model/services/base.rb +11 -0
- data/lib/lutaml/model/services/logger.rb +2 -2
- data/lib/lutaml/model/services/rule_value_extractor.rb +92 -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 +3 -0
- data/lib/lutaml/model/transform/key_value_transform.rb +60 -50
- data/lib/lutaml/model/transform/xml_transform.rb +46 -57
- data/lib/lutaml/model/transform.rb +22 -8
- 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 +5 -1
- data/lib/lutaml/model/type.rb +5 -2
- data/lib/lutaml/model/utils.rb +30 -8
- data/lib/lutaml/model/validation.rb +6 -4
- data/lib/lutaml/model/version.rb +1 -1
- data/lib/lutaml/model/xml/document.rb +37 -19
- data/lib/lutaml/model/xml/mapping.rb +74 -13
- data/lib/lutaml/model/xml/mapping_rule.rb +10 -2
- data/lib/lutaml/model/xml/nokogiri_adapter.rb +5 -3
- data/lib/lutaml/model/xml/oga/element.rb +4 -1
- data/lib/lutaml/model/xml/oga_adapter.rb +4 -3
- data/lib/lutaml/model/xml/ox_adapter.rb +20 -6
- data/lib/lutaml/model/xml/xml_element.rb +3 -28
- data/lib/lutaml/model/xml_adapter/element.rb +1 -1
- data/lib/lutaml/model/xml_adapter/nokogiri_adapter.rb +1 -1
- data/lib/lutaml/model/xml_adapter/oga_adapter.rb +1 -1
- data/lib/lutaml/model/xml_adapter/ox_adapter.rb +1 -1
- 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 +7 -31
- data/spec/benchmarks/xml_parsing_benchmark_spec.rb +4 -5
- 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/choice_spec.rb +44 -0
- data/spec/lutaml/model/custom_collection_spec.rb +830 -0
- data/spec/lutaml/model/custom_model_spec.rb +15 -3
- data/spec/lutaml/model/defaults_spec.rb +5 -1
- data/spec/lutaml/model/global_register_spec.rb +108 -0
- data/spec/lutaml/model/group_spec.rb +9 -3
- data/spec/lutaml/model/jsonl/standard_adapter_spec.rb +91 -0
- data/spec/lutaml/model/jsonl_spec.rb +229 -0
- data/spec/lutaml/model/multiple_mapping_spec.rb +1 -1
- data/spec/lutaml/model/register/key_value_spec.rb +275 -0
- data/spec/lutaml/model/register/xml_spec.rb +187 -0
- data/spec/lutaml/model/register_spec.rb +147 -0
- 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 +31 -0
- data/spec/lutaml/model/type_spec.rb +8 -4
- 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/xml_element_spec.rb +7 -1
- data/spec/lutaml/model/xml_adapter/xml_namespace_spec.rb +6 -6
- data/spec/lutaml/model/xml_adapter_spec.rb +24 -0
- data/spec/lutaml/model/xml_mapping_rule_spec.rb +11 -4
- data/spec/lutaml/model/xml_mapping_spec.rb +1 -1
- 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 +1 -0
- metadata +105 -9
- data/lib/lutaml/model/schema/templates/simple_type.rb +0 -247
- /data/lib/lutaml/model/{hash → hash_adapter}/document.rb +0 -0
- /data/lib/lutaml/model/{hash → hash_adapter}/mapping.rb +0 -0
- /data/lib/lutaml/model/{hash → hash_adapter}/mapping_rule.rb +0 -0
- /data/lib/lutaml/model/{hash → hash_adapter}/standard_adapter.rb +0 -0
- /data/lib/lutaml/model/{hash → hash_adapter}/transform.rb +0 -0
@@ -2,7 +2,12 @@ module Lutaml
|
|
2
2
|
module Model
|
3
3
|
class XmlTransform < Lutaml::Model::Transform
|
4
4
|
def data_to_model(data, _format, options = {})
|
5
|
-
|
5
|
+
if model_class.include?(Lutaml::Model::Serialize)
|
6
|
+
instance = model_class.new({}, register: register)
|
7
|
+
else
|
8
|
+
instance = model_class.new
|
9
|
+
register_accessor_methods_for(instance, register)
|
10
|
+
end
|
6
11
|
apply_xml_mapping(data, instance, options)
|
7
12
|
end
|
8
13
|
|
@@ -29,11 +34,11 @@ module Lutaml
|
|
29
34
|
validate_sequence!(doc.root.order)
|
30
35
|
|
31
36
|
mappings.each do |rule|
|
32
|
-
raise "Attribute '#{rule.to}' not found in #{context}" unless valid_rule?(rule)
|
33
|
-
|
34
37
|
attr = attribute_for_rule(rule)
|
35
38
|
next if attr&.derived?
|
36
39
|
|
40
|
+
raise "Attribute '#{rule.to}' not found in #{context}" unless valid_rule?(rule, attr)
|
41
|
+
|
37
42
|
new_opts = options.dup
|
38
43
|
if rule.namespace_set?
|
39
44
|
new_opts[:default_namespace] = rule.namespace
|
@@ -46,9 +51,9 @@ module Lutaml
|
|
46
51
|
else
|
47
52
|
val = value_for_rule(doc, rule, new_opts, instance)
|
48
53
|
|
49
|
-
if (
|
54
|
+
if (val.nil? || Utils.uninitialized?(val)) && (instance.using_default?(rule.to) || rule.render_default)
|
50
55
|
defaults_used << rule.to
|
51
|
-
attr&.default || rule.to_value_for(instance)
|
56
|
+
attr&.default(register) || rule.to_value_for(instance)
|
52
57
|
else
|
53
58
|
val
|
54
59
|
end
|
@@ -106,49 +111,45 @@ module Lutaml
|
|
106
111
|
|
107
112
|
def value_for_rule(doc, rule, options, instance)
|
108
113
|
rule_names = rule.namespaced_names(options[:default_namespace])
|
114
|
+
return doc.root.find_attribute_value(rule_names) if rule.attribute?
|
109
115
|
|
110
|
-
|
111
|
-
|
112
|
-
else
|
113
|
-
attr = attribute_for_rule(rule)
|
114
|
-
children = doc.children.select do |child|
|
115
|
-
rule_names.include?(child.namespaced_name) && !child.text?
|
116
|
-
end
|
116
|
+
attr = attribute_for_rule(rule)
|
117
|
+
attr_type = attr&.type(register)
|
117
118
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
end
|
119
|
+
children = doc.children.select do |child|
|
120
|
+
rule_names.include?(child.namespaced_name) && !child.text?
|
121
|
+
end
|
122
122
|
|
123
|
-
|
123
|
+
if rule.has_custom_method_for_deserialization? || attr_type == Lutaml::Model::Type::Hash
|
124
|
+
return_child = attr_type == Lutaml::Model::Type::Hash || !attr.collection? if attr
|
125
|
+
return return_child ? children.first : children
|
126
|
+
end
|
124
127
|
|
125
|
-
|
128
|
+
return handle_cdata(children) if rule.cdata
|
129
|
+
return Lutaml::Model::UninitializedClass.instance if children.empty?
|
126
130
|
|
127
|
-
|
128
|
-
instance.value_set_for(attr.name)
|
129
|
-
else
|
130
|
-
children = nil
|
131
|
-
values = Lutaml::Model::UninitializedClass.instance
|
132
|
-
end
|
131
|
+
values = attr.build_collection
|
133
132
|
|
134
|
-
|
135
|
-
if !rule.has_custom_method_for_deserialization? && attr.type <= Serialize
|
136
|
-
cast_options = options.except(:mappings)
|
137
|
-
cast_options[:polymorphic] = rule.polymorphic if rule.polymorphic
|
133
|
+
instance.value_set_for(attr.name)
|
138
134
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
135
|
+
children.each do |child|
|
136
|
+
if !rule.has_custom_method_for_deserialization? && attr_type <= Serialize
|
137
|
+
cast_options = options.except(:mappings)
|
138
|
+
cast_options[:polymorphic] = rule.polymorphic if rule.polymorphic
|
139
|
+
cast_options[:register] = register
|
144
140
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
141
|
+
values << attr.cast(child, :xml, register, cast_options)
|
142
|
+
elsif attr.raw?
|
143
|
+
values << inner_xml_of(child)
|
144
|
+
else
|
145
|
+
return nil if rule.render_nil_as_nil? && child.nil_element?
|
149
146
|
|
150
|
-
|
147
|
+
text = child.nil_element? ? nil : (child&.text&.+ child&.cdata)
|
148
|
+
values << text
|
149
|
+
end
|
151
150
|
end
|
151
|
+
|
152
|
+
normalized_value_for_attr(values, attr)
|
152
153
|
end
|
153
154
|
|
154
155
|
def handle_cdata(children)
|
@@ -173,30 +174,16 @@ module Lutaml
|
|
173
174
|
end
|
174
175
|
|
175
176
|
def normalize_xml_value(value, rule, attr, options = {})
|
176
|
-
|
177
|
+
collection_class = attr&.collection_class || Array
|
178
|
+
value = [value].compact if !value.nil? && attr&.collection? && !value.is_a?(collection_class)
|
177
179
|
|
178
180
|
return value unless cast_value?(attr, rule)
|
179
181
|
|
180
|
-
|
181
|
-
attr.cast(
|
182
|
-
value,
|
183
|
-
:xml,
|
184
|
-
options,
|
185
|
-
)
|
182
|
+
attr.cast(value, :xml, register, options)
|
186
183
|
end
|
187
184
|
|
188
185
|
def cast_value?(attr, rule)
|
189
|
-
attr &&
|
190
|
-
!rule.raw_mapping? &&
|
191
|
-
!rule.content_mapping? &&
|
192
|
-
!rule.custom_methods[:from]
|
193
|
-
end
|
194
|
-
|
195
|
-
def text_hash?(attr, value)
|
196
|
-
return false unless value.is_a?(Hash)
|
197
|
-
return value.one? && value.text? unless attr
|
198
|
-
|
199
|
-
!(attr.type <= Serialize) && attr.type != Lutaml::Model::Type::Hash
|
186
|
+
attr && rule.castable?
|
200
187
|
end
|
201
188
|
|
202
189
|
def ensure_utf8(value)
|
@@ -228,10 +215,12 @@ module Lutaml
|
|
228
215
|
|
229
216
|
def validate_sequence!(element_order)
|
230
217
|
mapping_sequence = mappings_for(:xml).element_sequence
|
218
|
+
return if mapping_sequence.empty?
|
219
|
+
|
231
220
|
current_order = element_order.filter_map(&:element_tag)
|
232
221
|
|
233
222
|
mapping_sequence.each do |mapping|
|
234
|
-
mapping.validate_content!(current_order)
|
223
|
+
mapping.validate_content!(current_order, context)
|
235
224
|
end
|
236
225
|
end
|
237
226
|
end
|
@@ -2,18 +2,19 @@ module Lutaml
|
|
2
2
|
module Model
|
3
3
|
class Transform
|
4
4
|
def self.data_to_model(context, data, format, options = {})
|
5
|
-
new(context).data_to_model(data, format, options)
|
5
|
+
new(context, options[:register]).data_to_model(data, format, options)
|
6
6
|
end
|
7
7
|
|
8
8
|
def self.model_to_data(context, model, format, options = {})
|
9
|
-
new(context).model_to_data(model, format, options)
|
9
|
+
new(context, model.register).model_to_data(model, format, options)
|
10
10
|
end
|
11
11
|
|
12
|
-
attr_reader :context, :attributes
|
12
|
+
attr_reader :context, :attributes, :register
|
13
13
|
|
14
|
-
def initialize(context)
|
14
|
+
def initialize(context, register = nil)
|
15
15
|
@context = context
|
16
16
|
@attributes = context.attributes
|
17
|
+
@register = register || Lutaml::Model::Config.default_register
|
17
18
|
end
|
18
19
|
|
19
20
|
def model_class
|
@@ -59,16 +60,29 @@ module Lutaml
|
|
59
60
|
context.mappings_for(format)
|
60
61
|
end
|
61
62
|
|
62
|
-
def
|
63
|
-
|
63
|
+
def defined_mappings_for(format)
|
64
|
+
context.mappings[format]
|
65
|
+
end
|
64
66
|
|
65
|
-
|
67
|
+
def valid_rule?(rule, attribute)
|
68
|
+
attribute || rule.custom_methods[:from]
|
66
69
|
end
|
67
70
|
|
68
71
|
def attribute_for_rule(rule)
|
69
72
|
return attributes[rule.to] unless rule.delegate
|
70
73
|
|
71
|
-
attributes[rule.delegate].type.attributes[rule.to]
|
74
|
+
attributes[rule.delegate].type(register).attributes[rule.to]
|
75
|
+
end
|
76
|
+
|
77
|
+
def register_accessor_methods_for(object, register)
|
78
|
+
klass = object.class
|
79
|
+
Utils.add_method_if_not_defined(klass, :register) do
|
80
|
+
@register
|
81
|
+
end
|
82
|
+
Utils.add_method_if_not_defined(klass, :register=) do |value|
|
83
|
+
@register = value
|
84
|
+
end
|
85
|
+
object.register = register
|
72
86
|
end
|
73
87
|
end
|
74
88
|
end
|
@@ -2,7 +2,7 @@ module Lutaml
|
|
2
2
|
module Model
|
3
3
|
module Type
|
4
4
|
class Boolean < Value
|
5
|
-
def self.cast(value)
|
5
|
+
def self.cast(value, _options = {})
|
6
6
|
return nil if value.nil?
|
7
7
|
return true if value == true || value.to_s.match?(/^(true|t|yes|y|1)$/i)
|
8
8
|
return false if value == false || value.to_s.match?(/^(false|f|no|n|0)$/i)
|
@@ -2,18 +2,20 @@ module Lutaml
|
|
2
2
|
module Model
|
3
3
|
module Type
|
4
4
|
class Decimal < Value
|
5
|
-
def self.cast(value)
|
5
|
+
def self.cast(value, options = {})
|
6
6
|
return nil if value.nil?
|
7
7
|
|
8
8
|
check_dependencies!(value)
|
9
|
-
case value
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
9
|
+
value = case value
|
10
|
+
when BigDecimal
|
11
|
+
# If already a BigDecimal, return as-is
|
12
|
+
value
|
13
|
+
else
|
14
|
+
# Convert to string first to handle various input types
|
15
|
+
BigDecimal(value.to_s)
|
16
|
+
end
|
17
|
+
Model::Services::Type::Validator::Number.validate!(value, options)
|
18
|
+
value
|
17
19
|
rescue ArgumentError
|
18
20
|
nil
|
19
21
|
end
|
@@ -2,31 +2,34 @@ module Lutaml
|
|
2
2
|
module Model
|
3
3
|
module Type
|
4
4
|
class Integer < Value
|
5
|
-
def self.cast(value)
|
5
|
+
def self.cast(value, options = {})
|
6
6
|
return nil if value.nil?
|
7
7
|
return 1 if value === true
|
8
8
|
return 0 if value === false
|
9
9
|
|
10
|
-
case value
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
10
|
+
value = case value
|
11
|
+
when ::String
|
12
|
+
if value.match?(/^0[0-7]+$/) # Octal
|
13
|
+
value.to_i(8)
|
14
|
+
elsif value.match?(/^-?\d+(\.\d+)?(e-?\d+)?$/i) # Float/exponential
|
15
|
+
Float(value).to_i
|
16
|
+
else
|
17
|
+
begin
|
18
|
+
Integer(value, 10)
|
19
|
+
rescue StandardError
|
20
|
+
nil
|
21
|
+
end
|
22
|
+
end
|
23
|
+
else
|
24
|
+
begin
|
25
|
+
Integer(value)
|
26
|
+
rescue StandardError
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
Model::Services::Type::Validator::Number.validate!(value, options)
|
32
|
+
value
|
30
33
|
end
|
31
34
|
|
32
35
|
# Override serialize to return Integer instead of String
|
@@ -2,10 +2,12 @@ module Lutaml
|
|
2
2
|
module Model
|
3
3
|
module Type
|
4
4
|
class String < Value
|
5
|
-
def self.cast(value)
|
5
|
+
def self.cast(value, options = {})
|
6
6
|
return nil if value.nil?
|
7
7
|
|
8
|
-
value.to_s
|
8
|
+
value = value.to_s
|
9
|
+
Model::Services::Type::Validator::String.validate!(value, options)
|
10
|
+
value
|
9
11
|
end
|
10
12
|
|
11
13
|
# xs:string format
|
data/lib/lutaml/model/type.rb
CHANGED
@@ -5,6 +5,7 @@ module Lutaml
|
|
5
5
|
string: "Lutaml::Model::Type::String",
|
6
6
|
integer: "Lutaml::Model::Type::Integer",
|
7
7
|
float: "Lutaml::Model::Type::Float",
|
8
|
+
double: "Lutaml::Model::Type::Float",
|
8
9
|
decimal: "Lutaml::Model::Type::Decimal",
|
9
10
|
date: "Lutaml::Model::Type::Date",
|
10
11
|
time: "Lutaml::Model::Type::Time",
|
@@ -32,6 +33,8 @@ module Lutaml
|
|
32
33
|
end
|
33
34
|
|
34
35
|
def lookup(type_name)
|
36
|
+
return type_name if type_name.is_a?(Class)
|
37
|
+
|
35
38
|
@registry ||= {}
|
36
39
|
klass = @registry[type_name.to_sym]
|
37
40
|
|
@@ -43,13 +46,13 @@ module Lutaml
|
|
43
46
|
def cast(value, type)
|
44
47
|
return nil if value.nil?
|
45
48
|
|
46
|
-
type.cast(value)
|
49
|
+
lookup(type).cast(value)
|
47
50
|
end
|
48
51
|
|
49
52
|
def serialize(value, type)
|
50
53
|
return nil if value.nil?
|
51
54
|
|
52
|
-
type.serialize(value)
|
55
|
+
lookup(type).serialize(value)
|
53
56
|
end
|
54
57
|
end
|
55
58
|
end
|
data/lib/lutaml/model/utils.rb
CHANGED
@@ -4,6 +4,8 @@ module Lutaml
|
|
4
4
|
module Model
|
5
5
|
module Utils
|
6
6
|
class << self
|
7
|
+
UNINITIALIZED = Lutaml::Model::UninitializedClass.instance
|
8
|
+
|
7
9
|
# Convert string to camel case
|
8
10
|
def camel_case(str)
|
9
11
|
return "" if str.nil? || str.empty?
|
@@ -34,14 +36,22 @@ module Lutaml
|
|
34
36
|
.downcase
|
35
37
|
end
|
36
38
|
|
37
|
-
|
38
|
-
|
39
|
+
# Extract the base name of the class
|
40
|
+
def base_class_name(klass)
|
41
|
+
klass.to_s.split("::").last
|
42
|
+
end
|
39
43
|
|
40
|
-
|
44
|
+
# Convert the extracted base class to snake case format
|
45
|
+
def base_class_snake_case(klass)
|
46
|
+
snake_case(base_class_name(klass))
|
47
|
+
end
|
48
|
+
|
49
|
+
def initialized?(value)
|
50
|
+
!value.equal?(UNINITIALIZED)
|
41
51
|
end
|
42
52
|
|
43
53
|
def uninitialized?(value)
|
44
|
-
|
54
|
+
value.equal?(UNINITIALIZED)
|
45
55
|
end
|
46
56
|
|
47
57
|
def present?(value)
|
@@ -63,6 +73,10 @@ module Lutaml
|
|
63
73
|
value.respond_to?(:empty?) ? value.empty? : false
|
64
74
|
end
|
65
75
|
|
76
|
+
def add_if_present(hash, key, value)
|
77
|
+
hash[key] = value if value
|
78
|
+
end
|
79
|
+
|
66
80
|
# Check if the hash contains the given key in string or symbol format
|
67
81
|
# @param hash [Hash] the hash to check
|
68
82
|
# @param key [String, Symbol] the key to check
|
@@ -82,17 +96,25 @@ module Lutaml
|
|
82
96
|
# @return [Object] the value associated with the key
|
83
97
|
# @example
|
84
98
|
# hash = { "key" => "value" }
|
85
|
-
#
|
86
|
-
#
|
87
|
-
#
|
88
|
-
def
|
99
|
+
# fetch_str_or_sym(hash, "key") # => "value"
|
100
|
+
# fetch_str_or_sym(hash, :key) # => "value"
|
101
|
+
# fetch_str_or_sym(hash, "invalid_key") # => nil
|
102
|
+
def fetch_str_or_sym(hash, key, default = nil)
|
89
103
|
if hash.key?(key.to_s)
|
90
104
|
hash[key.to_s]
|
91
105
|
elsif hash.key?(key.to_sym)
|
92
106
|
hash[key.to_sym]
|
107
|
+
else
|
108
|
+
default
|
93
109
|
end
|
94
110
|
end
|
95
111
|
|
112
|
+
def add_singleton_method_if_not_defined(instance, method_name, &block)
|
113
|
+
return if instance.respond_to?(method_name)
|
114
|
+
|
115
|
+
instance.define_singleton_method(method_name, &block)
|
116
|
+
end
|
117
|
+
|
96
118
|
def add_method_if_not_defined(klass, method_name, &block)
|
97
119
|
unless klass.method_defined?(method_name)
|
98
120
|
klass.class_eval do
|
@@ -1,20 +1,22 @@
|
|
1
1
|
module Lutaml
|
2
2
|
module Model
|
3
3
|
module Validation
|
4
|
-
def validate
|
4
|
+
def validate(register: Lutaml::Model::Config.default_register)
|
5
5
|
errors = []
|
6
|
+
|
6
7
|
self.class.attributes.each do |name, attr|
|
7
8
|
value = public_send(:"#{name}")
|
8
9
|
begin
|
9
10
|
if value.respond_to?(:validate)
|
10
11
|
errors.concat(value.validate)
|
11
12
|
else
|
12
|
-
attr.validate_value!(value)
|
13
|
+
attr.validate_value!(value, register)
|
13
14
|
end
|
14
15
|
rescue Lutaml::Model::InvalidValueError,
|
15
16
|
Lutaml::Model::CollectionCountOutOfRangeError,
|
16
17
|
Lutaml::Model::CollectionTrueMissingError,
|
17
18
|
Lutaml::Model::PolymorphicError,
|
19
|
+
Lutaml::Model::ValidationFailedError,
|
18
20
|
PatternNotMatchedError => e
|
19
21
|
errors << e
|
20
22
|
end
|
@@ -23,8 +25,8 @@ module Lutaml
|
|
23
25
|
validate_helper(errors)
|
24
26
|
end
|
25
27
|
|
26
|
-
def validate!
|
27
|
-
errors = validate
|
28
|
+
def validate!(register: Lutaml::Model::Config.default_register)
|
29
|
+
errors = validate(register: register)
|
28
30
|
raise Lutaml::Model::ValidationError.new(errors) if errors.any?
|
29
31
|
end
|
30
32
|
|