11package io .swagger .v3 .parser .util ;
22
3+ import static io .swagger .v3 .parser .util .RefUtils .computeDefinitionName ;
4+ import static io .swagger .v3 .parser .util .RefUtils .computeRefFormat ;
5+ import static io .swagger .v3 .parser .util .RefUtils .isAnExternalRefFormat ;
6+
7+ import java .util .ArrayList ;
8+ import java .util .HashMap ;
9+ import java .util .HashSet ;
10+ import java .util .IdentityHashMap ;
11+ import java .util .LinkedHashMap ;
12+ import java .util .List ;
13+ import java .util .Map ;
14+ import java .util .Set ;
15+ import java .util .stream .Collectors ;
16+
317import io .swagger .v3 .oas .models .Components ;
418import io .swagger .v3 .oas .models .OpenAPI ;
519import io .swagger .v3 .oas .models .Operation ;
2236import io .swagger .v3 .parser .models .RefFormat ;
2337import org .slf4j .Logger ;
2438import org .slf4j .LoggerFactory ;
25- import java .util .ArrayList ;
26- import java .util .HashMap ;
27- import java .util .HashSet ;
28- import java .util .IdentityHashMap ;
29- import java .util .LinkedHashMap ;
30- import java .util .List ;
31- import java .util .Map ;
32- import java .util .Set ;
33- import java .util .stream .Collectors ;
34-
35- import static io .swagger .v3 .parser .util .RefUtils .computeDefinitionName ;
36- import static io .swagger .v3 .parser .util .RefUtils .computeRefFormat ;
37- import static io .swagger .v3 .parser .util .RefUtils .isAnExternalRefFormat ;
3839
3940public class ResolverFully {
4041 private static final Logger LOGGER = LoggerFactory .getLogger (ResolverFully .class );
@@ -325,14 +326,7 @@ public Schema resolveSchema(Schema schema) {
325326 Schema innerProperty = obj .getProperties ().get (propertyName );
326327 // reference check
327328 if (schema != innerProperty ) {
328- if (resolvedProperties .get (propertyName ) == null || resolvedProperties .get (propertyName ) != innerProperty ) {
329- LOGGER .debug ("avoiding infinite loop" );
330- Schema resolved = resolveSchema (innerProperty );
331- updated .put (propertyName , resolved );
332- resolvedProperties .put (propertyName , resolved );
333- }else {
334- updated .put (propertyName , resolvedProperties .get (propertyName ));
335- }
329+ updated .put (propertyName , resolveSchemaProperty (propertyName , innerProperty ));
336330 }
337331 }
338332 obj .setProperties (updated );
@@ -341,191 +335,59 @@ public Schema resolveSchema(Schema schema) {
341335 }
342336
343337
344- if (schema instanceof ComposedSchema ) {
338+ Schema result = schema ;
339+
340+ if (schema instanceof ComposedSchema ) {
345341 ComposedSchema composedSchema = (ComposedSchema ) schema ;
346- boolean adjacent = false ;
347- if (aggregateCombinators ) {
348- Schema model = SchemaTypeUtil .createSchema (composedSchema .getType (), composedSchema .getFormat ());
349- Set <String > requiredProperties = new HashSet <>();
350- Set <Object > examples = new HashSet <>();
351342
352- if (( composedSchema .getAllOf () != null && composedSchema . getAnyOf () != null && composedSchema . getOneOf () != null )||
353- ( composedSchema . getAllOf () != null && composedSchema .getAnyOf () != null ) ||
354- ( composedSchema . getAllOf () != null && composedSchema .getOneOf () != null )||
355- ( composedSchema . getOneOf () != null && composedSchema . getAnyOf () != null )){
343+ boolean hasAllOf = composedSchema .getAllOf () != null ;
344+ boolean hasAnyOf = composedSchema .getAnyOf () != null ;
345+ boolean hasOneOf = composedSchema .getOneOf () != null ;
346+ boolean adjacent = ( hasAllOf && hasAnyOf ) || ( hasAllOf && hasOneOf ) || ( hasAnyOf && hasOneOf );
356347
357- adjacent = true ;
348+ if (aggregateCombinators && (hasAllOf || adjacent )) {
349+ Schema combinedModel = SchemaTypeUtil .createSchema (composedSchema .getType (), composedSchema .getFormat ());
350+ Set <Object > examples = new HashSet <>();
358351
352+ if (hasAllOf ) {
353+ aggregateSchemaCombinators (composedSchema , combinedModel , composedSchema .getAllOf (), examples );
359354 }
360-
361- if (composedSchema .getAllOf () != null ) {
362- for (Schema innerModel : composedSchema .getAllOf ()) {
363- Schema resolved = resolveSchema (innerModel );
364- Map <String , Schema > properties = resolved .getProperties ();
365- if (resolved .getProperties () != null ) {
366- for (String key : properties .keySet ()) {
367- Schema prop = (Schema ) resolved .getProperties ().get (key );
368- if (resolvedProperties .get (key ) == null || resolvedProperties .get (key ) != prop ) {
369- LOGGER .debug ("avoiding infinite loop" );
370- Schema resolvedProp = resolveSchema (prop );
371- model .addProperties (key ,resolvedProp );
372- resolvedProperties .put (key , resolvedProp );
373- }else {
374- model .addProperties (key ,resolvedProperties .get (key ));
375- }
376- }
377- if (resolved .getRequired () != null ) {
378- for (int i = 0 ; i < resolved .getRequired ().size (); i ++) {
379- if (resolved .getRequired ().get (i ) != null ) {
380- requiredProperties .add (resolved .getRequired ().get (i ).toString ());
381- }
382- }
383- }
384- }
385- if (requiredProperties .size () > 0 ) {
386- model .setRequired (new ArrayList <>(requiredProperties ));
387- }
388- if (resolved .getExample () != null ) {
389- examples .add (resolved .getExample ());
390- }
391- if (composedSchema .getExtensions () != null ) {
392- Map <String , Object > extensions = composedSchema .getExtensions ();
393- for (String key : extensions .keySet ()) {
394- model .addExtension (key , composedSchema .getExtensions ().get (key ));
395- }
396- }
397- }
398-
399- } if (composedSchema .getOneOf () != null ) {
400- if (adjacent == false ) {
401- Schema resolved ;
402- List <Schema > list = new ArrayList <>();
403- for (Schema innerModel : composedSchema .getOneOf ()) {
404- resolved = resolveSchema (innerModel );
405- list .add (resolved );
406- }
407- composedSchema .setOneOf (list );
408- return composedSchema ;
409- }else {
410- for (Schema innerModel : composedSchema .getOneOf ()) {
411- Schema resolved = resolveSchema (innerModel );
412- Map <String , Schema > properties = resolved .getProperties ();
413- if (resolved .getProperties () != null ) {
414- for (String key : properties .keySet ()) {
415- Schema prop = (Schema ) resolved .getProperties ().get (key );
416- if (resolvedProperties .get (key ) == null || resolvedProperties .get (key ) != prop ) {
417- LOGGER .debug ("avoiding infinite loop" );
418- Schema resolvedProp = resolveSchema (prop );
419- model .addProperties (key ,resolvedProp );
420- resolvedProperties .put (key , resolvedProp );
421- }else {
422- model .addProperties (key ,resolvedProperties .get (key ));
423- }
424- }
425- if (resolved .getRequired () != null ) {
426- for (int i = 0 ; i < resolved .getRequired ().size (); i ++) {
427- if (resolved .getRequired ().get (i ) != null ) {
428- requiredProperties .add (resolved .getRequired ().get (i ).toString ());
429- }
430- }
431- }
432- }
433- if (requiredProperties .size () > 0 ) {
434- model .setRequired (new ArrayList <>(requiredProperties ));
435- }
436- if (resolved .getExample () != null ) {
437- examples .add (resolved .getExample ());
438- }
439- if (composedSchema .getExtensions () != null ) {
440- Map <String , Object > extensions = composedSchema .getExtensions ();
441- for (String key : extensions .keySet ()) {
442- model .addExtension (key , composedSchema .getExtensions ().get (key ));
443- }
444- }
445- }
446- }
447-
448- } if (composedSchema .getAnyOf () != null ) {
449- if (adjacent == false ) {
450- Schema resolved ;
451- List <Schema > list = new ArrayList <>();
452- for (Schema innerModel : composedSchema .getAnyOf ()) {
453- resolved = resolveSchema (innerModel );
454- list .add (resolved );
455- }
456- composedSchema .setAnyOf (list );
457- return composedSchema ;
458- }else {
459- for (Schema innerModel : composedSchema .getAnyOf ()) {
460- Schema resolved = resolveSchema (innerModel );
461- Map <String , Schema > properties = resolved .getProperties ();
462- if (resolved .getProperties () != null ) {
463- for (String key : properties .keySet ()) {
464- Schema prop = (Schema ) resolved .getProperties ().get (key );
465- if (resolvedProperties .get (key ) == null || resolvedProperties .get (key ) != prop ) {
466- LOGGER .debug ("avoiding infinite loop" );
467- Schema resolvedProp = resolveSchema (prop );
468- model .addProperties (key ,resolvedProp );
469- resolvedProperties .put (key , resolvedProp );
470- }else {
471- model .addProperties (key ,resolvedProperties .get (key ));
472- }
473- }
474- if (resolved .getRequired () != null ) {
475- for (int i = 0 ; i < resolved .getRequired ().size (); i ++) {
476- if (resolved .getRequired ().get (i ) != null ) {
477- requiredProperties .add (resolved .getRequired ().get (i ).toString ());
478- }
479- }
480- }
481- }
482- if (requiredProperties .size () > 0 ) {
483- model .setRequired (new ArrayList <>(requiredProperties ));
484- }
485- if (resolved .getExample () != null ) {
486- examples .add (resolved .getExample ());
487- }
488- if (composedSchema .getExtensions () != null ) {
489- Map <String , Object > extensions = composedSchema .getExtensions ();
490- for (String key : extensions .keySet ()) {
491- model .addExtension (key , composedSchema .getExtensions ().get (key ));
492- }
493- }
494- }
495- }
355+ if (hasOneOf ) {
356+ aggregateSchemaCombinators (composedSchema , combinedModel , composedSchema .getOneOf (), examples );
357+ }
358+ if (hasAnyOf ) {
359+ aggregateSchemaCombinators (composedSchema , combinedModel , composedSchema .getAnyOf (), examples );
496360 }
361+
497362 if (schema .getExample () != null ) {
498- model .setExample (schema .getExample ());
363+ combinedModel .setExample (schema .getExample ());
499364 } else if (!examples .isEmpty ()) {
500- model .setExample (examples );
365+ combinedModel .setExample (examples );
501366 }
502- return model ;
367+
368+ result = combinedModel ;
369+
503370 } else {
504- // User don't want to aggregate composed schema, we only solve refs
505- if (composedSchema . getAllOf () != null )
371+ // User doesn't need or want to aggregate composed schema, we only solve refs
372+ if (hasAllOf ) {
506373 composedSchema .allOf (composedSchema .getAllOf ().stream ().map (this ::resolveSchema ).collect (Collectors .toList ()));
507- if (composedSchema .getOneOf () != null )
374+ }
375+ if (hasOneOf ) {
508376 composedSchema .oneOf (composedSchema .getOneOf ().stream ().map (this ::resolveSchema ).collect (Collectors .toList ()));
509- if (composedSchema .getAnyOf () != null )
377+ }
378+ if (hasAnyOf ) {
510379 composedSchema .anyOf (composedSchema .getAnyOf ().stream ().map (this ::resolveSchema ).collect (Collectors .toList ()));
511- return composedSchema ;
380+ }
512381 }
513382 }
514383
515- if (schema .getProperties () != null ) {
516- Schema model = schema ;
384+ if (result .getProperties () != null ) {
385+ Schema model = result ;
517386 Map <String , Schema > updated = new LinkedHashMap <>();
518387 Map <String , Schema > properties = model .getProperties ();
519388 for (String propertyName : properties .keySet ()) {
520389 Schema property = (Schema ) model .getProperties ().get (propertyName );
521- if (resolvedProperties .get (propertyName ) == null || resolvedProperties .get (propertyName ) != property ) {
522- LOGGER .debug ("avoiding infinite loop" );
523- Schema resolved = resolveSchema (property );
524- updated .put (propertyName , resolved );
525- resolvedProperties .put (propertyName , resolved );
526- }else {
527- updated .put (propertyName , resolvedProperties .get (propertyName ));
528- }
390+ updated .put (propertyName , resolveSchemaProperty (propertyName , property ));
529391 }
530392
531393 for (String key : updated .keySet ()) {
@@ -549,7 +411,7 @@ public Schema resolveSchema(Schema schema) {
549411 return model ;
550412 }
551413
552- return schema ;
414+ return result ;
553415 }
554416
555417 public Map <String ,Example > resolveExample (Map <String ,Example > examples ){
@@ -571,4 +433,58 @@ public Map<String,Example> resolveExample(Map<String,Example> examples){
571433 return resolveExamples ;
572434
573435 }
436+
437+ private void aggregateSchemaCombinators (ComposedSchema sourceSchema , Schema targetSchema ,
438+ List <Schema > schemasToAggregate , Set <Object > examples ) {
439+
440+ Set <String > requiredProperties = new HashSet <>();
441+
442+ for (Schema innerModel : schemasToAggregate ) {
443+ Schema resolved = resolveSchema (innerModel );
444+ Map <String , Schema > properties = resolved .getProperties ();
445+ if (resolved .getProperties () != null ) {
446+ for (String key : properties .keySet ()) {
447+ Schema prop = (Schema ) resolved .getProperties ().get (key );
448+ targetSchema .addProperties (key , resolveSchemaProperty (key , prop ));
449+ }
450+
451+ if (resolved .getRequired () != null ) {
452+ for (Object required : resolved .getRequired ()) {
453+ if (required != null ) {
454+ requiredProperties .add (required .toString ());
455+ }
456+ }
457+ }
458+ }
459+ if (resolved .getExample () != null ) {
460+ examples .add (resolved .getExample ());
461+ }
462+ if (sourceSchema .getExtensions () != null ) {
463+ Map <String , Object > extensions = sourceSchema .getExtensions ();
464+ for (String key : extensions .keySet ()) {
465+ targetSchema .addExtension (key , sourceSchema .getExtensions ().get (key ));
466+ }
467+ }
468+ }
469+
470+ if (requiredProperties .size () > 0 ) {
471+ List <String > required = new ArrayList <>();
472+ if (targetSchema .getRequired () != null ) {
473+ required .addAll (targetSchema .getRequired ());
474+ }
475+ required .addAll (requiredProperties );
476+ targetSchema .setRequired (required );
477+ }
478+ }
479+
480+ private Schema resolveSchemaProperty (String propertyName , Schema innerProperty ) {
481+ if (resolvedProperties .get (propertyName ) == null || resolvedProperties .get (propertyName ) != innerProperty ) {
482+ LOGGER .debug ("avoiding infinite loop" );
483+ Schema resolved = resolveSchema (innerProperty );
484+ resolvedProperties .put (propertyName , resolved );
485+ return resolved ;
486+ } else {
487+ return resolvedProperties .get (propertyName );
488+ }
489+ }
574490}
0 commit comments