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 aa998591159f6..2b3334e05d553 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
@@ -49,6 +49,7 @@
import org.elasticsearch.client.ml.GetOverallBucketsRequest;
import org.elasticsearch.client.ml.GetRecordsRequest;
import org.elasticsearch.client.ml.OpenJobRequest;
+import org.elasticsearch.client.ml.PostCalendarEventRequest;
import org.elasticsearch.client.ml.PostDataRequest;
import org.elasticsearch.client.ml.PreviewDatafeedRequest;
import org.elasticsearch.client.ml.PutCalendarJobRequest;
@@ -509,6 +510,21 @@ static Request deleteCalendar(DeleteCalendarRequest deleteCalendarRequest) {
return request;
}
+ static Request postCalendarEvents(PostCalendarEventRequest postCalendarEventRequest) throws IOException {
+ String endpoint = new EndpointBuilder()
+ .addPathPartAsIs("_xpack")
+ .addPathPartAsIs("ml")
+ .addPathPartAsIs("calendars")
+ .addPathPart(postCalendarEventRequest.getCalendarId())
+ .addPathPartAsIs("events")
+ .build();
+ Request request = new Request(HttpPost.METHOD_NAME, endpoint);
+ request.setEntity(createEntity(postCalendarEventRequest,
+ REQUEST_BODY_CONTENT_TYPE,
+ PostCalendarEventRequest.EXCLUDE_CALENDAR_ID_PARAMS));
+ return request;
+ }
+
static Request putFilter(PutFilterRequest putFilterRequest) throws IOException {
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 a35bbb042e7a2..a6706cf0a230a 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
@@ -59,6 +59,8 @@
import org.elasticsearch.client.ml.GetRecordsResponse;
import org.elasticsearch.client.ml.OpenJobRequest;
import org.elasticsearch.client.ml.OpenJobResponse;
+import org.elasticsearch.client.ml.PostCalendarEventRequest;
+import org.elasticsearch.client.ml.PostCalendarEventResponse;
import org.elasticsearch.client.ml.PostDataRequest;
import org.elasticsearch.client.ml.PostDataResponse;
import org.elasticsearch.client.ml.PreviewDatafeedRequest;
@@ -1299,6 +1301,47 @@ public void deleteCalendarAsync(DeleteCalendarRequest request, RequestOptions op
Collections.emptySet());
}
+ /**
+ * Creates new events for a a machine learning calendar
+ *
+ * For additional info
+ * see
+ * Add Events to Calendar API
+ *
+ * @param request The request
+ * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
+ * @return The {@link PostCalendarEventRequest} containing the scheduled events
+ * @throws IOException when there is a serialization issue sending the request or receiving the response
+ */
+ public PostCalendarEventResponse postCalendarEvent(PostCalendarEventRequest request, RequestOptions options) throws IOException {
+ return restHighLevelClient.performRequestAndParseEntity(request,
+ MLRequestConverters::postCalendarEvents,
+ options,
+ PostCalendarEventResponse::fromXContent,
+ Collections.emptySet());
+ }
+
+ /**
+ * Creates new events for a a machine learning calendar asynchronously, notifies the listener on completion
+ *
+ * For additional info
+ * see
+ * Add Events to Calendar API
+ *
+ * @param request The request
+ * @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 postCalendarEventAsync(PostCalendarEventRequest request, RequestOptions options,
+ ActionListener listener) {
+ restHighLevelClient.performRequestAsyncAndParseEntity(request,
+ MLRequestConverters::postCalendarEvents,
+ options,
+ PostCalendarEventResponse::fromXContent,
+ listener,
+ Collections.emptySet());
+ }
+
/**
* Creates a new Machine Learning Filter
*
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java
index 4381b9879d3a1..844a1d4e8296f 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java
@@ -652,7 +652,12 @@ static Request deleteScript(DeleteStoredScriptRequest deleteStoredScriptRequest)
}
static HttpEntity createEntity(ToXContent toXContent, XContentType xContentType) throws IOException {
- BytesRef source = XContentHelper.toXContent(toXContent, xContentType, false).toBytesRef();
+ return createEntity(toXContent, xContentType, ToXContent.EMPTY_PARAMS);
+ }
+
+ static HttpEntity createEntity(ToXContent toXContent, XContentType xContentType, ToXContent.Params toXContentParams)
+ throws IOException {
+ BytesRef source = XContentHelper.toXContent(toXContent, xContentType, toXContentParams, false).toBytesRef();
return new ByteArrayEntity(source.bytes, source.offset, source.length, createContentType(xContentType));
}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/PostCalendarEventRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/PostCalendarEventRequest.java
new file mode 100644
index 0000000000000..2c43ec9ab7769
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/PostCalendarEventRequest.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.ActionRequest;
+import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.ml.calendars.Calendar;
+import org.elasticsearch.client.ml.calendars.ScheduledEvent;
+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.Collections;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Request to add a ScheduledEvent to a Machine Learning calendar
+ */
+public class PostCalendarEventRequest extends ActionRequest implements ToXContentObject {
+
+ private final String calendarId;
+ private final List scheduledEvents;
+
+ public static final String INCLUDE_CALENDAR_ID_KEY = "include_calendar_id";
+ public static final ParseField EVENTS = new ParseField("events");
+
+ @SuppressWarnings("unchecked")
+ public static final ConstructingObjectParser PARSER =
+ new ConstructingObjectParser<>("post_calendar_event_request",
+ a -> new PostCalendarEventRequest((String)a[0], (List)a[1]));
+
+ static {
+ PARSER.declareString(ConstructingObjectParser.constructorArg(), Calendar.ID);
+ PARSER.declareObjectArray(ConstructingObjectParser.constructorArg(),
+ (p, c) -> ScheduledEvent.PARSER.apply(p, null), EVENTS);
+ }
+ public static final MapParams EXCLUDE_CALENDAR_ID_PARAMS =
+ new MapParams(Collections.singletonMap(INCLUDE_CALENDAR_ID_KEY, Boolean.toString(false)));
+
+ /**
+ * Create a new PostCalendarEventRequest with an existing non-null calendarId and a list of Scheduled events
+ *
+ * @param calendarId The ID of the calendar, must be non-null
+ * @param scheduledEvents The non-null, non-empty, list of {@link ScheduledEvent} objects to add to the calendar
+ */
+ public PostCalendarEventRequest(String calendarId, List scheduledEvents) {
+ this.calendarId = Objects.requireNonNull(calendarId, "[calendar_id] must not be null.");
+ this.scheduledEvents = Objects.requireNonNull(scheduledEvents, "[events] must not be null.");
+ if (scheduledEvents.isEmpty()) {
+ throw new IllegalArgumentException("At least 1 event is required");
+ }
+ }
+
+ public String getCalendarId() {
+ return calendarId;
+ }
+
+ public List getScheduledEvents() {
+ return scheduledEvents;
+ }
+
+ @Override
+ public ActionRequestValidationException validate() {
+ return null;
+ }
+
+ @Override
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+ builder.startObject();
+ if (params.paramAsBoolean(INCLUDE_CALENDAR_ID_KEY, true)) {
+ builder.field(Calendar.ID.getPreferredName(), calendarId);
+ }
+ builder.field(EVENTS.getPreferredName(), scheduledEvents);
+ builder.endObject();
+ return builder;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(calendarId, scheduledEvents);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ PostCalendarEventRequest other = (PostCalendarEventRequest) obj;
+ return Objects.equals(calendarId, other.calendarId) && Objects.equals(scheduledEvents, other.scheduledEvents);
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/PostCalendarEventResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/PostCalendarEventResponse.java
new file mode 100644
index 0000000000000..56e3cdce24f1b
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/PostCalendarEventResponse.java
@@ -0,0 +1,93 @@
+/*
+ * 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.client.ml.calendars.ScheduledEvent;
+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.List;
+import java.util.Objects;
+
+/**
+ * Response to adding ScheduledEvent(s) to a Machine Learning calendar
+ */
+public class PostCalendarEventResponse extends ActionResponse implements ToXContentObject {
+
+ private final List scheduledEvents;
+ public static final ParseField EVENTS = new ParseField("events");
+
+ @SuppressWarnings("unchecked")
+ public static final ConstructingObjectParser PARSER =
+ new ConstructingObjectParser<>("post_calendar_event_response",
+ true,
+ a -> new PostCalendarEventResponse((List)a[0]));
+
+ static {
+ PARSER.declareObjectArray(ConstructingObjectParser.constructorArg(),
+ (p, c) -> ScheduledEvent.PARSER.apply(p, null), EVENTS);
+ }
+
+ public static PostCalendarEventResponse fromXContent(XContentParser parser) throws IOException {
+ return PARSER.parse(parser, null);
+ }
+
+ /**
+ * Create a new PostCalendarEventResponse containing the scheduled Events
+ *
+ * @param scheduledEvents The list of {@link ScheduledEvent} objects
+ */
+ public PostCalendarEventResponse(List scheduledEvents) {
+ this.scheduledEvents = scheduledEvents;
+ }
+
+ public List getScheduledEvents() {
+ return scheduledEvents;
+ }
+
+ @Override
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+ builder.startObject();
+ builder.field(EVENTS.getPreferredName(), scheduledEvents);
+ builder.endObject();
+ return builder;
+ }
+
+ @Override
+ public int hashCode(){
+ return Objects.hash(scheduledEvents);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ PostCalendarEventResponse other = (PostCalendarEventResponse) obj;
+ return Objects.equals(scheduledEvents, other.scheduledEvents);
+ }
+}
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/MLRequestConvertersTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/MLRequestConvertersTests.java
index a38584b0d020e..7e2687202af85 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/MLRequestConvertersTests.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/MLRequestConvertersTests.java
@@ -45,6 +45,7 @@
import org.elasticsearch.client.ml.GetOverallBucketsRequest;
import org.elasticsearch.client.ml.GetRecordsRequest;
import org.elasticsearch.client.ml.OpenJobRequest;
+import org.elasticsearch.client.ml.PostCalendarEventRequest;
import org.elasticsearch.client.ml.PostDataRequest;
import org.elasticsearch.client.ml.PreviewDatafeedRequest;
import org.elasticsearch.client.ml.PutCalendarJobRequest;
@@ -59,6 +60,8 @@
import org.elasticsearch.client.ml.UpdateJobRequest;
import org.elasticsearch.client.ml.calendars.Calendar;
import org.elasticsearch.client.ml.calendars.CalendarTests;
+import org.elasticsearch.client.ml.calendars.ScheduledEvent;
+import org.elasticsearch.client.ml.calendars.ScheduledEventTests;
import org.elasticsearch.client.ml.datafeed.DatafeedConfig;
import org.elasticsearch.client.ml.datafeed.DatafeedConfigTests;
import org.elasticsearch.client.ml.job.config.AnalysisConfig;
@@ -71,6 +74,7 @@
import org.elasticsearch.client.ml.job.util.PageParams;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.unit.TimeValue;
+import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.common.xcontent.json.JsonXContent;
@@ -81,6 +85,7 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import static org.hamcrest.Matchers.equalTo;
@@ -558,6 +563,22 @@ public void testDeleteCalendar() {
assertEquals("/_xpack/ml/calendars/" + deleteCalendarRequest.getCalendarId(), request.getEndpoint());
}
+ public void testPostCalendarEvent() throws Exception {
+ String calendarId = randomAlphaOfLength(10);
+ List events = Arrays.asList(ScheduledEventTests.testInstance(),
+ ScheduledEventTests.testInstance(),
+ ScheduledEventTests.testInstance());
+ PostCalendarEventRequest postCalendarEventRequest = new PostCalendarEventRequest(calendarId, events);
+
+ Request request = MLRequestConverters.postCalendarEvents(postCalendarEventRequest);
+ assertEquals(HttpPost.METHOD_NAME, request.getMethod());
+ assertEquals("/_xpack/ml/calendars/" + calendarId + "/events", request.getEndpoint());
+
+ XContentBuilder builder = JsonXContent.contentBuilder();
+ builder = postCalendarEventRequest.toXContent(builder, PostCalendarEventRequest.EXCLUDE_CALENDAR_ID_PARAMS);
+ assertEquals(Strings.toString(builder), requestEntityToString(request));
+ }
+
public void testPutFilter() throws IOException {
MlFilter filter = MlFilterTests.createRandomBuilder("foo").build();
PutFilterRequest putFilterRequest = new PutFilterRequest(filter);
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java
index bffdc1aa1a07b..5307529fb679e 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java
@@ -54,6 +54,8 @@
import org.elasticsearch.client.ml.GetJobStatsResponse;
import org.elasticsearch.client.ml.OpenJobRequest;
import org.elasticsearch.client.ml.OpenJobResponse;
+import org.elasticsearch.client.ml.PostCalendarEventRequest;
+import org.elasticsearch.client.ml.PostCalendarEventResponse;
import org.elasticsearch.client.ml.PostDataRequest;
import org.elasticsearch.client.ml.PostDataResponse;
import org.elasticsearch.client.ml.PreviewDatafeedRequest;
@@ -76,6 +78,8 @@
import org.elasticsearch.client.ml.UpdateJobRequest;
import org.elasticsearch.client.ml.calendars.Calendar;
import org.elasticsearch.client.ml.calendars.CalendarTests;
+import org.elasticsearch.client.ml.calendars.ScheduledEvent;
+import org.elasticsearch.client.ml.calendars.ScheduledEventTests;
import org.elasticsearch.client.ml.datafeed.DatafeedConfig;
import org.elasticsearch.client.ml.datafeed.DatafeedState;
import org.elasticsearch.client.ml.datafeed.DatafeedStats;
@@ -889,6 +893,24 @@ public void testDeleteCalendar() throws IOException {
assertThat(exception.status().getStatus(), equalTo(404));
}
+ public void testPostCalendarEvent() throws Exception {
+ Calendar calendar = CalendarTests.testInstance();
+ MachineLearningClient machineLearningClient = highLevelClient().machineLearning();
+ machineLearningClient.putCalendar(new PutCalendarRequest(calendar), RequestOptions.DEFAULT);
+
+ List events = new ArrayList<>(3);
+ for (int i = 0; i < 3; i++) {
+ events.add(ScheduledEventTests.testInstance(calendar.getId(), null));
+ }
+
+ PostCalendarEventRequest postCalendarEventRequest = new PostCalendarEventRequest(calendar.getId(), events);
+
+ PostCalendarEventResponse postCalendarEventResponse = execute(postCalendarEventRequest,
+ machineLearningClient::postCalendarEvent,
+ machineLearningClient::postCalendarEventAsync);
+ assertThat(postCalendarEventResponse.getScheduledEvents(), containsInAnyOrder(events.toArray()));
+ }
+
public void testPutFilter() throws Exception {
String filterId = "filter-job-test";
MlFilter mlFilter = MlFilter.builder(filterId)
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java
index a2f29fae60a0d..30e36e8e9f007 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java
@@ -72,6 +72,8 @@
import org.elasticsearch.client.ml.GetRecordsResponse;
import org.elasticsearch.client.ml.OpenJobRequest;
import org.elasticsearch.client.ml.OpenJobResponse;
+import org.elasticsearch.client.ml.PostCalendarEventRequest;
+import org.elasticsearch.client.ml.PostCalendarEventResponse;
import org.elasticsearch.client.ml.PostDataRequest;
import org.elasticsearch.client.ml.PostDataResponse;
import org.elasticsearch.client.ml.PreviewDatafeedRequest;
@@ -93,6 +95,8 @@
import org.elasticsearch.client.ml.UpdateFilterRequest;
import org.elasticsearch.client.ml.UpdateJobRequest;
import org.elasticsearch.client.ml.calendars.Calendar;
+import org.elasticsearch.client.ml.calendars.ScheduledEvent;
+import org.elasticsearch.client.ml.calendars.ScheduledEventTests;
import org.elasticsearch.client.ml.datafeed.ChunkingConfig;
import org.elasticsearch.client.ml.datafeed.DatafeedConfig;
import org.elasticsearch.client.ml.datafeed.DatafeedStats;
@@ -2244,6 +2248,61 @@ public void onFailure(Exception e) {
assertTrue(latch.await(30L, TimeUnit.SECONDS));
}
+ public void testPostCalendarEvent() throws IOException, InterruptedException {
+ RestHighLevelClient client = highLevelClient();
+
+ Calendar calendar = new Calendar("holidays", Collections.singletonList("job_1"), "A calendar for public holidays");
+ PutCalendarRequest putRequest = new PutCalendarRequest(calendar);
+ client.machineLearning().putCalendar(putRequest, RequestOptions.DEFAULT);
+ {
+ List events = Collections.singletonList(ScheduledEventTests.testInstance(calendar.getId(), null));
+
+ // tag::post-calendar-event-request
+ PostCalendarEventRequest request = new PostCalendarEventRequest("holidays", // <1>
+ events); // <2>
+ // end::post-calendar-event-request
+
+ // tag::post-calendar-event-execute
+ PostCalendarEventResponse response = client.machineLearning().postCalendarEvent(request, RequestOptions.DEFAULT);
+ // end::post-calendar-event-execute
+
+ // tag::post-calendar-event-response
+ List scheduledEvents = response.getScheduledEvents(); // <1>
+ // end::post-calendar-event-response
+
+ assertEquals(1, scheduledEvents.size());
+ }
+ {
+ List events = Collections.singletonList(ScheduledEventTests.testInstance());
+ PostCalendarEventRequest request = new PostCalendarEventRequest("holidays", events); // <1>
+
+ // tag::post-calendar-event-execute-listener
+ ActionListener listener =
+ new ActionListener() {
+ @Override
+ public void onResponse(PostCalendarEventResponse postCalendarsResponse) {
+ // <1>
+ }
+
+ @Override
+ public void onFailure(Exception e) {
+ // <2>
+ }
+ };
+ // end::post-calendar-event-execute-listener
+
+ // Replace the empty listener by a blocking listener in test
+ final CountDownLatch latch = new CountDownLatch(1);
+ listener = new LatchedActionListener<>(listener, latch);
+
+ // tag::post-calendar-event-execute-async
+ client.machineLearning().postCalendarEventAsync(request, RequestOptions.DEFAULT, listener); // <1>
+ // end::post-calendar-event-execute-async
+
+ assertTrue(latch.await(30L, TimeUnit.SECONDS));
+ }
+ }
+
public void testCreateFilter() throws Exception {
RestHighLevelClient client = highLevelClient();
{
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/PostCalendarEventRequestTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/PostCalendarEventRequestTests.java
new file mode 100644
index 0000000000000..c8f65bd9113fe
--- /dev/null
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/PostCalendarEventRequestTests.java
@@ -0,0 +1,53 @@
+/*
+ * 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.calendars.ScheduledEvent;
+import org.elasticsearch.client.ml.calendars.ScheduledEventTests;
+import org.elasticsearch.common.xcontent.XContentParser;
+import org.elasticsearch.test.AbstractXContentTestCase;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class PostCalendarEventRequestTests extends AbstractXContentTestCase {
+
+ @Override
+ protected PostCalendarEventRequest createTestInstance() {
+ String calendarId = randomAlphaOfLength(10);
+ int numberOfEvents = randomIntBetween(1, 10);
+ List events = new ArrayList<>(numberOfEvents);
+ for (int i = 0; i < numberOfEvents; i++) {
+ events.add(ScheduledEventTests.testInstance());
+ }
+ return new PostCalendarEventRequest(calendarId, events);
+ }
+
+ @Override
+ protected PostCalendarEventRequest doParseInstance(XContentParser parser) throws IOException {
+ return PostCalendarEventRequest.PARSER.apply(parser, null);
+ }
+
+ @Override
+ protected boolean supportsUnknownFields() {
+ return false;
+ }
+}
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/PostCalendarEventResponseTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/PostCalendarEventResponseTests.java
new file mode 100644
index 0000000000000..8f8be0981c864
--- /dev/null
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/PostCalendarEventResponseTests.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.ml;
+
+import org.elasticsearch.client.ml.calendars.ScheduledEvent;
+import org.elasticsearch.client.ml.calendars.ScheduledEventTests;
+import org.elasticsearch.common.xcontent.XContentParser;
+import org.elasticsearch.test.AbstractXContentTestCase;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class PostCalendarEventResponseTests extends AbstractXContentTestCase {
+ @Override
+ protected PostCalendarEventResponse createTestInstance() {
+ int numberOfEvents = randomIntBetween(1, 10);
+ List events = new ArrayList<>(numberOfEvents);
+ for (int i = 0; i < numberOfEvents; i++) {
+ events.add(ScheduledEventTests.testInstance());
+ }
+ return new PostCalendarEventResponse(events);
+ }
+
+ @Override
+ protected PostCalendarEventResponse doParseInstance(XContentParser parser) throws IOException {
+ return PostCalendarEventResponse.fromXContent(parser);
+ }
+
+ @Override
+ protected boolean supportsUnknownFields() {
+ return true;
+ }
+}
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/calendars/ScheduledEventTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/calendars/ScheduledEventTests.java
index 0b7a293340245..77380c2bd35e6 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/calendars/ScheduledEventTests.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/calendars/ScheduledEventTests.java
@@ -19,6 +19,7 @@
package org.elasticsearch.client.ml.calendars;
+import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.test.AbstractXContentTestCase;
@@ -26,12 +27,16 @@
public class ScheduledEventTests extends AbstractXContentTestCase {
- public static ScheduledEvent testInstance() {
+ public static ScheduledEvent testInstance(String calendarId, @Nullable String eventId) {
Date start = new Date(randomNonNegativeLong());
Date end = new Date(start.getTime() + randomIntBetween(1, 10000) * 1000);
- return new ScheduledEvent(randomAlphaOfLength(10), start, end, randomAlphaOfLengthBetween(1, 20),
- randomBoolean() ? null : randomAlphaOfLength(7));
+ return new ScheduledEvent(randomAlphaOfLength(10), start, end, calendarId, eventId);
+ }
+
+ public static ScheduledEvent testInstance() {
+ return testInstance(randomAlphaOfLengthBetween(1, 20),
+ randomBoolean() ? null : randomAlphaOfLength(7));
}
@Override
diff --git a/docs/java-rest/high-level/ml/post-calendar-event.asciidoc b/docs/java-rest/high-level/ml/post-calendar-event.asciidoc
new file mode 100644
index 0000000000000..ba7c69acf03d9
--- /dev/null
+++ b/docs/java-rest/high-level/ml/post-calendar-event.asciidoc
@@ -0,0 +1,38 @@
+--
+:api: post-calendar-event
+:request: PostCalendarEventRequest
+:response: PostCalendarEventResponse
+--
+[id="{upid}-{api}"]
+=== Post Calendar Event API
+Adds new ScheduledEvents to an existing {ml} calendar.
+
+The API accepts a +{request}+ and responds
+with a +{response}+ object.
+
+[id="{upid}-{api}-request"]
+==== Post Calendar Event Request
+
+A +{request}+ is constructed with a calendar ID object
+and a non-empty list of scheduled events.
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests-file}[{api}-request]
+--------------------------------------------------
+<1> Non-null existing calendar ID
+<2> Non-null, non-empty collection of `ScheduledEvent` objects
+
+
+[id="{upid}-{api}-response"]
+==== Post Calendar Event Response
+
+The returned +{response}+ contains the added `ScheduledEvent` objects:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests-file}[{api}-response]
+--------------------------------------------------
+<1> The `ScheduledEvent` objects that were added to the calendar
+
+include::../execution.asciidoc[]
diff --git a/docs/java-rest/high-level/supported-apis.asciidoc b/docs/java-rest/high-level/supported-apis.asciidoc
index a4e4907e5abce..a8964d7dcae47 100644
--- a/docs/java-rest/high-level/supported-apis.asciidoc
+++ b/docs/java-rest/high-level/supported-apis.asciidoc
@@ -266,6 +266,7 @@ The Java High Level REST Client supports the following Machine Learning APIs:
* <<{upid}-get-categories>>
* <<{upid}-get-calendars>>
* <<{upid}-put-calendar>>
+* <<{upid}-post-calendar-event>>
* <<{upid}-put-calendar-job>>
* <<{upid}-delete-calendar>>
* <<{upid}-put-filter>>
@@ -301,6 +302,7 @@ include::ml/get-influencers.asciidoc[]
include::ml/get-categories.asciidoc[]
include::ml/get-calendars.asciidoc[]
include::ml/put-calendar.asciidoc[]
+include::ml/post-calendar-event.asciidoc[]
include::ml/put-calendar-job.asciidoc[]
include::ml/delete-calendar.asciidoc[]
include::ml/put-filter.asciidoc[]