File: allof.rb

package info (click to toggle)
ruby-json-schema 6.0.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 472 kB
  • sloc: ruby: 2,494; makefile: 4
file content (66 lines) | stat: -rw-r--r-- 2,950 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
55
56
57
58
59
60
61
62
63
64
65
66
require 'json-schema/attribute'

module JSON
  class Schema
    class AllOfAttribute < Attribute
      def self.validate(current_schema, data, fragments, processor, validator, options = {})
        # Create an hash to hold errors that are generated during validation
        errors = Hash.new { |hsh, k| hsh[k] = [] }
        valid = true
        message = nil

        current_schema.schema['allOf'].each_with_index do |element, schema_index|
          schema = JSON::Schema.new(element, current_schema.uri, validator)

          # We're going to add a little cruft here to try and maintain any validation errors that occur in the allOf
          # We'll handle this by keeping an error count before and after validation, extracting those errors and pushing them onto an error array
          pre_validation_error_count = validation_errors(processor).count

          begin
            # Cannot raise if noAdditionalProperties is true, we need to
            # evaluate each sub schema within the allOf, before raising.
            if options[:noAdditionalProperties] == true
              schema.validate(data, fragments, processor, options.merge(record_errors: true))
            else
              schema.validate(data, fragments, processor, options)
            end
          rescue ValidationError => e
            valid = false
            message = e.message
          end

          diff = validation_errors(processor).count - pre_validation_error_count

          while diff > 0
            diff -= 1
            errors["allOf ##{schema_index}"].push(validation_errors(processor).pop)
          end
        end

        # Find any properties that are missing across all subschemas.
        common_missing_properties = {}
        if options[:noAdditionalProperties] == true && !errors.empty?
          all_property_errors = errors.values.flatten.map(&:properties)
          common_missing_properties = (all_property_errors.first || []).to_set

          all_property_errors[1..].each do |curr_property_errors|
            common_missing_properties &= curr_property_errors.to_set
          end
        end

        # PropertiesV4Attribute represents errors that would indicate an
        # additional property was detected. If we filter these out, we should
        # be left with errors that are not dependent on any other sub schema.
        non_missing_property_errors = errors.values.flatten.reject do |error|
          error.failed_attribute == JSON::Schema::PropertiesV4Attribute
        end

        if !valid || !non_missing_property_errors.empty? || !common_missing_properties.empty?
          message ||= "The property '#{build_fragment(fragments)}' of type #{type_of_data(data)} did not match all of the required schemas"
          validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
          validation_errors(processor).last.sub_errors = errors
        end
      end
    end
  end
end