1
1
package com .algolia ;
2
2
3
3
import com .algolia .exceptions .*;
4
+ import com .algolia .utils .JSON ;
4
5
import com .algolia .utils .Requester ;
5
6
import com .algolia .utils .UserAgent ;
6
7
import java .io .IOException ;
12
13
import java .time .OffsetDateTime ;
13
14
import java .util .*;
14
15
import java .util .Map .Entry ;
16
+ import java .util .concurrent .CompletableFuture ;
15
17
import okhttp3 .*;
16
18
import okhttp3 .internal .http .HttpMethod ;
17
19
@@ -195,7 +197,7 @@ public String parameterToString(Object param) {
195
197
* @param mime MIME (Multipurpose Internet Mail Extensions)
196
198
* @return True if the given MIME is JSON, false otherwise.
197
199
*/
198
- public boolean isJsonMime (String mime ) {
200
+ public static boolean isJsonMime (String mime ) {
199
201
String jsonMime =
200
202
"(?i)^(application/json|[^;/ \t ]+/[^;/ \t ]+[+]json)[ \t ]*(;.*)?$" ;
201
203
return mime != null && (mime .matches (jsonMime ) || mime .equals ("*/*" ));
@@ -215,65 +217,6 @@ public String escapeString(String str) {
215
217
}
216
218
}
217
219
218
- /**
219
- * Deserialize response body to Java object, according to the return type and the Content-Type
220
- * response header.
221
- *
222
- * @param <T> Type
223
- * @param response HTTP response
224
- * @param returnType The type of the Java object
225
- * @return The deserialized Java object
226
- * @throws AlgoliaRuntimeException If fail to deserialize response body, i.e. cannot read response
227
- * body or the Content-Type of the response is not supported.
228
- */
229
- public <T > T deserialize (Response response , Type returnType )
230
- throws AlgoliaRuntimeException {
231
- if (response == null || returnType == null ) {
232
- return null ;
233
- }
234
-
235
- if ("byte[]" .equals (returnType .toString ())) {
236
- // Handle binary response (byte array).
237
- try {
238
- return (T ) response .body ().bytes ();
239
- } catch (IOException e ) {
240
- throw new AlgoliaRuntimeException (e );
241
- }
242
- }
243
-
244
- String respBody ;
245
- try {
246
- if (response .body () != null ) respBody =
247
- response .body ().string (); else respBody = null ;
248
- } catch (IOException e ) {
249
- throw new AlgoliaRuntimeException (e );
250
- }
251
-
252
- if (respBody == null || "" .equals (respBody )) {
253
- return null ;
254
- }
255
-
256
- String contentType = response .headers ().get ("Content-Type" );
257
- if (contentType == null ) {
258
- // ensuring a default content type
259
- contentType = "application/json" ;
260
- }
261
- if (isJsonMime (contentType )) {
262
- return JSON .deserialize (respBody , returnType );
263
- } else if (returnType .equals (String .class )) {
264
- // Expecting string, return the raw response body.
265
- return (T ) respBody ;
266
- } else {
267
- throw new AlgoliaApiException (
268
- "Content type \" " +
269
- contentType +
270
- "\" is not supported for type: " +
271
- returnType ,
272
- response .code ()
273
- );
274
- }
275
- }
276
-
277
220
/**
278
221
* Serialize the given Java object into request body according to the object's class and the
279
222
* request Content-Type.
@@ -303,147 +246,40 @@ public RequestBody serialize(Object obj, String contentType)
303
246
}
304
247
}
305
248
306
- /**
307
- * {@link #execute(Call, Type)}
308
- *
309
- * @param <T> Type
310
- * @param call An instance of the Call object
311
- * @return ApiResponse<T>
312
- * @throws AlgoliaRuntimeException If fail to execute the call
313
- */
314
- public <T > ApiResponse <T > execute (Call call ) throws AlgoliaRuntimeException {
315
- return execute (call , null );
316
- }
317
-
318
- /**
319
- * Execute HTTP call and deserialize the HTTP response body into the given return type.
320
- *
321
- * @param returnType The return type used to deserialize HTTP response body
322
- * @param <T> The return type corresponding to (same with) returnType
323
- * @param call Call
324
- * @return ApiResponse object containing response status, headers and data, which is a Java object
325
- * deserialized from response body and would be null when returnType is null.
326
- * @throws AlgoliaRuntimeException If fail to execute the call
327
- */
328
- public <T > ApiResponse <T > execute (Call call , Type returnType )
329
- throws AlgoliaRuntimeException {
330
- try {
331
- Response response = call .execute ();
332
- T data = handleResponse (response , returnType );
333
- return new ApiResponse <T >(
334
- response .code (),
335
- response .headers ().toMultimap (),
336
- data
337
- );
338
- } catch (IOException e ) {
339
- throw new AlgoliaRuntimeException (e );
340
- }
341
- }
342
-
343
- /**
344
- * {@link #executeAsync(Call, Type, ApiCallback)}
345
- *
346
- * @param <T> Type
347
- * @param call An instance of the Call object
348
- * @param callback ApiCallback<T>
349
- */
350
- public <T > void executeAsync (Call call , ApiCallback <T > callback ) {
351
- executeAsync (call , null , callback );
352
- }
353
-
354
249
/**
355
250
* Execute HTTP call asynchronously.
356
251
*
357
252
* @param <T> Type
358
- * @param call The callback to be executed when the API call finishes
359
253
* @param returnType Return type
360
- * @param callback ApiCallback
361
254
* @see #execute(Call, Type)
362
255
*/
363
- public <T > void executeAsync (
256
+ public <T > CompletableFuture < T > executeAsync (
364
257
Call call ,
365
- final Type returnType ,
366
- final ApiCallback <T > callback
258
+ final Type returnType
367
259
) {
260
+ final CompletableFuture <T > future = new CompletableFuture <>();
368
261
call .enqueue (
369
262
new Callback () {
370
263
@ Override
371
264
public void onFailure (Call call , IOException e ) {
372
- callback . onFailure (new AlgoliaRuntimeException (e ), 0 , null );
265
+ future . completeExceptionally (new AlgoliaRuntimeException (e ));
373
266
}
374
267
375
268
@ Override
376
269
public void onResponse (Call call , Response response )
377
270
throws IOException {
378
- T result ;
379
271
try {
380
- result = (T ) handleResponse (response , returnType );
272
+ T result = requester .handleResponse (response , returnType );
273
+ future .complete (result );
381
274
} catch (AlgoliaRuntimeException e ) {
382
- callback .onFailure (
383
- e ,
384
- response .code (),
385
- response .headers ().toMultimap ()
386
- );
387
- return ;
275
+ future .completeExceptionally (e );
388
276
} catch (Exception e ) {
389
- callback .onFailure (
390
- new AlgoliaRuntimeException (e ),
391
- response .code (),
392
- response .headers ().toMultimap ()
393
- );
394
- return ;
277
+ future .completeExceptionally (new AlgoliaRuntimeException (e ));
395
278
}
396
- callback .onSuccess (
397
- result ,
398
- response .code (),
399
- response .headers ().toMultimap ()
400
- );
401
279
}
402
280
}
403
281
);
404
- }
405
-
406
- /**
407
- * Handle the given response, return the deserialized object when the response is successful.
408
- *
409
- * @param <T> Type
410
- * @param response Response
411
- * @param returnType Return type
412
- * @return Type
413
- * @throws AlgoliaRuntimeException If the response has an unsuccessful status code or fail to
414
- * deserialize the response body
415
- */
416
- public <T > T handleResponse (Response response , Type returnType )
417
- throws AlgoliaRuntimeException {
418
- if (response .isSuccessful ()) {
419
- if (returnType == null || response .code () == 204 ) {
420
- // returning null if the returnType is not defined,
421
- // or the status code is 204 (No Content)
422
- if (response .body () != null ) {
423
- try {
424
- response .body ().close ();
425
- } catch (Exception e ) {
426
- throw new AlgoliaApiException (
427
- response .message (),
428
- e ,
429
- response .code ()
430
- );
431
- }
432
- }
433
- return null ;
434
- } else {
435
- return deserialize (response , returnType );
436
- }
437
- } else {
438
- if (response .body () != null ) {
439
- try {
440
- response .body ().string ();
441
- } catch (IOException e ) {
442
- throw new AlgoliaApiException (response .message (), e , response .code ());
443
- }
444
- }
445
- throw new AlgoliaApiException (response .message (), response .code ());
446
- }
282
+ return future ;
447
283
}
448
284
449
285
/**
@@ -455,7 +291,6 @@ public <T> T handleResponse(Response response, Type returnType)
455
291
* @param queryParams The query parameters
456
292
* @param body The request body object
457
293
* @param headerParams The header parameters
458
- * @param callback Callback for upload/download progress
459
294
* @return The HTTP call
460
295
* @throws AlgoliaRuntimeException If fail to serialize the request body object
461
296
*/
@@ -464,16 +299,14 @@ public Call buildCall(
464
299
String method ,
465
300
Map <String , String > queryParams ,
466
301
Object body ,
467
- Map <String , String > headerParams ,
468
- ApiCallback callback
302
+ Map <String , String > headerParams
469
303
) throws AlgoliaRuntimeException {
470
304
Request request = buildRequest (
471
305
path ,
472
306
method ,
473
307
queryParams ,
474
308
body ,
475
- headerParams ,
476
- callback
309
+ headerParams
477
310
);
478
311
479
312
return requester .newCall (request );
@@ -488,7 +321,6 @@ public Call buildCall(
488
321
* @param queryParams The query parameters
489
322
* @param body The request body object
490
323
* @param headerParams The header parameters
491
- * @param callback Callback for upload/download progress
492
324
* @return The HTTP request
493
325
* @throws AlgoliaRuntimeException If fail to serialize the request body object
494
326
*/
@@ -497,20 +329,21 @@ public Request buildRequest(
497
329
String method ,
498
330
Map <String , String > queryParams ,
499
331
Object body ,
500
- Map <String , String > headerParams ,
501
- ApiCallback callback
332
+ Map <String , String > headerParams
502
333
) throws AlgoliaRuntimeException {
503
334
headerParams .put ("X-Algolia-Application-Id" , this .appId );
504
335
headerParams .put ("X-Algolia-API-Key" , this .apiKey );
505
336
headerParams .put ("Accept" , "application/json" );
506
337
headerParams .put ("Content-Type" , "application/json" );
507
338
339
+ String contentType = "application/json" ;
340
+ headerParams .put ("Accept" , contentType );
341
+ headerParams .put ("Content-Type" , contentType );
342
+
508
343
final String url = buildUrl (path , queryParams );
509
344
final Request .Builder reqBuilder = new Request .Builder ().url (url );
510
345
processHeaderParams (headerParams , reqBuilder );
511
346
512
- String contentType = (String ) headerParams .get ("Content-Type" );
513
-
514
347
RequestBody reqBody ;
515
348
if (!HttpMethod .permitsRequestBody (method )) {
516
349
reqBody = null ;
@@ -526,23 +359,7 @@ public Request buildRequest(
526
359
reqBody = serialize (body , contentType );
527
360
}
528
361
529
- // Associate callback with request (if not null) so interceptor can
530
- // access it when creating ProgressResponseBody
531
- reqBuilder .tag (callback );
532
-
533
- Request request = null ;
534
-
535
- if (callback != null && reqBody != null ) {
536
- ProgressRequestBody progressRequestBody = new ProgressRequestBody (
537
- reqBody ,
538
- callback
539
- );
540
- request = reqBuilder .method (method , progressRequestBody ).build ();
541
- } else {
542
- request = reqBuilder .method (method , reqBody ).build ();
543
- }
544
-
545
- return request ;
362
+ return reqBuilder .method (method , reqBody ).build ();
546
363
}
547
364
548
365
/**
0 commit comments