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 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
# frozen_string_literal: true
module JSONSchemer
module Draft202012
module Vocab
module Core
class Schema < Keyword
def parse
schema.meta_schema = if value == schema.base_uri.to_s
schema
else
META_SCHEMAS_BY_BASE_URI_STR[value] || root.resolve_ref(URI(value))
end
value
end
end
class Vocabulary < Keyword
def parse
value.each_with_object({}) do |(vocabulary, required), out|
if VOCABULARIES.key?(vocabulary)
out[vocabulary] = VOCABULARIES.fetch(vocabulary)
elsif required
raise UnknownVocabulary, vocabulary
end
end.tap do |vocabularies|
schema.keywords = vocabularies.sort_by do |vocabulary, _keywords|
VOCABULARY_ORDER.fetch(vocabulary, Float::INFINITY)
end.each_with_object({}) do |(_vocabulary, keywords), out|
out.merge!(keywords)
end
schema.keyword_order = schema.keywords.transform_values.with_index { |_keyword_class, index| index }
end
end
end
class Id < Keyword
def parse
URI.join(schema.base_uri, value).tap do |uri|
schema.base_uri = uri
root.resources[:lexical][uri] = schema
end
end
end
class Anchor < Keyword
def parse
URI.join(schema.base_uri, "##{value}").tap do |uri|
root.resources[:lexical][uri] = schema
end
end
end
class Ref < Keyword
def self.exclusive?
false
end
def ref_uri
@ref_uri ||= URI.join(schema.base_uri, value)
end
def ref_schema
@ref_schema ||= root.resolve_ref(ref_uri)
end
def validate(instance, instance_location, keyword_location, context)
ref_schema.validate_instance(instance, instance_location, keyword_location, context)
end
end
class DynamicAnchor < Keyword
def parse
URI.join(schema.base_uri, "##{value}").tap do |uri|
root.resources[:lexical][uri] = schema
root.resources[:dynamic][uri] = schema
end
end
end
class DynamicRef < Keyword
def ref_uri
@ref_uri ||= URI.join(schema.base_uri, value)
end
def ref_schema
@ref_schema ||= root.resolve_ref(ref_uri)
end
def dynamic_anchor
return @dynamic_anchor if defined?(@dynamic_anchor)
fragment = ref_schema.parsed['$dynamicAnchor']&.parsed&.fragment
@dynamic_anchor = (fragment == ref_uri.fragment ? fragment : nil)
end
def validate(instance, instance_location, keyword_location, context)
schema = ref_schema
if dynamic_anchor
context.dynamic_scope.each do |ancestor|
dynamic_uri = URI.join(ancestor.base_uri, "##{dynamic_anchor}")
if ancestor.root.resources.fetch(:dynamic).key?(dynamic_uri)
schema = ancestor.root.resources.fetch(:dynamic).fetch(dynamic_uri)
break
end
end
end
schema.validate_instance(instance, instance_location, keyword_location, context)
end
end
class Defs < Keyword
def parse
value.each_with_object({}) do |(key, subschema), out|
out[key] = subschema(subschema, key)
end
end
end
class Comment < Keyword; end
class XError < Keyword
def message(error_key)
value.is_a?(Hash) ? (value[error_key] || value[CATCHALL]) : value
end
end
class UnknownKeyword < Keyword
def parse
if value.is_a?(Hash)
{}
elsif value.is_a?(Array)
[]
else
value
end
end
def fetch(token)
if value.is_a?(Hash)
parsed[token] ||= JSONSchemer::Schema::UNKNOWN_KEYWORD_CLASS.new(value.fetch(token), self, token, schema)
elsif value.is_a?(Array)
parsed[token.to_i] ||= JSONSchemer::Schema::UNKNOWN_KEYWORD_CLASS.new(value.fetch(token.to_i), self, token, schema)
else
raise KeyError.new(:receiver => parsed, :key => token)
end
end
def parsed_schema
@parsed_schema ||= subschema(value)
end
def validate(instance, instance_location, keyword_location, _context)
result(instance, instance_location, keyword_location, true, :annotation => value)
end
end
end
end
end
end
|