Skip to content
This repository was archived by the owner on Jan 31, 2022. It is now read-only.

Commit da496fe

Browse files
committed
Merge branch 'master' into feat/deleteBy
2 parents 9e87896 + 73d08fb commit da496fe

File tree

11 files changed

+949
-264
lines changed

11 files changed

+949
-264
lines changed

algoliasearch/src/main/java/com/algolia/search/saas/AbstractClient.java

Lines changed: 67 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,10 @@ public LibraryVersion(@NonNull String name, @NonNull String version) {
7878

7979
@Override
8080
public boolean equals(Object object) {
81-
if (!(object instanceof LibraryVersion))
81+
if (!(object instanceof LibraryVersion)) {
8282
return false;
83-
LibraryVersion other = (LibraryVersion)object;
83+
}
84+
LibraryVersion other = (LibraryVersion) object;
8485
return this.name.equals(other.name) && this.version.equals(other.version);
8586
}
8687

@@ -150,7 +151,8 @@ private static class HostStatus {
150151
protected ExecutorService searchExecutorService = Executors.newFixedThreadPool(4);
151152

152153
/** Executor used to run completion handlers. By default, runs on the main thread. */
153-
protected @NonNull Executor completionExecutor = new HandlerExecutor(new Handler(Looper.getMainLooper()));
154+
protected @NonNull
155+
Executor completionExecutor = new HandlerExecutor(new Handler(Looper.getMainLooper()));
154156

155157
protected Map<String, WeakReference<Object>> indices = new HashMap<>();
156158

@@ -162,19 +164,21 @@ private static class HostStatus {
162164
* Create a new client.
163165
*
164166
* @param applicationID [optional] The application ID.
165-
* @param apiKey [optional] A valid API key for the service.
166-
* @param readHosts List of hosts for read operations.
167-
* @param writeHosts List of hosts for write operations.
167+
* @param apiKey [optional] A valid API key for the service.
168+
* @param readHosts List of hosts for read operations.
169+
* @param writeHosts List of hosts for write operations.
168170
*/
169171
protected AbstractClient(@Nullable String applicationID, @Nullable String apiKey, @Nullable String[] readHosts, @Nullable String[] writeHosts) {
170172
this.applicationID = applicationID;
171173
this.apiKey = apiKey;
172174
this.addUserAgent(new LibraryVersion("Algolia for Android", version));
173175
this.addUserAgent(new LibraryVersion("Android", Build.VERSION.RELEASE));
174-
if (readHosts != null)
176+
if (readHosts != null) {
175177
setReadHosts(readHosts);
176-
if (writeHosts != null)
178+
}
179+
if (writeHosts != null) {
177180
setWriteHosts(writeHosts);
181+
}
178182
}
179183

180184
// ----------------------------------------------------------------------
@@ -322,7 +326,9 @@ public void setHostDownDelay(int hostDownDelay) {
322326
* @param userAgent The library to add.
323327
*/
324328
public void addUserAgent(@NonNull LibraryVersion userAgent) {
325-
userAgents.add(userAgent);
329+
if (!userAgents.contains(userAgent)) {
330+
userAgents.add(userAgent);
331+
}
326332
updateUserAgents();
327333
}
328334

@@ -398,28 +404,28 @@ private enum Method {
398404
GET, POST, PUT, DELETE
399405
}
400406

401-
protected byte[] getRequestRaw(String url, boolean search) throws AlgoliaException {
402-
return _requestRaw(Method.GET, url, null, getReadHostsThatAreUp(), connectTimeout, search ? searchTimeout : readTimeout);
407+
protected byte[] getRequestRaw(@NonNull String url, @Nullable Map<String, String> urlParameters, boolean search, @Nullable RequestOptions requestOptions) throws AlgoliaException {
408+
return _requestRaw(Method.GET, url, urlParameters, /* json: */ null, getReadHostsThatAreUp(), connectTimeout, search ? searchTimeout : readTimeout, requestOptions);
403409
}
404410

405-
protected JSONObject getRequest(String url, boolean search) throws AlgoliaException {
406-
return _request(Method.GET, url, null, getReadHostsThatAreUp(), connectTimeout, search ? searchTimeout : readTimeout);
411+
protected JSONObject getRequest(@NonNull String url, @Nullable Map<String, String> urlParameters, boolean search, @Nullable RequestOptions requestOptions) throws AlgoliaException {
412+
return _request(Method.GET, url, urlParameters, /* json: */ null, getReadHostsThatAreUp(), connectTimeout, search ? searchTimeout : readTimeout, requestOptions);
407413
}
408414

409-
protected JSONObject deleteRequest(String url) throws AlgoliaException {
410-
return _request(Method.DELETE, url, null, getWriteHostsThatAreUp(), connectTimeout, readTimeout);
415+
protected JSONObject deleteRequest(@NonNull String url, @Nullable Map<String, String> urlParameters, @Nullable RequestOptions requestOptions) throws AlgoliaException {
416+
return _request(Method.DELETE, url, urlParameters, /* json: */ null, getWriteHostsThatAreUp(), connectTimeout, readTimeout, requestOptions);
411417
}
412418

413-
protected JSONObject postRequest(String url, String obj, boolean readOperation) throws AlgoliaException {
414-
return _request(Method.POST, url, obj, (readOperation ? getReadHostsThatAreUp() : getWriteHostsThatAreUp()), connectTimeout, (readOperation ? searchTimeout : readTimeout));
419+
protected JSONObject postRequest(@NonNull String url, @Nullable Map<String, String> urlParameters, @Nullable String obj, boolean readOperation, @Nullable RequestOptions requestOptions) throws AlgoliaException {
420+
return _request(Method.POST, url, urlParameters, obj, (readOperation ? getReadHostsThatAreUp() : getWriteHostsThatAreUp()), connectTimeout, (readOperation ? searchTimeout : readTimeout), requestOptions);
415421
}
416422

417-
protected byte[] postRequestRaw(String url, String obj, boolean readOperation) throws AlgoliaException {
418-
return _requestRaw(Method.POST, url, obj, (readOperation ? getReadHostsThatAreUp() : getWriteHostsThatAreUp()), connectTimeout, (readOperation ? searchTimeout : readTimeout));
423+
protected byte[] postRequestRaw(@NonNull String url, @Nullable Map<String, String> urlParameters, @Nullable String obj, boolean readOperation, @Nullable RequestOptions requestOptions) throws AlgoliaException {
424+
return _requestRaw(Method.POST, url, urlParameters, obj, (readOperation ? getReadHostsThatAreUp() : getWriteHostsThatAreUp()), connectTimeout, (readOperation ? searchTimeout : readTimeout), requestOptions);
419425
}
420426

421-
protected JSONObject putRequest(String url, String obj) throws AlgoliaException {
422-
return _request(Method.PUT, url, obj, getWriteHostsThatAreUp(), connectTimeout, readTimeout);
427+
protected JSONObject putRequest(@NonNull String url, @Nullable Map<String, String> urlParameters, @NonNull String obj, @Nullable RequestOptions requestOptions) throws AlgoliaException {
428+
return _request(Method.PUT, url, urlParameters, obj, getWriteHostsThatAreUp(), connectTimeout, readTimeout, requestOptions);
423429
}
424430

425431
/**
@@ -444,6 +450,7 @@ private static String _toCharArray(InputStream stream) throws IOException {
444450

445451
/**
446452
* Reads the InputStream into a byte array
453+
*
447454
* @param stream the InputStream to read
448455
* @return the stream's content as a byte[]
449456
* @throws AlgoliaException if the stream can't be read or flushed
@@ -482,17 +489,18 @@ private static JSONObject _getAnswerJSONObject(InputStream istream) throws IOExc
482489
* Send the query according to parameters and returns its result as a JSONObject
483490
*
484491
* @param m HTTP Method to use
485-
* @param url endpoint URL
492+
* @param url Endpoint URL, *without query string*. The query string is handled by `urlParameters`.
493+
* @param urlParameters URL parameters
486494
* @param json optional JSON Object to send
487495
* @param hostsArray array of hosts to try successively
488496
* @param connectTimeout maximum wait time to open connection
489497
* @param readTimeout maximum time to read data on socket
490498
* @return a JSONObject containing the resulting data or error
491499
* @throws AlgoliaException if the request data is not valid json
492500
*/
493-
private JSONObject _request(Method m, String url, String json, List<String> hostsArray, int connectTimeout, int readTimeout) throws AlgoliaException {
501+
private JSONObject _request(@NonNull Method m, @NonNull String url, @Nullable Map<String, String> urlParameters, @Nullable String json, @NonNull List<String> hostsArray, int connectTimeout, int readTimeout, @Nullable RequestOptions requestOptions) throws AlgoliaException {
494502
try {
495-
return _getJSONObject(_requestRaw(m, url, json, hostsArray, connectTimeout, readTimeout));
503+
return _getJSONObject(_requestRaw(m, url, urlParameters, json, hostsArray, connectTimeout, readTimeout, requestOptions));
496504
} catch (JSONException e) {
497505
throw new AlgoliaException("JSON decode error:" + e.getMessage());
498506
} catch (UnsupportedEncodingException e) {
@@ -504,15 +512,16 @@ private JSONObject _request(Method m, String url, String json, List<String> host
504512
* Send the query according to parameters and returns its result as a JSONObject
505513
*
506514
* @param m HTTP Method to use
507-
* @param url endpoint URL
508-
* @param json optional JSON Object to send
515+
* @param url Endpoint URL, *without query string*. The query string is handled by `urlParameters`.
516+
* @param urlParameters URL parameters
517+
* @param json (optional) JSON body
509518
* @param hostsArray array of hosts to try successively
510519
* @param connectTimeout maximum wait time to open connection
511520
* @param readTimeout maximum time to read data on socket
512521
* @return a JSONObject containing the resulting data or error
513522
* @throws AlgoliaException in case of connection or data handling error
514523
*/
515-
private byte[] _requestRaw(Method m, String url, String json, List<String> hostsArray, int connectTimeout, int readTimeout) throws AlgoliaException {
524+
private byte[] _requestRaw(@NonNull Method m, @NonNull String url, @Nullable Map<String, String> urlParameters, @Nullable String json, @NonNull List<String> hostsArray, int connectTimeout, int readTimeout, @Nullable RequestOptions requestOptions) throws AlgoliaException {
516525
String requestMethod;
517526
List<Exception> errors = new ArrayList<>(hostsArray.size());
518527
// for each host
@@ -536,17 +545,32 @@ private byte[] _requestRaw(Method m, String url, String json, List<String> hosts
536545

537546
InputStream stream = null;
538547
HttpURLConnection hostConnection = null;
539-
// set URL
540548
try {
541-
URL hostURL = new URL("https://" + host + url);
549+
// Compute final URL parameters.
550+
final Map<String, String> parameters = new HashMap<>();
551+
if (urlParameters != null) {
552+
parameters.putAll(urlParameters);
553+
}
554+
if (requestOptions != null) {
555+
parameters.putAll(requestOptions.urlParameters);
556+
}
557+
558+
// Build URL.
559+
String urlString = "https://" + host + url;
560+
if (!parameters.isEmpty()) {
561+
urlString += "?" + AbstractQuery.build(parameters);
562+
}
563+
URL hostURL = new URL(urlString);
564+
565+
// Open connection.
542566
hostConnection = (HttpURLConnection) hostURL.openConnection();
543567

544568
//set timeouts
545569
hostConnection.setRequestMethod(requestMethod);
546570
hostConnection.setConnectTimeout(connectTimeout);
547571
hostConnection.setReadTimeout(readTimeout);
548572

549-
// set auth headers
573+
// Headers
550574
hostConnection.setRequestProperty("X-Algolia-Application-Id", this.applicationID);
551575
// If API key is too big, send it in the request's body (if applicable).
552576
if (this.apiKey != null && this.apiKey.length() > MAX_API_KEY_LENGTH && json != null) {
@@ -560,9 +584,16 @@ private byte[] _requestRaw(Method m, String url, String json, List<String> hosts
560584
} else {
561585
hostConnection.setRequestProperty("X-Algolia-API-Key", this.apiKey);
562586
}
587+
// Client-level headers
563588
for (Map.Entry<String, String> entry : this.headers.entrySet()) {
564589
hostConnection.setRequestProperty(entry.getKey(), entry.getValue());
565590
}
591+
// Request-level headers
592+
if (requestOptions != null) {
593+
for (Map.Entry<String, String> entry : requestOptions.headers.entrySet()) {
594+
hostConnection.setRequestProperty(entry.getKey(), entry.getValue());
595+
}
596+
}
566597

567598
// set user agent
568599
hostConnection.setRequestProperty("User-Agent", userAgentRaw);
@@ -614,12 +645,10 @@ private byte[] _requestRaw(Method m, String url, String json, List<String> hosts
614645
}
615646
return rawResponse;
616647

617-
}
618-
catch (JSONException e) { // fatal
648+
} catch (JSONException e) { // fatal
619649
consumeQuietly(hostConnection);
620650
throw new AlgoliaException("Invalid JSON returned by server", e);
621-
}
622-
catch (UnsupportedEncodingException e) { // fatal
651+
} catch (UnsupportedEncodingException e) { // fatal
623652
consumeQuietly(hostConnection);
624653
throw new AlgoliaException("Invalid encoding returned by server", e);
625654
} catch (IOException e) { // host error, continue on the next host
@@ -673,6 +702,7 @@ private void checkTimeout(int connectTimeout) {
673702

674703
/**
675704
* Get the hosts that are not considered down in a given list.
705+
*
676706
* @param hosts a list of hosts whose {@link HostStatus} will be checked.
677707
* @return the hosts considered up, or all hosts if none is known to be reachable.
678708
*/
@@ -703,7 +733,7 @@ abstract protected class AsyncTaskRequest extends FutureRequest {
703733
* Construct a new request with the specified completion handler, executing on the client's search executor,
704734
* and calling the completion handler on the client's completion executor.
705735
*
706-
* @param completionHandler The completion handler to be notified of results. May be null if the caller omitted it.
736+
* @param completionHandler The completion handler to be notified of results. May be null if the caller omitted it.
707737
*/
708738
protected AsyncTaskRequest(@Nullable CompletionHandler completionHandler) {
709739
this(completionHandler, searchExecutorService);
@@ -713,8 +743,8 @@ protected AsyncTaskRequest(@Nullable CompletionHandler completionHandler) {
713743
* Construct a new request with the specified completion handler, executing on the specified executor, and
714744
* calling the completion handler on the client's completion executor.
715745
*
716-
* @param completionHandler The completion handler to be notified of results. May be null if the caller omitted it.
717-
* @param requestExecutor Executor on which to execute the request.
746+
* @param completionHandler The completion handler to be notified of results. May be null if the caller omitted it.
747+
* @param requestExecutor Executor on which to execute the request.
718748
*/
719749
protected AsyncTaskRequest(@Nullable CompletionHandler completionHandler, @NonNull Executor requestExecutor) {
720750
super(completionHandler, requestExecutor, completionExecutor);

algoliasearch/src/main/java/com/algolia/search/saas/AbstractQuery.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,14 @@ public int hashCode() {
113113
// NOTE: Using a tree map to have parameters sorted by key on output.
114114
@NonNull private Map<String, String> parameters = new TreeMap<>();
115115

116+
/**
117+
* Access the store of query parameters. For internal use only.
118+
* @return The parameters in this query.
119+
*/
120+
Map<String, String> getParameters() {
121+
return parameters;
122+
}
123+
116124
// ----------------------------------------------------------------------
117125
// Construction
118126
// ----------------------------------------------------------------------
@@ -167,6 +175,14 @@ public int hashCode() {
167175
* @return A string suitable for use inside the query part of a URL (i.e. after the question mark).
168176
*/
169177
public @NonNull String build() {
178+
return build(parameters);
179+
}
180+
181+
/**
182+
* Build a query string from a map of URL parameters.
183+
* @return A string suitable for use inside the query part of a URL (i.e. after the question mark).
184+
*/
185+
static @NonNull String build(@NonNull Map<String, String> parameters) {
170186
StringBuilder stringBuilder = new StringBuilder();
171187
try {
172188
for (Map.Entry<String, String> entry : parameters.entrySet()) {

0 commit comments

Comments
 (0)