@@ -203,25 +203,125 @@ private boolean doValidate(ExecutionContext executionContext, SetView<Validation
203
203
204
204
@ Override
205
205
public Set <ValidationMessage > walk (ExecutionContext executionContext , JsonNode node , JsonNode rootNode , JsonNodePath instanceLocation , boolean shouldValidateSchema ) {
206
- HashSet <ValidationMessage > validationMessages = new LinkedHashSet <>();
207
- if (node instanceof ArrayNode ) {
208
- ArrayNode arrayNode = (ArrayNode ) node ;
209
- JsonNode defaultNode = null ;
210
- if (this .validationContext .getConfig ().getApplyDefaultsStrategy ().shouldApplyArrayDefaults ()
211
- && this .schema != null ) {
212
- defaultNode = getDefaultNode (this .schema );
206
+ Set <ValidationMessage > validationMessages = new LinkedHashSet <>();
207
+ boolean collectAnnotations = collectAnnotations ();
208
+
209
+ // Add items annotation
210
+ if (collectAnnotations || collectAnnotations (executionContext )) {
211
+ if (this .schema != null ) {
212
+ // Applies to all
213
+ executionContext .getAnnotations ()
214
+ .put (JsonNodeAnnotation .builder ().instanceLocation (instanceLocation )
215
+ .evaluationPath (this .evaluationPath ).schemaLocation (this .schemaLocation )
216
+ .keyword (getKeyword ()).value (true ).build ());
217
+ } else if (this .tupleSchema != null ) {
218
+ // Tuples
219
+ int items = node .isArray () ? node .size () : 1 ;
220
+ int schemas = this .tupleSchema .size ();
221
+ if (items > schemas ) {
222
+ // More items than schemas so the keyword only applied to the number of schemas
223
+ executionContext .getAnnotations ()
224
+ .put (JsonNodeAnnotation .builder ().instanceLocation (instanceLocation )
225
+ .evaluationPath (this .evaluationPath ).schemaLocation (this .schemaLocation )
226
+ .keyword (getKeyword ()).value (schemas ).build ());
227
+ } else {
228
+ // Applies to all
229
+ executionContext .getAnnotations ()
230
+ .put (JsonNodeAnnotation .builder ().instanceLocation (instanceLocation )
231
+ .evaluationPath (this .evaluationPath ).schemaLocation (this .schemaLocation )
232
+ .keyword (getKeyword ()).value (true ).build ());
233
+ }
213
234
}
214
- int i = 0 ;
215
- for (JsonNode n : arrayNode ) {
216
- if (n .isNull () && defaultNode != null ) {
217
- arrayNode .set (i , defaultNode );
218
- n = defaultNode ;
235
+ }
236
+
237
+ if (this .schema != null ) {
238
+ // Walk the schema.
239
+ if (node instanceof ArrayNode ) {
240
+ int count = Math .max (1 , node .size ());
241
+ ArrayNode arrayNode = (ArrayNode ) node ;
242
+ JsonNode defaultNode = null ;
243
+ if (this .validationContext .getConfig ().getApplyDefaultsStrategy ().shouldApplyArrayDefaults ()) {
244
+ defaultNode = getDefaultNode (this .schema );
245
+ }
246
+ for (int i = 0 ; i < count ; i ++) {
247
+ JsonNode n = arrayNode .get (i );
248
+ if (n != null ) {
249
+ if (n .isNull () && defaultNode != null ) {
250
+ arrayNode .set (i , defaultNode );
251
+ n = defaultNode ;
252
+ }
253
+ }
254
+ walkSchema (executionContext , this .schema , n , rootNode , instanceLocation .append (i ), shouldValidateSchema , validationMessages , ValidatorTypeCode .ITEMS .getValue ());
255
+ }
256
+ } else {
257
+ walkSchema (executionContext , this .schema , null , rootNode , instanceLocation .append (0 ), shouldValidateSchema , validationMessages , ValidatorTypeCode .ITEMS .getValue ());
258
+ }
259
+ }
260
+ else if (this .tupleSchema != null ) {
261
+ int prefixItems = this .tupleSchema .size ();
262
+ for (int i = 0 ; i < prefixItems ; i ++) {
263
+ // walk tuple schema
264
+ if (node instanceof ArrayNode ) {
265
+ ArrayNode arrayNode = (ArrayNode ) node ;
266
+ JsonNode defaultNode = null ;
267
+ JsonNode n = arrayNode .get (i );
268
+ if (this .validationContext .getConfig ().getApplyDefaultsStrategy ().shouldApplyArrayDefaults ()) {
269
+ defaultNode = getDefaultNode (this .tupleSchema .get (i ));
270
+ }
271
+ if (n != null ) {
272
+ if (n .isNull () && defaultNode != null ) {
273
+ arrayNode .set (i , defaultNode );
274
+ n = defaultNode ;
275
+ }
276
+ }
277
+ walkSchema (executionContext , this .tupleSchema .get (i ), n , rootNode , instanceLocation .append (i ),
278
+ shouldValidateSchema , validationMessages , ValidatorTypeCode .ITEMS .getValue ());
279
+ } else {
280
+ walkSchema (executionContext , this .tupleSchema .get (i ), null , rootNode , instanceLocation .append (i ),
281
+ shouldValidateSchema , validationMessages , ValidatorTypeCode .ITEMS .getValue ());
282
+ }
283
+ }
284
+ if (this .additionalSchema != null ) {
285
+ boolean hasAdditionalItem = false ;
286
+
287
+ int additionalItems = Math .max (1 , (node != null ? node .size () : 0 ) - prefixItems );
288
+ for (int x = 0 ; x < additionalItems ; x ++) {
289
+ int i = x + prefixItems ;
290
+ // walk additional item schema
291
+ if (node instanceof ArrayNode ) {
292
+ ArrayNode arrayNode = (ArrayNode ) node ;
293
+ JsonNode defaultNode = null ;
294
+ JsonNode n = arrayNode .get (i );
295
+ if (this .validationContext .getConfig ().getApplyDefaultsStrategy ().shouldApplyArrayDefaults ()) {
296
+ defaultNode = getDefaultNode (this .additionalSchema );
297
+ }
298
+ if (n != null ) {
299
+ if (n .isNull () && defaultNode != null ) {
300
+ arrayNode .set (i , defaultNode );
301
+ n = defaultNode ;
302
+ }
303
+ }
304
+ walkSchema (executionContext , this .additionalSchema , n , rootNode , instanceLocation .append (i ),
305
+ shouldValidateSchema , validationMessages , PROPERTY_ADDITIONAL_ITEMS );
306
+ if (n != null ) {
307
+ hasAdditionalItem = true ;
308
+ }
309
+ } else {
310
+ walkSchema (executionContext , this .additionalSchema , null , rootNode , instanceLocation .append (i ),
311
+ shouldValidateSchema , validationMessages , PROPERTY_ADDITIONAL_ITEMS );
312
+ }
313
+ }
314
+
315
+ if (hasAdditionalItem ) {
316
+ if (collectAnnotations || collectAnnotations (executionContext , "additionalItems" )) {
317
+ executionContext .getAnnotations ()
318
+ .put (JsonNodeAnnotation .builder ().instanceLocation (instanceLocation )
319
+ .evaluationPath (this .additionalItemsEvaluationPath )
320
+ .schemaLocation (this .additionalItemsSchemaLocation )
321
+ .keyword ("additionalItems" ).value (true ).build ());
322
+ }
219
323
}
220
- doWalk (executionContext , validationMessages , i , n , rootNode , instanceLocation , shouldValidateSchema );
221
- i ++;
222
324
}
223
- } else {
224
- doWalk (executionContext , validationMessages , 0 , node , rootNode , instanceLocation , shouldValidateSchema );
225
325
}
226
326
return validationMessages ;
227
327
}
@@ -237,36 +337,14 @@ private static JsonNode getDefaultNode(JsonSchema schema) {
237
337
return result ;
238
338
}
239
339
240
- private void doWalk (ExecutionContext executionContext , HashSet <ValidationMessage > validationMessages , int i , JsonNode node ,
241
- JsonNode rootNode , JsonNodePath instanceLocation , boolean shouldValidateSchema ) {
242
- if (this .schema != null ) {
243
- // Walk the schema.
244
- walkSchema (executionContext , this .schema , node , rootNode , instanceLocation .append (i ), shouldValidateSchema , validationMessages );
245
- }
246
-
247
- if (this .tupleSchema != null ) {
248
- if (i < this .tupleSchema .size ()) {
249
- // walk tuple schema
250
- walkSchema (executionContext , this .tupleSchema .get (i ), node , rootNode , instanceLocation .append (i ),
251
- shouldValidateSchema , validationMessages );
252
- } else {
253
- if (this .additionalSchema != null ) {
254
- // walk additional item schema
255
- walkSchema (executionContext , this .additionalSchema , node , rootNode , instanceLocation .append (i ),
256
- shouldValidateSchema , validationMessages );
257
- }
258
- }
259
- }
260
- }
261
-
262
340
private void walkSchema (ExecutionContext executionContext , JsonSchema walkSchema , JsonNode node , JsonNode rootNode ,
263
- JsonNodePath instanceLocation , boolean shouldValidateSchema , Set <ValidationMessage > validationMessages ) {
264
- boolean executeWalk = this .validationContext .getConfig ().getItemWalkListenerRunner ().runPreWalkListeners (executionContext , ValidatorTypeCode . ITEMS . getValue () ,
341
+ JsonNodePath instanceLocation , boolean shouldValidateSchema , Set <ValidationMessage > validationMessages , String keyword ) {
342
+ boolean executeWalk = this .validationContext .getConfig ().getItemWalkListenerRunner ().runPreWalkListeners (executionContext , keyword ,
265
343
node , rootNode , instanceLocation , walkSchema , this );
266
344
if (executeWalk ) {
267
345
validationMessages .addAll (walkSchema .walk (executionContext , node , rootNode , instanceLocation , shouldValidateSchema ));
268
346
}
269
- this .validationContext .getConfig ().getItemWalkListenerRunner ().runPostWalkListeners (executionContext , ValidatorTypeCode . ITEMS . getValue () , node , rootNode ,
347
+ this .validationContext .getConfig ().getItemWalkListenerRunner ().runPostWalkListeners (executionContext , keyword , node , rootNode ,
270
348
instanceLocation , walkSchema , this , validationMessages );
271
349
272
350
}
0 commit comments