ignores) {
return new ResponseListener() {
@@ -1108,15 +1352,6 @@ public class RestHighLevelClient implements Closeable {
}
}
- private static RequestOptions optionsForHeaders(Header[] headers) {
- RequestOptions.Builder options = RequestOptions.DEFAULT.toBuilder();
- for (Header header : headers) {
- Objects.requireNonNull(header, "header cannot be null");
- options.addHeader(header.getName(), header.getValue());
- }
- return options.build();
- }
-
static boolean convertExistsResponse(Response response) {
return response.getStatusLine().getStatusCode() == 200;
}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityClient.java
new file mode 100644
index 00000000000..a4bc34004c2
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityClient.java
@@ -0,0 +1,128 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.client;
+
+import org.elasticsearch.action.ActionListener;
+import org.elasticsearch.client.security.DisableUserRequest;
+import org.elasticsearch.client.security.EnableUserRequest;
+import org.elasticsearch.client.security.PutUserRequest;
+import org.elasticsearch.client.security.PutUserResponse;
+import org.elasticsearch.client.security.EmptyResponse;
+
+import java.io.IOException;
+
+import static java.util.Collections.emptySet;
+
+/**
+ * A wrapper for the {@link RestHighLevelClient} that provides methods for accessing the Security APIs.
+ *
+ * See Security APIs on elastic.co
+ */
+public final class SecurityClient {
+
+ private final RestHighLevelClient restHighLevelClient;
+
+ SecurityClient(RestHighLevelClient restHighLevelClient) {
+ this.restHighLevelClient = restHighLevelClient;
+ }
+
+ /**
+ * Create/update a user in the native realm synchronously.
+ * See
+ * the docs for more.
+ * @param request the request with the user's information
+ * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
+ * @return the response from the put user call
+ * @throws IOException in case there is a problem sending the request or parsing back the response
+ */
+ public PutUserResponse putUser(PutUserRequest request, RequestOptions options) throws IOException {
+ return restHighLevelClient.performRequestAndParseEntity(request, SecurityRequestConverters::putUser, options,
+ PutUserResponse::fromXContent, emptySet());
+ }
+
+ /**
+ * Asynchronously create/update a user in the native realm.
+ * See
+ * the docs for more.
+ * @param request the request with the user's information
+ * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
+ * @param listener the listener to be notified upon request completion
+ */
+ public void putUserAsync(PutUserRequest request, RequestOptions options, ActionListener listener) {
+ restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::putUser, options,
+ PutUserResponse::fromXContent, listener, emptySet());
+ }
+
+ /**
+ * Enable a native realm or built-in user synchronously.
+ * See
+ * the docs for more.
+ * @param request the request with the user to enable
+ * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
+ * @return the response from the enable user call
+ * @throws IOException in case there is a problem sending the request or parsing back the response
+ */
+ public EmptyResponse enableUser(EnableUserRequest request, RequestOptions options) throws IOException {
+ return restHighLevelClient.performRequestAndParseEntity(request, SecurityRequestConverters::enableUser, options,
+ EmptyResponse::fromXContent, emptySet());
+ }
+
+ /**
+ * Enable a native realm or built-in user asynchronously.
+ * See
+ * the docs for more.
+ * @param request the request with the user to enable
+ * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
+ * @param listener the listener to be notified upon request completion
+ */
+ public void enableUserAsync(EnableUserRequest request, RequestOptions options,
+ ActionListener listener) {
+ restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::enableUser, options,
+ EmptyResponse::fromXContent, listener, emptySet());
+ }
+
+ /**
+ * Disable a native realm or built-in user synchronously.
+ * See
+ * the docs for more.
+ * @param request the request with the user to disable
+ * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
+ * @return the response from the enable user call
+ * @throws IOException in case there is a problem sending the request or parsing back the response
+ */
+ public EmptyResponse disableUser(DisableUserRequest request, RequestOptions options) throws IOException {
+ return restHighLevelClient.performRequestAndParseEntity(request, SecurityRequestConverters::disableUser, options,
+ EmptyResponse::fromXContent, emptySet());
+ }
+
+ /**
+ * Disable a native realm or built-in user asynchronously.
+ * See
+ * the docs for more.
+ * @param request the request with the user to disable
+ * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
+ * @param listener the listener to be notified upon request completion
+ */
+ public void disableUserAsync(DisableUserRequest request, RequestOptions options,
+ ActionListener listener) {
+ restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::disableUser, options,
+ EmptyResponse::fromXContent, listener, emptySet());
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityRequestConverters.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityRequestConverters.java
new file mode 100644
index 00000000000..8533e0f1b4c
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityRequestConverters.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.client;
+
+import org.apache.http.client.methods.HttpPut;
+import org.elasticsearch.client.security.DisableUserRequest;
+import org.elasticsearch.client.security.EnableUserRequest;
+import org.elasticsearch.client.security.PutUserRequest;
+import org.elasticsearch.client.security.SetUserEnabledRequest;
+
+import java.io.IOException;
+
+import static org.elasticsearch.client.RequestConverters.REQUEST_BODY_CONTENT_TYPE;
+import static org.elasticsearch.client.RequestConverters.createEntity;
+
+final class SecurityRequestConverters {
+
+ private SecurityRequestConverters() {}
+
+ static Request putUser(PutUserRequest putUserRequest) throws IOException {
+ String endpoint = new RequestConverters.EndpointBuilder()
+ .addPathPartAsIs("_xpack/security/user")
+ .addPathPart(putUserRequest.getUsername())
+ .build();
+ Request request = new Request(HttpPut.METHOD_NAME, endpoint);
+ request.setEntity(createEntity(putUserRequest, REQUEST_BODY_CONTENT_TYPE));
+ RequestConverters.Params params = new RequestConverters.Params(request);
+ params.withRefreshPolicy(putUserRequest.getRefreshPolicy());
+ return request;
+ }
+
+ static Request enableUser(EnableUserRequest enableUserRequest) {
+ return setUserEnabled(enableUserRequest);
+ }
+
+ static Request disableUser(DisableUserRequest disableUserRequest) {
+ return setUserEnabled(disableUserRequest);
+ }
+
+ private static Request setUserEnabled(SetUserEnabledRequest setUserEnabledRequest) {
+ String endpoint = new RequestConverters.EndpointBuilder()
+ .addPathPartAsIs("_xpack/security/user")
+ .addPathPart(setUserEnabledRequest.getUsername())
+ .addPathPart(setUserEnabledRequest.isEnabled() ? "_enable" : "_disable")
+ .build();
+ Request request = new Request(HttpPut.METHOD_NAME, endpoint);
+ RequestConverters.Params params = new RequestConverters.Params(request);
+ params.withRefreshPolicy(setUserEnabledRequest.getRefreshPolicy());
+ return request;
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/SnapshotClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/SnapshotClient.java
index 7df0df4836d..f3a49f06459 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/SnapshotClient.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/SnapshotClient.java
@@ -65,7 +65,7 @@ public final class SnapshotClient {
*/
public GetRepositoriesResponse getRepository(GetRepositoriesRequest getRepositoriesRequest, RequestOptions options)
throws IOException {
- return restHighLevelClient.performRequestAndParseEntity(getRepositoriesRequest, RequestConverters::getRepositories, options,
+ return restHighLevelClient.performRequestAndParseEntity(getRepositoriesRequest, SnapshotRequestConverters::getRepositories, options,
GetRepositoriesResponse::fromXContent, emptySet());
}
@@ -80,7 +80,7 @@ public final class SnapshotClient {
*/
public void getRepositoryAsync(GetRepositoriesRequest getRepositoriesRequest, RequestOptions options,
ActionListener listener) {
- restHighLevelClient.performRequestAsyncAndParseEntity(getRepositoriesRequest, RequestConverters::getRepositories, options,
+ restHighLevelClient.performRequestAsyncAndParseEntity(getRepositoriesRequest, SnapshotRequestConverters::getRepositories, options,
GetRepositoriesResponse::fromXContent, listener, emptySet());
}
@@ -94,7 +94,7 @@ public final class SnapshotClient {
* @throws IOException in case there is a problem sending the request or parsing back the response
*/
public AcknowledgedResponse createRepository(PutRepositoryRequest putRepositoryRequest, RequestOptions options) throws IOException {
- return restHighLevelClient.performRequestAndParseEntity(putRepositoryRequest, RequestConverters::createRepository, options,
+ return restHighLevelClient.performRequestAndParseEntity(putRepositoryRequest, SnapshotRequestConverters::createRepository, options,
AcknowledgedResponse::fromXContent, emptySet());
}
@@ -108,7 +108,7 @@ public final class SnapshotClient {
*/
public void createRepositoryAsync(PutRepositoryRequest putRepositoryRequest, RequestOptions options,
ActionListener listener) {
- restHighLevelClient.performRequestAsyncAndParseEntity(putRepositoryRequest, RequestConverters::createRepository, options,
+ restHighLevelClient.performRequestAsyncAndParseEntity(putRepositoryRequest, SnapshotRequestConverters::createRepository, options,
AcknowledgedResponse::fromXContent, listener, emptySet());
}
@@ -123,8 +123,8 @@ public final class SnapshotClient {
*/
public AcknowledgedResponse deleteRepository(DeleteRepositoryRequest deleteRepositoryRequest, RequestOptions options)
throws IOException {
- return restHighLevelClient.performRequestAndParseEntity(deleteRepositoryRequest, RequestConverters::deleteRepository, options,
- AcknowledgedResponse::fromXContent, emptySet());
+ return restHighLevelClient.performRequestAndParseEntity(deleteRepositoryRequest, SnapshotRequestConverters::deleteRepository,
+ options, AcknowledgedResponse::fromXContent, emptySet());
}
/**
@@ -137,7 +137,7 @@ public final class SnapshotClient {
*/
public void deleteRepositoryAsync(DeleteRepositoryRequest deleteRepositoryRequest, RequestOptions options,
ActionListener listener) {
- restHighLevelClient.performRequestAsyncAndParseEntity(deleteRepositoryRequest, RequestConverters::deleteRepository, options,
+ restHighLevelClient.performRequestAsyncAndParseEntity(deleteRepositoryRequest, SnapshotRequestConverters::deleteRepository, options,
AcknowledgedResponse::fromXContent, listener, emptySet());
}
@@ -152,8 +152,8 @@ public final class SnapshotClient {
*/
public VerifyRepositoryResponse verifyRepository(VerifyRepositoryRequest verifyRepositoryRequest, RequestOptions options)
throws IOException {
- return restHighLevelClient.performRequestAndParseEntity(verifyRepositoryRequest, RequestConverters::verifyRepository, options,
- VerifyRepositoryResponse::fromXContent, emptySet());
+ return restHighLevelClient.performRequestAndParseEntity(verifyRepositoryRequest, SnapshotRequestConverters::verifyRepository,
+ options, VerifyRepositoryResponse::fromXContent, emptySet());
}
/**
@@ -166,7 +166,7 @@ public final class SnapshotClient {
*/
public void verifyRepositoryAsync(VerifyRepositoryRequest verifyRepositoryRequest, RequestOptions options,
ActionListener listener) {
- restHighLevelClient.performRequestAsyncAndParseEntity(verifyRepositoryRequest, RequestConverters::verifyRepository, options,
+ restHighLevelClient.performRequestAsyncAndParseEntity(verifyRepositoryRequest, SnapshotRequestConverters::verifyRepository, options,
VerifyRepositoryResponse::fromXContent, listener, emptySet());
}
@@ -178,7 +178,7 @@ public final class SnapshotClient {
*/
public CreateSnapshotResponse create(CreateSnapshotRequest createSnapshotRequest, RequestOptions options)
throws IOException {
- return restHighLevelClient.performRequestAndParseEntity(createSnapshotRequest, RequestConverters::createSnapshot, options,
+ return restHighLevelClient.performRequestAndParseEntity(createSnapshotRequest, SnapshotRequestConverters::createSnapshot, options,
CreateSnapshotResponse::fromXContent, emptySet());
}
@@ -190,7 +190,7 @@ public final class SnapshotClient {
*/
public void createAsync(CreateSnapshotRequest createSnapshotRequest, RequestOptions options,
ActionListener listener) {
- restHighLevelClient.performRequestAsyncAndParseEntity(createSnapshotRequest, RequestConverters::createSnapshot, options,
+ restHighLevelClient.performRequestAsyncAndParseEntity(createSnapshotRequest, SnapshotRequestConverters::createSnapshot, options,
CreateSnapshotResponse::fromXContent, listener, emptySet());
}
@@ -205,7 +205,7 @@ public final class SnapshotClient {
* @throws IOException in case there is a problem sending the request or parsing back the response
*/
public GetSnapshotsResponse get(GetSnapshotsRequest getSnapshotsRequest, RequestOptions options) throws IOException {
- return restHighLevelClient.performRequestAndParseEntity(getSnapshotsRequest, RequestConverters::getSnapshots, options,
+ return restHighLevelClient.performRequestAndParseEntity(getSnapshotsRequest, SnapshotRequestConverters::getSnapshots, options,
GetSnapshotsResponse::fromXContent, emptySet());
}
@@ -219,7 +219,7 @@ public final class SnapshotClient {
* @param listener the listener to be notified upon request completion
*/
public void getAsync(GetSnapshotsRequest getSnapshotsRequest, RequestOptions options, ActionListener listener) {
- restHighLevelClient.performRequestAsyncAndParseEntity(getSnapshotsRequest, RequestConverters::getSnapshots, options,
+ restHighLevelClient.performRequestAsyncAndParseEntity(getSnapshotsRequest, SnapshotRequestConverters::getSnapshots, options,
GetSnapshotsResponse::fromXContent, listener, emptySet());
}
@@ -234,7 +234,7 @@ public final class SnapshotClient {
*/
public SnapshotsStatusResponse status(SnapshotsStatusRequest snapshotsStatusRequest, RequestOptions options)
throws IOException {
- return restHighLevelClient.performRequestAndParseEntity(snapshotsStatusRequest, RequestConverters::snapshotsStatus, options,
+ return restHighLevelClient.performRequestAndParseEntity(snapshotsStatusRequest, SnapshotRequestConverters::snapshotsStatus, options,
SnapshotsStatusResponse::fromXContent, emptySet());
}
@@ -248,7 +248,7 @@ public final class SnapshotClient {
*/
public void statusAsync(SnapshotsStatusRequest snapshotsStatusRequest, RequestOptions options,
ActionListener listener) {
- restHighLevelClient.performRequestAsyncAndParseEntity(snapshotsStatusRequest, RequestConverters::snapshotsStatus, options,
+ restHighLevelClient.performRequestAsyncAndParseEntity(snapshotsStatusRequest, SnapshotRequestConverters::snapshotsStatus, options,
SnapshotsStatusResponse::fromXContent, listener, emptySet());
}
@@ -263,7 +263,7 @@ public final class SnapshotClient {
* @throws IOException in case there is a problem sending the request or parsing back the response
*/
public RestoreSnapshotResponse restore(RestoreSnapshotRequest restoreSnapshotRequest, RequestOptions options) throws IOException {
- return restHighLevelClient.performRequestAndParseEntity(restoreSnapshotRequest, RequestConverters::restoreSnapshot, options,
+ return restHighLevelClient.performRequestAndParseEntity(restoreSnapshotRequest, SnapshotRequestConverters::restoreSnapshot, options,
RestoreSnapshotResponse::fromXContent, emptySet());
}
@@ -278,7 +278,7 @@ public final class SnapshotClient {
*/
public void restoreAsync(RestoreSnapshotRequest restoreSnapshotRequest, RequestOptions options,
ActionListener listener) {
- restHighLevelClient.performRequestAsyncAndParseEntity(restoreSnapshotRequest, RequestConverters::restoreSnapshot, options,
+ restHighLevelClient.performRequestAsyncAndParseEntity(restoreSnapshotRequest, SnapshotRequestConverters::restoreSnapshot, options,
RestoreSnapshotResponse::fromXContent, listener, emptySet());
}
@@ -293,7 +293,7 @@ public final class SnapshotClient {
* @throws IOException in case there is a problem sending the request or parsing back the response
*/
public AcknowledgedResponse delete(DeleteSnapshotRequest deleteSnapshotRequest, RequestOptions options) throws IOException {
- return restHighLevelClient.performRequestAndParseEntity(deleteSnapshotRequest, RequestConverters::deleteSnapshot, options,
+ return restHighLevelClient.performRequestAndParseEntity(deleteSnapshotRequest, SnapshotRequestConverters::deleteSnapshot, options,
AcknowledgedResponse::fromXContent, emptySet());
}
@@ -308,7 +308,7 @@ public final class SnapshotClient {
*/
public void deleteAsync(DeleteSnapshotRequest deleteSnapshotRequest, RequestOptions options,
ActionListener listener) {
- restHighLevelClient.performRequestAsyncAndParseEntity(deleteSnapshotRequest, RequestConverters::deleteSnapshot, options,
+ restHighLevelClient.performRequestAsyncAndParseEntity(deleteSnapshotRequest, SnapshotRequestConverters::deleteSnapshot, options,
AcknowledgedResponse::fromXContent, listener, emptySet());
}
}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/SnapshotRequestConverters.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/SnapshotRequestConverters.java
new file mode 100644
index 00000000000..7ddd0892585
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/SnapshotRequestConverters.java
@@ -0,0 +1,162 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.client;
+
+import org.apache.http.client.methods.HttpDelete;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpPut;
+import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteRepositoryRequest;
+import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRequest;
+import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequest;
+import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryRequest;
+import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotRequest;
+import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
+import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsRequest;
+import org.elasticsearch.action.admin.cluster.snapshots.restore.RestoreSnapshotRequest;
+import org.elasticsearch.action.admin.cluster.snapshots.status.SnapshotsStatusRequest;
+import org.elasticsearch.common.Strings;
+
+import java.io.IOException;
+
+public class SnapshotRequestConverters {
+
+ static Request getRepositories(GetRepositoriesRequest getRepositoriesRequest) {
+ String[] repositories = getRepositoriesRequest.repositories() == null ? Strings.EMPTY_ARRAY : getRepositoriesRequest.repositories();
+ String endpoint = new RequestConverters.EndpointBuilder().addPathPartAsIs("_snapshot").addCommaSeparatedPathParts(repositories)
+ .build();
+ Request request = new Request(HttpGet.METHOD_NAME, endpoint);
+
+ RequestConverters.Params parameters = new RequestConverters.Params(request);
+ parameters.withMasterTimeout(getRepositoriesRequest.masterNodeTimeout());
+ parameters.withLocal(getRepositoriesRequest.local());
+ return request;
+ }
+
+ static Request createRepository(PutRepositoryRequest putRepositoryRequest) throws IOException {
+ String endpoint = new RequestConverters.EndpointBuilder().addPathPart("_snapshot").addPathPart(putRepositoryRequest.name()).build();
+ Request request = new Request(HttpPut.METHOD_NAME, endpoint);
+
+ RequestConverters.Params parameters = new RequestConverters.Params(request);
+ parameters.withMasterTimeout(putRepositoryRequest.masterNodeTimeout());
+ parameters.withTimeout(putRepositoryRequest.timeout());
+ parameters.withVerify(putRepositoryRequest.verify());
+
+ request.setEntity(RequestConverters.createEntity(putRepositoryRequest, RequestConverters.REQUEST_BODY_CONTENT_TYPE));
+ return request;
+ }
+
+ static Request deleteRepository(DeleteRepositoryRequest deleteRepositoryRequest) {
+ String endpoint = new RequestConverters.EndpointBuilder().addPathPartAsIs("_snapshot").addPathPart(deleteRepositoryRequest.name())
+ .build();
+ Request request = new Request(HttpDelete.METHOD_NAME, endpoint);
+
+ RequestConverters.Params parameters = new RequestConverters.Params(request);
+ parameters.withMasterTimeout(deleteRepositoryRequest.masterNodeTimeout());
+ parameters.withTimeout(deleteRepositoryRequest.timeout());
+ return request;
+ }
+
+ static Request verifyRepository(VerifyRepositoryRequest verifyRepositoryRequest) {
+ String endpoint = new RequestConverters.EndpointBuilder().addPathPartAsIs("_snapshot")
+ .addPathPart(verifyRepositoryRequest.name())
+ .addPathPartAsIs("_verify")
+ .build();
+ Request request = new Request(HttpPost.METHOD_NAME, endpoint);
+
+ RequestConverters.Params parameters = new RequestConverters.Params(request);
+ parameters.withMasterTimeout(verifyRepositoryRequest.masterNodeTimeout());
+ parameters.withTimeout(verifyRepositoryRequest.timeout());
+ return request;
+ }
+
+ static Request createSnapshot(CreateSnapshotRequest createSnapshotRequest) throws IOException {
+ String endpoint = new RequestConverters.EndpointBuilder().addPathPart("_snapshot")
+ .addPathPart(createSnapshotRequest.repository())
+ .addPathPart(createSnapshotRequest.snapshot())
+ .build();
+ Request request = new Request(HttpPut.METHOD_NAME, endpoint);
+ RequestConverters.Params params = new RequestConverters.Params(request);
+ params.withMasterTimeout(createSnapshotRequest.masterNodeTimeout());
+ params.withWaitForCompletion(createSnapshotRequest.waitForCompletion());
+ request.setEntity(RequestConverters.createEntity(createSnapshotRequest, RequestConverters.REQUEST_BODY_CONTENT_TYPE));
+ return request;
+ }
+
+ static Request getSnapshots(GetSnapshotsRequest getSnapshotsRequest) {
+ RequestConverters.EndpointBuilder endpointBuilder = new RequestConverters.EndpointBuilder().addPathPartAsIs("_snapshot")
+ .addPathPart(getSnapshotsRequest.repository());
+ String endpoint;
+ if (getSnapshotsRequest.snapshots().length == 0) {
+ endpoint = endpointBuilder.addPathPart("_all").build();
+ } else {
+ endpoint = endpointBuilder.addCommaSeparatedPathParts(getSnapshotsRequest.snapshots()).build();
+ }
+
+ Request request = new Request(HttpGet.METHOD_NAME, endpoint);
+
+ RequestConverters.Params parameters = new RequestConverters.Params(request);
+ parameters.withMasterTimeout(getSnapshotsRequest.masterNodeTimeout());
+ parameters.putParam("ignore_unavailable", Boolean.toString(getSnapshotsRequest.ignoreUnavailable()));
+ parameters.putParam("verbose", Boolean.toString(getSnapshotsRequest.verbose()));
+
+ return request;
+ }
+
+ static Request snapshotsStatus(SnapshotsStatusRequest snapshotsStatusRequest) {
+ String endpoint = new RequestConverters.EndpointBuilder().addPathPartAsIs("_snapshot")
+ .addPathPart(snapshotsStatusRequest.repository())
+ .addCommaSeparatedPathParts(snapshotsStatusRequest.snapshots())
+ .addPathPartAsIs("_status")
+ .build();
+ Request request = new Request(HttpGet.METHOD_NAME, endpoint);
+
+ RequestConverters.Params parameters = new RequestConverters.Params(request);
+ parameters.withMasterTimeout(snapshotsStatusRequest.masterNodeTimeout());
+ parameters.withIgnoreUnavailable(snapshotsStatusRequest.ignoreUnavailable());
+ return request;
+ }
+
+ static Request restoreSnapshot(RestoreSnapshotRequest restoreSnapshotRequest) throws IOException {
+ String endpoint = new RequestConverters.EndpointBuilder().addPathPartAsIs("_snapshot")
+ .addPathPart(restoreSnapshotRequest.repository())
+ .addPathPart(restoreSnapshotRequest.snapshot())
+ .addPathPartAsIs("_restore")
+ .build();
+ Request request = new Request(HttpPost.METHOD_NAME, endpoint);
+ RequestConverters.Params parameters = new RequestConverters.Params(request);
+ parameters.withMasterTimeout(restoreSnapshotRequest.masterNodeTimeout());
+ parameters.withWaitForCompletion(restoreSnapshotRequest.waitForCompletion());
+ request.setEntity(RequestConverters.createEntity(restoreSnapshotRequest, RequestConverters.REQUEST_BODY_CONTENT_TYPE));
+ return request;
+ }
+
+ static Request deleteSnapshot(DeleteSnapshotRequest deleteSnapshotRequest) {
+ String endpoint = new RequestConverters.EndpointBuilder().addPathPartAsIs("_snapshot")
+ .addPathPart(deleteSnapshotRequest.repository())
+ .addPathPart(deleteSnapshotRequest.snapshot())
+ .build();
+ Request request = new Request(HttpDelete.METHOD_NAME, endpoint);
+
+ RequestConverters.Params parameters = new RequestConverters.Params(request);
+ parameters.withMasterTimeout(deleteSnapshotRequest.masterNodeTimeout());
+ return request;
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/TasksClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/TasksClient.java
index ebba636b8fa..3b957b2defb 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/TasksClient.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/TasksClient.java
@@ -51,7 +51,7 @@ public final class TasksClient {
* @throws IOException in case there is a problem sending the request or parsing back the response
*/
public ListTasksResponse list(ListTasksRequest request, RequestOptions options) throws IOException {
- return restHighLevelClient.performRequestAndParseEntity(request, RequestConverters::listTasks, options,
+ return restHighLevelClient.performRequestAndParseEntity(request, TasksRequestConverters::listTasks, options,
ListTasksResponse::fromXContent, emptySet());
}
@@ -64,7 +64,7 @@ public final class TasksClient {
* @param listener the listener to be notified upon request completion
*/
public void listAsync(ListTasksRequest request, RequestOptions options, ActionListener listener) {
- restHighLevelClient.performRequestAsyncAndParseEntity(request, RequestConverters::listTasks, options,
+ restHighLevelClient.performRequestAsyncAndParseEntity(request, TasksRequestConverters::listTasks, options,
ListTasksResponse::fromXContent, listener, emptySet());
}
@@ -82,7 +82,7 @@ public final class TasksClient {
public CancelTasksResponse cancel(CancelTasksRequest cancelTasksRequest, RequestOptions options ) throws IOException {
return restHighLevelClient.performRequestAndParseEntity(
cancelTasksRequest,
- RequestConverters::cancelTasks,
+ TasksRequestConverters::cancelTasks,
options,
CancelTasksResponse::fromXContent,
emptySet()
@@ -101,7 +101,7 @@ public final class TasksClient {
public void cancelAsync(CancelTasksRequest cancelTasksRequest, RequestOptions options, ActionListener listener) {
restHighLevelClient.performRequestAsyncAndParseEntity(
cancelTasksRequest,
- RequestConverters::cancelTasks,
+ TasksRequestConverters::cancelTasks,
options,
CancelTasksResponse::fromXContent,
listener,
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/TasksRequestConverters.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/TasksRequestConverters.java
new file mode 100644
index 00000000000..93b407a82fe
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/TasksRequestConverters.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.client;
+
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.elasticsearch.action.admin.cluster.node.tasks.cancel.CancelTasksRequest;
+import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksRequest;
+
+public class TasksRequestConverters {
+
+ static Request cancelTasks(CancelTasksRequest cancelTasksRequest) {
+ Request request = new Request(HttpPost.METHOD_NAME, "/_tasks/_cancel");
+ RequestConverters.Params params = new RequestConverters.Params(request);
+ params.withTimeout(cancelTasksRequest.getTimeout())
+ .withTaskId(cancelTasksRequest.getTaskId())
+ .withNodes(cancelTasksRequest.getNodes())
+ .withParentTaskId(cancelTasksRequest.getParentTaskId())
+ .withActions(cancelTasksRequest.getActions());
+ return request;
+ }
+
+ static Request listTasks(ListTasksRequest listTaskRequest) {
+ if (listTaskRequest.getTaskId() != null && listTaskRequest.getTaskId().isSet()) {
+ throw new IllegalArgumentException("TaskId cannot be used for list tasks request");
+ }
+ Request request = new Request(HttpGet.METHOD_NAME, "/_tasks");
+ RequestConverters.Params params = new RequestConverters.Params(request);
+ params.withTimeout(listTaskRequest.getTimeout())
+ .withDetailed(listTaskRequest.getDetailed())
+ .withWaitForCompletion(listTaskRequest.getWaitForCompletion())
+ .withParentTaskId(listTaskRequest.getParentTaskId())
+ .withNodes(listTaskRequest.getNodes())
+ .withActions(listTaskRequest.getActions())
+ .putParam("group_by", "none");
+ return request;
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/TimedRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/TimedRequest.java
new file mode 100644
index 00000000000..af8fbe3e72b
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/TimedRequest.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.elasticsearch.client;
+
+import org.elasticsearch.common.unit.TimeValue;
+
+/**
+ * A base request for any requests that supply timeouts.
+ *
+ * Please note, any requests that use a ackTimeout should set timeout as they
+ * represent the same backing field on the server.
+ */
+public class TimedRequest implements Validatable {
+
+ private TimeValue timeout;
+ private TimeValue masterTimeout;
+
+ public void setTimeout(TimeValue timeout) {
+ this.timeout = timeout;
+
+ }
+
+ public void setMasterTimeout(TimeValue masterTimeout) {
+ this.masterTimeout = masterTimeout;
+ }
+
+ /**
+ * Returns the request timeout
+ */
+ public TimeValue timeout() {
+ return timeout;
+ }
+
+ /**
+ * Returns the timeout for the request to be completed on the master node
+ */
+ public TimeValue masterNodeTimeout() {
+ return masterTimeout;
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/Validatable.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/Validatable.java
new file mode 100644
index 00000000000..fe4a1fc42cb
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/Validatable.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.elasticsearch.client;
+
+import java.util.Optional;
+
+/**
+ * Defines a validation layer for Requests.
+ */
+public interface Validatable {
+ /**
+ * Perform validation. This method does not have to be overridden in the event that no validation needs to be done,
+ * or the validation was done during object construction time. A {@link ValidationException} that is not null is
+ * assumed to contain validation errors and will be thrown.
+ *
+ * @return An {@link Optional} {@link ValidationException} that contains a list of validation errors.
+ */
+ default Optional validate() {
+ return Optional.empty();
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ValidationException.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ValidationException.java
new file mode 100644
index 00000000000..6b5d738d675
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ValidationException.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.elasticsearch.client;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Encapsulates an accumulation of validation errors
+ */
+public class ValidationException extends IllegalArgumentException {
+ private final List validationErrors = new ArrayList<>();
+
+ /**
+ * Add a new validation error to the accumulating validation errors
+ * @param error the error to add
+ */
+ public void addValidationError(String error) {
+ validationErrors.add(error);
+ }
+
+ /**
+ * Returns the validation errors accumulated
+ */
+ public final List validationErrors() {
+ return validationErrors;
+ }
+
+ @Override
+ public final String getMessage() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Validation Failed: ");
+ int index = 0;
+ for (String error : validationErrors) {
+ sb.append(++index).append(": ").append(error).append(";");
+ }
+ return sb.toString();
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/WatcherClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/WatcherClient.java
index 48487926f02..b1a3eb3f87b 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/WatcherClient.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/WatcherClient.java
@@ -47,7 +47,7 @@ public final class WatcherClient {
* @throws IOException in case there is a problem sending the request or parsing back the response
*/
public PutWatchResponse putWatch(PutWatchRequest request, RequestOptions options) throws IOException {
- return restHighLevelClient.performRequestAndParseEntity(request, RequestConverters::xPackWatcherPutWatch, options,
+ return restHighLevelClient.performRequestAndParseEntity(request, WatcherRequestConverters::putWatch, options,
PutWatchResponse::fromXContent, emptySet());
}
@@ -61,7 +61,7 @@ public final class WatcherClient {
*/
public void putWatchAsync(PutWatchRequest request, RequestOptions options,
ActionListener listener) {
- restHighLevelClient.performRequestAsyncAndParseEntity(request, RequestConverters::xPackWatcherPutWatch, options,
+ restHighLevelClient.performRequestAsyncAndParseEntity(request, WatcherRequestConverters::putWatch, options,
PutWatchResponse::fromXContent, listener, emptySet());
}
@@ -75,7 +75,7 @@ public final class WatcherClient {
* @throws IOException in case there is a problem sending the request or parsing back the response
*/
public DeleteWatchResponse deleteWatch(DeleteWatchRequest request, RequestOptions options) throws IOException {
- return restHighLevelClient.performRequestAndParseEntity(request, RequestConverters::xPackWatcherDeleteWatch, options,
+ return restHighLevelClient.performRequestAndParseEntity(request, WatcherRequestConverters::deleteWatch, options,
DeleteWatchResponse::fromXContent, singleton(404));
}
@@ -88,7 +88,7 @@ public final class WatcherClient {
* @param listener the listener to be notified upon request completion
*/
public void deleteWatchAsync(DeleteWatchRequest request, RequestOptions options, ActionListener listener) {
- restHighLevelClient.performRequestAsyncAndParseEntity(request, RequestConverters::xPackWatcherDeleteWatch, options,
+ restHighLevelClient.performRequestAsyncAndParseEntity(request, WatcherRequestConverters::deleteWatch, options,
DeleteWatchResponse::fromXContent, listener, singleton(404));
}
}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/WatcherRequestConverters.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/WatcherRequestConverters.java
new file mode 100644
index 00000000000..3b52d1c7b99
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/WatcherRequestConverters.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.client;
+
+import org.apache.http.client.methods.HttpDelete;
+import org.apache.http.client.methods.HttpPut;
+import org.apache.http.entity.ByteArrayEntity;
+import org.apache.http.entity.ContentType;
+import org.elasticsearch.common.bytes.BytesReference;
+import org.elasticsearch.protocol.xpack.watcher.DeleteWatchRequest;
+import org.elasticsearch.protocol.xpack.watcher.PutWatchRequest;
+
+public class WatcherRequestConverters {
+
+ static Request putWatch(PutWatchRequest putWatchRequest) {
+ String endpoint = new RequestConverters.EndpointBuilder()
+ .addPathPartAsIs("_xpack")
+ .addPathPartAsIs("watcher")
+ .addPathPartAsIs("watch")
+ .addPathPart(putWatchRequest.getId())
+ .build();
+
+ Request request = new Request(HttpPut.METHOD_NAME, endpoint);
+ RequestConverters.Params params = new RequestConverters.Params(request).withVersion(putWatchRequest.getVersion());
+ if (putWatchRequest.isActive() == false) {
+ params.putParam("active", "false");
+ }
+ ContentType contentType = RequestConverters.createContentType(putWatchRequest.xContentType());
+ BytesReference source = putWatchRequest.getSource();
+ request.setEntity(new ByteArrayEntity(source.toBytesRef().bytes, 0, source.length(), contentType));
+ return request;
+ }
+
+ static Request deleteWatch(DeleteWatchRequest deleteWatchRequest) {
+ String endpoint = new RequestConverters.EndpointBuilder()
+ .addPathPartAsIs("_xpack")
+ .addPathPartAsIs("watcher")
+ .addPathPartAsIs("watch")
+ .addPathPart(deleteWatchRequest.getId())
+ .build();
+
+ Request request = new Request(HttpDelete.METHOD_NAME, endpoint);
+ return request;
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/XPackClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/XPackClient.java
index 2af49ba1a1b..9cd8413fa79 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/XPackClient.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/XPackClient.java
@@ -56,7 +56,7 @@ public final class XPackClient {
* @throws IOException in case there is a problem sending the request or parsing back the response
*/
public XPackInfoResponse info(XPackInfoRequest request, RequestOptions options) throws IOException {
- return restHighLevelClient.performRequestAndParseEntity(request, RequestConverters::xPackInfo, options,
+ return restHighLevelClient.performRequestAndParseEntity(request, XPackRequestConverters::info, options,
XPackInfoResponse::fromXContent, emptySet());
}
@@ -70,7 +70,7 @@ public final class XPackClient {
*/
public void infoAsync(XPackInfoRequest request, RequestOptions options,
ActionListener listener) {
- restHighLevelClient.performRequestAsyncAndParseEntity(request, RequestConverters::xPackInfo, options,
+ restHighLevelClient.performRequestAsyncAndParseEntity(request, XPackRequestConverters::info, options,
XPackInfoResponse::fromXContent, listener, emptySet());
}
@@ -81,7 +81,7 @@ public final class XPackClient {
* @throws IOException in case there is a problem sending the request or parsing back the response
*/
public XPackUsageResponse usage(XPackUsageRequest request, RequestOptions options) throws IOException {
- return restHighLevelClient.performRequestAndParseEntity(request, RequestConverters::xpackUsage, options,
+ return restHighLevelClient.performRequestAndParseEntity(request, XPackRequestConverters::usage, options,
XPackUsageResponse::fromXContent, emptySet());
}
@@ -91,7 +91,7 @@ public final class XPackClient {
* @param listener the listener to be notified upon request completion
*/
public void usageAsync(XPackUsageRequest request, RequestOptions options, ActionListener listener) {
- restHighLevelClient.performRequestAsyncAndParseEntity(request, RequestConverters::xpackUsage, options,
+ restHighLevelClient.performRequestAsyncAndParseEntity(request, XPackRequestConverters::usage, options,
XPackUsageResponse::fromXContent, listener, emptySet());
}
}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/XPackRequestConverters.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/XPackRequestConverters.java
new file mode 100644
index 00000000000..1e2e15ad97c
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/XPackRequestConverters.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.client;
+
+import org.apache.http.client.methods.HttpGet;
+import org.elasticsearch.protocol.xpack.XPackInfoRequest;
+import org.elasticsearch.protocol.xpack.XPackUsageRequest;
+
+import java.util.EnumSet;
+import java.util.Locale;
+import java.util.stream.Collectors;
+
+public class XPackRequestConverters {
+
+ static Request info(XPackInfoRequest infoRequest) {
+ Request request = new Request(HttpGet.METHOD_NAME, "/_xpack");
+ if (false == infoRequest.isVerbose()) {
+ request.addParameter("human", "false");
+ }
+ if (false == infoRequest.getCategories().equals(EnumSet.allOf(XPackInfoRequest.Category.class))) {
+ request.addParameter("categories", infoRequest.getCategories().stream()
+ .map(c -> c.toString().toLowerCase(Locale.ROOT))
+ .collect(Collectors.joining(",")));
+ }
+ return request;
+ }
+
+ static Request usage(XPackUsageRequest usageRequest) {
+ Request request = new Request(HttpGet.METHOD_NAME, "/_xpack/usage");
+ RequestConverters.Params parameters = new RequestConverters.Params(request);
+ parameters.withMasterTimeout(usageRequest.masterNodeTimeout());
+ return request;
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/AbstractResultResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/AbstractResultResponse.java
new file mode 100644
index 00000000000..1b609797dd6
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/AbstractResultResponse.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.elasticsearch.client.ml;
+
+import org.elasticsearch.action.ActionResponse;
+import org.elasticsearch.common.ParseField;
+import org.elasticsearch.common.xcontent.ToXContent;
+import org.elasticsearch.common.xcontent.ToXContentObject;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Abstract class that provides a list of results and their count.
+ */
+public abstract class AbstractResultResponse extends ActionResponse implements ToXContentObject {
+
+ public static final ParseField COUNT = new ParseField("count");
+
+ private final ParseField resultsField;
+ protected final List results;
+ protected final long count;
+
+ AbstractResultResponse(ParseField resultsField, List results, long count) {
+ this.resultsField = Objects.requireNonNull(resultsField,
+ "[results_field] must not be null");
+ this.results = Collections.unmodifiableList(results);
+ this.count = count;
+ }
+
+ @Override
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+ builder.startObject();
+ builder.field(COUNT.getPreferredName(), count);
+ builder.field(resultsField.getPreferredName(), results);
+ builder.endObject();
+ return builder;
+ }
+
+ public long count() {
+ return count;
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/CloseJobRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/CloseJobRequest.java
new file mode 100644
index 00000000000..19f3df8e432
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/CloseJobRequest.java
@@ -0,0 +1,195 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.elasticsearch.client.ml;
+
+import org.elasticsearch.action.ActionRequest;
+import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.common.ParseField;
+import org.elasticsearch.common.Strings;
+import org.elasticsearch.common.unit.TimeValue;
+import org.elasticsearch.common.xcontent.ConstructingObjectParser;
+import org.elasticsearch.common.xcontent.ObjectParser;
+import org.elasticsearch.common.xcontent.ToXContentObject;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+
+import java.io.IOException;
+import java.security.InvalidParameterException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Request to close Machine Learning Jobs
+ */
+public class CloseJobRequest extends ActionRequest implements ToXContentObject {
+
+ public static final ParseField JOB_ID = new ParseField("job_id");
+ public static final ParseField TIMEOUT = new ParseField("timeout");
+ public static final ParseField FORCE = new ParseField("force");
+ public static final ParseField ALLOW_NO_JOBS = new ParseField("allow_no_jobs");
+
+ @SuppressWarnings("unchecked")
+ public static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>(
+ "close_job_request",
+ true, a -> new CloseJobRequest((List) a[0]));
+
+ static {
+ PARSER.declareField(ConstructingObjectParser.constructorArg(),
+ p -> Arrays.asList(Strings.commaDelimitedListToStringArray(p.text())),
+ JOB_ID, ObjectParser.ValueType.STRING_ARRAY);
+ PARSER.declareString((obj, val) -> obj.setTimeout(TimeValue.parseTimeValue(val, TIMEOUT.getPreferredName())), TIMEOUT);
+ PARSER.declareBoolean(CloseJobRequest::setForce, FORCE);
+ PARSER.declareBoolean(CloseJobRequest::setAllowNoJobs, ALLOW_NO_JOBS);
+ }
+
+ private static final String ALL_JOBS = "_all";
+
+ private final List jobIds;
+ private TimeValue timeout;
+ private Boolean force;
+ private Boolean allowNoJobs;
+
+ /**
+ * Explicitly close all jobs
+ *
+ * @return a {@link CloseJobRequest} for all existing jobs
+ */
+ public static CloseJobRequest closeAllJobsRequest(){
+ return new CloseJobRequest(ALL_JOBS);
+ }
+
+ CloseJobRequest(List jobIds) {
+ if (jobIds.isEmpty()) {
+ throw new InvalidParameterException("jobIds must not be empty");
+ }
+ if (jobIds.stream().anyMatch(Objects::isNull)) {
+ throw new NullPointerException("jobIds must not contain null values");
+ }
+ this.jobIds = new ArrayList<>(jobIds);
+ }
+
+ /**
+ * Close the specified Jobs via their unique jobIds
+ *
+ * @param jobIds must be non-null and non-empty and each jobId must be non-null
+ */
+ public CloseJobRequest(String... jobIds) {
+ this(Arrays.asList(jobIds));
+ }
+
+ /**
+ * All the jobIds to be closed
+ */
+ public List getJobIds() {
+ return jobIds;
+ }
+
+ public TimeValue getTimeout() {
+ return timeout;
+ }
+
+ /**
+ * How long to wait for the close request to complete before timing out.
+ *
+ * @param timeout Default value: 30 minutes
+ */
+ public void setTimeout(TimeValue timeout) {
+ this.timeout = timeout;
+ }
+
+ public Boolean isForce() {
+ return force;
+ }
+
+ /**
+ * Should the closing be forced.
+ *
+ * Use to close a failed job, or to forcefully close a job which has not responded to its initial close request.
+ *
+ * @param force When {@code true} forcefully close the job. Defaults to {@code false}
+ */
+ public void setForce(boolean force) {
+ this.force = force;
+ }
+
+ public Boolean isAllowNoJobs() {
+ return this.allowNoJobs;
+ }
+
+ /**
+ * Whether to ignore if a wildcard expression matches no jobs.
+ *
+ * This includes `_all` string or when no jobs have been specified
+ *
+ * @param allowNoJobs When {@code true} ignore if wildcard or `_all` matches no jobs. Defaults to {@code true}
+ */
+ public void setAllowNoJobs(boolean allowNoJobs) {
+ this.allowNoJobs = allowNoJobs;
+ }
+
+ @Override
+ public ActionRequestValidationException validate() {
+ return null;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(jobIds, timeout, force, allowNoJobs);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (other == null || getClass() != other.getClass()) {
+ return false;
+ }
+
+ CloseJobRequest that = (CloseJobRequest) other;
+ return Objects.equals(jobIds, that.jobIds) &&
+ Objects.equals(timeout, that.timeout) &&
+ Objects.equals(force, that.force) &&
+ Objects.equals(allowNoJobs, that.allowNoJobs);
+ }
+
+ @Override
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+ builder.startObject();
+ builder.field(JOB_ID.getPreferredName(), Strings.collectionToCommaDelimitedString(jobIds));
+ if (timeout != null) {
+ builder.field(TIMEOUT.getPreferredName(), timeout.getStringRep());
+ }
+ if (force != null) {
+ builder.field(FORCE.getPreferredName(), force);
+ }
+ if (allowNoJobs != null) {
+ builder.field(ALLOW_NO_JOBS.getPreferredName(), allowNoJobs);
+ }
+ builder.endObject();
+ return builder;
+ }
+
+ @Override
+ public String toString() {
+ return Strings.toString(this);
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/CloseJobResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/CloseJobResponse.java
new file mode 100644
index 00000000000..2ac1e0faee3
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/CloseJobResponse.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.elasticsearch.client.ml;
+
+import org.elasticsearch.action.ActionResponse;
+import org.elasticsearch.common.ParseField;
+import org.elasticsearch.common.xcontent.ConstructingObjectParser;
+import org.elasticsearch.common.xcontent.ToXContentObject;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentParser;
+
+import java.io.IOException;
+import java.util.Objects;
+
+/**
+ * Response indicating if the Job(s) closed or not
+ */
+public class CloseJobResponse extends ActionResponse implements ToXContentObject {
+
+ private static final ParseField CLOSED = new ParseField("closed");
+
+ public static final ConstructingObjectParser PARSER =
+ new ConstructingObjectParser<>("close_job_response", true, (a) -> new CloseJobResponse((Boolean)a[0]));
+
+ static {
+ PARSER.declareBoolean(ConstructingObjectParser.constructorArg(), CLOSED);
+ }
+
+ private boolean closed;
+
+ public CloseJobResponse(boolean closed) {
+ this.closed = closed;
+ }
+
+ public static CloseJobResponse fromXContent(XContentParser parser) throws IOException {
+ return PARSER.parse(parser, null);
+ }
+
+ /**
+ * Has the job closed or not
+ * @return boolean value indicating the job closed status
+ */
+ public boolean isClosed() {
+ return closed;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (other == null || getClass() != other.getClass()) {
+ return false;
+ }
+
+ CloseJobResponse that = (CloseJobResponse) other;
+ return isClosed() == that.isClosed();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(isClosed());
+ }
+
+ @Override
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+ builder.startObject();
+ builder.field(CLOSED.getPreferredName(), closed);
+ builder.endObject();
+ return builder;
+ }
+}
diff --git a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/DeleteJobRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteJobRequest.java
similarity index 82%
rename from x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/DeleteJobRequest.java
rename to client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteJobRequest.java
index 1b7450de092..a355f7ec659 100644
--- a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/DeleteJobRequest.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteJobRequest.java
@@ -16,13 +16,16 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.elasticsearch.protocol.xpack.ml;
+package org.elasticsearch.client.ml;
import org.elasticsearch.action.ActionRequest;
import org.elasticsearch.action.ActionRequestValidationException;
import java.util.Objects;
+/**
+ * Request to delete a Machine Learning Job via its ID
+ */
public class DeleteJobRequest extends ActionRequest {
private String jobId;
@@ -36,6 +39,10 @@ public class DeleteJobRequest extends ActionRequest {
return jobId;
}
+ /**
+ * The jobId which to delete
+ * @param jobId unique jobId to delete, must not be null
+ */
public void setJobId(String jobId) {
this.jobId = Objects.requireNonNull(jobId, "[job_id] must not be null");
}
@@ -44,6 +51,12 @@ public class DeleteJobRequest extends ActionRequest {
return force;
}
+ /**
+ * Used to forcefully delete an opened job.
+ * This method is quicker than closing and deleting the job.
+ *
+ * @param force When {@code true} forcefully delete an opened job. Defaults to {@code false}
+ */
public void setForce(boolean force) {
this.force = force;
}
diff --git a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/DeleteJobResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteJobResponse.java
similarity index 94%
rename from x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/DeleteJobResponse.java
rename to client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteJobResponse.java
index 0b4faa38f54..86cafd9e093 100644
--- a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/DeleteJobResponse.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteJobResponse.java
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.elasticsearch.protocol.xpack.ml;
+package org.elasticsearch.client.ml;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.common.xcontent.XContentParser;
@@ -24,6 +24,9 @@ import org.elasticsearch.common.xcontent.XContentParser;
import java.io.IOException;
import java.util.Objects;
+/**
+ * Response acknowledging the Machine Learning Job request
+ */
public class DeleteJobResponse extends AcknowledgedResponse {
public DeleteJobResponse(boolean acknowledged) {
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/FlushJobRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/FlushJobRequest.java
new file mode 100644
index 00000000000..067851d4526
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/FlushJobRequest.java
@@ -0,0 +1,195 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.elasticsearch.client.ml;
+
+import org.elasticsearch.action.ActionRequest;
+import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.ml.job.config.Job;
+import org.elasticsearch.common.ParseField;
+import org.elasticsearch.common.xcontent.ConstructingObjectParser;
+import org.elasticsearch.common.xcontent.ToXContentObject;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+
+import java.io.IOException;
+import java.util.Objects;
+
+/**
+ * Request object to flush a given Machine Learning job.
+ */
+public class FlushJobRequest extends ActionRequest implements ToXContentObject {
+
+ public static final ParseField CALC_INTERIM = new ParseField("calc_interim");
+ public static final ParseField START = new ParseField("start");
+ public static final ParseField END = new ParseField("end");
+ public static final ParseField ADVANCE_TIME = new ParseField("advance_time");
+ public static final ParseField SKIP_TIME = new ParseField("skip_time");
+
+ public static final ConstructingObjectParser PARSER =
+ new ConstructingObjectParser<>("flush_job_request", (a) -> new FlushJobRequest((String) a[0]));
+
+ static {
+ PARSER.declareString(ConstructingObjectParser.constructorArg(), Job.ID);
+ PARSER.declareBoolean(FlushJobRequest::setCalcInterim, CALC_INTERIM);
+ PARSER.declareString(FlushJobRequest::setStart, START);
+ PARSER.declareString(FlushJobRequest::setEnd, END);
+ PARSER.declareString(FlushJobRequest::setAdvanceTime, ADVANCE_TIME);
+ PARSER.declareString(FlushJobRequest::setSkipTime, SKIP_TIME);
+ }
+
+ private final String jobId;
+ private Boolean calcInterim;
+ private String start;
+ private String end;
+ private String advanceTime;
+ private String skipTime;
+
+ /**
+ * Create new Flush job request
+ *
+ * @param jobId The job ID of the job to flush
+ */
+ public FlushJobRequest(String jobId) {
+ this.jobId = jobId;
+ }
+
+ public String getJobId() {
+ return jobId;
+ }
+
+ public boolean getCalcInterim() {
+ return calcInterim;
+ }
+
+ /**
+ * When {@code true} calculates the interim results for the most recent bucket or all buckets within the latency period.
+ *
+ * @param calcInterim defaults to {@code false}.
+ */
+ public void setCalcInterim(boolean calcInterim) {
+ this.calcInterim = calcInterim;
+ }
+
+ public String getStart() {
+ return start;
+ }
+
+ /**
+ * When used in conjunction with {@link FlushJobRequest#calcInterim},
+ * specifies the start of the range of buckets on which to calculate interim results.
+ *
+ * @param start the beginning of the range of buckets; may be an epoch seconds, epoch millis or an ISO string
+ */
+ public void setStart(String start) {
+ this.start = start;
+ }
+
+ public String getEnd() {
+ return end;
+ }
+
+ /**
+ * When used in conjunction with {@link FlushJobRequest#calcInterim}, specifies the end of the range
+ * of buckets on which to calculate interim results
+ *
+ * @param end the end of the range of buckets; may be an epoch seconds, epoch millis or an ISO string
+ */
+ public void setEnd(String end) {
+ this.end = end;
+ }
+
+ public String getAdvanceTime() {
+ return advanceTime;
+ }
+
+ /**
+ * Specifies to advance to a particular time value.
+ * Results are generated and the model is updated for data from the specified time interval.
+ *
+ * @param advanceTime String representation of a timestamp; may be an epoch seconds, epoch millis or an ISO string
+ */
+ public void setAdvanceTime(String advanceTime) {
+ this.advanceTime = advanceTime;
+ }
+
+ public String getSkipTime() {
+ return skipTime;
+ }
+
+ /**
+ * Specifies to skip to a particular time value.
+ * Results are not generated and the model is not updated for data from the specified time interval.
+ *
+ * @param skipTime String representation of a timestamp; may be an epoch seconds, epoch millis or an ISO string
+ */
+ public void setSkipTime(String skipTime) {
+ this.skipTime = skipTime;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(jobId, calcInterim, start, end, advanceTime, skipTime);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+
+ FlushJobRequest other = (FlushJobRequest) obj;
+ return Objects.equals(jobId, other.jobId) &&
+ calcInterim == other.calcInterim &&
+ Objects.equals(start, other.start) &&
+ Objects.equals(end, other.end) &&
+ Objects.equals(advanceTime, other.advanceTime) &&
+ Objects.equals(skipTime, other.skipTime);
+ }
+
+ @Override
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+ builder.startObject();
+ builder.field(Job.ID.getPreferredName(), jobId);
+ if (calcInterim != null) {
+ builder.field(CALC_INTERIM.getPreferredName(), calcInterim);
+ }
+ if (start != null) {
+ builder.field(START.getPreferredName(), start);
+ }
+ if (end != null) {
+ builder.field(END.getPreferredName(), end);
+ }
+ if (advanceTime != null) {
+ builder.field(ADVANCE_TIME.getPreferredName(), advanceTime);
+ }
+ if (skipTime != null) {
+ builder.field(SKIP_TIME.getPreferredName(), skipTime);
+ }
+ builder.endObject();
+ return builder;
+ }
+
+ @Override
+ public ActionRequestValidationException validate() {
+ return null;
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/FlushJobResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/FlushJobResponse.java
new file mode 100644
index 00000000000..048b07b504a
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/FlushJobResponse.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.elasticsearch.client.ml;
+
+import org.elasticsearch.action.ActionResponse;
+import org.elasticsearch.common.Nullable;
+import org.elasticsearch.common.ParseField;
+import org.elasticsearch.common.xcontent.ConstructingObjectParser;
+import org.elasticsearch.common.xcontent.ToXContentObject;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentParser;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.Objects;
+
+/**
+ * Response object containing flush acknowledgement and additional data
+ */
+public class FlushJobResponse extends ActionResponse implements ToXContentObject {
+
+ public static final ParseField FLUSHED = new ParseField("flushed");
+ public static final ParseField LAST_FINALIZED_BUCKET_END = new ParseField("last_finalized_bucket_end");
+
+ public static final ConstructingObjectParser PARSER =
+ new ConstructingObjectParser<>("flush_job_response",
+ true,
+ (a) -> {
+ boolean flushed = (boolean) a[0];
+ Date date = a[1] == null ? null : new Date((long) a[1]);
+ return new FlushJobResponse(flushed, date);
+ });
+
+ static {
+ PARSER.declareBoolean(ConstructingObjectParser.constructorArg(), FLUSHED);
+ PARSER.declareLong(ConstructingObjectParser.optionalConstructorArg(), LAST_FINALIZED_BUCKET_END);
+ }
+
+ public static FlushJobResponse fromXContent(XContentParser parser) throws IOException {
+ return PARSER.parse(parser, null);
+ }
+
+ private final boolean flushed;
+ private final Date lastFinalizedBucketEnd;
+
+ public FlushJobResponse(boolean flushed, @Nullable Date lastFinalizedBucketEnd) {
+ this.flushed = flushed;
+ this.lastFinalizedBucketEnd = lastFinalizedBucketEnd;
+ }
+
+ /**
+ * Was the job successfully flushed or not
+ */
+ public boolean isFlushed() {
+ return flushed;
+ }
+
+ /**
+ * Provides the timestamp (in milliseconds-since-the-epoch) of the end of the last bucket that was processed.
+ */
+ @Nullable
+ public Date getLastFinalizedBucketEnd() {
+ return lastFinalizedBucketEnd;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(flushed, lastFinalizedBucketEnd);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (other == null || getClass() != other.getClass()) {
+ return false;
+ }
+
+ FlushJobResponse that = (FlushJobResponse) other;
+ return that.flushed == flushed && Objects.equals(lastFinalizedBucketEnd, that.lastFinalizedBucketEnd);
+ }
+
+ @Override
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+ builder.startObject();
+ builder.field(FLUSHED.getPreferredName(), flushed);
+ if (lastFinalizedBucketEnd != null) {
+ builder.timeField(LAST_FINALIZED_BUCKET_END.getPreferredName(),
+ LAST_FINALIZED_BUCKET_END.getPreferredName() + "_string", lastFinalizedBucketEnd.getTime());
+ }
+ builder.endObject();
+ return builder;
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/ForecastJobRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/ForecastJobRequest.java
new file mode 100644
index 00000000000..67d290c37f0
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/ForecastJobRequest.java
@@ -0,0 +1,140 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.elasticsearch.client.ml;
+
+import org.elasticsearch.action.ActionRequest;
+import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.ml.job.config.Job;
+import org.elasticsearch.common.ParseField;
+import org.elasticsearch.common.unit.TimeValue;
+import org.elasticsearch.common.xcontent.ConstructingObjectParser;
+import org.elasticsearch.common.xcontent.ToXContent;
+import org.elasticsearch.common.xcontent.ToXContentObject;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+
+import java.io.IOException;
+import java.util.Objects;
+
+/**
+ * Pojo for forecasting an existing and open Machine Learning Job
+ */
+public class ForecastJobRequest extends ActionRequest implements ToXContentObject {
+
+ public static final ParseField DURATION = new ParseField("duration");
+ public static final ParseField EXPIRES_IN = new ParseField("expires_in");
+
+ public static final ConstructingObjectParser PARSER =
+ new ConstructingObjectParser<>("forecast_job_request", (a) -> new ForecastJobRequest((String)a[0]));
+
+ static {
+ PARSER.declareString(ConstructingObjectParser.constructorArg(), Job.ID);
+ PARSER.declareString(
+ (request, val) -> request.setDuration(TimeValue.parseTimeValue(val, DURATION.getPreferredName())), DURATION);
+ PARSER.declareString(
+ (request, val) -> request.setExpiresIn(TimeValue.parseTimeValue(val, EXPIRES_IN.getPreferredName())), EXPIRES_IN);
+ }
+
+ private final String jobId;
+ private TimeValue duration;
+ private TimeValue expiresIn;
+
+ /**
+ * A new forecast request
+ *
+ * @param jobId the non-null, existing, and opened jobId to forecast
+ */
+ public ForecastJobRequest(String jobId) {
+ this.jobId = jobId;
+ }
+
+ public String getJobId() {
+ return jobId;
+ }
+
+ public TimeValue getDuration() {
+ return duration;
+ }
+
+ /**
+ * Set the forecast duration
+ *
+ * A period of time that indicates how far into the future to forecast.
+ * The default value is 1 day. The forecast starts at the last record that was processed.
+ *
+ * @param duration TimeValue for the duration of the forecast
+ */
+ public void setDuration(TimeValue duration) {
+ this.duration = duration;
+ }
+
+ public TimeValue getExpiresIn() {
+ return expiresIn;
+ }
+
+ /**
+ * Set the forecast expiration
+ *
+ * The period of time that forecast results are retained.
+ * After a forecast expires, the results are deleted. The default value is 14 days.
+ * If set to a value of 0, the forecast is never automatically deleted.
+ *
+ * @param expiresIn TimeValue for the forecast expiration
+ */
+ public void setExpiresIn(TimeValue expiresIn) {
+ this.expiresIn = expiresIn;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(jobId, duration, expiresIn);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ ForecastJobRequest other = (ForecastJobRequest) obj;
+ return Objects.equals(jobId, other.jobId)
+ && Objects.equals(duration, other.duration)
+ && Objects.equals(expiresIn, other.expiresIn);
+ }
+
+ @Override
+ public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException {
+ builder.startObject();
+ builder.field(Job.ID.getPreferredName(), jobId);
+ if (duration != null) {
+ builder.field(DURATION.getPreferredName(), duration.getStringRep());
+ }
+ if (expiresIn != null) {
+ builder.field(EXPIRES_IN.getPreferredName(), expiresIn.getStringRep());
+ }
+ builder.endObject();
+ return builder;
+ }
+
+ @Override
+ public ActionRequestValidationException validate() {
+ return null;
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/ForecastJobResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/ForecastJobResponse.java
new file mode 100644
index 00000000000..b45275c5e59
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/ForecastJobResponse.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.elasticsearch.client.ml;
+
+import org.elasticsearch.action.ActionResponse;
+import org.elasticsearch.common.ParseField;
+import org.elasticsearch.common.xcontent.ConstructingObjectParser;
+import org.elasticsearch.common.xcontent.ToXContentObject;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentParser;
+
+import java.io.IOException;
+import java.util.Objects;
+
+/**
+ * Forecast response object
+ */
+public class ForecastJobResponse extends ActionResponse implements ToXContentObject {
+
+ public static final ParseField ACKNOWLEDGED = new ParseField("acknowledged");
+ public static final ParseField FORECAST_ID = new ParseField("forecast_id");
+
+ public static final ConstructingObjectParser PARSER =
+ new ConstructingObjectParser<>("forecast_job_response",
+ true,
+ (a) -> new ForecastJobResponse((Boolean)a[0], (String)a[1]));
+
+ static {
+ PARSER.declareBoolean(ConstructingObjectParser.constructorArg(), ACKNOWLEDGED);
+ PARSER.declareString(ConstructingObjectParser.constructorArg(), FORECAST_ID);
+ }
+
+ public static ForecastJobResponse fromXContent(XContentParser parser) throws IOException {
+ return PARSER.parse(parser, null);
+ }
+
+ private final boolean acknowledged;
+ private final String forecastId;
+
+ public ForecastJobResponse(boolean acknowledged, String forecastId) {
+ this.acknowledged = acknowledged;
+ this.forecastId = forecastId;
+ }
+
+ /**
+ * Forecast creating acknowledgement
+ * @return {@code true} indicates success, {@code false} otherwise
+ */
+ public boolean isAcknowledged() {
+ return acknowledged;
+ }
+
+ /**
+ * The created forecast ID
+ */
+ public String getForecastId() {
+ return forecastId;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(acknowledged, forecastId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ ForecastJobResponse other = (ForecastJobResponse) obj;
+ return Objects.equals(acknowledged, other.acknowledged)
+ && Objects.equals(forecastId, other.forecastId);
+ }
+
+ @Override
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+ builder.startObject();
+ builder.field(ACKNOWLEDGED.getPreferredName(), acknowledged);
+ builder.field(FORECAST_ID.getPreferredName(), forecastId);
+ builder.endObject();
+ return builder;
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetBucketsRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetBucketsRequest.java
new file mode 100644
index 00000000000..927fd08c1ca
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetBucketsRequest.java
@@ -0,0 +1,267 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.elasticsearch.client.ml;
+
+import org.elasticsearch.action.ActionRequest;
+import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.ml.job.config.Job;
+import org.elasticsearch.client.ml.job.results.Result;
+import org.elasticsearch.client.ml.job.util.PageParams;
+import org.elasticsearch.common.ParseField;
+import org.elasticsearch.common.xcontent.ObjectParser;
+import org.elasticsearch.common.xcontent.ToXContentObject;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+
+import java.io.IOException;
+import java.util.Objects;
+
+/**
+ * A request to retrieve buckets of a given job
+ */
+public class GetBucketsRequest extends ActionRequest implements ToXContentObject {
+
+ public static final ParseField EXPAND = new ParseField("expand");
+ public static final ParseField EXCLUDE_INTERIM = new ParseField("exclude_interim");
+ public static final ParseField START = new ParseField("start");
+ public static final ParseField END = new ParseField("end");
+ public static final ParseField ANOMALY_SCORE = new ParseField("anomaly_score");
+ public static final ParseField SORT = new ParseField("sort");
+ public static final ParseField DESCENDING = new ParseField("desc");
+
+ public static final ObjectParser PARSER = new ObjectParser<>("get_buckets_request", GetBucketsRequest::new);
+
+ static {
+ PARSER.declareString((request, jobId) -> request.jobId = jobId, Job.ID);
+ PARSER.declareString(GetBucketsRequest::setTimestamp, Result.TIMESTAMP);
+ PARSER.declareBoolean(GetBucketsRequest::setExpand, EXPAND);
+ PARSER.declareBoolean(GetBucketsRequest::setExcludeInterim, EXCLUDE_INTERIM);
+ PARSER.declareStringOrNull(GetBucketsRequest::setStart, START);
+ PARSER.declareStringOrNull(GetBucketsRequest::setEnd, END);
+ PARSER.declareObject(GetBucketsRequest::setPageParams, PageParams.PARSER, PageParams.PAGE);
+ PARSER.declareDouble(GetBucketsRequest::setAnomalyScore, ANOMALY_SCORE);
+ PARSER.declareString(GetBucketsRequest::setSort, SORT);
+ PARSER.declareBoolean(GetBucketsRequest::setDescending, DESCENDING);
+ }
+
+ private String jobId;
+ private String timestamp;
+ private Boolean expand;
+ private Boolean excludeInterim;
+ private String start;
+ private String end;
+ private PageParams pageParams;
+ private Double anomalyScore;
+ private String sort;
+ private Boolean descending;
+
+ private GetBucketsRequest() {}
+
+ /**
+ * Constructs a request to retrieve buckets of a given job
+ * @param jobId id of the job to retrieve buckets of
+ */
+ public GetBucketsRequest(String jobId) {
+ this.jobId = Objects.requireNonNull(jobId);
+ }
+
+ public String getJobId() {
+ return jobId;
+ }
+
+ /**
+ * Sets the timestamp of a specific bucket to be retrieved.
+ * @param timestamp String representation of a timestamp; may be an epoch seconds, epoch millis or an ISO string
+ */
+ public void setTimestamp(String timestamp) {
+ this.timestamp = timestamp;
+ }
+
+ public String getTimestamp() {
+ return timestamp;
+ }
+
+ public boolean isExpand() {
+ return expand;
+ }
+
+ /**
+ * Sets the value of "expand".
+ * When {@code true}, buckets will be expanded to include their records.
+ * @param expand value of "expand" to be set
+ */
+ public void setExpand(Boolean expand) {
+ this.expand = expand;
+ }
+
+ public Boolean isExcludeInterim() {
+ return excludeInterim;
+ }
+
+ /**
+ * Sets the value of "exclude_interim".
+ * When {@code true}, interim buckets will be filtered out.
+ * @param excludeInterim value of "exclude_interim" to be set
+ */
+ public void setExcludeInterim(Boolean excludeInterim) {
+ this.excludeInterim = excludeInterim;
+ }
+
+ public String getStart() {
+ return start;
+ }
+
+ /**
+ * Sets the value of "start" which is a timestamp.
+ * Only buckets whose timestamp is on or after the "start" value will be returned.
+ * @param start String representation of a timestamp; may be an epoch seconds, epoch millis or an ISO string
+ */
+ public void setStart(String start) {
+ this.start = start;
+ }
+
+ public String getEnd() {
+ return end;
+ }
+
+ /**
+ * Sets the value of "end" which is a timestamp.
+ * Only buckets whose timestamp is before the "end" value will be returned.
+ * @param end String representation of a timestamp; may be an epoch seconds, epoch millis or an ISO string
+ */
+ public void setEnd(String end) {
+ this.end = end;
+ }
+
+ public PageParams getPageParams() {
+ return pageParams;
+ }
+
+ /**
+ * Sets the paging parameters
+ * @param pageParams the paging parameters
+ */
+ public void setPageParams(PageParams pageParams) {
+ this.pageParams = pageParams;
+ }
+
+ public Double getAnomalyScore() {
+ return anomalyScore;
+ }
+
+ /**
+ * Sets the value of "anomaly_score".
+ * Only buckets with "anomaly_score" equal or greater will be returned.
+ * @param anomalyScore value of "anomaly_score".
+ */
+ public void setAnomalyScore(Double anomalyScore) {
+ this.anomalyScore = anomalyScore;
+ }
+
+ public String getSort() {
+ return sort;
+ }
+
+ /**
+ * Sets the value of "sort".
+ * Specifies the bucket field to sort on.
+ * @param sort value of "sort".
+ */
+ public void setSort(String sort) {
+ this.sort = sort;
+ }
+
+ public Boolean isDescending() {
+ return descending;
+ }
+
+ /**
+ * Sets the value of "desc".
+ * Specifies the sorting order.
+ * @param descending value of "desc"
+ */
+ public void setDescending(boolean descending) {
+ this.descending = descending;
+ }
+
+ @Override
+ public ActionRequestValidationException validate() {
+ return null;
+ }
+
+ @Override
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+ builder.startObject();
+ builder.field(Job.ID.getPreferredName(), jobId);
+ if (timestamp != null) {
+ builder.field(Result.TIMESTAMP.getPreferredName(), timestamp);
+ }
+ if (expand != null) {
+ builder.field(EXPAND.getPreferredName(), expand);
+ }
+ if (excludeInterim != null) {
+ builder.field(EXCLUDE_INTERIM.getPreferredName(), excludeInterim);
+ }
+ if (start != null) {
+ builder.field(START.getPreferredName(), start);
+ }
+ if (end != null) {
+ builder.field(END.getPreferredName(), end);
+ }
+ if (pageParams != null) {
+ builder.field(PageParams.PAGE.getPreferredName(), pageParams);
+ }
+ if (anomalyScore != null) {
+ builder.field(ANOMALY_SCORE.getPreferredName(), anomalyScore);
+ }
+ if (sort != null) {
+ builder.field(SORT.getPreferredName(), sort);
+ }
+ if (descending != null) {
+ builder.field(DESCENDING.getPreferredName(), descending);
+ }
+ builder.endObject();
+ return builder;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(jobId, timestamp, expand, excludeInterim, anomalyScore, pageParams, start, end, sort, descending);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ GetBucketsRequest other = (GetBucketsRequest) obj;
+ return Objects.equals(jobId, other.jobId) &&
+ Objects.equals(timestamp, other.timestamp) &&
+ Objects.equals(expand, other.expand) &&
+ Objects.equals(excludeInterim, other.excludeInterim) &&
+ Objects.equals(anomalyScore, other.anomalyScore) &&
+ Objects.equals(pageParams, other.pageParams) &&
+ Objects.equals(start, other.start) &&
+ Objects.equals(end, other.end) &&
+ Objects.equals(sort, other.sort) &&
+ Objects.equals(descending, other.descending);
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetBucketsResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetBucketsResponse.java
new file mode 100644
index 00000000000..de8736b86d9
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetBucketsResponse.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.elasticsearch.client.ml;
+
+import org.elasticsearch.client.ml.job.results.Bucket;
+import org.elasticsearch.common.ParseField;
+import org.elasticsearch.common.xcontent.ConstructingObjectParser;
+import org.elasticsearch.common.xcontent.XContentParser;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A response containing the requested buckets
+ */
+public class GetBucketsResponse extends AbstractResultResponse {
+
+ public static final ParseField BUCKETS = new ParseField("buckets");
+
+ @SuppressWarnings("unchecked")
+ public static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>("get_buckets_response",
+ true, a -> new GetBucketsResponse((List) a[0], (long) a[1]));
+
+ static {
+ PARSER.declareObjectArray(ConstructingObjectParser.constructorArg(), Bucket.PARSER, BUCKETS);
+ PARSER.declareLong(ConstructingObjectParser.constructorArg(), COUNT);
+ }
+
+ public static GetBucketsResponse fromXContent(XContentParser parser) throws IOException {
+ return PARSER.parse(parser, null);
+ }
+
+ GetBucketsResponse(List buckets, long count) {
+ super(BUCKETS, buckets, count);
+ }
+
+ /**
+ * The retrieved buckets
+ * @return the retrieved buckets
+ */
+ public List buckets() {
+ return results;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(count, results);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ GetBucketsResponse other = (GetBucketsResponse) obj;
+ return count == other.count && Objects.equals(results, other.results);
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetInfluencersRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetInfluencersRequest.java
new file mode 100644
index 00000000000..f57d327db3a
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetInfluencersRequest.java
@@ -0,0 +1,227 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.elasticsearch.client.ml;
+
+import org.elasticsearch.action.ActionRequest;
+import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.ml.job.config.Job;
+import org.elasticsearch.client.ml.job.util.PageParams;
+import org.elasticsearch.common.ParseField;
+import org.elasticsearch.common.xcontent.ConstructingObjectParser;
+import org.elasticsearch.common.xcontent.ToXContentObject;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+
+import java.io.IOException;
+import java.util.Objects;
+
+/**
+ * A request to retrieve influencers of a given job
+ */
+public class GetInfluencersRequest extends ActionRequest implements ToXContentObject {
+
+ public static final ParseField EXCLUDE_INTERIM = new ParseField("exclude_interim");
+ public static final ParseField START = new ParseField("start");
+ public static final ParseField END = new ParseField("end");
+ public static final ParseField INFLUENCER_SCORE = new ParseField("influencer_score");
+ public static final ParseField SORT = new ParseField("sort");
+ public static final ParseField DESCENDING = new ParseField("desc");
+
+ public static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>(
+ "get_influencers_request", a -> new GetInfluencersRequest((String) a[0]));
+
+ static {
+ PARSER.declareString(ConstructingObjectParser.constructorArg(), Job.ID);
+ PARSER.declareBoolean(GetInfluencersRequest::setExcludeInterim, EXCLUDE_INTERIM);
+ PARSER.declareStringOrNull(GetInfluencersRequest::setStart, START);
+ PARSER.declareStringOrNull(GetInfluencersRequest::setEnd, END);
+ PARSER.declareObject(GetInfluencersRequest::setPageParams, PageParams.PARSER, PageParams.PAGE);
+ PARSER.declareDouble(GetInfluencersRequest::setInfluencerScore, INFLUENCER_SCORE);
+ PARSER.declareString(GetInfluencersRequest::setSort, SORT);
+ PARSER.declareBoolean(GetInfluencersRequest::setDescending, DESCENDING);
+ }
+
+ private final String jobId;
+ private Boolean excludeInterim;
+ private String start;
+ private String end;
+ private Double influencerScore;
+ private PageParams pageParams;
+ private String sort;
+ private Boolean descending;
+
+ /**
+ * Constructs a request to retrieve influencers of a given job
+ * @param jobId id of the job to retrieve influencers of
+ */
+ public GetInfluencersRequest(String jobId) {
+ this.jobId = Objects.requireNonNull(jobId);
+ }
+
+ public String getJobId() {
+ return jobId;
+ }
+
+ public Boolean isExcludeInterim() {
+ return excludeInterim;
+ }
+
+ /**
+ * Sets the value of "exclude_interim".
+ * When {@code true}, interim influencers will be filtered out.
+ * @param excludeInterim value of "exclude_interim" to be set
+ */
+ public void setExcludeInterim(Boolean excludeInterim) {
+ this.excludeInterim = excludeInterim;
+ }
+
+ public String getStart() {
+ return start;
+ }
+
+ /**
+ * Sets the value of "start" which is a timestamp.
+ * Only influencers whose timestamp is on or after the "start" value will be returned.
+ * @param start String representation of a timestamp; may be an epoch seconds, epoch millis or an ISO string
+ */
+ public void setStart(String start) {
+ this.start = start;
+ }
+
+ public String getEnd() {
+ return end;
+ }
+
+ /**
+ * Sets the value of "end" which is a timestamp.
+ * Only influencers whose timestamp is before the "end" value will be returned.
+ * @param end String representation of a timestamp; may be an epoch seconds, epoch millis or an ISO string
+ */
+ public void setEnd(String end) {
+ this.end = end;
+ }
+
+ public PageParams getPageParams() {
+ return pageParams;
+ }
+
+ /**
+ * Sets the paging parameters
+ * @param pageParams The paging parameters
+ */
+ public void setPageParams(PageParams pageParams) {
+ this.pageParams = pageParams;
+ }
+
+ public Double getInfluencerScore() {
+ return influencerScore;
+ }
+
+ /**
+ * Sets the value of "influencer_score".
+ * Only influencers with "influencer_score" equal or greater will be returned.
+ * @param influencerScore value of "influencer_score".
+ */
+ public void setInfluencerScore(Double influencerScore) {
+ this.influencerScore = influencerScore;
+ }
+
+ public String getSort() {
+ return sort;
+ }
+
+ /**
+ * Sets the value of "sort".
+ * Specifies the influencer field to sort on.
+ * @param sort value of "sort".
+ */
+ public void setSort(String sort) {
+ this.sort = sort;
+ }
+
+ public Boolean isDescending() {
+ return descending;
+ }
+
+ /**
+ * Sets the value of "desc".
+ * Specifies the sorting order.
+ * @param descending value of "desc"
+ */
+ public void setDescending(Boolean descending) {
+ this.descending = descending;
+ }
+
+ @Override
+ public ActionRequestValidationException validate() {
+ return null;
+ }
+
+ @Override
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+ builder.startObject();
+ builder.field(Job.ID.getPreferredName(), jobId);
+ if (excludeInterim != null) {
+ builder.field(EXCLUDE_INTERIM.getPreferredName(), excludeInterim);
+ }
+ if (start != null) {
+ builder.field(START.getPreferredName(), start);
+ }
+ if (end != null) {
+ builder.field(END.getPreferredName(), end);
+ }
+ if (pageParams != null) {
+ builder.field(PageParams.PAGE.getPreferredName(), pageParams);
+ }
+ if (influencerScore != null) {
+ builder.field(INFLUENCER_SCORE.getPreferredName(), influencerScore);
+ }
+ if (sort != null) {
+ builder.field(SORT.getPreferredName(), sort);
+ }
+ if (descending != null) {
+ builder.field(DESCENDING.getPreferredName(), descending);
+ }
+ builder.endObject();
+ return builder;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(jobId, excludeInterim, influencerScore, pageParams, start, end, sort, descending);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ GetInfluencersRequest other = (GetInfluencersRequest) obj;
+ return Objects.equals(jobId, other.jobId) &&
+ Objects.equals(excludeInterim, other.excludeInterim) &&
+ Objects.equals(influencerScore, other.influencerScore) &&
+ Objects.equals(pageParams, other.pageParams) &&
+ Objects.equals(start, other.start) &&
+ Objects.equals(end, other.end) &&
+ Objects.equals(sort, other.sort) &&
+ Objects.equals(descending, other.descending);
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetInfluencersResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetInfluencersResponse.java
new file mode 100644
index 00000000000..113d960008c
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetInfluencersResponse.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.elasticsearch.client.ml;
+
+import org.elasticsearch.client.ml.job.results.Influencer;
+import org.elasticsearch.common.ParseField;
+import org.elasticsearch.common.xcontent.ConstructingObjectParser;
+import org.elasticsearch.common.xcontent.XContentParser;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A response containing the requested influencers
+ */
+public class GetInfluencersResponse extends AbstractResultResponse {
+
+ public static final ParseField INFLUENCERS = new ParseField("influencers");
+
+ @SuppressWarnings("unchecked")
+ public static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>(
+ "get_influencers_response", true, a -> new GetInfluencersResponse((List) a[0], (long) a[1]));
+
+ static {
+ PARSER.declareObjectArray(ConstructingObjectParser.constructorArg(), Influencer.PARSER, INFLUENCERS);
+ PARSER.declareLong(ConstructingObjectParser.constructorArg(), COUNT);
+ }
+
+ public static GetInfluencersResponse fromXContent(XContentParser parser) throws IOException {
+ return PARSER.parse(parser, null);
+ }
+
+ GetInfluencersResponse(List influencers, long count) {
+ super(INFLUENCERS, influencers, count);
+ }
+
+ /**
+ * The retrieved influencers
+ * @return the retrieved influencers
+ */
+ public List influencers() {
+ return results;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(count, results);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ GetInfluencersResponse other = (GetInfluencersResponse) obj;
+ return count == other.count && Objects.equals(results, other.results);
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobRequest.java
new file mode 100644
index 00000000000..3de7037e5c8
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobRequest.java
@@ -0,0 +1,144 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.elasticsearch.client.ml;
+
+import org.elasticsearch.action.ActionRequest;
+import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.ml.job.config.Job;
+import org.elasticsearch.common.ParseField;
+import org.elasticsearch.common.xcontent.ConstructingObjectParser;
+import org.elasticsearch.common.xcontent.ToXContentObject;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Request object to get {@link Job} objects with the matching `jobId`s or
+ * `groupName`s.
+ *
+ * `_all` explicitly gets all the jobs in the cluster
+ * An empty request (no `jobId`s) implicitly gets all the jobs in the cluster
+ */
+public class GetJobRequest extends ActionRequest implements ToXContentObject {
+
+ public static final ParseField JOB_IDS = new ParseField("job_ids");
+ public static final ParseField ALLOW_NO_JOBS = new ParseField("allow_no_jobs");
+
+ private static final String ALL_JOBS = "_all";
+ private final List jobIds;
+ private Boolean allowNoJobs;
+
+ @SuppressWarnings("unchecked")
+ public static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>(
+ "get_job_request",
+ true, a -> new GetJobRequest(a[0] == null ? new ArrayList<>() : (List) a[0]));
+
+ static {
+ PARSER.declareStringArray(ConstructingObjectParser.optionalConstructorArg(), JOB_IDS);
+ PARSER.declareBoolean(GetJobRequest::setAllowNoJobs, ALLOW_NO_JOBS);
+ }
+
+ /**
+ * Helper method to create a query that will get ALL jobs
+ * @return new {@link GetJobRequest} object searching for the jobId "_all"
+ */
+ public static GetJobRequest getAllJobsRequest() {
+ return new GetJobRequest(ALL_JOBS);
+ }
+
+ /**
+ * Get the specified {@link Job} configurations via their unique jobIds
+ * @param jobIds must not contain any null values
+ */
+ public GetJobRequest(String... jobIds) {
+ this(Arrays.asList(jobIds));
+ }
+
+ GetJobRequest(List jobIds) {
+ if (jobIds.stream().anyMatch(Objects::isNull)) {
+ throw new NullPointerException("jobIds must not contain null values");
+ }
+ this.jobIds = new ArrayList<>(jobIds);
+ }
+
+ /**
+ * All the jobIds for which to get configuration information
+ */
+ public List getJobIds() {
+ return jobIds;
+ }
+
+ /**
+ * Whether to ignore if a wildcard expression matches no jobs.
+ *
+ * @param allowNoJobs If this is {@code false}, then an error is returned when a wildcard (or `_all`) does not match any jobs
+ */
+ public void setAllowNoJobs(boolean allowNoJobs) {
+ this.allowNoJobs = allowNoJobs;
+ }
+
+ public Boolean isAllowNoJobs() {
+ return allowNoJobs;
+ }
+
+ @Override
+ public ActionRequestValidationException validate() {
+ return null;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(jobIds, allowNoJobs);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (other == null || other.getClass() != getClass()) {
+ return false;
+ }
+
+ GetJobRequest that = (GetJobRequest) other;
+ return Objects.equals(jobIds, that.jobIds) &&
+ Objects.equals(allowNoJobs, that.allowNoJobs);
+ }
+
+ @Override
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+ builder.startObject();
+
+ if (jobIds.isEmpty() == false) {
+ builder.field(JOB_IDS.getPreferredName(), jobIds);
+ }
+
+ if (allowNoJobs != null) {
+ builder.field(ALLOW_NO_JOBS.getPreferredName(), allowNoJobs);
+ }
+
+ builder.endObject();
+ return builder;
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobResponse.java
new file mode 100644
index 00000000000..0cdf08c6c24
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobResponse.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.elasticsearch.client.ml;
+
+import org.elasticsearch.client.ml.job.config.Job;
+import org.elasticsearch.common.ParseField;
+import org.elasticsearch.common.Strings;
+import org.elasticsearch.common.xcontent.ConstructingObjectParser;
+import org.elasticsearch.common.xcontent.XContentParser;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
+
+/**
+ * Contains a {@link List} of the found {@link Job} objects and the total count found
+ */
+public class GetJobResponse extends AbstractResultResponse {
+
+ public static final ParseField RESULTS_FIELD = new ParseField("jobs");
+
+ @SuppressWarnings("unchecked")
+ public static final ConstructingObjectParser PARSER =
+ new ConstructingObjectParser<>("jobs_response", true,
+ a -> new GetJobResponse((List) a[0], (long) a[1]));
+
+ static {
+ PARSER.declareObjectArray(constructorArg(), Job.PARSER, RESULTS_FIELD);
+ PARSER.declareLong(constructorArg(), AbstractResultResponse.COUNT);
+ }
+
+ GetJobResponse(List jobBuilders, long count) {
+ super(RESULTS_FIELD, jobBuilders.stream().map(Job.Builder::build).collect(Collectors.toList()), count);
+ }
+
+ /**
+ * The collection of {@link Job} objects found in the query
+ */
+ public List jobs() {
+ return results;
+ }
+
+ public static GetJobResponse fromXContent(XContentParser parser) throws IOException {
+ return PARSER.parse(parser, null);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(results, count);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+
+ GetJobResponse other = (GetJobResponse) obj;
+ return Objects.equals(results, other.results) && count == other.count;
+ }
+
+ @Override
+ public final String toString() {
+ return Strings.toString(this);
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobStatsRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobStatsRequest.java
new file mode 100644
index 00000000000..d8eb350755d
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobStatsRequest.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.elasticsearch.client.ml;
+
+import org.elasticsearch.action.ActionRequest;
+import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.ml.job.config.Job;
+import org.elasticsearch.common.ParseField;
+import org.elasticsearch.common.Strings;
+import org.elasticsearch.common.xcontent.ConstructingObjectParser;
+import org.elasticsearch.common.xcontent.ObjectParser;
+import org.elasticsearch.common.xcontent.ToXContentObject;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+
+
+/**
+ * Request object to get {@link org.elasticsearch.client.ml.job.stats.JobStats} by their respective jobIds
+ *
+ * `_all` explicitly gets all the jobs' statistics in the cluster
+ * An empty request (no `jobId`s) implicitly gets all the jobs' statistics in the cluster
+ */
+public class GetJobStatsRequest extends ActionRequest implements ToXContentObject {
+
+ public static final ParseField ALLOW_NO_JOBS = new ParseField("allow_no_jobs");
+
+ @SuppressWarnings("unchecked")
+ public static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>(
+ "get_jobs_stats_request", a -> new GetJobStatsRequest((List) a[0]));
+
+ static {
+ PARSER.declareField(ConstructingObjectParser.constructorArg(),
+ p -> Arrays.asList(Strings.commaDelimitedListToStringArray(p.text())),
+ Job.ID, ObjectParser.ValueType.STRING_ARRAY);
+ PARSER.declareBoolean(GetJobStatsRequest::setAllowNoJobs, ALLOW_NO_JOBS);
+ }
+
+ private static final String ALL_JOBS = "_all";
+
+ private final List jobIds;
+ private Boolean allowNoJobs;
+
+ /**
+ * Explicitly gets all jobs statistics
+ *
+ * @return a {@link GetJobStatsRequest} for all existing jobs
+ */
+ public static GetJobStatsRequest getAllJobStatsRequest(){
+ return new GetJobStatsRequest(ALL_JOBS);
+ }
+
+ GetJobStatsRequest(List jobIds) {
+ if (jobIds.stream().anyMatch(Objects::isNull)) {
+ throw new NullPointerException("jobIds must not contain null values");
+ }
+ this.jobIds = new ArrayList<>(jobIds);
+ }
+
+ /**
+ * Get the specified Job's statistics via their unique jobIds
+ *
+ * @param jobIds must be non-null and each jobId must be non-null
+ */
+ public GetJobStatsRequest(String... jobIds) {
+ this(Arrays.asList(jobIds));
+ }
+
+ /**
+ * All the jobIds for which to get statistics
+ */
+ public List getJobIds() {
+ return jobIds;
+ }
+
+ public Boolean isAllowNoJobs() {
+ return this.allowNoJobs;
+ }
+
+ /**
+ * Whether to ignore if a wildcard expression matches no jobs.
+ *
+ * This includes `_all` string or when no jobs have been specified
+ *
+ * @param allowNoJobs When {@code true} ignore if wildcard or `_all` matches no jobs. Defaults to {@code true}
+ */
+ public void setAllowNoJobs(boolean allowNoJobs) {
+ this.allowNoJobs = allowNoJobs;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(jobIds, allowNoJobs);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (other == null || getClass() != other.getClass()) {
+ return false;
+ }
+
+ GetJobStatsRequest that = (GetJobStatsRequest) other;
+ return Objects.equals(jobIds, that.jobIds) &&
+ Objects.equals(allowNoJobs, that.allowNoJobs);
+ }
+
+ @Override
+ public ActionRequestValidationException validate() {
+ return null;
+ }
+
+ @Override
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+ builder.startObject();
+ builder.field(Job.ID.getPreferredName(), Strings.collectionToCommaDelimitedString(jobIds));
+ if (allowNoJobs != null) {
+ builder.field(ALLOW_NO_JOBS.getPreferredName(), allowNoJobs);
+ }
+ builder.endObject();
+ return builder;
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobStatsResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobStatsResponse.java
new file mode 100644
index 00000000000..2e3ba113d19
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobStatsResponse.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.elasticsearch.client.ml;
+
+import org.elasticsearch.common.ParseField;
+import org.elasticsearch.common.Strings;
+import org.elasticsearch.common.xcontent.ConstructingObjectParser;
+import org.elasticsearch.common.xcontent.XContentParser;
+import org.elasticsearch.client.ml.job.stats.JobStats;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Objects;
+
+import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
+
+/**
+ * Contains a {@link List} of the found {@link JobStats} objects and the total count found
+ */
+public class GetJobStatsResponse extends AbstractResultResponse {
+
+ public static final ParseField RESULTS_FIELD = new ParseField("jobs");
+
+ @SuppressWarnings("unchecked")
+ public static final ConstructingObjectParser PARSER =
+ new ConstructingObjectParser<>("jobs_stats_response", true,
+ a -> new GetJobStatsResponse((List) a[0], (long) a[1]));
+
+ static {
+ PARSER.declareObjectArray(constructorArg(), JobStats.PARSER, RESULTS_FIELD);
+ PARSER.declareLong(constructorArg(), COUNT);
+ }
+
+ GetJobStatsResponse(List jobStats, long count) {
+ super(RESULTS_FIELD, jobStats, count);
+ }
+
+ /**
+ * The collection of {@link JobStats} objects found in the query
+ */
+ public List jobStats() {
+ return results;
+ }
+
+ public static GetJobStatsResponse fromXContent(XContentParser parser) throws IOException {
+ return PARSER.parse(parser, null);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(results, count);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+
+ GetJobStatsResponse other = (GetJobStatsResponse) obj;
+ return Objects.equals(results, other.results) && count == other.count;
+ }
+
+ @Override
+ public final String toString() {
+ return Strings.toString(this);
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetOverallBucketsRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetOverallBucketsRequest.java
new file mode 100644
index 00000000000..97bde11d8c6
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetOverallBucketsRequest.java
@@ -0,0 +1,266 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.elasticsearch.client.ml;
+
+import org.elasticsearch.action.ActionRequest;
+import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.ml.job.config.Job;
+import org.elasticsearch.common.ParseField;
+import org.elasticsearch.common.Strings;
+import org.elasticsearch.common.unit.TimeValue;
+import org.elasticsearch.common.xcontent.ConstructingObjectParser;
+import org.elasticsearch.common.xcontent.ToXContentObject;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A request to retrieve overall buckets of set of jobs
+ */
+public class GetOverallBucketsRequest extends ActionRequest implements ToXContentObject {
+
+ public static final ParseField TOP_N = new ParseField("top_n");
+ public static final ParseField BUCKET_SPAN = new ParseField("bucket_span");
+ public static final ParseField OVERALL_SCORE = new ParseField("overall_score");
+ public static final ParseField EXCLUDE_INTERIM = new ParseField("exclude_interim");
+ public static final ParseField START = new ParseField("start");
+ public static final ParseField END = new ParseField("end");
+ public static final ParseField ALLOW_NO_JOBS = new ParseField("allow_no_jobs");
+
+ private static final String ALL_JOBS = "_all";
+
+ @SuppressWarnings("unchecked")
+ public static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>(
+ "get_overall_buckets_request", a -> new GetOverallBucketsRequest((String) a[0]));
+
+ static {
+ PARSER.declareString(ConstructingObjectParser.constructorArg(), Job.ID);
+ PARSER.declareInt(GetOverallBucketsRequest::setTopN, TOP_N);
+ PARSER.declareString(GetOverallBucketsRequest::setBucketSpan, BUCKET_SPAN);
+ PARSER.declareBoolean(GetOverallBucketsRequest::setExcludeInterim, EXCLUDE_INTERIM);
+ PARSER.declareDouble(GetOverallBucketsRequest::setOverallScore, OVERALL_SCORE);
+ PARSER.declareStringOrNull(GetOverallBucketsRequest::setStart, START);
+ PARSER.declareStringOrNull(GetOverallBucketsRequest::setEnd, END);
+ PARSER.declareBoolean(GetOverallBucketsRequest::setAllowNoJobs, ALLOW_NO_JOBS);
+ }
+
+ private final List jobIds;
+ private Integer topN;
+ private TimeValue bucketSpan;
+ private Boolean excludeInterim;
+ private Double overallScore;
+ private String start;
+ private String end;
+ private Boolean allowNoJobs;
+
+ private GetOverallBucketsRequest(String jobId) {
+ this(Strings.tokenizeToStringArray(jobId, ","));
+ }
+
+ /**
+ * Constructs a request to retrieve overall buckets for a set of jobs
+ * @param jobIds The job identifiers. Each can be a job identifier, a group name, or a wildcard expression.
+ */
+ public GetOverallBucketsRequest(String... jobIds) {
+ this(Arrays.asList(jobIds));
+ }
+
+ /**
+ * Constructs a request to retrieve overall buckets for a set of jobs
+ * @param jobIds The job identifiers. Each can be a job identifier, a group name, or a wildcard expression.
+ */
+ public GetOverallBucketsRequest(List jobIds) {
+ if (jobIds.stream().anyMatch(Objects::isNull)) {
+ throw new NullPointerException("jobIds must not contain null values");
+ }
+ if (jobIds.isEmpty()) {
+ this.jobIds = Collections.singletonList(ALL_JOBS);
+ } else {
+ this.jobIds = Collections.unmodifiableList(jobIds);
+ }
+ }
+
+ public List getJobIds() {
+ return jobIds;
+ }
+
+ public Integer getTopN() {
+ return topN;
+ }
+
+ /**
+ * Sets the value of `top_n`.
+ * @param topN The number of top job bucket scores to be used in the overall_score calculation. Defaults to 1.
+ */
+ public void setTopN(Integer topN) {
+ this.topN = topN;
+ }
+
+ public TimeValue getBucketSpan() {
+ return bucketSpan;
+ }
+
+ /**
+ * Sets the value of `bucket_span`.
+ * @param bucketSpan The span of the overall buckets. Must be greater or equal to the largest job’s bucket_span.
+ * Defaults to the largest job’s bucket_span.
+ */
+ public void setBucketSpan(TimeValue bucketSpan) {
+ this.bucketSpan = bucketSpan;
+ }
+
+ private void setBucketSpan(String bucketSpan) {
+ this.bucketSpan = TimeValue.parseTimeValue(bucketSpan, BUCKET_SPAN.getPreferredName());
+ }
+
+ public boolean isExcludeInterim() {
+ return excludeInterim;
+ }
+
+ /**
+ * Sets the value of "exclude_interim".
+ * When {@code true}, interim overall buckets will be filtered out.
+ * Overall buckets are interim if any of the job buckets within the overall bucket interval are interim.
+ * @param excludeInterim value of "exclude_interim" to be set
+ */
+ public void setExcludeInterim(Boolean excludeInterim) {
+ this.excludeInterim = excludeInterim;
+ }
+
+ public String getStart() {
+ return start;
+ }
+
+ /**
+ * Sets the value of "start" which is a timestamp.
+ * Only overall buckets whose timestamp is on or after the "start" value will be returned.
+ * @param start String representation of a timestamp; may be an epoch seconds, epoch millis or an ISO string
+ */
+ public void setStart(String start) {
+ this.start = start;
+ }
+
+ public String getEnd() {
+ return end;
+ }
+
+ /**
+ * Sets the value of "end" which is a timestamp.
+ * Only overall buckets whose timestamp is before the "end" value will be returned.
+ * @param end String representation of a timestamp; may be an epoch seconds, epoch millis or an ISO string
+ */
+ public void setEnd(String end) {
+ this.end = end;
+ }
+
+ public Double getOverallScore() {
+ return overallScore;
+ }
+
+ /**
+ * Sets the value of "overall_score".
+ * Only buckets with "overall_score" equal or greater will be returned.
+ * @param overallScore value of "anomaly_score".
+ */
+ public void setOverallScore(double overallScore) {
+ this.overallScore = overallScore;
+ }
+
+ /**
+ * See {@link GetJobRequest#isAllowNoJobs()}
+ * @param allowNoJobs value of "allow_no_jobs".
+ */
+ public void setAllowNoJobs(boolean allowNoJobs) {
+ this.allowNoJobs = allowNoJobs;
+ }
+
+ /**
+ * Whether to ignore if a wildcard expression matches no jobs.
+ *
+ * If this is `false`, then an error is returned when a wildcard (or `_all`) does not match any jobs
+ */
+ public Boolean isAllowNoJobs() {
+ return allowNoJobs;
+ }
+
+ @Override
+ public ActionRequestValidationException validate() {
+ return null;
+ }
+
+ @Override
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+ builder.startObject();
+
+ if (jobIds.isEmpty() == false) {
+ builder.field(Job.ID.getPreferredName(), Strings.collectionToCommaDelimitedString(jobIds));
+ }
+ if (topN != null) {
+ builder.field(TOP_N.getPreferredName(), topN);
+ }
+ if (bucketSpan != null) {
+ builder.field(BUCKET_SPAN.getPreferredName(), bucketSpan.getStringRep());
+ }
+ if (excludeInterim != null) {
+ builder.field(EXCLUDE_INTERIM.getPreferredName(), excludeInterim);
+ }
+ if (start != null) {
+ builder.field(START.getPreferredName(), start);
+ }
+ if (end != null) {
+ builder.field(END.getPreferredName(), end);
+ }
+ if (overallScore != null) {
+ builder.field(OVERALL_SCORE.getPreferredName(), overallScore);
+ }
+ if (allowNoJobs != null) {
+ builder.field(ALLOW_NO_JOBS.getPreferredName(), allowNoJobs);
+ }
+ builder.endObject();
+ return builder;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(jobIds, topN, bucketSpan, excludeInterim, overallScore, start, end, allowNoJobs);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ GetOverallBucketsRequest other = (GetOverallBucketsRequest) obj;
+ return Objects.equals(jobIds, other.jobIds) &&
+ Objects.equals(topN, other.topN) &&
+ Objects.equals(bucketSpan, other.bucketSpan) &&
+ Objects.equals(excludeInterim, other.excludeInterim) &&
+ Objects.equals(overallScore, other.overallScore) &&
+ Objects.equals(start, other.start) &&
+ Objects.equals(end, other.end) &&
+ Objects.equals(allowNoJobs, other.allowNoJobs);
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetOverallBucketsResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetOverallBucketsResponse.java
new file mode 100644
index 00000000000..8c9b7e29cb6
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetOverallBucketsResponse.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.elasticsearch.client.ml;
+
+import org.elasticsearch.client.ml.job.results.OverallBucket;
+import org.elasticsearch.common.ParseField;
+import org.elasticsearch.common.xcontent.ConstructingObjectParser;
+import org.elasticsearch.common.xcontent.XContentParser;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A response containing the requested overall buckets
+ */
+public class GetOverallBucketsResponse extends AbstractResultResponse {
+
+ public static final ParseField OVERALL_BUCKETS = new ParseField("overall_buckets");
+
+ @SuppressWarnings("unchecked")
+ public static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>(
+ "get_overall_buckets_response", true, a -> new GetOverallBucketsResponse((List) a[0], (long) a[1]));
+
+ static {
+ PARSER.declareObjectArray(ConstructingObjectParser.constructorArg(), OverallBucket.PARSER, OVERALL_BUCKETS);
+ PARSER.declareLong(ConstructingObjectParser.constructorArg(), COUNT);
+ }
+
+ public static GetOverallBucketsResponse fromXContent(XContentParser parser) throws IOException {
+ return PARSER.parse(parser, null);
+ }
+
+ GetOverallBucketsResponse(List overallBuckets, long count) {
+ super(OVERALL_BUCKETS, overallBuckets, count);
+ }
+
+ /**
+ * The retrieved overall buckets
+ * @return the retrieved overall buckets
+ */
+ public List overallBuckets() {
+ return results;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(count, results);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ GetOverallBucketsResponse other = (GetOverallBucketsResponse) obj;
+ return count == other.count && Objects.equals(results, other.results);
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetRecordsRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetRecordsRequest.java
new file mode 100644
index 00000000000..3c11cbd2c10
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetRecordsRequest.java
@@ -0,0 +1,222 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.elasticsearch.client.ml;
+
+import org.elasticsearch.client.Validatable;
+import org.elasticsearch.client.ml.job.config.Job;
+import org.elasticsearch.client.ml.job.util.PageParams;
+import org.elasticsearch.common.ParseField;
+import org.elasticsearch.common.xcontent.ObjectParser;
+import org.elasticsearch.common.xcontent.ToXContentObject;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+
+import java.io.IOException;
+import java.util.Objects;
+
+/**
+ * A request to retrieve records of a given job
+ */
+public class GetRecordsRequest implements ToXContentObject, Validatable {
+
+ public static final ParseField EXCLUDE_INTERIM = new ParseField("exclude_interim");
+ public static final ParseField START = new ParseField("start");
+ public static final ParseField END = new ParseField("end");
+ public static final ParseField RECORD_SCORE = new ParseField("record_score");
+ public static final ParseField SORT = new ParseField("sort");
+ public static final ParseField DESCENDING = new ParseField("desc");
+
+ public static final ObjectParser PARSER = new ObjectParser<>("get_records_request", GetRecordsRequest::new);
+
+ static {
+ PARSER.declareString((request, jobId) -> request.jobId = jobId, Job.ID);
+ PARSER.declareBoolean(GetRecordsRequest::setExcludeInterim, EXCLUDE_INTERIM);
+ PARSER.declareStringOrNull(GetRecordsRequest::setStart, START);
+ PARSER.declareStringOrNull(GetRecordsRequest::setEnd, END);
+ PARSER.declareObject(GetRecordsRequest::setPageParams, PageParams.PARSER, PageParams.PAGE);
+ PARSER.declareDouble(GetRecordsRequest::setRecordScore, RECORD_SCORE);
+ PARSER.declareString(GetRecordsRequest::setSort, SORT);
+ PARSER.declareBoolean(GetRecordsRequest::setDescending, DESCENDING);
+ }
+
+ private String jobId;
+ private Boolean excludeInterim;
+ private String start;
+ private String end;
+ private PageParams pageParams;
+ private Double recordScore;
+ private String sort;
+ private Boolean descending;
+
+ private GetRecordsRequest() {}
+
+ /**
+ * Constructs a request to retrieve records of a given job
+ * @param jobId id of the job to retrieve records of
+ */
+ public GetRecordsRequest(String jobId) {
+ this.jobId = Objects.requireNonNull(jobId);
+ }
+
+ public String getJobId() {
+ return jobId;
+ }
+
+ public Boolean isExcludeInterim() {
+ return excludeInterim;
+ }
+
+ /**
+ * Sets the value of "exclude_interim".
+ * When {@code true}, interim records will be filtered out.
+ * @param excludeInterim value of "exclude_interim" to be set
+ */
+ public void setExcludeInterim(Boolean excludeInterim) {
+ this.excludeInterim = excludeInterim;
+ }
+
+ public String getStart() {
+ return start;
+ }
+
+ /**
+ * Sets the value of "start" which is a timestamp.
+ * Only records whose timestamp is on or after the "start" value will be returned.
+ * @param start String representation of a timestamp; may be an epoch seconds, epoch millis or an ISO string
+ */
+ public void setStart(String start) {
+ this.start = start;
+ }
+
+ public String getEnd() {
+ return end;
+ }
+
+ /**
+ * Sets the value of "end" which is a timestamp.
+ * Only records whose timestamp is before the "end" value will be returned.
+ * @param end String representation of a timestamp; may be an epoch seconds, epoch millis or an ISO string
+ */
+ public void setEnd(String end) {
+ this.end = end;
+ }
+
+ public PageParams getPageParams() {
+ return pageParams;
+ }
+
+ /**
+ * Sets the paging parameters
+ * @param pageParams The paging parameters
+ */
+ public void setPageParams(PageParams pageParams) {
+ this.pageParams = pageParams;
+ }
+
+ public Double getRecordScore() {
+ return recordScore;
+ }
+
+ /**
+ * Sets the value of "record_score".
+ * Only records with "record_score" equal or greater will be returned.
+ * @param recordScore value of "record_score".
+ */
+ public void setRecordScore(Double recordScore) {
+ this.recordScore = recordScore;
+ }
+
+ public String getSort() {
+ return sort;
+ }
+
+ /**
+ * Sets the value of "sort".
+ * Specifies the record field to sort on.
+ * @param sort value of "sort".
+ */
+ public void setSort(String sort) {
+ this.sort = sort;
+ }
+
+ public Boolean isDescending() {
+ return descending;
+ }
+
+ /**
+ * Sets the value of "desc".
+ * Specifies the sorting order.
+ * @param descending value of "desc"
+ */
+ public void setDescending(Boolean descending) {
+ this.descending = descending;
+ }
+
+ @Override
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+ builder.startObject();
+ builder.field(Job.ID.getPreferredName(), jobId);
+ if (excludeInterim != null) {
+ builder.field(EXCLUDE_INTERIM.getPreferredName(), excludeInterim);
+ }
+ if (start != null) {
+ builder.field(START.getPreferredName(), start);
+ }
+ if (end != null) {
+ builder.field(END.getPreferredName(), end);
+ }
+ if (pageParams != null) {
+ builder.field(PageParams.PAGE.getPreferredName(), pageParams);
+ }
+ if (recordScore != null) {
+ builder.field(RECORD_SCORE.getPreferredName(), recordScore);
+ }
+ if (sort != null) {
+ builder.field(SORT.getPreferredName(), sort);
+ }
+ if (descending != null) {
+ builder.field(DESCENDING.getPreferredName(), descending);
+ }
+ builder.endObject();
+ return builder;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(jobId, excludeInterim, recordScore, pageParams, start, end, sort, descending);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ GetRecordsRequest other = (GetRecordsRequest) obj;
+ return Objects.equals(jobId, other.jobId) &&
+ Objects.equals(excludeInterim, other.excludeInterim) &&
+ Objects.equals(recordScore, other.recordScore) &&
+ Objects.equals(pageParams, other.pageParams) &&
+ Objects.equals(start, other.start) &&
+ Objects.equals(end, other.end) &&
+ Objects.equals(sort, other.sort) &&
+ Objects.equals(descending, other.descending);
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetRecordsResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetRecordsResponse.java
new file mode 100644
index 00000000000..0d8efd5c6ea
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetRecordsResponse.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.elasticsearch.client.ml;
+
+import org.elasticsearch.client.ml.job.results.AnomalyRecord;
+import org.elasticsearch.common.ParseField;
+import org.elasticsearch.common.xcontent.ConstructingObjectParser;
+import org.elasticsearch.common.xcontent.XContentParser;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A response containing the requested records
+ */
+public class GetRecordsResponse extends AbstractResultResponse {
+
+ public static final ParseField RECORDS = new ParseField("records");
+
+ @SuppressWarnings("unchecked")
+ public static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>("get_records_response",
+ true, a -> new GetRecordsResponse((List) a[0], (long) a[1]));
+
+ static {
+ PARSER.declareObjectArray(ConstructingObjectParser.constructorArg(), AnomalyRecord.PARSER, RECORDS);
+ PARSER.declareLong(ConstructingObjectParser.constructorArg(), COUNT);
+ }
+
+ public static GetRecordsResponse fromXContent(XContentParser parser) throws IOException {
+ return PARSER.parse(parser, null);
+ }
+
+ GetRecordsResponse(List records, long count) {
+ super(RECORDS, records, count);
+ }
+
+ /**
+ * The retrieved records
+ * @return the retrieved records
+ */
+ public List records() {
+ return results;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(count, results);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ GetRecordsResponse other = (GetRecordsResponse) obj;
+ return count == other.count && Objects.equals(results, other.results);
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/NodeAttributes.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/NodeAttributes.java
new file mode 100644
index 00000000000..892df340abd
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/NodeAttributes.java
@@ -0,0 +1,150 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.elasticsearch.client.ml;
+
+import org.elasticsearch.common.ParseField;
+import org.elasticsearch.common.xcontent.ConstructingObjectParser;
+import org.elasticsearch.common.xcontent.ObjectParser;
+import org.elasticsearch.common.xcontent.ToXContentObject;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * A Pojo class containing an Elastic Node's attributes
+ */
+public class NodeAttributes implements ToXContentObject {
+
+ public static final ParseField ID = new ParseField("id");
+ public static final ParseField NAME = new ParseField("name");
+ public static final ParseField EPHEMERAL_ID = new ParseField("ephemeral_id");
+ public static final ParseField TRANSPORT_ADDRESS = new ParseField("transport_address");
+ public static final ParseField ATTRIBUTES = new ParseField("attributes");
+
+ @SuppressWarnings("unchecked")
+ public static final ConstructingObjectParser PARSER =
+ new ConstructingObjectParser<>("node", true,
+ (a) -> {
+ int i = 0;
+ String id = (String) a[i++];
+ String name = (String) a[i++];
+ String ephemeralId = (String) a[i++];
+ String transportAddress = (String) a[i++];
+ Map attributes = (Map) a[i];
+ return new NodeAttributes(id, name, ephemeralId, transportAddress, attributes);
+ });
+
+ static {
+ PARSER.declareString(ConstructingObjectParser.constructorArg(), ID);
+ PARSER.declareString(ConstructingObjectParser.constructorArg(), NAME);
+ PARSER.declareString(ConstructingObjectParser.constructorArg(), EPHEMERAL_ID);
+ PARSER.declareString(ConstructingObjectParser.constructorArg(), TRANSPORT_ADDRESS);
+ PARSER.declareField(ConstructingObjectParser.constructorArg(),
+ (p, c) -> p.mapStrings(),
+ ATTRIBUTES,
+ ObjectParser.ValueType.OBJECT);
+ }
+
+ private final String id;
+ private final String name;
+ private final String ephemeralId;
+ private final String transportAddress;
+ private final Map attributes;
+
+ public NodeAttributes(String id, String name, String ephemeralId, String transportAddress, Map attributes) {
+ this.id = id;
+ this.name = name;
+ this.ephemeralId = ephemeralId;
+ this.transportAddress = transportAddress;
+ this.attributes = Collections.unmodifiableMap(attributes);
+ }
+
+ /**
+ * The unique identifier of the node.
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * The node name.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * The ephemeral id of the node.
+ */
+ public String getEphemeralId() {
+ return ephemeralId;
+ }
+
+ /**
+ * The host and port where transport HTTP connections are accepted.
+ */
+ public String getTransportAddress() {
+ return transportAddress;
+ }
+
+ /**
+ * Additional attributes related to this node e.g., {"ml.max_open_jobs": "10"}.
+ */
+ public Map getAttributes() {
+ return attributes;
+ }
+
+ @Override
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+ builder.startObject();
+ builder.field(ID.getPreferredName(), id);
+ builder.field(NAME.getPreferredName(), name);
+ builder.field(EPHEMERAL_ID.getPreferredName(), ephemeralId);
+ builder.field(TRANSPORT_ADDRESS.getPreferredName(), transportAddress);
+ builder.field(ATTRIBUTES.getPreferredName(), attributes);
+ builder.endObject();
+ return builder;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, name, ephemeralId, transportAddress, attributes);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (other == null || getClass() != other.getClass()) {
+ return false;
+ }
+
+ NodeAttributes that = (NodeAttributes) other;
+ return Objects.equals(id, that.id) &&
+ Objects.equals(name, that.name) &&
+ Objects.equals(ephemeralId, that.ephemeralId) &&
+ Objects.equals(transportAddress, that.transportAddress) &&
+ Objects.equals(attributes, that.attributes);
+ }
+}
diff --git a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/OpenJobRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/OpenJobRequest.java
similarity index 85%
rename from x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/OpenJobRequest.java
rename to client/rest-high-level/src/main/java/org/elasticsearch/client/ml/OpenJobRequest.java
index a18a18bb55a..5b8e68cd72d 100644
--- a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/OpenJobRequest.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/OpenJobRequest.java
@@ -16,23 +16,25 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.elasticsearch.protocol.xpack.ml;
+package org.elasticsearch.client.ml;
import org.elasticsearch.action.ActionRequest;
import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.ml.job.config.Job;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
-import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
-import org.elasticsearch.protocol.xpack.ml.job.config.Job;
import java.io.IOException;
import java.util.Objects;
+/**
+ * Request to open a Machine Learning Job
+ */
public class OpenJobRequest extends ActionRequest implements ToXContentObject {
public static final ParseField TIMEOUT = new ParseField("timeout");
@@ -51,6 +53,11 @@ public class OpenJobRequest extends ActionRequest implements ToXContentObject {
private String jobId;
private TimeValue timeout;
+ /**
+ * Create a new request with the desired jobId
+ *
+ * @param jobId unique jobId, must not be null
+ */
public OpenJobRequest(String jobId) {
this.jobId = Objects.requireNonNull(jobId, "[job_id] must not be null");
}
@@ -59,6 +66,11 @@ public class OpenJobRequest extends ActionRequest implements ToXContentObject {
return jobId;
}
+ /**
+ * The jobId to open
+ *
+ * @param jobId unique jobId, must not be null
+ */
public void setJobId(String jobId) {
this.jobId = Objects.requireNonNull(jobId, "[job_id] must not be null");
}
@@ -67,6 +79,11 @@ public class OpenJobRequest extends ActionRequest implements ToXContentObject {
return timeout;
}
+ /**
+ * How long to wait for job to open before timing out the request
+ *
+ * @param timeout default value of 30 minutes
+ */
public void setTimeout(TimeValue timeout) {
this.timeout = timeout;
}
@@ -77,7 +94,7 @@ public class OpenJobRequest extends ActionRequest implements ToXContentObject {
}
@Override
- public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException {
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
builder.field(Job.ID.getPreferredName(), jobId);
if (timeout != null) {
diff --git a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/OpenJobResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/OpenJobResponse.java
similarity index 78%
rename from x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/OpenJobResponse.java
rename to client/rest-high-level/src/main/java/org/elasticsearch/client/ml/OpenJobResponse.java
index d8850ddbbe3..2536aeeaf78 100644
--- a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/OpenJobResponse.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/OpenJobResponse.java
@@ -16,11 +16,11 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.elasticsearch.protocol.xpack.ml;
+package org.elasticsearch.client.ml;
import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.common.ParseField;
-import org.elasticsearch.common.xcontent.ObjectParser;
+import org.elasticsearch.common.xcontent.ConstructingObjectParser;
import org.elasticsearch.common.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
@@ -28,22 +28,23 @@ import org.elasticsearch.common.xcontent.XContentParser;
import java.io.IOException;
import java.util.Objects;
+/**
+ * Response indicating if the Machine Learning Job is now opened or not
+ */
public class OpenJobResponse extends ActionResponse implements ToXContentObject {
private static final ParseField OPENED = new ParseField("opened");
- public static final ObjectParser PARSER = new ObjectParser<>("open_job_response", true, OpenJobResponse::new);
+ public static final ConstructingObjectParser PARSER =
+ new ConstructingObjectParser<>("open_job_response", true, (a) -> new OpenJobResponse((Boolean)a[0]));
static {
- PARSER.declareBoolean(OpenJobResponse::setOpened, OPENED);
+ PARSER.declareBoolean(ConstructingObjectParser.constructorArg(), OPENED);
}
private boolean opened;
- OpenJobResponse() {
- }
-
- public OpenJobResponse(boolean opened) {
+ OpenJobResponse(boolean opened) {
this.opened = opened;
}
@@ -51,14 +52,15 @@ public class OpenJobResponse extends ActionResponse implements ToXContentObject
return PARSER.parse(parser, null);
}
+ /**
+ * Has the job opened or not
+ *
+ * @return boolean value indicating the job opened status
+ */
public boolean isOpened() {
return opened;
}
- public void setOpened(boolean opened) {
- this.opened = opened;
- }
-
@Override
public boolean equals(Object other) {
if (this == other) {
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/PostDataRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/PostDataRequest.java
new file mode 100644
index 00000000000..cc015fc4837
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/PostDataRequest.java
@@ -0,0 +1,229 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.elasticsearch.client.ml;
+
+import org.elasticsearch.action.ActionRequest;
+import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.ml.job.config.Job;
+import org.elasticsearch.common.ParseField;
+import org.elasticsearch.common.bytes.BytesArray;
+import org.elasticsearch.common.bytes.BytesReference;
+import org.elasticsearch.common.xcontent.ConstructingObjectParser;
+import org.elasticsearch.common.xcontent.ToXContentObject;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentType;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * POJO for posting data to a Machine Learning job
+ */
+public class PostDataRequest extends ActionRequest implements ToXContentObject {
+
+ public static final ParseField RESET_START = new ParseField("reset_start");
+ public static final ParseField RESET_END = new ParseField("reset_end");
+ public static final ParseField CONTENT_TYPE = new ParseField("content_type");
+
+ public static final ConstructingObjectParser PARSER =
+ new ConstructingObjectParser<>("post_data_request",
+ (a) -> new PostDataRequest((String)a[0], XContentType.fromMediaTypeOrFormat((String)a[1]), new byte[0]));
+
+ static {
+ PARSER.declareString(ConstructingObjectParser.constructorArg(), Job.ID);
+ PARSER.declareString(ConstructingObjectParser.constructorArg(), CONTENT_TYPE);
+ PARSER.declareStringOrNull(PostDataRequest::setResetEnd, RESET_END);
+ PARSER.declareStringOrNull(PostDataRequest::setResetStart, RESET_START);
+ }
+
+ private final String jobId;
+ private final XContentType xContentType;
+ private final BytesReference content;
+ private String resetStart;
+ private String resetEnd;
+
+ /**
+ * Create a new PostDataRequest object
+ *
+ * @param jobId non-null jobId of the job to post data to
+ * @param xContentType content type of the data to post. Only {@link XContentType#JSON} or {@link XContentType#SMILE} are supported
+ * @param content bulk serialized content in the format of the passed {@link XContentType}
+ */
+ public PostDataRequest(String jobId, XContentType xContentType, BytesReference content) {
+ this.jobId = Objects.requireNonNull(jobId, "job_id must not be null");
+ this.xContentType = Objects.requireNonNull(xContentType, "content_type must not be null");
+ this.content = Objects.requireNonNull(content, "content must not be null");
+ }
+
+ /**
+ * Create a new PostDataRequest object referencing the passed {@code byte[]} content
+ *
+ * @param jobId non-null jobId of the job to post data to
+ * @param xContentType content type of the data to post. Only {@link XContentType#JSON} or {@link XContentType#SMILE} are supported
+ * @param content bulk serialized content in the format of the passed {@link XContentType}
+ */
+ public PostDataRequest(String jobId, XContentType xContentType, byte[] content) {
+ this(jobId, xContentType, new BytesArray(content));
+ }
+
+ /**
+ * Create a new PostDataRequest object referencing the passed {@link JsonBuilder} object
+ *
+ * @param jobId non-null jobId of the job to post data to
+ * @param builder {@link JsonBuilder} object containing documents to be serialized and sent in {@link XContentType#JSON} format
+ */
+ public PostDataRequest(String jobId, JsonBuilder builder) {
+ this(jobId, XContentType.JSON, builder.build());
+ }
+
+ public String getJobId() {
+ return jobId;
+ }
+
+ public String getResetStart() {
+ return resetStart;
+ }
+
+ /**
+ * Specifies the start of the bucket resetting range
+ *
+ * @param resetStart String representation of a timestamp; may be an epoch seconds, epoch millis or an ISO 8601 string
+ */
+ public void setResetStart(String resetStart) {
+ this.resetStart = resetStart;
+ }
+
+ public String getResetEnd() {
+ return resetEnd;
+ }
+
+ /**
+ * Specifies the end of the bucket resetting range
+ *
+ * @param resetEnd String representation of a timestamp; may be an epoch seconds, epoch millis or an ISO 8601 string
+ */
+ public void setResetEnd(String resetEnd) {
+ this.resetEnd = resetEnd;
+ }
+
+ public BytesReference getContent() {
+ return content;
+ }
+
+ public XContentType getXContentType() {
+ return xContentType;
+ }
+
+ @Override
+ public int hashCode() {
+ //We leave out the content for server side parity
+ return Objects.hash(jobId, resetStart, resetEnd, xContentType);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if(obj == this) {
+ return true;
+ }
+
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+
+ //We leave out the content for server side parity
+ PostDataRequest other = (PostDataRequest) obj;
+ return Objects.equals(jobId, other.jobId) &&
+ Objects.equals(resetStart, other.resetStart) &&
+ Objects.equals(resetEnd, other.resetEnd) &&
+ Objects.equals(xContentType, other.xContentType);
+ }
+
+ @Override
+ public ActionRequestValidationException validate() {
+ return null;
+ }
+
+ @Override
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+ builder.startObject();
+ builder.field(Job.ID.getPreferredName(), jobId);
+ builder.field(CONTENT_TYPE.getPreferredName(), xContentType.mediaType());
+ if (resetEnd != null) {
+ builder.field(RESET_END.getPreferredName(), resetEnd);
+ }
+ if (resetStart != null) {
+ builder.field(RESET_START.getPreferredName(), resetStart);
+ }
+ builder.endObject();
+ return builder;
+ }
+
+ /**
+ * Class for incrementally building a bulk document request in {@link XContentType#JSON} format
+ */
+ public static class JsonBuilder {
+
+ private final List