listener) {
restHighLevelClient.performRequestAsyncAndParseEntity( request, IngestRequestConverters::getPipeline, options,
- GetPipelineResponse::fromXContent, listener, emptySet());
+ GetPipelineResponse::fromXContent, listener, Collections.singleton(404));
}
/**
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/MLRequestConverters.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/MLRequestConverters.java
index 1030464be4f..e3570a2a837 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/MLRequestConverters.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/MLRequestConverters.java
@@ -38,6 +38,7 @@ import org.elasticsearch.client.ml.GetBucketsRequest;
import org.elasticsearch.client.ml.GetCalendarsRequest;
import org.elasticsearch.client.ml.GetCategoriesRequest;
import org.elasticsearch.client.ml.GetDatafeedRequest;
+import org.elasticsearch.client.ml.GetDatafeedStatsRequest;
import org.elasticsearch.client.ml.GetInfluencersRequest;
import org.elasticsearch.client.ml.GetJobRequest;
import org.elasticsearch.client.ml.GetJobStatsRequest;
@@ -45,6 +46,7 @@ import org.elasticsearch.client.ml.GetOverallBucketsRequest;
import org.elasticsearch.client.ml.GetRecordsRequest;
import org.elasticsearch.client.ml.OpenJobRequest;
import org.elasticsearch.client.ml.PostDataRequest;
+import org.elasticsearch.client.ml.PreviewDatafeedRequest;
import org.elasticsearch.client.ml.PutCalendarRequest;
import org.elasticsearch.client.ml.PutDatafeedRequest;
import org.elasticsearch.client.ml.PutJobRequest;
@@ -146,7 +148,12 @@ final class MLRequestConverters {
Request request = new Request(HttpDelete.METHOD_NAME, endpoint);
RequestConverters.Params params = new RequestConverters.Params(request);
- params.putParam("force", Boolean.toString(deleteJobRequest.isForce()));
+ if (deleteJobRequest.getForce() != null) {
+ params.putParam("force", Boolean.toString(deleteJobRequest.getForce()));
+ }
+ if (deleteJobRequest.getWaitForCompletion() != null) {
+ params.putParam("wait_for_completion", Boolean.toString(deleteJobRequest.getWaitForCompletion()));
+ }
return request;
}
@@ -259,6 +266,34 @@ final class MLRequestConverters {
return request;
}
+ static Request getDatafeedStats(GetDatafeedStatsRequest getDatafeedStatsRequest) {
+ String endpoint = new EndpointBuilder()
+ .addPathPartAsIs("_xpack")
+ .addPathPartAsIs("ml")
+ .addPathPartAsIs("datafeeds")
+ .addPathPart(Strings.collectionToCommaDelimitedString(getDatafeedStatsRequest.getDatafeedIds()))
+ .addPathPartAsIs("_stats")
+ .build();
+ Request request = new Request(HttpGet.METHOD_NAME, endpoint);
+
+ RequestConverters.Params params = new RequestConverters.Params(request);
+ if (getDatafeedStatsRequest.isAllowNoDatafeeds() != null) {
+ params.putParam("allow_no_datafeeds", Boolean.toString(getDatafeedStatsRequest.isAllowNoDatafeeds()));
+ }
+ return request;
+ }
+
+ static Request previewDatafeed(PreviewDatafeedRequest previewDatafeedRequest) {
+ String endpoint = new EndpointBuilder()
+ .addPathPartAsIs("_xpack")
+ .addPathPartAsIs("ml")
+ .addPathPartAsIs("datafeeds")
+ .addPathPart(previewDatafeedRequest.getDatafeedId())
+ .addPathPartAsIs("_preview")
+ .build();
+ return new Request(HttpGet.METHOD_NAME, endpoint);
+ }
+
static Request deleteForecast(DeleteForecastRequest deleteForecastRequest) {
String endpoint = new EndpointBuilder()
.addPathPartAsIs("_xpack")
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java
index 43bc18fad0d..8c442d8ffa6 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java
@@ -26,6 +26,7 @@ import org.elasticsearch.client.ml.DeleteCalendarRequest;
import org.elasticsearch.client.ml.DeleteDatafeedRequest;
import org.elasticsearch.client.ml.DeleteForecastRequest;
import org.elasticsearch.client.ml.DeleteJobRequest;
+import org.elasticsearch.client.ml.DeleteJobResponse;
import org.elasticsearch.client.ml.FlushJobRequest;
import org.elasticsearch.client.ml.FlushJobResponse;
import org.elasticsearch.client.ml.ForecastJobRequest;
@@ -38,6 +39,8 @@ import org.elasticsearch.client.ml.GetCategoriesRequest;
import org.elasticsearch.client.ml.GetCategoriesResponse;
import org.elasticsearch.client.ml.GetDatafeedRequest;
import org.elasticsearch.client.ml.GetDatafeedResponse;
+import org.elasticsearch.client.ml.GetDatafeedStatsRequest;
+import org.elasticsearch.client.ml.GetDatafeedStatsResponse;
import org.elasticsearch.client.ml.GetInfluencersRequest;
import org.elasticsearch.client.ml.GetInfluencersResponse;
import org.elasticsearch.client.ml.GetJobRequest;
@@ -52,6 +55,8 @@ import org.elasticsearch.client.ml.OpenJobRequest;
import org.elasticsearch.client.ml.OpenJobResponse;
import org.elasticsearch.client.ml.PostDataRequest;
import org.elasticsearch.client.ml.PostDataResponse;
+import org.elasticsearch.client.ml.PreviewDatafeedRequest;
+import org.elasticsearch.client.ml.PreviewDatafeedResponse;
import org.elasticsearch.client.ml.PutCalendarRequest;
import org.elasticsearch.client.ml.PutCalendarResponse;
import org.elasticsearch.client.ml.PutDatafeedRequest;
@@ -181,7 +186,7 @@ public final class MachineLearningClient {
}
/**
- * Gets one or more Machine Learning job configuration info, asynchronously.
+ * Gets usage statistics for one or more Machine Learning jobs, asynchronously.
*
* For additional info
* see Get job stats docs
@@ -207,14 +212,15 @@ public final class MachineLearningClient {
*
* @param request The request to delete the job
* @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
- * @return action acknowledgement
+ * @return The action response which contains the acknowledgement or the task id depending on whether the action was set to wait for
+ * completion
* @throws IOException when there is a serialization issue sending the request or receiving the response
*/
- public AcknowledgedResponse deleteJob(DeleteJobRequest request, RequestOptions options) throws IOException {
+ public DeleteJobResponse deleteJob(DeleteJobRequest request, RequestOptions options) throws IOException {
return restHighLevelClient.performRequestAndParseEntity(request,
MLRequestConverters::deleteJob,
options,
- AcknowledgedResponse::fromXContent,
+ DeleteJobResponse::fromXContent,
Collections.emptySet());
}
@@ -228,11 +234,11 @@ public final class MachineLearningClient {
* @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
* @param listener Listener to be notified upon request completion
*/
- public void deleteJobAsync(DeleteJobRequest request, RequestOptions options, ActionListener listener) {
+ public void deleteJobAsync(DeleteJobRequest request, RequestOptions options, ActionListener listener) {
restHighLevelClient.performRequestAsyncAndParseEntity(request,
MLRequestConverters::deleteJob,
options,
- AcknowledgedResponse::fromXContent,
+ DeleteJobResponse::fromXContent,
listener,
Collections.emptySet());
}
@@ -649,6 +655,90 @@ public final class MachineLearningClient {
Collections.emptySet());
}
+ /**
+ * Gets statistics for one or more Machine Learning datafeeds
+ *
+ * For additional info
+ * see Get datafeed stats docs
+ *
+ * @param request {@link GetDatafeedStatsRequest} Request containing a list of datafeedId(s) and additional options
+ * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
+ * @return {@link GetDatafeedStatsResponse} response object containing
+ * the {@link org.elasticsearch.client.ml.datafeed.DatafeedStats} objects and the number of datafeeds found
+ * @throws IOException when there is a serialization issue sending the request or receiving the response
+ */
+ public GetDatafeedStatsResponse getDatafeedStats(GetDatafeedStatsRequest request, RequestOptions options) throws IOException {
+ return restHighLevelClient.performRequestAndParseEntity(request,
+ MLRequestConverters::getDatafeedStats,
+ options,
+ GetDatafeedStatsResponse::fromXContent,
+ Collections.emptySet());
+ }
+
+ /**
+ * Previews the given Machine Learning Datafeed
+ *
+ * For additional info
+ * see
+ * ML Preview Datafeed documentation
+ *
+ * @param request The request to preview the datafeed
+ * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
+ * @return {@link PreviewDatafeedResponse} object containing a {@link org.elasticsearch.common.bytes.BytesReference} of the data in
+ * JSON format
+ * @throws IOException when there is a serialization issue sending the request or receiving the response
+ */
+ public PreviewDatafeedResponse previewDatafeed(PreviewDatafeedRequest request, RequestOptions options) throws IOException {
+ return restHighLevelClient.performRequestAndParseEntity(request,
+ MLRequestConverters::previewDatafeed,
+ options,
+ PreviewDatafeedResponse::fromXContent,
+ Collections.emptySet());
+ }
+
+ /**
+ * Gets statistics for one or more Machine Learning datafeeds, asynchronously.
+ *
+ * For additional info
+ * see Get datafeed stats docs
+ *
+ * @param request {@link GetDatafeedStatsRequest} Request containing a list of datafeedId(s) and additional options
+ * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
+ * @param listener Listener to be notified with {@link GetDatafeedStatsResponse} upon request completion
+ */
+ public void getDatafeedStatsAsync(GetDatafeedStatsRequest request,
+ RequestOptions options,
+ ActionListener listener) {
+ restHighLevelClient.performRequestAsyncAndParseEntity(request,
+ MLRequestConverters::getDatafeedStats,
+ options,
+ GetDatafeedStatsResponse::fromXContent,
+ listener,
+ Collections.emptySet());
+ }
+
+ /**
+ * Previews the given Machine Learning Datafeed asynchronously and notifies the listener on completion
+ *
+ * For additional info
+ * see
+ * ML Preview Datafeed documentation
+ *
+ * @param request The request to preview the datafeed
+ * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
+ * @param listener Listener to be notified upon request completion
+ */
+ public void previewDatafeedAsync(PreviewDatafeedRequest request,
+ RequestOptions options,
+ ActionListener listener) {
+ restHighLevelClient.performRequestAsyncAndParseEntity(request,
+ MLRequestConverters::previewDatafeed,
+ options,
+ PreviewDatafeedResponse::fromXContent,
+ listener,
+ Collections.emptySet());
+ }
+
/**
* Updates a Machine Learning {@link org.elasticsearch.client.ml.job.config.Job}
*
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 c182cc27e84..cfa5e6e61fa 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
@@ -19,6 +19,8 @@
package org.elasticsearch.client;
import org.elasticsearch.action.ActionListener;
+import org.elasticsearch.client.watcher.ActivateWatchRequest;
+import org.elasticsearch.client.watcher.ActivateWatchResponse;
import org.elasticsearch.client.watcher.AckWatchRequest;
import org.elasticsearch.client.watcher.AckWatchResponse;
import org.elasticsearch.protocol.xpack.watcher.DeleteWatchRequest;
@@ -121,4 +123,31 @@ public final class WatcherClient {
AckWatchResponse::fromXContent, listener, emptySet());
}
+ /**
+ * Activate a watch from the cluster
+ * See
+ * the docs for more.
+ * @param request the request
+ * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
+ * @return the response
+ * @throws IOException in case there is a problem sending the request or parsing back the response
+ */
+ public ActivateWatchResponse activateWatch(ActivateWatchRequest request, RequestOptions options) throws IOException {
+ return restHighLevelClient.performRequestAndParseEntity(request, WatcherRequestConverters::activateWatch, options,
+ ActivateWatchResponse::fromXContent, singleton(404));
+ }
+
+ /**
+ * Asynchronously activates a watch from the cluster
+ * See
+ * the docs for more.
+ * @param request the request
+ * @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 activateWatchAsync(ActivateWatchRequest request, RequestOptions options, ActionListener listener) {
+ restHighLevelClient.performRequestAsyncAndParseEntity(request, WatcherRequestConverters::activateWatch, options,
+ ActivateWatchResponse::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
index 7a8fa19633e..3a17056f9bf 100644
--- 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
@@ -23,6 +23,7 @@ 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.client.watcher.ActivateWatchRequest;
import org.elasticsearch.client.watcher.AckWatchRequest;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.protocol.xpack.watcher.DeleteWatchRequest;
@@ -73,4 +74,16 @@ public class WatcherRequestConverters {
Request request = new Request(HttpPut.METHOD_NAME, endpoint);
return request;
}
+
+ static Request activateWatch(ActivateWatchRequest activateWatchRequest) {
+ String endpoint = new RequestConverters.EndpointBuilder()
+ .addPathPartAsIs("_xpack")
+ .addPathPartAsIs("watcher")
+ .addPathPartAsIs("watch")
+ .addPathPart(activateWatchRequest.getWatchId())
+ .addPathPartAsIs("_activate")
+ .build();
+ Request request = new Request(HttpPut.METHOD_NAME, endpoint);
+ return request;
+ }
}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteJobRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteJobRequest.java
index a355f7ec659..44e3668059c 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteJobRequest.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteJobRequest.java
@@ -29,7 +29,8 @@ import java.util.Objects;
public class DeleteJobRequest extends ActionRequest {
private String jobId;
- private boolean force;
+ private Boolean force;
+ private Boolean waitForCompletion;
public DeleteJobRequest(String jobId) {
this.jobId = Objects.requireNonNull(jobId, "[job_id] must not be null");
@@ -47,7 +48,7 @@ public class DeleteJobRequest extends ActionRequest {
this.jobId = Objects.requireNonNull(jobId, "[job_id] must not be null");
}
- public boolean isForce() {
+ public Boolean getForce() {
return force;
}
@@ -57,10 +58,24 @@ public class DeleteJobRequest extends ActionRequest {
*
* @param force When {@code true} forcefully delete an opened job. Defaults to {@code false}
*/
- public void setForce(boolean force) {
+ public void setForce(Boolean force) {
this.force = force;
}
+ public Boolean getWaitForCompletion() {
+ return waitForCompletion;
+ }
+
+ /**
+ * Set whether this request should wait until the operation has completed before returning
+ * @param waitForCompletion When {@code true} the call will wait for the job deletion to complete.
+ * Otherwise, the deletion will be executed asynchronously and the response
+ * will contain the task id.
+ */
+ public void setWaitForCompletion(Boolean waitForCompletion) {
+ this.waitForCompletion = waitForCompletion;
+ }
+
@Override
public ActionRequestValidationException validate() {
return null;
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteJobResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteJobResponse.java
new file mode 100644
index 00000000000..f1487c8c276
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/DeleteJobResponse.java
@@ -0,0 +1,113 @@
+/*
+ * 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.ObjectParser;
+import org.elasticsearch.common.xcontent.ToXContentObject;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentParser;
+import org.elasticsearch.tasks.TaskId;
+
+import java.io.IOException;
+import java.util.Objects;
+
+/**
+ * Response object that contains the acknowledgement or the task id
+ * depending on whether the delete job action was requested to wait for completion.
+ */
+public class DeleteJobResponse extends ActionResponse implements ToXContentObject {
+
+ private static final ParseField ACKNOWLEDGED = new ParseField("acknowledged");
+ private static final ParseField TASK = new ParseField("task");
+
+ public static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>("delete_job_response",
+ true, a-> new DeleteJobResponse((Boolean) a[0], (TaskId) a[1]));
+
+ static {
+ PARSER.declareBoolean(ConstructingObjectParser.optionalConstructorArg(), ACKNOWLEDGED);
+ PARSER.declareField(ConstructingObjectParser.optionalConstructorArg(), TaskId.parser(), TASK, ObjectParser.ValueType.STRING);
+ }
+
+ public static DeleteJobResponse fromXContent(XContentParser parser) throws IOException {
+ return PARSER.parse(parser, null);
+ }
+
+ private final Boolean acknowledged;
+ private final TaskId task;
+
+ DeleteJobResponse(@Nullable Boolean acknowledged, @Nullable TaskId task) {
+ assert acknowledged != null || task != null;
+ this.acknowledged = acknowledged;
+ this.task = task;
+ }
+
+ /**
+ * Get the action acknowledgement
+ * @return {@code null} when the request had {@link DeleteJobRequest#getWaitForCompletion()} set to {@code false} or
+ * otherwise a {@code boolean} that indicates whether the job was deleted successfully.
+ */
+ public Boolean getAcknowledged() {
+ return acknowledged;
+ }
+
+ /**
+ * Get the task id
+ * @return {@code null} when the request had {@link DeleteJobRequest#getWaitForCompletion()} set to {@code true} or
+ * otherwise the id of the job deletion task.
+ */
+ public TaskId getTask() {
+ return task;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(acknowledged, task);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (other == null || getClass() != other.getClass()) {
+ return false;
+ }
+
+ DeleteJobResponse that = (DeleteJobResponse) other;
+ return Objects.equals(acknowledged, that.acknowledged) && Objects.equals(task, that.task);
+ }
+
+ @Override
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+ builder.startObject();
+ if (acknowledged != null) {
+ builder.field(ACKNOWLEDGED.getPreferredName(), acknowledged);
+ }
+ if (task != null) {
+ builder.field(TASK.getPreferredName(), task.toString());
+ }
+ builder.endObject();
+ return builder;
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetDatafeedStatsRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetDatafeedStatsRequest.java
new file mode 100644
index 00000000000..b4949708c17
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetDatafeedStatsRequest.java
@@ -0,0 +1,147 @@
+/*
+ * 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.datafeed.DatafeedConfig;
+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.ToXContent;
+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.datafeed.DatafeedStats} by their respective datafeedIds
+ *
+ * {@code _all} explicitly gets all the datafeeds' statistics in the cluster
+ * An empty request (no {@code datafeedId}s) implicitly gets all the datafeeds' statistics in the cluster
+ */
+public class GetDatafeedStatsRequest extends ActionRequest implements ToXContentObject {
+
+ public static final ParseField ALLOW_NO_DATAFEEDS = new ParseField("allow_no_datafeeds");
+
+ @SuppressWarnings("unchecked")
+ public static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>(
+ "get_datafeed_stats_request", a -> new GetDatafeedStatsRequest((List) a[0]));
+
+ static {
+ PARSER.declareField(ConstructingObjectParser.constructorArg(),
+ p -> Arrays.asList(Strings.commaDelimitedListToStringArray(p.text())),
+ DatafeedConfig.ID, ObjectParser.ValueType.STRING_ARRAY);
+ PARSER.declareBoolean(GetDatafeedStatsRequest::setAllowNoDatafeeds, ALLOW_NO_DATAFEEDS);
+ }
+
+ private static final String ALL_DATAFEEDS = "_all";
+
+ private final List datafeedIds;
+ private Boolean allowNoDatafeeds;
+
+ /**
+ * Explicitly gets all datafeeds statistics
+ *
+ * @return a {@link GetDatafeedStatsRequest} for all existing datafeeds
+ */
+ public static GetDatafeedStatsRequest getAllDatafeedStatsRequest(){
+ return new GetDatafeedStatsRequest(ALL_DATAFEEDS);
+ }
+
+ GetDatafeedStatsRequest(List datafeedIds) {
+ if (datafeedIds.stream().anyMatch(Objects::isNull)) {
+ throw new NullPointerException("datafeedIds must not contain null values");
+ }
+ this.datafeedIds = new ArrayList<>(datafeedIds);
+ }
+
+ /**
+ * Get the specified Datafeed's statistics via their unique datafeedIds
+ *
+ * @param datafeedIds must be non-null and each datafeedId must be non-null
+ */
+ public GetDatafeedStatsRequest(String... datafeedIds) {
+ this(Arrays.asList(datafeedIds));
+ }
+
+ /**
+ * All the datafeedIds for which to get statistics
+ */
+ public List getDatafeedIds() {
+ return datafeedIds;
+ }
+
+ public Boolean isAllowNoDatafeeds() {
+ return this.allowNoDatafeeds;
+ }
+
+ /**
+ * Whether to ignore if a wildcard expression matches no datafeeds.
+ *
+ * This includes {@code _all} string or when no datafeeds have been specified
+ *
+ * @param allowNoDatafeeds When {@code true} ignore if wildcard or {@code _all} matches no datafeeds. Defaults to {@code true}
+ */
+ public void setAllowNoDatafeeds(boolean allowNoDatafeeds) {
+ this.allowNoDatafeeds = allowNoDatafeeds;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(datafeedIds, allowNoDatafeeds);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (other == null || getClass() != other.getClass()) {
+ return false;
+ }
+
+ GetDatafeedStatsRequest that = (GetDatafeedStatsRequest) other;
+ return Objects.equals(datafeedIds, that.datafeedIds) &&
+ Objects.equals(allowNoDatafeeds, that.allowNoDatafeeds);
+ }
+
+ @Override
+ public ActionRequestValidationException validate() {
+ return null;
+ }
+
+ @Override
+ public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException {
+ builder.startObject();
+ builder.field(DatafeedConfig.ID.getPreferredName(), Strings.collectionToCommaDelimitedString(datafeedIds));
+ if (allowNoDatafeeds != null) {
+ builder.field(ALLOW_NO_DATAFEEDS.getPreferredName(), allowNoDatafeeds);
+ }
+ builder.endObject();
+ return builder;
+ }
+
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetDatafeedStatsResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetDatafeedStatsResponse.java
new file mode 100644
index 00000000000..548c8fe2359
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetDatafeedStatsResponse.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.datafeed.DatafeedStats;
+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 static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
+
+/**
+ * Contains a {@link List} of the found {@link DatafeedStats} objects and the total count found
+ */
+public class GetDatafeedStatsResponse extends AbstractResultResponse {
+
+ public static final ParseField RESULTS_FIELD = new ParseField("datafeeds");
+
+ @SuppressWarnings("unchecked")
+ public static final ConstructingObjectParser PARSER =
+ new ConstructingObjectParser<>("get_datafeed_stats_response",
+ true,
+ a -> new GetDatafeedStatsResponse((List) a[0], (long) a[1]));
+
+ static {
+ PARSER.declareObjectArray(constructorArg(), DatafeedStats.PARSER, RESULTS_FIELD);
+ PARSER.declareLong(constructorArg(), COUNT);
+ }
+
+ GetDatafeedStatsResponse(List results, long count) {
+ super(RESULTS_FIELD, results, count);
+ }
+
+ /**
+ * The collection of {@link DatafeedStats} objects found in the query
+ */
+ public List datafeedStats() {
+ return results;
+ }
+
+ public static GetDatafeedStatsResponse 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;
+ }
+
+ GetDatafeedStatsResponse other = (GetDatafeedStatsResponse) 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/PreviewDatafeedRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/PreviewDatafeedRequest.java
new file mode 100644
index 00000000000..a21e96b4642
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/PreviewDatafeedRequest.java
@@ -0,0 +1,100 @@
+/*
+ * 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.datafeed.DatafeedConfig;
+import org.elasticsearch.common.Strings;
+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;
+
+/**
+ * Request to preview a MachineLearning Datafeed
+ */
+public class PreviewDatafeedRequest extends ActionRequest implements ToXContentObject {
+
+ public static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>(
+ "open_datafeed_request", true, a -> new PreviewDatafeedRequest((String) a[0]));
+
+ static {
+ PARSER.declareString(ConstructingObjectParser.constructorArg(), DatafeedConfig.ID);
+ }
+
+ public static PreviewDatafeedRequest fromXContent(XContentParser parser) throws IOException {
+ return PARSER.parse(parser, null);
+ }
+
+ private final String datafeedId;
+
+ /**
+ * Create a new request with the desired datafeedId
+ *
+ * @param datafeedId unique datafeedId, must not be null
+ */
+ public PreviewDatafeedRequest(String datafeedId) {
+ this.datafeedId = Objects.requireNonNull(datafeedId, "[datafeed_id] must not be null");
+ }
+
+ public String getDatafeedId() {
+ return datafeedId;
+ }
+
+ @Override
+ public ActionRequestValidationException validate() {
+ return null;
+ }
+
+ @Override
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+ builder.startObject();
+ builder.field(DatafeedConfig.ID.getPreferredName(), datafeedId);
+ builder.endObject();
+ return builder;
+ }
+
+ @Override
+ public String toString() {
+ return Strings.toString(this);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(datafeedId);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (other == null || getClass() != other.getClass()) {
+ return false;
+ }
+
+ PreviewDatafeedRequest that = (PreviewDatafeedRequest) other;
+ return Objects.equals(datafeedId, that.datafeedId);
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/PreviewDatafeedResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/PreviewDatafeedResponse.java
new file mode 100644
index 00000000000..ca96f153c60
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/PreviewDatafeedResponse.java
@@ -0,0 +1,113 @@
+/*
+ * 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.Strings;
+import org.elasticsearch.common.bytes.BytesReference;
+import org.elasticsearch.common.io.stream.StreamInput;
+import org.elasticsearch.common.xcontent.DeprecationHandler;
+import org.elasticsearch.common.xcontent.NamedXContentRegistry;
+import org.elasticsearch.common.xcontent.ToXContentObject;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentFactory;
+import org.elasticsearch.common.xcontent.XContentParser;
+import org.elasticsearch.common.xcontent.XContentType;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * Response containing a datafeed preview in JSON format
+ */
+public class PreviewDatafeedResponse extends ActionResponse implements ToXContentObject {
+
+ private BytesReference preview;
+
+ public static PreviewDatafeedResponse fromXContent(XContentParser parser) throws IOException {
+ try (XContentBuilder builder = XContentFactory.jsonBuilder()) {
+ parser.nextToken();
+ builder.copyCurrentStructure(parser);
+ return new PreviewDatafeedResponse(BytesReference.bytes(builder));
+ }
+ }
+
+ public PreviewDatafeedResponse(BytesReference preview) {
+ this.preview = preview;
+ }
+
+ public BytesReference getPreview() {
+ return preview;
+ }
+
+ /**
+ * Parses the preview to a list of {@link Map} objects
+ * @return List of previewed data
+ * @throws IOException If there is a parsing issue with the {@link BytesReference}
+ * @throws java.lang.ClassCastException If casting the raw {@link Object} entries to a {@link Map} fails
+ */
+ @SuppressWarnings("unchecked")
+ public List