Skip to content

Commit 03b463b

Browse files
committed
Merge pull request #1920 from Shyri/android-volley-library
Android volley library enhancement and tests
2 parents 53abd8a + 877661a commit 03b463b

File tree

6 files changed

+598
-30
lines changed

6 files changed

+598
-30
lines changed

modules/swagger-codegen/src/main/resources/android/libraries/volley/api.mustache

Lines changed: 90 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,12 @@ import com.android.volley.VolleyError;
1717
import org.apache.http.HttpEntity;
1818
import org.apache.http.entity.mime.MultipartEntityBuilder;
1919

20-
import java.util.Map;
20+
import java.util.ArrayList;
2121
import java.util.HashMap;
22-
import java.io.File;
22+
import java.util.List;
23+
import java.util.Map;
24+
import java.util.concurrent.ExecutionException;
25+
import java.util.concurrent.TimeoutException;
2326

2427
{{#operations}}
2528
public class {{classname}} {
@@ -44,11 +47,93 @@ public class {{classname}} {
4447

4548
{{#operation}}
4649
/**
47-
* {{summary}}
48-
* {{notes}}
50+
* {{summary}}
51+
* {{notes}}
4952
{{#allParams}} * @param {{paramName}} {{description}}
5053
{{/allParams}} * @return {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}}
51-
*/
54+
*/
55+
public {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} {{nickname}} ({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws TimeoutException, ExecutionException, InterruptedException, ApiException {
56+
Object postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}};
57+
{{#allParams}}{{#required}}
58+
// verify the required parameter '{{paramName}}' is set
59+
if ({{paramName}} == null) {
60+
VolleyError error = new VolleyError("Missing the required parameter '{{paramName}}' when calling {{nickname}}",
61+
new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{nickname}}"));
62+
}
63+
{{/required}}{{/allParams}}
64+
65+
// create path and map variables
66+
String path = "{{path}}".replaceAll("\\{format\\}","json"){{#pathParams}}.replaceAll("\\{" + "{{baseName}}" + "\\}", apiInvoker.escapeString({{{paramName}}}.toString())){{/pathParams}};
67+
68+
// query params
69+
List<Pair> queryParams = new ArrayList<Pair>();
70+
// header params
71+
Map<String, String> headerParams = new HashMap<String, String>();
72+
// form params
73+
Map<String, String> formParams = new HashMap<String, String>();
74+
75+
{{#queryParams}}
76+
queryParams.addAll(ApiInvoker.parameterToPairs("{{#collectionFormat}}{{{collectionFormat}}}{{/collectionFormat}}", "{{baseName}}", {{paramName}}));
77+
{{/queryParams}}
78+
79+
{{#headerParams}}
80+
headerParams.put("{{baseName}}", ApiInvoker.parameterToString({{paramName}}));
81+
{{/headerParams}}
82+
83+
String[] contentTypes = {
84+
{{#consumes}}"{{mediaType}}"{{#hasMore}},{{/hasMore}}{{/consumes}}
85+
};
86+
String contentType = contentTypes.length > 0 ? contentTypes[0] : "application/json";
87+
88+
if (contentType.startsWith("multipart/form-data")) {
89+
// file uploading
90+
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
91+
{{#formParams}}{{#notFile}}
92+
if ({{paramName}} != null) {
93+
builder.addTextBody("{{baseName}}", ApiInvoker.parameterToString({{paramName}}), ApiInvoker.TEXT_PLAIN_UTF8);
94+
}
95+
{{/notFile}}{{#isFile}}
96+
if ({{paramName}} != null) {
97+
builder.addBinaryBody("{{baseName}}", {{paramName}});
98+
}
99+
{{/isFile}}{{/formParams}}
100+
101+
HttpEntity httpEntity = builder.build();
102+
postBody = httpEntity;
103+
} else {
104+
// normal form params
105+
{{#formParams}}{{#notFile}}formParams.put("{{baseName}}", ApiInvoker.parameterToString({{paramName}}));{{/notFile}}
106+
{{/formParams}}
107+
}
108+
109+
String[] authNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} };
110+
111+
try {
112+
String response = apiInvoker.invokeAPI (basePath, path, "{{httpMethod}}", queryParams, postBody, headerParams, formParams, contentType, authNames);
113+
if(response != null){
114+
return {{#returnType}}({{{returnType}}}) ApiInvoker.deserialize(response, "{{returnContainer}}", {{returnBaseType}}.class){{/returnType}};
115+
} else {
116+
return {{#returnType}}null{{/returnType}};
117+
}
118+
} catch (ApiException ex) {
119+
throw ex;
120+
} catch (InterruptedException ex) {
121+
throw ex;
122+
} catch (ExecutionException ex) {
123+
if(ex.getCause() instanceof VolleyError) {
124+
throw new ApiException(((VolleyError) ex.getCause()).networkResponse.statusCode, ((VolleyError) ex.getCause()).getMessage());
125+
}
126+
throw ex;
127+
} catch (TimeoutException ex) {
128+
throw ex;
129+
}
130+
}
131+
132+
/**
133+
* {{summary}}
134+
* {{notes}}
135+
{{#allParams}} * @param {{paramName}} {{description}}{{/allParams}}
136+
*/
52137
public void {{nickname}} ({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{^hasMore}}, {{/hasMore}}{{/allParams}}final Response.Listener<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}String{{/returnType}}> responseListener, final Response.ErrorListener errorListener) {
53138
Object postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}};
54139

modules/swagger-codegen/src/main/resources/android/libraries/volley/apiInvoker.mustache

Lines changed: 90 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
package {{invokerPackage}};
22

3-
import android.content.Context;
4-
3+
import com.android.volley.Cache;
4+
import com.android.volley.Network;
5+
import com.android.volley.Request;
56
import com.android.volley.RequestQueue;
67
import com.android.volley.Response;
7-
import com.android.volley.toolbox.Volley;
8+
import com.android.volley.ResponseDelivery;
9+
import com.android.volley.toolbox.BasicNetwork;
10+
import com.android.volley.toolbox.HttpStack;
11+
import com.android.volley.toolbox.HurlStack;
12+
import com.android.volley.toolbox.NoCache;
13+
import com.android.volley.toolbox.RequestFuture;
814
import com.google.gson.JsonParseException;
915

1016
import org.apache.http.Consts;
@@ -22,6 +28,9 @@ import java.util.HashMap;
2228
import java.util.List;
2329
import java.util.Map;
2430
import java.util.TimeZone;
31+
import java.util.concurrent.ExecutionException;
32+
import java.util.concurrent.TimeUnit;
33+
import java.util.concurrent.TimeoutException;
2534

2635
import {{invokerPackage}}.auth.Authentication;
2736
import {{invokerPackage}}.auth.ApiKeyAuth;
@@ -36,11 +45,12 @@ public class ApiInvoker {
3645
private static ApiInvoker INSTANCE;
3746
private Map<String, String> defaultHeaderMap = new HashMap<String, String>();
3847
39-
private Context context;
4048
private RequestQueue mRequestQueue;
4149
4250
private Map<String, Authentication> authentications;
4351
52+
private int connectionTimeout;
53+
4454
/** Content type "text/plain" with UTF-8 encoding. */
4555
public static final ContentType TEXT_PLAIN_UTF8 = ContentType.create("text/plain", Consts.UTF_8);
4656
@@ -165,8 +175,16 @@ public class ApiInvoker {
165175
return params;
166176
}
167177

168-
public static void initializeInstance(Context context) {
169-
INSTANCE = new ApiInvoker(context);
178+
public static void initializeInstance() {
179+
initializeInstance(null);
180+
}
181+
182+
public static void initializeInstance(Cache cache) {
183+
initializeInstance(cache, null, 0, null, 30);
184+
}
185+
186+
public static void initializeInstance(Cache cache, Network network, int threadPoolSize, ResponseDelivery delivery, int connectionTimeout) {
187+
INSTANCE = new ApiInvoker(cache, network, threadPoolSize, delivery, connectionTimeout);
170188
setUserAgent("Android-Volley-Swagger");
171189
172190
// Setup authentications (key: authentication name, value: authentication).
@@ -178,17 +196,27 @@ public class ApiInvoker {
178196
{{#isBasic}}
179197
INSTANCE.authentications.put("{{name}}", new HttpBasicAuth());
180198
{{/isBasic}}
199+
{{#isOAuth}}
200+
INSTANCE.authentications.put("{{name}}", new OAuth());
201+
{{/isOAuth}}
181202
{{/authMethods}}
182203
// Prevent the authentications from being modified.
183204
INSTANCE.authentications = Collections.unmodifiableMap(INSTANCE.authentications);
184205
}
185-
private ApiInvoker(Context context) {
186-
this.context = context;
187-
initConnectionManager();
188-
}
189206

190-
public ApiInvoker() {
191-
initConnectionManager();
207+
private ApiInvoker(Cache cache, Network network, int threadPoolSize, ResponseDelivery delivery, int connectionTimeout) {
208+
if(cache == null) cache = new NoCache();
209+
if(network == null) {
210+
HttpStack stack = new HurlStack();
211+
network = new BasicNetwork(stack);
212+
}
213+
214+
if(delivery == null) {
215+
initConnectionRequest(cache, network);
216+
} else {
217+
initConnectionRequest(cache, network, threadPoolSize, delivery);
218+
}
219+
this.connectionTimeout = connectionTimeout;
192220
}
193221

194222
public static ApiInvoker getInstance() {
@@ -304,6 +332,14 @@ public class ApiInvoker {
304332
throw new RuntimeException("No API key authentication configured!");
305333
}
306334

335+
public void setConnectionTimeout(int connectionTimeout){
336+
this.connectionTimeout = connectionTimeout;
337+
}
338+
339+
public int getConnectionTimeout() {
340+
return connectionTimeout;
341+
}
342+
307343
/**
308344
* Update query and header parameters based on authentication settings.
309345
*
@@ -317,7 +353,21 @@ public class ApiInvoker {
317353
}
318354
}
319355

356+
public String invokeAPI(String host, String path, String method, List<Pair> queryParams, Object body, Map<String, String> headerParams, Map<String, String> formParams, String contentType, String[] authNames) throws ApiException, InterruptedException, ExecutionException, TimeoutException {
357+
RequestFuture<String> future = RequestFuture.newFuture();
358+
Request request = createRequest(host, path, method, queryParams, body, headerParams, formParams, contentType, authNames, future, future);
359+
if(request != null) {
360+
mRequestQueue.add(request);
361+
return future.get(connectionTimeout, TimeUnit.SECONDS);
362+
} else return "no data";
363+
}
364+
320365
public void invokeAPI(String host, String path, String method, List<Pair> queryParams, Object body, Map<String, String> headerParams, Map<String, String> formParams, String contentType, String[] authNames, Response.Listener<String> stringRequest, Response.ErrorListener errorListener) throws ApiException {
366+
Request request = createRequest(host, path, method, queryParams, body, headerParams, formParams, contentType, authNames, stringRequest, errorListener);
367+
if (request != null) mRequestQueue.add(request);
368+
}
369+
370+
public Request<String> createRequest(String host, String path, String method, List<Pair> queryParams, Object body, Map<String, String> headerParams, Map<String, String> formParams, String contentType, String[] authNames, Response.Listener<String> stringRequest, Response.ErrorListener errorListener) throws ApiException {
321371
StringBuilder b = new StringBuilder();
322372
b.append("?");
323373
@@ -374,13 +424,13 @@ public class ApiInvoker {
374424
}
375425
formParamStr = formParamBuilder.toString();
376426
}
427+
Request request = null;
377428

378429
if ("GET".equals(method)) {
379-
GetRequest request = new GetRequest(url, headers, null, stringRequest, errorListener);
380-
mRequestQueue.add(request);
430+
request = new GetRequest(url, headers, null, stringRequest, errorListener);
381431
}
382432
else if ("POST".equals(method)) {
383-
PostRequest request = null;
433+
request = null;
384434
if (formParamStr != null) {
385435
request = new PostRequest(url, headers, contentType, new StringEntity(formParamStr, "UTF-8"), stringRequest, errorListener);
386436
} else if (body != null) {
@@ -389,11 +439,12 @@ public class ApiInvoker {
389439
} else {
390440
request = new PostRequest(url, headers, contentType, new StringEntity(serialize(body), "UTF-8"), stringRequest, errorListener);
391441
}
442+
} else {
443+
request = new PostRequest(url, headers, null, null, stringRequest, errorListener);
392444
}
393-
if(request != null) mRequestQueue.add(request);
394445
}
395446
else if ("PUT".equals(method)) {
396-
PutRequest request = null;
447+
request = null;
397448
if (formParamStr != null) {
398449
request = new PutRequest(url, headers, contentType, new StringEntity(formParamStr, "UTF-8"), stringRequest, errorListener);
399450
} else if (body != null) {
@@ -402,11 +453,12 @@ public class ApiInvoker {
402453
} else {
403454
request = new PutRequest(url, headers, contentType, new StringEntity(serialize(body), "UTF-8"), stringRequest, errorListener);
404455
}
456+
} else {
457+
request = new PutRequest(url, headers, null, null, stringRequest, errorListener);
405458
}
406-
if(request != null) mRequestQueue.add(request);
407459
}
408460
else if ("DELETE".equals(method)) {
409-
DeleteRequest request = null;
461+
request = null;
410462
if (formParamStr != null) {
411463
request = new DeleteRequest(url, headers, contentType, new StringEntity(formParamStr, "UTF-8"), stringRequest, errorListener);
412464
} else if (body != null) {
@@ -415,11 +467,12 @@ public class ApiInvoker {
415467
} else {
416468
request = new DeleteRequest(url, headers, contentType, new StringEntity(serialize(body), "UTF-8"), stringRequest, errorListener);
417469
}
470+
} else {
471+
request = new DeleteRequest(url, headers, null, null, stringRequest, errorListener);
418472
}
419-
if(request != null) mRequestQueue.add(request);
420473
}
421474
else if ("PATCH".equals(method)) {
422-
PatchRequest request = null;
475+
request = null;
423476
if (formParamStr != null) {
424477
request = new PatchRequest(url, headers, contentType, new StringEntity(formParamStr, "UTF-8"), stringRequest, errorListener);
425478
} else if (body != null) {
@@ -428,12 +481,24 @@ public class ApiInvoker {
428481
} else {
429482
request = new PatchRequest(url, headers, contentType, new StringEntity(serialize(body), "UTF-8"), stringRequest, errorListener);
430483
}
431-
}
432-
if(request != null) mRequestQueue.add(request);
484+
} else {
485+
request = new PatchRequest(url, headers, null, null, stringRequest, errorListener);
486+
}
433487
}
488+
return request;
489+
}
490+
491+
private void initConnectionRequest(Cache cache, Network network) {
492+
mRequestQueue = new RequestQueue(cache, network);
493+
mRequestQueue.start();
494+
}
495+
496+
private void initConnectionRequest(Cache cache, Network network, int threadPoolSize, ResponseDelivery delivery) {
497+
mRequestQueue = new RequestQueue(cache, network, threadPoolSize, delivery);
498+
mRequestQueue.start();
434499
}
435500

436-
private void initConnectionManager() {
437-
mRequestQueue = Volley.newRequestQueue(context);
501+
public void stopQueue() {
502+
mRequestQueue.stop();
438503
}
439504
}

modules/swagger-codegen/src/main/resources/android/libraries/volley/auth/apikeyauth.mustache

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ public class ApiKeyAuth implements Authentication {
4444
@Override
4545
public void applyToParams(List<Pair> queryParams, Map<String, String> headerParams) {
4646
String value;
47+
if (apiKey == null) {
48+
return;
49+
}
4750
if (apiKeyPrefix != null) {
4851
value = apiKeyPrefix + " " + apiKey;
4952
} else {
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package {{invokerPackage}}.auth;
2+
3+
import {{invokerPackage}}.Pair;
4+
5+
import java.util.Map;
6+
import java.util.List;
7+
8+
public class OAuth implements Authentication {
9+
@Override
10+
public void applyToParams(List<Pair> queryParams, Map<String, String> headerParams) {
11+
// TODO stub
12+
}
13+
}

modules/swagger-codegen/src/main/resources/android/libraries/volley/build.mustache

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ android {
4949
}
5050
}
5151
}
52+
53+
testOptions {
54+
unitTests.returnDefaultValues = true
55+
}
5256
}
5357

5458

@@ -58,6 +62,8 @@ ext {
5862
httpclient_version = "4.3.3"
5963
volley_version = "1.0.19"
6064
junit_version = "4.8.1"
65+
robolectric_version = "3.0"
66+
concurrent_unit_version = "0.4.2"
6167
}
6268

6369
dependencies {
@@ -67,6 +73,8 @@ dependencies {
6773
compile "org.apache.httpcomponents:httpmime:$httpclient_version"
6874
compile "com.mcxiaoke.volley:library:${volley_version}@aar"
6975
testCompile "junit:junit:$junit_version"
76+
testCompile "org.robolectric:robolectric:${robolectric_version}"
77+
testCompile "net.jodah:concurrentunit:${concurrentunitVersion}"
7078
}
7179

7280
afterEvaluate {

0 commit comments

Comments
 (0)