Class: JDDF::Schema

Inherits:
Struct
  • Object
show all
Defined in:
lib/jddf/schema.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.from_json(hash) ⇒ Object

Raises:

  • (TypeError.new)


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
# File 'lib/jddf/schema.rb', line 37

def self.from_json(hash)
  raise TypeError.new, 'hash must be a Hash' unless hash.is_a?(Hash)

  schema = Schema.new

  if hash.include?('definitions')
    unless hash['definitions'].is_a?(Hash)
      raise TypeError, 'definitions not Hash'
    end

    schema.definitions = hash['definitions'].map do |key, schema|
      [key, from_json(schema)]
    end.to_h
  end

  if hash.include?('ref')
    raise TypeError, 'ref not String' unless hash['ref'].is_a?(String)

    schema.ref = hash['ref']
  end

  if hash.include?('type')
    raise TypeError, 'type not String' unless hash['type'].is_a?(String)

    unless TYPES.map(&:to_s).include?(hash['type'])
      raise TypeError, "type not in #{TYPES}"
    end

    schema.type = hash['type'].to_sym
  end

  if hash.include?('enum')
    raise TypeError, 'enum not Array' unless hash['enum'].is_a?(Array)
    raise ArgumentError, 'enum is empty array' if hash['enum'].empty?

    hash['enum'].each do |value|
      raise TypeError, 'enum element not String' unless value.is_a?(String)
    end

    schema.enum = hash['enum'].to_set

    if schema.enum.size != hash['enum'].size
      raise ArgumentError, 'enum contains duplicates'
    end
  end

  if hash.include?('elements')
    raise TypeError, 'elements not Hash' unless hash['elements'].is_a?(Hash)

    schema.elements = from_json(hash['elements'])
  end

  if hash.include?('properties')
    unless hash['properties'].is_a?(Hash)
      raise TypeError, 'properties not Hash'
    end

    schema.properties = hash['properties'].map do |key, schema|
      [key, from_json(schema)]
    end.to_h
  end

  if hash.include?('optionalProperties')
    unless hash['optionalProperties'].is_a?(Hash)
      raise TypeError, 'optionalProperties not Hash'
    end

    optional_properties = hash['optionalProperties'].map do |key, schema|
      [key, from_json(schema)]
    end.to_h

    schema.optional_properties = optional_properties
  end

  if hash.include?('additionalProperties')
    unless [true, false].include?(hash['additionalProperties'])
      raise TypeError, 'additionalProperties not boolean'
    end

    schema.additional_properties = hash['additionalProperties']
  end

  if hash.include?('values')
    raise TypeError, 'values not Hash' unless hash['values'].is_a?(Hash)

    schema.values = from_json(hash['values'])
  end

  if hash.include?('discriminator')
    unless hash['discriminator'].is_a?(Hash)
      raise TypeError, 'discriminator not Hash'
    end

    schema.discriminator = Discriminator.from_json(hash['discriminator'])
  end

  schema
end

Instance Method Details

#formObject



136
137
138
139
140
141
142
143
144
145
146
# File 'lib/jddf/schema.rb', line 136

def form
  return :ref if ref
  return :type if type
  return :enum if enum
  return :elements if elements
  return :properties if properties || optional_properties
  return :values if values
  return :discriminator if discriminator

  :empty
end

#verify(root = self) ⇒ Object



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/jddf/schema.rb', line 148

def verify(root = self)
  empty = true

  if ref
    empty = false

    unless root.definitions&.keys&.include?(ref)
      raise ArgumentError, 'reference to non-existent definition'
    end
  end

  if type
    raise ArgumentError, 'invalid form' unless empty

    empty = false
  end

  if enum
    raise ArgumentError, 'invalid form' unless empty

    empty = false
  end

  if elements
    raise ArgumentError, 'invalid form' unless empty

    empty = false

    elements.verify(root)
  end

  if properties || optional_properties
    raise ArgumentError, 'invalid form' unless empty

    empty = false

    properties&.values&.each { |schema| schema.verify(root) }
    optional_properties&.values&.each { |schema| schema.verify(root) }
  end

  if values
    raise ArgumentError, 'invalid form' unless empty

    empty = false

    values.verify(root)
  end

  if properties && optional_properties
    unless (properties.keys & optional_properties.keys).empty?
      raise ArgumentError, 'properties and optional_properties share key'
    end
  end

  if discriminator
    raise ArgumentError, 'invalid form' unless empty

    discriminator.mapping.values.each do |schema|
      schema.verify(root)

      unless schema.form == :properties
        raise ArgumentError, 'mapping value not of properties form'
      end

      if schema&.properties&.include?(discriminator.tag) ||
         schema&.optional_properties&.include?(discriminator.tag)
        raise ArgumentError, 'tag appears in mapping properties'
      end
    end
  end

  self
end