json_schema 0.0.14 → 0.0.15

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.
@@ -7,42 +7,20 @@ module JsonSchema
7
7
  # reference to the top-level schema before doing anything else.
8
8
  class DocumentStore
9
9
  def initialize
10
- @uri_map = {}
11
- end
12
-
13
- def add_pointer_reference(uri, path, schema)
14
- raise "can't add nil URI" if uri.nil?
15
-
16
- if !@uri_map[uri][:pointer_map].key?(path)
17
- @uri_map[uri][:pointer_map][path] = schema
18
- end
10
+ @schema_map = {}
19
11
  end
20
12
 
21
13
  def add_uri_reference(uri, schema)
22
14
  raise "can't add nil URI" if uri.nil?
23
-
24
- # Children without an ID keep the same URI as their parents. So since we
25
- # traverse trees from top to bottom, just keep the first reference.
26
- if !@uri_map.key?(uri)
27
- @uri_map[uri] = {
28
- pointer_map: {
29
- JsonReference.reference("#").to_s => schema
30
- },
31
- schema: schema
32
- }
33
- end
15
+ @schema_map[uri] = schema
34
16
  end
35
17
 
36
- def lookup_pointer(uri, pointer)
37
- @uri_map[uri][:pointer_map][pointer]
18
+ def each
19
+ @schema_map.each { |k, v| yield(k, v) }
38
20
  end
39
21
 
40
22
  def lookup_uri(uri)
41
- if @uri_map[uri]
42
- @uri_map[uri][:schema]
43
- else
44
- nil
45
- end
23
+ @schema_map[uri]
46
24
  end
47
25
  end
48
26
  end
@@ -182,7 +182,7 @@ module JsonSchema
182
182
 
183
183
  if l["targetSchema"]
184
184
  link.target_schema =
185
- parse_data(l["schema"], schema, "links/#{i}/targetSchema")
185
+ parse_data(l["targetSchema"], schema, "links/#{i}/targetSchema")
186
186
  end
187
187
 
188
188
  link
@@ -3,13 +3,22 @@ require "set"
3
3
  module JsonSchema
4
4
  class ReferenceExpander
5
5
  attr_accessor :errors
6
+ attr_accessor :store
6
7
 
7
8
  def expand(schema, options = {})
8
- @errors = []
9
- @schema = schema
10
- @store = options[:store] ||= DocumentStore.new
9
+ @errors = []
10
+ @local_store = DocumentStore.new
11
+ @schema = schema
12
+ @schema_paths = {}
13
+ @store = options[:store] || DocumentStore.new
14
+ @uri = URI.parse(schema.uri)
15
+
16
+ @store.each do |uri, store_schema|
17
+ build_schema_paths(uri, store_schema)
18
+ end
11
19
 
12
- @store.add_uri_reference("/", schema)
20
+ # we run #to_s on lookup for URIs; the #to_s of nil is ""
21
+ build_schema_paths("", schema)
13
22
 
14
23
  traverse_schema(schema)
15
24
 
@@ -31,6 +40,34 @@ module JsonSchema
31
40
 
32
41
  private
33
42
 
43
+ def add_reference(schema)
44
+ uri = URI.parse(schema.uri)
45
+ if uri.absolute?
46
+ @store.add_uri_reference(schema.uri, schema)
47
+ else
48
+ @local_store.add_uri_reference(schema.uri, schema)
49
+ end
50
+ end
51
+
52
+ def build_schema_paths(uri, schema)
53
+ return if schema.reference
54
+
55
+ paths = @schema_paths[uri] ||= {}
56
+ paths[schema.pointer] = schema
57
+
58
+ schema_children(schema).each do |subschema|
59
+ build_schema_paths(uri, subschema)
60
+ end
61
+
62
+ # Also insert alternate tree for schema's custom URI. O(crazy).
63
+ if schema.uri != uri
64
+ fragment, parent = schema.fragment, schema.parent
65
+ schema.fragment, schema.parent = "#", nil
66
+ build_schema_paths(schema.uri, schema)
67
+ schema.fragment, schema.parent = fragment, parent
68
+ end
69
+ end
70
+
34
71
  def dereference(ref_schema, ref_stack)
35
72
  ref = ref_schema.reference
36
73
 
@@ -69,11 +106,23 @@ module JsonSchema
69
106
  true
70
107
  end
71
108
 
72
- def resolve_pointer(ref_schema, uri_path, resolved_schema)
109
+ def lookup_pointer(uri, pointer)
110
+ paths = @schema_paths[uri.to_s] ||= {}
111
+ paths[pointer]
112
+ end
113
+
114
+ def lookup_reference(uri)
115
+ if uri.absolute?
116
+ @store.lookup_uri(uri.to_s)
117
+ else
118
+ @local_store.lookup_uri(uri.to_s)
119
+ end
120
+ end
121
+
122
+ def resolve_pointer(ref_schema, resolved_schema)
73
123
  ref = ref_schema.reference
