Module: Lutaml::Model::RestrictionValidation
- Included in:
- Attribute
- Defined in:
- lib/lutaml/model/restriction_validation.rb
Overview
Module for enforcing value restrictions on attributes.
Provides the lazy validation seam used by Attribute#validate_value!:
a configuration check (applicability of the effective facets to the
resolved type) and a value check (ordered bounds / string length) that
reuses the shared Type validators and translates their errors into
model-level errors carrying the attribute name.
The effective facet set is the conjunctive merge of Layer-1 attribute
options (lowered to canonical keys) and the Layer-2 facets declared on a
Type::Value subclass; the tightest constraint per key wins.
Instance Method Summary collapse
-
#effective_restriction_facets(resolved_type) ⇒ Object
Effective facet set for schema emission: the validator's merge plus the pre-#191
values:/pattern:options. -
#validate_restriction_configuration!(resolved_type) ⇒ Object
Verify the effective facets are applicable to the resolved type.
-
#validate_restriction_values!(value, resolved_type) ⇒ Object
Enforce the effective facets against the value, translating the reused validator's Type::* errors into model-level errors that carry the attribute name so
validatecan collect them.
Instance Method Details
#effective_restriction_facets(resolved_type) ⇒ Object
Effective facet set for schema emission: the validator's merge plus the
pre-#191 values:/pattern: options. Those are enforced at runtime by
a separate path (so they are absent from the validation facet set); fold
them in here so the exported XSD is not weaker than what is enforced.
79 80 81 82 83 84 85 86 87 88 |
# File 'lib/lutaml/model/restriction_validation.rb', line 79 def effective_restriction_facets(resolved_type) facets = effective_facets(resolved_type) facets = merge_values_option(facets, resolved_type) if @options.key?(:values) facets = merge_pattern_option(facets) if @options.key?(:pattern) # Folding in the values: option can empty an enumeration (a disjoint # set enforced by both layers); that is an unsatisfiable restriction, # not an unrestricted one, so reject it as the merged interval does. reject_empty_enumeration!(facets) facets end |
#validate_restriction_configuration!(resolved_type) ⇒ Object
Verify the effective facets are applicable to the resolved type. The type is only known after register resolution, so this runs at validation time and raises ahead of the value checks.
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/lutaml/model/restriction_validation.rb', line 20 def validate_restriction_configuration!(resolved_type) facets = effective_facets(resolved_type) if @options.key?(:signed) && !numeric_type?(resolved_type) raise ArgumentError, "Invalid options for `#{name}`: " \ "`signed` is only allowed for numeric types" end if ordered_facets?(facets) && !ordered_type?(resolved_type) raise ArgumentError, "Invalid options for `#{name}`: " \ "`min`, `max`, `inclusive` and `exclusive` are only allowed " \ "for numeric types or temporal (date/time) types" end if length_facets?(facets) && !string_type?(resolved_type) raise ArgumentError, "Invalid options for `#{name}`: " \ "`min_length` and `max_length` are only allowed for :string type" end if facets.key?(:pattern) && !string_type?(resolved_type) raise ArgumentError, "Invalid options for `#{name}`: " \ "`pattern` is only allowed for string-derived types" end if digit_facets?(facets) && !digit_type?(resolved_type) raise ArgumentError, "Invalid options for `#{name}`: " \ "`total_digits` and `fraction_digits` are only allowed " \ "for :integer and :decimal types" end end |
#validate_restriction_values!(value, resolved_type) ⇒ Object
Enforce the effective facets against the value, translating the reused
validator's Type::* errors into model-level errors that carry the
attribute name so validate can collect them.
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/lutaml/model/restriction_validation.rb', line 59 def validate_restriction_values!(value, resolved_type) facets = effective_facets(resolved_type) return if facets.empty? return if value.nil? || Utils.uninitialized?(value) unless collection? && collection_instance?(value) return validate_element_facets!(value, resolved_type, facets) end value.each do |element| next if element.nil? || Utils.uninitialized?(element) validate_element_facets!(element, resolved_type, facets) end end |