1515import io .swagger .v3 .oas .annotations .media .Schema ;
1616import io .swagger .v3 .oas .annotations .responses .ApiResponse ;
1717import io .swagger .v3 .oas .annotations .responses .ApiResponses ;
18+ import io .swagger .v3 .oas .annotations .security .SecurityRequirements ;
19+ import io .swagger .v3 .oas .models .examples .Example ;
1820import io .swagger .v3 .oas .models .headers .Header ;
1921import io .swagger .v3 .oas .models .media .ComposedSchema ;
2022import io .swagger .v3 .oas .models .media .StringSchema ;
23+ import io .swagger .v3 .oas .models .security .SecurityRequirement ;
2124import org .objectweb .asm .Type ;
2225import org .objectweb .asm .tree .AnnotationNode ;
2326import org .objectweb .asm .tree .MethodNode ;
2427
28+ import java .util .ArrayList ;
2529import java .util .Collections ;
2630import java .util .HashMap ;
2731import java .util .LinkedHashMap ;
3034import java .util .Objects ;
3135import java .util .Optional ;
3236import java .util .function .BiConsumer ;
37+ import java .util .function .Consumer ;
3338import java .util .stream .Collectors ;
3439
3540import static io .jooby .internal .openapi .AsmUtils .boolValue ;
@@ -49,6 +54,22 @@ public static void parse(ParserContext ctx, MethodNode method, OperationExt oper
4954 .findFirst ()
5055 .ifPresent (a -> swaggerOperation (ctx , operation , toMap (a )));
5156
57+ /** SecurityRequirements: */
58+ findAnnotationByType (method .visibleAnnotations ,
59+ singletonList (SecurityRequirements .class .getName ()))
60+ .stream ()
61+ .map (a ->
62+ (List <AnnotationNode >) toMap (a ).getOrDefault ("value" , emptyList ())
63+ )
64+ .forEach (a -> securityRequirements (operation , a ));
65+
66+ /** SecurityRequirement: */
67+ findAnnotationByType (method .visibleAnnotations ,
68+ singletonList (io .swagger .v3 .oas .annotations .security .SecurityRequirement .class .getName ()))
69+ .stream ()
70+ .findFirst ()
71+ .ifPresent (a -> securityRequirements (operation , Collections .singletonList (a )));
72+
5273 /** @ApiResponses: */
5374 findAnnotationByType (method .visibleAnnotations , singletonList (ApiResponses .class .getName ()))
5475 .stream ()
@@ -97,6 +118,9 @@ private static void swaggerOperation(ParserContext ctx, OperationExt operation,
97118 List <String > tags = (List <String >) annotation .getOrDefault ("tags" , emptyList ());
98119 tags .forEach (operation ::addTagsItem );
99120
121+ securityRequirements (operation ,
122+ (List <AnnotationNode >) annotation .getOrDefault ("security" , Collections .emptyList ()));
123+
100124 parameters (ctx , operation ,
101125 (List <AnnotationNode >) annotation .getOrDefault ("parameters" , Collections .emptyList ()));
102126
@@ -105,6 +129,24 @@ private static void swaggerOperation(ParserContext ctx, OperationExt operation,
105129 responses (ctx , operation , annotation );
106130 }
107131
132+ private static void securityRequirements (OperationExt operation ,
133+ List <AnnotationNode > securityRequirements ) {
134+ List <SecurityRequirement > requirements = new ArrayList <>();
135+ for (AnnotationNode annotation : securityRequirements ) {
136+ Map <String , Object > securityMap = toMap (annotation );
137+ String name = (String ) securityMap .get ("name" );
138+ List <String > scopes = (List <String >) securityMap
139+ .getOrDefault ("scopes" , Collections .emptyList ());
140+ SecurityRequirement requirement = new SecurityRequirement ();
141+ requirement .addList (name , scopes );
142+
143+ requirements .add (requirement );
144+ }
145+ if (requirements .size () > 0 ) {
146+ operation .setSecurity (requirements );
147+ }
148+ }
149+
108150 private static void requestBody (ParserContext ctx , OperationExt operation ,
109151 Map <String , Object > annotation ) {
110152 if (annotation .size () > 0 ) {
@@ -166,6 +208,31 @@ private static void parameters(ParserContext ctx, OperationExt operation,
166208 enumValue (parameterMap , "explode" , value -> parameter .setExample (Boolean .valueOf (value )));
167209 stringValue (parameterMap , "ref" , ref -> parameter .set$ref (RefUtils .constructRef (ref )));
168210 arrayOrSchema (ctx , parameterMap ).ifPresent (parameter ::setSchema );
211+ examples (parameterMap , parameter ::setExample , parameter ::setExamples );
212+ }
213+ }
214+
215+ private static void examples (Map <String , Object > annotation , Consumer <String > exampleConsumer ,
216+ Consumer <Map <String , Example >> consumer ) {
217+ List <Map <String , Object >> annotations = ((List <AnnotationNode >) annotation
218+ .getOrDefault ("examples" , emptyList ())).stream ()
219+ .map (AsmUtils ::toMap )
220+ .collect (Collectors .toList ());
221+
222+ Map <String , Example > examples = new LinkedHashMap <>();
223+ stringValue (annotation , "example" , exampleConsumer );
224+
225+ for (Map <String , Object > e : annotations ) {
226+ Example example = new Example ();
227+ stringValue (e , "summary" , example ::setSummary );
228+ stringValue (e , "description" , example ::setDescription );
229+ stringValue (e , "value" , example ::setValue );
230+ stringValue (e , "externalValue" , example ::setExternalValue );
231+ String key = (String ) e .getOrDefault ("name" , "example" + examples .size ());
232+ examples .put (key , example );
233+ }
234+ if (examples .size () > 0 ) {
235+ consumer .accept (examples );
169236 }
170237 }
171238
0 commit comments