1010import java .util .Collections ;
1111import java .util .HashSet ;
1212import java .util .List ;
13+ import java .util .Map ;
1314import java .util .Objects ;
15+ import java .util .Optional ;
16+ import java .util .OptionalDouble ;
17+ import java .util .OptionalInt ;
18+ import java .util .OptionalLong ;
1419import java .util .Set ;
1520import java .util .stream .Stream ;
1621
1722import io .swagger .v3 .oas .annotations .Parameter ;
1823import org .apache .commons .lang3 .ArrayUtils ;
1924
2025import org .springframework .core .MethodParameter ;
21- import org .springframework .lang .NonNull ;
2226import org .springframework .lang .Nullable ;
2327
2428class MethodParameterPojoExtractor {
25- private static final Set <Class <?>> SIMPLE_TYPES ;
26- private static final Set <Class <?>> COLLECTION_TYPES ;
27-
28- static {
29- Set <Class <?>> simpleTypes = new HashSet <>();
30- simpleTypes .add (boolean .class );
31- simpleTypes .add (char .class );
32- simpleTypes .add (byte .class );
33- simpleTypes .add (short .class );
34- simpleTypes .add (int .class );
35- simpleTypes .add (long .class );
36- simpleTypes .add (float .class );
37- simpleTypes .add (double .class );
38-
39- simpleTypes .add (Boolean .class );
40- simpleTypes .add (Character .class );
41- simpleTypes .add (Byte .class );
42- simpleTypes .add (Short .class );
43- simpleTypes .add (Integer .class );
44- simpleTypes .add (Long .class );
45- simpleTypes .add (Float .class );
46- simpleTypes .add (Double .class );
47-
48- simpleTypes .add (CharSequence .class );
49- simpleTypes .add (Number .class );
50-
51- SIMPLE_TYPES = Collections .unmodifiableSet (simpleTypes );
52-
53- Set <Class <?>> collectionTypes = new HashSet <>();
54- collectionTypes .add (Iterable .class );
55-
56- COLLECTION_TYPES = Collections .unmodifiableSet (collectionTypes );
29+ static Stream <MethodParameter > extractFrom (Class <?> clazz ) {
30+ return extractFrom (clazz , "" );
5731 }
5832
59- private static final Nullable NULLABLE_ANNOTATION = new Nullable () {
60- @ Override
61- public Class <? extends Annotation > annotationType () {
62- return Nullable .class ;
63- }
64- };
65-
66- @ NonNull
67- static Stream <MethodParameter > extractFrom (Class <?> clazz ) {
33+ private static Stream <MethodParameter > extractFrom (Class <?> clazz , String fieldNamePrefix ) {
6834 return allFieldsOf (clazz ).stream ()
69- .flatMap (f -> fromGetterOfField (clazz , f ))
35+ .flatMap (f -> fromGetterOfField (clazz , f , fieldNamePrefix ))
7036 .filter (Objects ::nonNull );
7137 }
7238
73- private static Stream <MethodParameter > fromGetterOfField (Class <?> paramClass , Field field ) {
39+ private static Stream <MethodParameter > fromGetterOfField (Class <?> paramClass , Field field , String fieldNamePrefix ) {
40+ if (isSimpleType (field .getType ())) {
41+ return fromSimpleClass (paramClass , field , fieldNamePrefix );
42+ }
43+ else {
44+ return extractFrom (field .getType (), fieldNamePrefix + field .getName () + "." );
45+ }
46+ }
47+
48+ private static Stream <MethodParameter > fromSimpleClass (Class <?> paramClass , Field field , String fieldNamePrefix ) {
49+ Annotation [] fieldAnnotations = field .getDeclaredAnnotations ();
50+ if (isOptional (field )) {
51+ fieldAnnotations = ArrayUtils .add (fieldAnnotations , NULLABLE_ANNOTATION );
52+ }
7453 try {
75- Annotation [] filedAnnotations = field .getDeclaredAnnotations ();
76- Parameter parameter = field .getAnnotation (Parameter .class );
77- if (parameter != null && !parameter .required ()) {
78- filedAnnotations = ArrayUtils .add (filedAnnotations , NULLABLE_ANNOTATION );
79- }
80- Annotation [] filedAnnotationsNew = filedAnnotations ;
54+ Annotation [] finalFieldAnnotations = fieldAnnotations ;
8155 return Stream .of (Introspector .getBeanInfo (paramClass ).getPropertyDescriptors ())
8256 .filter (d -> d .getName ().equals (field .getName ()))
8357 .map (PropertyDescriptor ::getReadMethod )
8458 .filter (Objects ::nonNull )
8559 .map (method -> new MethodParameter (method , -1 ))
86- .map (param -> new DelegatingMethodParameter (param , field .getName (), filedAnnotationsNew ));
60+ .map (param -> new DelegatingMethodParameter (param , fieldNamePrefix + field .getName (), finalFieldAnnotations ));
8761 }
8862 catch (IntrospectionException e ) {
8963 return Stream .of ();
9064 }
9165 }
9266
67+ private static boolean isOptional (Field field ) {
68+ Parameter parameter = field .getAnnotation (Parameter .class );
69+ return parameter == null || !parameter .required ();
70+ }
71+
9372 private static List <Field > allFieldsOf (Class <?> clazz ) {
9473 List <Field > fields = new ArrayList <>();
9574 do {
@@ -98,4 +77,37 @@ private static List<Field> allFieldsOf(Class<?> clazz) {
9877 } while (clazz != null );
9978 return fields ;
10079 }
80+
81+ private static boolean isSimpleType (Class <?> clazz ) {
82+ if (clazz .isPrimitive ()) return true ;
83+ if (clazz .isArray ()) return true ;
84+ if (clazz .isEnum ()) return true ;
85+ return SIMPLE_TYPES .stream ().anyMatch (c -> c .isAssignableFrom (clazz ));
86+ }
87+
88+ private static final Nullable NULLABLE_ANNOTATION = new Nullable () {
89+ @ Override
90+ public Class <? extends Annotation > annotationType () {
91+ return Nullable .class ;
92+ }
93+ };
94+
95+ private static final Set <Class <?>> SIMPLE_TYPES ;
96+
97+ static {
98+ Set <Class <?>> simpleTypes = new HashSet <>();
99+ simpleTypes .add (Boolean .class );
100+ simpleTypes .add (Character .class );
101+ simpleTypes .add (Number .class );
102+ simpleTypes .add (CharSequence .class );
103+ simpleTypes .add (Optional .class );
104+ simpleTypes .add (OptionalInt .class );
105+ simpleTypes .add (OptionalLong .class );
106+ simpleTypes .add (OptionalDouble .class );
107+
108+ simpleTypes .add (Map .class );
109+ simpleTypes .add (Iterable .class );
110+
111+ SIMPLE_TYPES = Collections .unmodifiableSet (simpleTypes );
112+ }
101113}
0 commit comments