74
124
 
75
- # we've already evaluated this precise URI/pointer combination before
76
- if !(new_schema = @store.lookup_pointer(uri_path, ref.pointer.to_s))
125
+ if !(new_schema = lookup_pointer(ref.uri, ref.pointer))
77
126
  data = JsonPointer.evaluate(resolved_schema.data, ref.pointer)
78
127
 
79
128
  # couldn't resolve pointer within known schema; that's an error
@@ -83,18 +132,17 @@ module JsonSchema
83
132
  return
84
133
  end
85
134
 
86
- # parse a new schema and use the same parent node
135
+ # Parse a new schema and use the same parent node. Basically this is
136
+ # exclusively for the case of a reference that needs to be
137
+ # de-referenced again to be resolved.
138
+ # TODO: Fix to never parse.
87
139
  new_schema = Parser.new.parse(data, ref_schema.parent)
88
-
89
- # add the reference into our document store right away; it will
90
- # eventually be fully expanded
91
- @store.add_pointer_reference(uri_path, ref.pointer.to_s, new_schema)
140
+ build_schema_paths(ref.uri, resolved_schema)
92
141
  else
93
142
  # insert a clone record so that the expander knows to expand it when
94
143
  # the schema traversal is finished
95
144
  new_schema.clones << ref_schema
96
145
  end
97
-
98
146
  new_schema
99
147
  end
100
148
 
@@ -107,7 +155,7 @@ module JsonSchema
107
155
  # allow resolution if something we've already parsed has claimed the
108
156
  # full URL
109
157
  if @store.lookup_uri(uri.to_s)
110
- resolve_uri(ref_schema, uri.to_s)
158
+ resolve_uri(ref_schema, uri)
111
159
  else
112
160
  message =
113
161
  %{Reference resolution over #{scheme} is not currently supported.}
@@ -116,23 +164,24 @@ module JsonSchema
116
164
  end
117
165
  # absolute
118
166
  elsif uri && uri.path[0] == "/"
119
- resolve_uri(ref_schema, uri.path)
167
+ resolve_uri(ref_schema, uri)
120
168
  # relative
121
169
  elsif uri
122
170
  # build an absolute path using the URI of the current schema
171
+ # TODO: fix this. References don't get URIs which might be an error.
123
172
  schema_uri = ref_schema.uri.chomp("/")
124
- resolve_uri(ref_schema, schema_uri + "/" + uri.path)
173
+ resolve_uri(ref_schema, URI.parse(schema_uri + "/" + uri.path))
125
174
  # just a JSON Pointer -- resolve against schema root
126
175
  else
127
- resolve_pointer(ref_schema, "/", @schema)
176
+ resolve_pointer(ref_schema, @schema)
128
177
  end
129
178
  end
130
179
 
131
- def resolve_uri(ref_schema, uri_path)
132
- if schema = @store.lookup_uri(uri_path)
133
- resolve_pointer(ref_schema, uri_path, schema)
180
+ def resolve_uri(ref_schema, uri)
181
+ if schema = lookup_reference(uri)
182
+ resolve_pointer(ref_schema, schema)
134
183
  else
135
- message = %{Couldn't resolve URI: #{uri_path}.}
184
+ message = %{Couldn't resolve URI: #{uri.to_s}.}
136
185
  @errors << SchemaError.new(ref_schema, message)
137
186
  nil
138
187
  end
@@ -195,15 +244,14 @@ module JsonSchema
195
244
  end
196
245
 
197
246
  def traverse_schema(schema)
198
- @store.add_uri_reference(schema.uri, schema)
247
+ add_reference(schema)
199
248
 
200
249
  schema_children(schema).each do |subschema|
201
250
  if subschema.reference && !subschema.expanded?
202
251
  dereference(subschema, [])
203
252
  end
204
253
 
205
- # traverse child schemas only if they're the original copy
206
- if subschema.expanded? && subschema.original?
254
+ if !subschema.reference
207
255
  traverse_schema(subschema)
208
256
  end
209
257
  end
@@ -22,7 +22,7 @@ describe JsonSchema::ReferenceExpander do
22
22
  it "takes a document store" do
23
23
  store = JsonSchema::DocumentStore.new
24
24
  expand(store: store)
25
- assert store.lookup_uri("/")
25
+ assert_equal store, @expander.store
26
26
  end
27
27
 
28
28
  it "will expand anyOf" do
@@ -155,7 +155,7 @@ describe JsonSchema::ReferenceExpander do
155
155
 
156
156
  # the *reference* schema should have expanded a pointer
157
157
  schema = @schema.properties["app"].properties["name"]
158
- assert_equal "#/properties/app/properties/name", schema.pointer
158
+ assert_equal "#/definitions/app/properties/name", schema.pointer
159
159
  end
160
160
 
161
161
  # clones are special in that they retain their original pointer despite where
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: json_schema
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.14
4
+ version: 0.0.15
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors: