@@ -203,25 +203,125 @@ private boolean doValidate(ExecutionContext executionContext, SetView<Validation
203203
204204 @ Override
205205 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+ }
213234 }
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+ }
219323 }
220- doWalk (executionContext , validationMessages , i , n , rootNode , instanceLocation , shouldValidateSchema );
221- i ++;
222324 }
223- } else {
224- doWalk (executionContext , validationMessages , 0 , node , rootNode , instanceLocation , shouldValidateSchema );
225325 }
226326 return validationMessages ;
227327 }
@@ -237,36 +337,14 @@ private static JsonNode getDefaultNode(JsonSchema schema) {
237337 return result ;
238338 }
239339
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-
262340 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 ,
265343 node , rootNode , instanceLocation , walkSchema , this );
266344 if (executeWalk ) {
267345 validationMessages .addAll (walkSchema .walk (executionContext , node , rootNode , instanceLocation , shouldValidateSchema ));
268346 }
269- this .validationContext .getConfig ().getItemWalkListenerRunner ().runPostWalkListeners (executionContext , ValidatorTypeCode . ITEMS . getValue () , node , rootNode ,
347+ this .validationContext .getConfig ().getItemWalkListenerRunner ().runPostWalkListeners (executionContext , keyword , node , rootNode ,
270348 instanceLocation , walkSchema , this , validationMessages );
271349
272350 }
0 commit comments