1616// under the License.
1717package org .apache .cloudstack .discovery ;
1818
19- import java .lang .reflect .Field ;
20- import java .util .ArrayList ;
21- import java .util .HashMap ;
22- import java .util .HashSet ;
23- import java .util .List ;
24- import java .util .Map ;
25- import java .util .Set ;
26-
27- import javax .annotation .PostConstruct ;
28- import javax .ejb .Local ;
29- import javax .inject .Inject ;
30-
19+ import com .cloud .serializer .Param ;
20+ import com .cloud .user .User ;
21+ import com .cloud .utils .ReflectUtil ;
22+ import com .cloud .utils .StringUtils ;
23+ import com .cloud .utils .component .PluggableService ;
24+ import com .google .gson .annotations .SerializedName ;
3125import org .apache .cloudstack .acl .APIChecker ;
32- import org .apache .cloudstack .api .APICommand ;
33- import org .apache .cloudstack .api .BaseAsyncCmd ;
34- import org .apache .cloudstack .api .BaseAsyncCreateCmd ;
35- import org .apache .cloudstack .api .BaseCmd ;
36- import org .apache .cloudstack .api .BaseResponse ;
37- import org .apache .cloudstack .api .Parameter ;
26+ import org .apache .cloudstack .api .*;
3827import org .apache .cloudstack .api .command .user .discovery .ListApisCmd ;
3928import org .apache .cloudstack .api .response .ApiDiscoveryResponse ;
4029import org .apache .cloudstack .api .response .ApiParameterResponse ;
4332import org .apache .log4j .Logger ;
4433import org .springframework .stereotype .Component ;
4534
46- import com .cloud .serializer .Param ;
47- import com .cloud .user .User ;
48- import com .cloud .utils .ReflectUtil ;
49- import com .cloud .utils .StringUtils ;
50- import com .cloud .utils .component .PluggableService ;
51- import com .google .gson .annotations .SerializedName ;
35+ import javax .annotation .PostConstruct ;
36+ import javax .ejb .Local ;
37+ import javax .inject .Inject ;
38+ import java .lang .reflect .Field ;
39+ import java .util .*;
5240
5341@ Component
5442@ Local (value = ApiDiscoveryService .class )
@@ -69,9 +57,9 @@ void init() {
6957 long startTime = System .nanoTime ();
7058 s_apiNameDiscoveryResponseMap = new HashMap <String , ApiDiscoveryResponse >();
7159 Set <Class <?>> cmdClasses = new HashSet <Class <?>>();
72- for (PluggableService service : _services ) {
60+ for (PluggableService service : _services ) {
7361 s_logger .debug (String .format ("getting api commands of service: %s" , service .getClass ().getName ()));
74- cmdClasses .addAll (service .getCommands ());
62+ cmdClasses .addAll (service .getCommands ());
7563 }
7664 cmdClasses .addAll (this .getCommands ());
7765 cacheResponseMap (cmdClasses );
@@ -80,72 +68,39 @@ void init() {
8068 }
8169 }
8270
83- protected void cacheResponseMap (Set <Class <?>> cmdClasses ) {
71+ protected Map < String , List < String >> cacheResponseMap (Set <Class <?>> cmdClasses ) {
8472 Map <String , List <String >> responseApiNameListMap = new HashMap <String , List <String >>();
8573
8674 for (Class <?> cmdClass : cmdClasses ) {
8775 APICommand apiCmdAnnotation = cmdClass .getAnnotation (APICommand .class );
88- if (apiCmdAnnotation == null )
76+ if (apiCmdAnnotation == null ) {
8977 apiCmdAnnotation = cmdClass .getSuperclass ().getAnnotation (APICommand .class );
78+ }
9079 if (apiCmdAnnotation == null
9180 || !apiCmdAnnotation .includeInApiDoc ()
92- || apiCmdAnnotation .name ().isEmpty ())
81+ || apiCmdAnnotation .name ().isEmpty ()) {
9382 continue ;
83+ }
9484
9585 String apiName = apiCmdAnnotation .name ();
86+ ApiDiscoveryResponse response = getCmdRequestMap (cmdClass , apiCmdAnnotation );
87+
9688 String responseName = apiCmdAnnotation .responseObject ().getName ();
9789 if (!responseName .contains ("SuccessResponse" )) {
98- if (!responseApiNameListMap .containsKey (responseName ))
90+ if (!responseApiNameListMap .containsKey (responseName )) {
9991 responseApiNameListMap .put (responseName , new ArrayList <String >());
92+ }
10093 responseApiNameListMap .get (responseName ).add (apiName );
10194 }
102- ApiDiscoveryResponse response = new ApiDiscoveryResponse ();
103- response .setName (apiName );
104- response .setDescription (apiCmdAnnotation .description ());
105- if (!apiCmdAnnotation .since ().isEmpty ())
106- response .setSince (apiCmdAnnotation .since ());
10795 response .setRelated (responseName );
10896
97+
10998 Field [] responseFields = apiCmdAnnotation .responseObject ().getDeclaredFields ();
11099 for (Field responseField : responseFields ) {
111- SerializedName serializedName = responseField .getAnnotation (SerializedName .class );
112- if (serializedName != null ) {
113- ApiResponseResponse responseResponse = new ApiResponseResponse ();
114- responseResponse .setName (serializedName .value ());
115- Param param = responseField .getAnnotation (Param .class );
116- if (param != null )
117- responseResponse .setDescription (param .description ());
118- responseResponse .setType (responseField .getType ().getSimpleName ().toLowerCase ());
119- response .addApiResponse (responseResponse );
120- }
100+ ApiResponseResponse responseResponse = getFieldResponseMap (responseField );
101+ response .addApiResponse (responseResponse );
121102 }
122103
123- Set <Field > fields = ReflectUtil .getAllFieldsForClass (cmdClass ,
124- new Class <?>[]{BaseCmd .class , BaseAsyncCmd .class , BaseAsyncCreateCmd .class });
125-
126- boolean isAsync = ReflectUtil .isCmdClassAsync (cmdClass ,
127- new Class <?>[] {BaseAsyncCmd .class , BaseAsyncCreateCmd .class });
128-
129- response .setAsync (isAsync );
130-
131- for (Field field : fields ) {
132- Parameter parameterAnnotation = field .getAnnotation (Parameter .class );
133- if (parameterAnnotation != null
134- && parameterAnnotation .expose ()
135- && parameterAnnotation .includeInApiDoc ()) {
136-
137- ApiParameterResponse paramResponse = new ApiParameterResponse ();
138- paramResponse .setName (parameterAnnotation .name ());
139- paramResponse .setDescription (parameterAnnotation .description ());
140- paramResponse .setType (parameterAnnotation .type ().toString ().toLowerCase ());
141- paramResponse .setLength (parameterAnnotation .length ());
142- paramResponse .setRequired (parameterAnnotation .required ());
143- if (!parameterAnnotation .since ().isEmpty ())
144- paramResponse .setSince (parameterAnnotation .since ());
145- paramResponse .setRelated (parameterAnnotation .entityType ()[0 ].getName ());
146- response .addParam (paramResponse );
147- }
148- }
149104 response .setObjectName ("api" );
150105 s_apiNameDiscoveryResponseMap .put (apiName , response );
151106 }
@@ -173,6 +128,76 @@ protected void cacheResponseMap(Set<Class<?>> cmdClasses) {
173128 }
174129 s_apiNameDiscoveryResponseMap .put (apiName , response );
175130 }
131+ return responseApiNameListMap ;
132+ }
133+
134+ private ApiResponseResponse getFieldResponseMap (Field responseField ) {
135+ ApiResponseResponse responseResponse = new ApiResponseResponse ();
136+ SerializedName serializedName = responseField .getAnnotation (SerializedName .class );
137+ Param param = responseField .getAnnotation (Param .class );
138+ if (serializedName != null && param != null ) {
139+ responseResponse .setName (serializedName .value ());
140+ responseResponse .setDescription (param .description ());
141+ responseResponse .setType (responseField .getType ().getSimpleName ().toLowerCase ());
142+ //If response is not of primitive type - we have a nested entity
143+ Class fieldClass = param .responseObject ();
144+ if (fieldClass != null ) {
145+ Class <?> superClass = fieldClass .getSuperclass ();
146+ if (superClass != null ) {
147+ String superName = superClass .getName ();
148+ if (superName .equals (BaseResponse .class .getName ())) {
149+ Field [] fields = fieldClass .getDeclaredFields ();
150+ for (Field field : fields ) {
151+ ApiResponseResponse innerResponse = getFieldResponseMap (field );
152+ if (innerResponse != null ) {
153+ responseResponse .addApiResponse (innerResponse );
154+ }
155+ }
156+ }
157+ }
158+ }
159+ }
160+ return responseResponse ;
161+ }
162+
163+ private ApiDiscoveryResponse getCmdRequestMap (Class <?> cmdClass , APICommand apiCmdAnnotation ) {
164+ String apiName = apiCmdAnnotation .name ();
165+ ApiDiscoveryResponse response = new ApiDiscoveryResponse ();
166+ response .setName (apiName );
167+ response .setDescription (apiCmdAnnotation .description ());
168+ if (!apiCmdAnnotation .since ().isEmpty ()) {
169+ response .setSince (apiCmdAnnotation .since ());
170+ }
171+
172+
173+ Set <Field > fields = ReflectUtil .getAllFieldsForClass (cmdClass ,
174+ new Class <?>[]{BaseCmd .class , BaseAsyncCmd .class , BaseAsyncCreateCmd .class });
175+
176+ boolean isAsync = ReflectUtil .isCmdClassAsync (cmdClass ,
177+ new Class <?>[]{BaseAsyncCmd .class , BaseAsyncCreateCmd .class });
178+
179+ response .setAsync (isAsync );
180+
181+ for (Field field : fields ) {
182+ Parameter parameterAnnotation = field .getAnnotation (Parameter .class );
183+ if (parameterAnnotation != null
184+ && parameterAnnotation .expose ()
185+ && parameterAnnotation .includeInApiDoc ()) {
186+
187+ ApiParameterResponse paramResponse = new ApiParameterResponse ();
188+ paramResponse .setName (parameterAnnotation .name ());
189+ paramResponse .setDescription (parameterAnnotation .description ());
190+ paramResponse .setType (parameterAnnotation .type ().toString ().toLowerCase ());
191+ paramResponse .setLength (parameterAnnotation .length ());
192+ paramResponse .setRequired (parameterAnnotation .required ());
193+ if (!parameterAnnotation .since ().isEmpty ()) {
194+ paramResponse .setSince (parameterAnnotation .since ());
195+ }
196+ paramResponse .setRelated (parameterAnnotation .entityType ()[0 ].getName ());
197+ response .addParam (paramResponse );
198+ }
199+ }
200+ return response ;
176201 }
177202
178203 @ Override
0 commit comments