@@ -61,7 +61,7 @@ public class SchemaLoader {
61
61
*/
62
62
@ FunctionalInterface
63
63
private interface CombinedSchemaProvider
64
- extends Function <Collection <Schema >, CombinedSchema .Builder > {
64
+ extends Function <Collection <Schema >, CombinedSchema .Builder > {
65
65
66
66
}
67
67
@@ -115,7 +115,7 @@ public static Schema load(final JSONObject schemaJson) {
115
115
public static Schema load (final JSONObject schemaJson , final SchemaClient httpClient ) {
116
116
String schemaId = schemaJson .optString ("id" );
117
117
return new SchemaLoader (schemaId , schemaJson , schemaJson , new HashMap <>(), httpClient )
118
- .load ().build ();
118
+ .load ().build ();
119
119
}
120
120
121
121
private final SchemaClient httpClient ;
@@ -143,29 +143,29 @@ public static Schema load(final JSONObject schemaJson, final SchemaClient httpCl
143
143
144
144
private void addDependencies (final Builder builder , final JSONObject deps ) {
145
145
Arrays .stream (JSONObject .getNames (deps ))
146
- .forEach (ifPresent -> addDependency (builder , ifPresent , deps .get (ifPresent )));
146
+ .forEach (ifPresent -> addDependency (builder , ifPresent , deps .get (ifPresent )));
147
147
}
148
148
149
149
private void addDependency (final Builder builder , final String ifPresent , final Object deps ) {
150
150
typeMultiplexer (deps )
151
- .ifObject ().then (obj -> {
152
- builder .schemaDependency (ifPresent , loadChild (obj ).build ());
153
- })
154
- .ifIs (JSONArray .class ).then (propNames -> {
155
- IntStream .range (0 , propNames .length ())
156
- .mapToObj (i -> propNames .getString (i ))
157
- .forEach (dependency -> builder .propertyDependency (ifPresent , dependency ));
158
- }).requireAny ();
151
+ .ifObject ().then (obj -> {
152
+ builder .schemaDependency (ifPresent , loadChild (obj ).build ());
153
+ })
154
+ .ifIs (JSONArray .class ).then (propNames -> {
155
+ IntStream .range (0 , propNames .length ())
156
+ .mapToObj (i -> propNames .getString (i ))
157
+ .forEach (dependency -> builder .propertyDependency (ifPresent , dependency ));
158
+ }).requireAny ();
159
159
}
160
160
161
161
private void addPropertySchemaDefinition (final String keyOfObj , final Object definition ,
162
162
final ObjectSchema .Builder builder ) {
163
163
typeMultiplexer (definition )
164
- .ifObject ()
165
- .then (obj -> {
166
- builder .addPropertySchema (keyOfObj , loadChild (obj ).build ());
167
- })
168
- .requireAny ();
164
+ .ifObject ()
165
+ .then (obj -> {
166
+ builder .addPropertySchema (keyOfObj , loadChild (obj ).build ());
167
+ })
168
+ .requireAny ();
169
169
}
170
170
171
171
private CombinedSchema .Builder buildAnyOfSchemaForMultipleTypes () {
@@ -188,15 +188,15 @@ private ArraySchema.Builder buildArraySchema() {
188
188
ifPresent ("uniqueItems" , Boolean .class , builder ::uniqueItems );
189
189
if (schemaJson .has ("additionalItems" )) {
190
190
typeMultiplexer ("additionalItems" , schemaJson .get ("additionalItems" ))
191
- .ifIs (Boolean .class ).then (builder ::additionalItems )
192
- .ifObject ().then (jsonObj -> builder .schemaOfAdditionalItems (loadChild (jsonObj ).build ()))
193
- .requireAny ();
191
+ .ifIs (Boolean .class ).then (builder ::additionalItems )
192
+ .ifObject ().then (jsonObj -> builder .schemaOfAdditionalItems (loadChild (jsonObj ).build ()))
193
+ .requireAny ();
194
194
}
195
195
if (schemaJson .has ("items" )) {
196
196
typeMultiplexer ("items" , schemaJson .get ("items" ))
197
- .ifObject ().then (itemSchema -> builder .allItemSchema (loadChild (itemSchema ).build ()))
198
- .ifIs (JSONArray .class ).then (arr -> buildTupleSchema (builder , arr ))
199
- .requireAny ();
197
+ .ifObject ().then (itemSchema -> builder .allItemSchema (loadChild (itemSchema ).build ()))
198
+ .ifIs (JSONArray .class ).then (arr -> buildTupleSchema (builder , arr ))
199
+ .requireAny ();
200
200
}
201
201
return builder ;
202
202
}
@@ -205,8 +205,8 @@ private EnumSchema.Builder buildEnumSchema() {
205
205
Set <Object > possibleValues = new HashSet <>();
206
206
JSONArray arr = schemaJson .getJSONArray ("enum" );
207
207
IntStream .range (0 , arr .length ())
208
- .mapToObj (arr ::get )
209
- .forEach (possibleValues ::add );
208
+ .mapToObj (arr ::get )
209
+ .forEach (possibleValues ::add );
210
210
return EnumSchema .builder ().possibleValues (possibleValues );
211
211
}
212
212
@@ -231,21 +231,21 @@ private ObjectSchema.Builder buildObjectSchema() {
231
231
ifPresent ("maxProperties" , Integer .class , builder ::maxProperties );
232
232
if (schemaJson .has ("properties" )) {
233
233
typeMultiplexer (schemaJson .get ("properties" ))
234
- .ifObject ().then (propertyDefs -> {
235
- populatePropertySchemas (propertyDefs , builder );
236
- }).requireAny ();
234
+ .ifObject ().then (propertyDefs -> {
235
+ populatePropertySchemas (propertyDefs , builder );
236
+ }).requireAny ();
237
237
}
238
238
if (schemaJson .has ("additionalProperties" )) {
239
239
typeMultiplexer ("additionalProperties" , schemaJson .get ("additionalProperties" ))
240
- .ifIs (Boolean .class ).then (builder ::additionalProperties )
241
- .ifObject ().then (def -> builder .schemaOfAdditionalProperties (loadChild (def ).build ()))
242
- .requireAny ();
240
+ .ifIs (Boolean .class ).then (builder ::additionalProperties )
241
+ .ifObject ().then (def -> builder .schemaOfAdditionalProperties (loadChild (def ).build ()))
242
+ .requireAny ();
243
243
}
244
244
if (schemaJson .has ("required" )) {
245
245
JSONArray requiredJson = schemaJson .getJSONArray ("required" );
246
246
IntStream .range (0 , requiredJson .length ())
247
- .mapToObj (requiredJson ::getString )
248
- .forEach (builder ::addRequiredProperty );
247
+ .mapToObj (requiredJson ::getString )
248
+ .forEach (builder ::addRequiredProperty );
249
249
}
250
250
if (schemaJson .has ("patternProperties" )) {
251
251
JSONObject patternPropsJson = schemaJson .getJSONObject ("patternProperties" );
@@ -266,7 +266,7 @@ private Schema.Builder<?> buildSchemaWithoutExplicitType() {
266
266
return EmptySchema .builder ();
267
267
}
268
268
if (schemaJson .has ("$ref" )) {
269
- return lookupReference (schemaJson .getString ("$ref" ));
269
+ return lookupReference (schemaJson .getString ("$ref" ), schemaJson );
270
270
}
271
271
Schema .Builder <?> rval = sniffSchemaByProps ();
272
272
if (rval != null ) {
@@ -289,11 +289,28 @@ private StringSchema.Builder buildStringSchema() {
289
289
private void buildTupleSchema (final ArraySchema .Builder builder , final JSONArray itemSchema ) {
290
290
for (int i = 0 ; i < itemSchema .length (); ++i ) {
291
291
typeMultiplexer (itemSchema .get (i ))
292
- .ifObject ().then (schema -> builder .addItemSchema (loadChild (schema ).build ()))
293
- .requireAny ();
292
+ .ifObject ().then (schema -> builder .addItemSchema (loadChild (schema ).build ()))
293
+ .requireAny ();
294
294
}
295
295
}
296
296
297
+ JSONObject extend (final JSONObject additional , final JSONObject original ) {
298
+ String [] additionalNames = JSONObject .getNames (additional );
299
+ if (additionalNames == null ) {
300
+ return original ;
301
+ }
302
+ String [] originalNames = JSONObject .getNames (original );
303
+ if (originalNames == null ) {
304
+ return additional ;
305
+ }
306
+ JSONObject rval = new JSONObject ();
307
+ Arrays .stream (originalNames )
308
+ .forEach (name -> rval .put (name , original .get (name )));
309
+ Arrays .stream (additionalNames )
310
+ .forEach (name -> rval .put (name , additional .get (name )));
311
+ return rval ;
312
+ }
313
+
297
314
private <E > void ifPresent (final String key , final Class <E > expectedType ,
298
315
final Consumer <E > consumer ) {
299
316
if (schemaJson .has (key )) {
@@ -373,22 +390,23 @@ private Schema.Builder<?> loadForType(final Object type) {
373
390
/**
374
391
* Returns a schema builder instance after looking up the JSON pointer.
375
392
*/
376
- private Schema .Builder <?> lookupReference (final String relPointerString ) {
393
+ private Schema .Builder <?> lookupReference (final String relPointerString , final JSONObject context ) {
377
394
String absPointerString = ReferenceResolver .resolve (id , relPointerString );
378
395
if (pointerSchemas .containsKey (absPointerString )) {
379
396
return pointerSchemas .get (absPointerString );
380
397
}
381
398
JSONPointer pointer = absPointerString .startsWith ("#" )
382
399
? JSONPointer .forDocument (rootSchemaJson , absPointerString )
383
- : JSONPointer .forURL (httpClient , absPointerString );
384
- ReferenceSchema .Builder refBuilder = ReferenceSchema .builder ();
385
- pointerSchemas .put (absPointerString , refBuilder );
386
- QueryResult result = pointer .query ();
387
- SchemaLoader childLoader = new SchemaLoader (id , result .getQueryResult (),
388
- result .getContainingDocument (), pointerSchemas , httpClient );
389
- Schema referredSchema = childLoader .load ().build ();
390
- refBuilder .build ().setReferredSchema (referredSchema );
391
- return refBuilder ;
400
+ : JSONPointer .forURL (httpClient , absPointerString );
401
+ ReferenceSchema .Builder refBuilder = ReferenceSchema .builder ();
402
+ pointerSchemas .put (absPointerString , refBuilder );
403
+ QueryResult result = pointer .query ();
404
+ JSONObject resultObject = extend (context , result .getQueryResult ());
405
+ SchemaLoader childLoader = new SchemaLoader (id , resultObject ,
406
+ result .getContainingDocument (), pointerSchemas , httpClient );
407
+ Schema referredSchema = childLoader .load ().build ();
408
+ refBuilder .build ().setReferredSchema (referredSchema );
409
+ return refBuilder ;
392
410
}
393
411
394
412
private void populatePropertySchemas (final JSONObject propertyDefs ,
0 commit comments