77
88import static io .jooby .internal .openapi .AsmUtils .*;
99import static io .jooby .internal .openapi .TypeFactory .*;
10- import static java .util .Arrays .asList ;
1110import static java .util .Collections .singletonList ;
1211
1312import java .util .*;
2221
2322import io .jooby .*;
2423import io .jooby .annotation .*;
24+ import io .jooby .value .Value ;
25+ import io .jooby .value .ValueFactory ;
2526import io .swagger .v3 .oas .models .media .Content ;
2627import io .swagger .v3 .oas .models .media .ObjectSchema ;
2728import io .swagger .v3 .oas .models .media .Schema ;
@@ -110,27 +111,52 @@ public boolean matches(String annotationType) {
110111
111112 public void setIn (Parameter parameter ) {}
112113
114+ public Optional <String > getDefaultValue (List <AnnotationNode > annotations ) {
115+ List <Class > names =
116+ Stream .of (annotations ()).filter (it -> it .getName ().startsWith ("io.jooby" )).toList ();
117+ for (var a : annotations ) {
118+ if (a .values != null ) {
119+ var matches = names .stream ().anyMatch (it -> Type .getDescriptor (it ).equals (a .desc ));
120+ if (matches ) {
121+ for (int i = 0 ; i < a .values .size (); i ++) {
122+ if (a .values .get (i ).equals ("value" )) {
123+ Object value = a .values .get (i + 1 );
124+ if (value != null && !value .toString ().trim ().isEmpty ()) {
125+ return Optional .of (value .toString ().trim ());
126+ }
127+ }
128+ }
129+ }
130+ }
131+ }
132+ return Optional .empty ();
133+ }
134+
113135 public Optional <String > getHttpName (List <AnnotationNode > annotations ) {
114- List <Class > names = new ArrayList <>(asList (annotations ()));
115- names .add (Named .class );
116- return annotations .stream ()
117- .filter (a -> names .stream ().anyMatch (c -> Type .getDescriptor (c ).equals (a .desc )))
118- .map (
119- a -> {
120- if (a .values != null ) {
121- for (int i = 0 ; i < a .values .size (); i ++) {
122- if (a .values .get (i ).equals ("value" )) {
123- Object value = a .values .get (i + 1 );
124- if (value != null && value .toString ().trim ().length () > 0 ) {
125- return value .toString ().trim ();
126- }
127- }
128- }
136+ List <Map .Entry <Class , String >> names =
137+ Stream .concat (Stream .of (annotations ()), Stream .of (Named .class ))
138+ .map (it -> Map .entry (it , it .getName ().startsWith ("io.jooby" ) ? "name" : "value" ))
139+ .toList ();
140+ for (var a : annotations ) {
141+ if (a .values != null ) {
142+ var mapping =
143+ names .stream ()
144+ .filter (it -> Type .getDescriptor (it .getKey ()).equals (a .desc ))
145+ .findFirst ()
146+ .orElse (null );
147+ if (mapping != null ) {
148+ for (int i = 0 ; i < a .values .size (); i ++) {
149+ if (a .values .get (i ).equals (mapping .getValue ())) {
150+ Object value = a .values .get (i + 1 );
151+ if (value != null && !value .toString ().trim ().isEmpty ()) {
152+ return Optional .of (value .toString ().trim ());
129153 }
130- return null ;
131- })
132- .filter (Objects ::nonNull )
133- .findFirst ();
154+ }
155+ }
156+ }
157+ }
158+ }
159+ return Optional .empty ();
134160 }
135161
136162 public static ParamType find (List <AnnotationNode > annotations ) {
@@ -383,9 +409,9 @@ private static List<ParameterExt> routerArguments(
383409 List <String > javaName ;
384410 if ((parameter .name .equals ("continuation" ) || parameter .name .equals ("$completion" ))
385411 && i == method .parameters .size () - 1 ) {
386- javaName = asList (parameter .name , "$continuation" );
412+ javaName = List . of (parameter .name , "$continuation" );
387413 } else {
388- javaName = singletonList (parameter .name );
414+ javaName = List . of (parameter .name );
389415 }
390416 /* Java Type: */
391417 LocalVariableNode variable =
@@ -435,11 +461,7 @@ private static List<ParameterExt> routerArguments(
435461 body .setJavaType (javaType );
436462 requestBody .accept (body );
437463 } else if (paramType == ParamType .FORM ) {
438- String field = paramType .getHttpName (annotations ).orElse (parameter .name );
439- if (required ) {
440- requiredFormFields .add (field );
441- }
442- Schema schemaProperty = ctx .schema (javaType );
464+ var schemaProperty = ctx .schema (javaType );
443465 if (ctx .schemaRef (javaType ).isPresent ()) {
444466 // form bean (i.e. single body)
445467 RequestBodyExt body = new RequestBodyExt ();
@@ -450,30 +472,45 @@ private static List<ParameterExt> routerArguments(
450472 body .setJavaType (javaType );
451473 requestBody .accept (body );
452474 } else {
475+ String field = paramType .getHttpName (annotations ).orElse (parameter .name );
476+ paramType
477+ .getDefaultValue (annotations )
478+ .flatMap (value -> convertValue (ctx , javaType , value ))
479+ .ifPresent (schemaProperty ::setDefault );
480+ if (schemaProperty .getDefault () == null ) {
481+ if (required ) {
482+ requiredFormFields .add (field );
483+ }
484+ }
453485 // single property
454486 form .put (field , schemaProperty );
455487 }
456488 } else {
457489 ParameterExt argument = new ParameterExt ();
458- argument .setName (paramType .getHttpName (annotations ).orElse (parameter .name ));
459490 argument .setJavaType (javaType );
491+ argument .setName (paramType .getHttpName (annotations ).orElse (parameter .name ));
492+ paramType
493+ .getDefaultValue (annotations )
494+ .flatMap (value -> convertValue (ctx , javaType , value ))
495+ .ifPresent (argument ::setDefaultValue );
460496 paramType .setIn (argument );
461- if (required ) {
462- argument .setRequired (true );
497+ if (argument .getDefaultValue () == null ) {
498+ if (required ) {
499+ argument .setRequired (true );
500+ }
463501 }
464502 result .add (argument );
465503 }
466504 }
467505 }
468- if (form .size () > 0 ) {
469- Schema schema = new ObjectSchema ();
506+ if (! form .isEmpty () ) {
507+ var schema = new ObjectSchema ();
470508 schema .setProperties (form );
471- if (requiredFormFields .size () > 0 ) {
509+ if (! requiredFormFields .isEmpty () ) {
472510 schema .setRequired (requiredFormFields );
473511 }
474512
475- io .swagger .v3 .oas .models .media .MediaType mediaType =
476- new io .swagger .v3 .oas .models .media .MediaType ();
513+ var mediaType = new io .swagger .v3 .oas .models .media .MediaType ();
477514 mediaType .setSchema (schema );
478515
479516 Content content = new Content ();
@@ -487,6 +524,40 @@ private static List<ParameterExt> routerArguments(
487524 return result ;
488525 }
489526
527+ private static Optional <?> convertValue (ParserContext ctx , String javaType , String value ) {
528+ try {
529+ switch (javaType ) {
530+ case "boolean" :
531+ return Optional .of (Boolean .parseBoolean (value ));
532+ case "int" :
533+ return Optional .of (Integer .parseInt (value ));
534+ case "long" :
535+ return Optional .of (Long .parseLong (value ));
536+ case "double" :
537+ return Optional .of (Double .parseDouble (value ));
538+ case "float" :
539+ return Optional .of (Float .parseFloat (value ));
540+ case "byte" :
541+ return Optional .of (Byte .parseByte (value ));
542+ case "short" :
543+ return Optional .of (Short .parseShort (value ));
544+ case "char" :
545+ return Optional .of (value .charAt (0 ));
546+ case "java.lang.String" :
547+ return Optional .of (value );
548+ default :
549+ {
550+ var realType = ctx .classLoader ().loadClass (javaType );
551+ ValueFactory factory = new ValueFactory ();
552+ return Optional .ofNullable (
553+ factory .convert (realType , Value .value (factory , "value" , value )));
554+ }
555+ }
556+ } catch (Exception ignored ) {
557+ return Optional .empty ();
558+ }
559+ }
560+
490561 private static boolean isNullable (MethodNode method , int paramIndex ) {
491562 if (paramIndex < method .invisibleAnnotableParameterCount ) {
492563 List <AnnotationNode > annotations = method .invisibleParameterAnnotations [paramIndex ];
@@ -604,7 +675,7 @@ private static boolean isRouter(MethodNode node) {
604675 List <String > annotationTypes =
605676 httpMethods ().stream ()
606677 .map (classname -> Type .getObjectType (classname .replace ("." , "/" )).getDescriptor ())
607- .collect ( Collectors . toList () );
678+ .toList ();
608679
609680 return node .visibleAnnotations .stream ().anyMatch (a -> annotationTypes .contains (a .desc ));
610681 }
0 commit comments