|
@@ -0,0 +1,345 @@
|
|
|
+/*
|
|
|
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
|
+ * or more contributor license agreements. Licensed under the Elastic License;
|
|
|
+ * you may not use this file except in compliance with the Elastic License.
|
|
|
+ */
|
|
|
+package org.elasticsearch.xpack.core.watcher.transport.actions;
|
|
|
+
|
|
|
+import org.elasticsearch.action.ActionRequest;
|
|
|
+import org.elasticsearch.action.ActionRequestValidationException;
|
|
|
+import org.elasticsearch.action.ActionResponse;
|
|
|
+import org.elasticsearch.action.ActionType;
|
|
|
+import org.elasticsearch.common.ParseField;
|
|
|
+import org.elasticsearch.common.io.stream.StreamInput;
|
|
|
+import org.elasticsearch.common.io.stream.StreamOutput;
|
|
|
+import org.elasticsearch.common.io.stream.Writeable;
|
|
|
+import org.elasticsearch.common.xcontent.ConstructingObjectParser;
|
|
|
+import org.elasticsearch.common.xcontent.ObjectParser;
|
|
|
+import org.elasticsearch.common.xcontent.ToXContent;
|
|
|
+import org.elasticsearch.common.xcontent.ToXContentFragment;
|
|
|
+import org.elasticsearch.common.xcontent.ToXContentObject;
|
|
|
+import org.elasticsearch.common.xcontent.XContentBuilder;
|
|
|
+import org.elasticsearch.common.xcontent.XContentParser;
|
|
|
+import org.elasticsearch.common.xcontent.XContentParser.Token;
|
|
|
+import org.elasticsearch.index.query.QueryBuilder;
|
|
|
+import org.elasticsearch.search.searchafter.SearchAfterBuilder;
|
|
|
+import org.elasticsearch.search.sort.FieldSortBuilder;
|
|
|
+import org.elasticsearch.xpack.core.watcher.support.xcontent.XContentSource;
|
|
|
+import org.elasticsearch.xpack.core.watcher.watch.WatchStatus;
|
|
|
+
|
|
|
+import java.io.IOException;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Objects;
|
|
|
+
|
|
|
+import static org.elasticsearch.common.xcontent.ConstructingObjectParser.optionalConstructorArg;
|
|
|
+import static org.elasticsearch.index.query.AbstractQueryBuilder.parseInnerQueryBuilder;
|
|
|
+
|
|
|
+public class QueryWatchesAction extends ActionType<QueryWatchesAction.Response> {
|
|
|
+
|
|
|
+ public static final QueryWatchesAction INSTANCE = new QueryWatchesAction();
|
|
|
+ public static final String NAME = "cluster:monitor/xpack/watcher/watch/query";
|
|
|
+
|
|
|
+ private QueryWatchesAction() {
|
|
|
+ super(NAME, Response::new);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static class Request extends ActionRequest implements ToXContentObject {
|
|
|
+
|
|
|
+ public static final ParseField FROM_FIELD = new ParseField("from");
|
|
|
+ public static final ParseField SIZE_FIELD = new ParseField("size");
|
|
|
+ public static final ParseField QUERY_FIELD = new ParseField("query");
|
|
|
+ public static final ParseField SORT_FIELD = new ParseField("sort");
|
|
|
+ public static final ParseField SEARCH_AFTER_FIELD = new ParseField("search_after");
|
|
|
+
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ private static final ConstructingObjectParser<Request, Void> PARSER = new ConstructingObjectParser<>(
|
|
|
+ "query_watches_request",
|
|
|
+ true,
|
|
|
+ (args, c) -> {
|
|
|
+ Integer from = (Integer) args[0];
|
|
|
+ Integer size = (Integer) args[1];
|
|
|
+ QueryBuilder query = (QueryBuilder) args[2];
|
|
|
+ List<FieldSortBuilder> sort = (List<FieldSortBuilder>) args[3];
|
|
|
+ SearchAfterBuilder searchAfter = (SearchAfterBuilder) args[4];
|
|
|
+ return new Request(from, size, query, sort, searchAfter);
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ static {
|
|
|
+ PARSER.declareInt(optionalConstructorArg(), FROM_FIELD);
|
|
|
+ PARSER.declareInt(optionalConstructorArg(), SIZE_FIELD);
|
|
|
+ PARSER.declareObject(optionalConstructorArg(), (p, c) -> parseInnerQueryBuilder(p), QUERY_FIELD);
|
|
|
+ PARSER.declareObjectArray(optionalConstructorArg(), (p, c) -> {
|
|
|
+ String fieldName = null;
|
|
|
+ FieldSortBuilder result = null;
|
|
|
+ for (Token token = p.nextToken(); token != Token.END_OBJECT; token = p.nextToken()) {
|
|
|
+ if (token == Token.FIELD_NAME) {
|
|
|
+ fieldName = p.currentName();
|
|
|
+ } else {
|
|
|
+ result = FieldSortBuilder.fromXContent(p, fieldName);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }, SORT_FIELD);
|
|
|
+ PARSER.declareField(optionalConstructorArg(), (p, c) -> SearchAfterBuilder.fromXContent(p), SEARCH_AFTER_FIELD,
|
|
|
+ ObjectParser.ValueType.VALUE_ARRAY);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static Request fromXContent(XContentParser parser) throws IOException {
|
|
|
+ return PARSER.parse(parser, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ private final Integer from;
|
|
|
+ private final Integer size;
|
|
|
+ private final QueryBuilder query;
|
|
|
+ private final List<FieldSortBuilder> sorts;
|
|
|
+ private final SearchAfterBuilder searchAfter;
|
|
|
+
|
|
|
+ public Request(StreamInput in) throws IOException {
|
|
|
+ super(in);
|
|
|
+ from = in.readOptionalVInt();
|
|
|
+ size = in.readOptionalVInt();
|
|
|
+ query = in.readOptionalNamedWriteable(QueryBuilder.class);
|
|
|
+ if (in.readBoolean()) {
|
|
|
+ sorts = in.readList(FieldSortBuilder::new);
|
|
|
+ } else {
|
|
|
+ sorts = null;
|
|
|
+ }
|
|
|
+ searchAfter = in.readOptionalWriteable(SearchAfterBuilder::new);
|
|
|
+ }
|
|
|
+
|
|
|
+ public Request(Integer from,
|
|
|
+ Integer size,
|
|
|
+ QueryBuilder query,
|
|
|
+ List<FieldSortBuilder> sorts,
|
|
|
+ SearchAfterBuilder searchAfter) {
|
|
|
+ this.from = from;
|
|
|
+ this.size = size;
|
|
|
+ this.query = query;
|
|
|
+ this.sorts = sorts;
|
|
|
+ this.searchAfter = searchAfter;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Integer getFrom() {
|
|
|
+ return from;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Integer getSize() {
|
|
|
+ return size;
|
|
|
+ }
|
|
|
+
|
|
|
+ public QueryBuilder getQuery() {
|
|
|
+ return query;
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<FieldSortBuilder> getSorts() {
|
|
|
+ return sorts;
|
|
|
+ }
|
|
|
+
|
|
|
+ public SearchAfterBuilder getSearchAfter() {
|
|
|
+ return searchAfter;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public ActionRequestValidationException validate() {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void writeTo(StreamOutput out) throws IOException {
|
|
|
+ super.writeTo(out);
|
|
|
+ out.writeOptionalVInt(from);
|
|
|
+ out.writeOptionalVInt(size);
|
|
|
+ out.writeOptionalNamedWriteable(query);
|
|
|
+ if (sorts != null) {
|
|
|
+ out.writeBoolean(true);
|
|
|
+ out.writeList(sorts);
|
|
|
+ } else {
|
|
|
+ out.writeBoolean(false);
|
|
|
+ }
|
|
|
+ out.writeOptionalWriteable(searchAfter);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException {
|
|
|
+ builder.startObject();
|
|
|
+ if (from != null) {
|
|
|
+ builder.field(FROM_FIELD.getPreferredName(), from);
|
|
|
+ }
|
|
|
+ if (size != null) {
|
|
|
+ builder.field(SIZE_FIELD.getPreferredName(), size);
|
|
|
+ }
|
|
|
+ if (query != null) {
|
|
|
+ builder.field(QUERY_FIELD.getPreferredName(), query);
|
|
|
+ }
|
|
|
+ if (sorts != null) {
|
|
|
+ builder.startArray(SORT_FIELD.getPreferredName());
|
|
|
+ for (FieldSortBuilder sort : sorts) {
|
|
|
+ sort.toXContent(builder, params);
|
|
|
+ }
|
|
|
+ builder.endArray();
|
|
|
+ }
|
|
|
+ if (searchAfter != null) {
|
|
|
+ builder.array(SEARCH_AFTER_FIELD.getPreferredName(), searchAfter.getSortValues());
|
|
|
+ }
|
|
|
+ return builder.endObject();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean equals(Object o) {
|
|
|
+ if (this == o) return true;
|
|
|
+ if (o == null || getClass() != o.getClass()) return false;
|
|
|
+ Request request = (Request) o;
|
|
|
+ return Objects.equals(from, request.from) &&
|
|
|
+ Objects.equals(size, request.size) &&
|
|
|
+ Objects.equals(query, request.query) &&
|
|
|
+ Objects.equals(sorts, request.sorts) &&
|
|
|
+ Objects.equals(searchAfter, request.searchAfter);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int hashCode() {
|
|
|
+ return Objects.hash(from, size, query, sorts, searchAfter);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static class Response extends ActionResponse implements ToXContentObject {
|
|
|
+
|
|
|
+ private final List<Item> watches;
|
|
|
+ private final long watchTotalCount;
|
|
|
+
|
|
|
+ public Response(long watchTotalCount, List<Item> watches) {
|
|
|
+ this.watches = watches;
|
|
|
+ this.watchTotalCount = watchTotalCount;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Response(StreamInput in) throws IOException {
|
|
|
+ super(in);
|
|
|
+ watches = in.readList(Item::new);
|
|
|
+ watchTotalCount = in.readVLong();
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<Item> getWatches() {
|
|
|
+ return watches;
|
|
|
+ }
|
|
|
+
|
|
|
+ public long getWatchTotalCount() {
|
|
|
+ return watchTotalCount;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void writeTo(StreamOutput out) throws IOException {
|
|
|
+ out.writeList(watches);
|
|
|
+ out.writeVLong(watchTotalCount);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
|
|
+ builder.startObject();
|
|
|
+ builder.field("count", watchTotalCount);
|
|
|
+ builder.startArray("watches");
|
|
|
+ for (Item watch : watches) {
|
|
|
+ builder.startObject();
|
|
|
+ watch.toXContent(builder, params);
|
|
|
+ builder.endObject();
|
|
|
+ }
|
|
|
+ builder.endArray();
|
|
|
+ return builder.endObject();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean equals(Object o) {
|
|
|
+ if (this == o) return true;
|
|
|
+ if (o == null || getClass() != o.getClass()) return false;
|
|
|
+ Response response = (Response) o;
|
|
|
+ return watchTotalCount == response.watchTotalCount &&
|
|
|
+ watches.equals(response.watches);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int hashCode() {
|
|
|
+ return Objects.hash(watches, watchTotalCount);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static class Item implements Writeable, ToXContentFragment {
|
|
|
+
|
|
|
+ private final String id;
|
|
|
+ private final XContentSource source;
|
|
|
+ private final WatchStatus status;
|
|
|
+ private final long seqNo;
|
|
|
+ private final long primaryTerm;
|
|
|
+
|
|
|
+ public Item(String id, XContentSource source, WatchStatus status, long seqNo, long primaryTerm) {
|
|
|
+ this.id = id;
|
|
|
+ this.source = source;
|
|
|
+ this.status = status;
|
|
|
+ this.seqNo = seqNo;
|
|
|
+ this.primaryTerm = primaryTerm;
|
|
|
+ }
|
|
|
+
|
|
|
+ public String getId() {
|
|
|
+ return id;
|
|
|
+ }
|
|
|
+
|
|
|
+ public XContentSource getSource() {
|
|
|
+ return source;
|
|
|
+ }
|
|
|
+
|
|
|
+ public WatchStatus getStatus() {
|
|
|
+ return status;
|
|
|
+ }
|
|
|
+
|
|
|
+ public long getSeqNo() {
|
|
|
+ return seqNo;
|
|
|
+ }
|
|
|
+
|
|
|
+ public long getPrimaryTerm() {
|
|
|
+ return primaryTerm;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Item(StreamInput in) throws IOException {
|
|
|
+ id = in.readString();
|
|
|
+ source = XContentSource.readFrom(in);
|
|
|
+ status = new WatchStatus(in);
|
|
|
+ seqNo = in.readZLong();
|
|
|
+ primaryTerm = in.readVLong();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void writeTo(StreamOutput out) throws IOException {
|
|
|
+ out.writeString(id);
|
|
|
+ XContentSource.writeTo(source, out);
|
|
|
+ status.writeTo(out);
|
|
|
+ out.writeZLong(seqNo);
|
|
|
+ out.writeVLong(primaryTerm);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
|
|
+ builder.field("_id", id);
|
|
|
+ builder.field("watch", source, params);
|
|
|
+ builder.field("status", status, params);
|
|
|
+ builder.field("_seq_no", seqNo);
|
|
|
+ builder.field("_primary_term", primaryTerm);
|
|
|
+ return builder;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean equals(Object o) {
|
|
|
+ if (this == o) return true;
|
|
|
+ if (o == null || getClass() != o.getClass()) return false;
|
|
|
+ Item item = (Item) o;
|
|
|
+ return seqNo == item.seqNo &&
|
|
|
+ primaryTerm == item.primaryTerm &&
|
|
|
+ id.equals(item.id) &&
|
|
|
+ source.equals(item.source);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int hashCode() {
|
|
|
+ return Objects.hash(id, source, seqNo, primaryTerm);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|