From 08d3bf937df002a1d8278123588e41b565bc8014 Mon Sep 17 00:00:00 2001 From: Nik Everett Date: Fri, 15 Apr 2016 16:03:38 -0400 Subject: [PATCH] Cut moving_avg aggregation to registerPipelineAggregation and remove its PROTOTYPE. Relates to #17085 --- .../elasticsearch/search/SearchModule.java | 6 +- .../pipeline/movavg/MovAvgParser.java | 183 ---------------- .../MovAvgPipelineAggregatorBuilder.java | 203 +++++++++++++++--- .../pipeline/movavg/models/EwmaModel.java | 10 +- .../movavg/models/HoltLinearModel.java | 10 +- .../movavg/models/HoltWintersModel.java | 10 +- .../pipeline/movavg/models/LinearModel.java | 6 +- .../models/MovAvgModelParserMapper.java | 2 - .../pipeline/movavg/models/SimpleModel.java | 6 +- 9 files changed, 198 insertions(+), 238 deletions(-) delete mode 100644 core/src/main/java/org/elasticsearch/search/aggregations/pipeline/movavg/MovAvgParser.java diff --git a/core/src/main/java/org/elasticsearch/search/SearchModule.java b/core/src/main/java/org/elasticsearch/search/SearchModule.java index 4ea307580b6..443e232bcd9 100644 --- a/core/src/main/java/org/elasticsearch/search/SearchModule.java +++ b/core/src/main/java/org/elasticsearch/search/SearchModule.java @@ -217,8 +217,8 @@ import org.elasticsearch.search.aggregations.pipeline.cumulativesum.CumulativeSu import org.elasticsearch.search.aggregations.pipeline.derivative.DerivativePipelineAggregator; import org.elasticsearch.search.aggregations.pipeline.derivative.DerivativePipelineAggregatorBuilder; import org.elasticsearch.search.aggregations.pipeline.derivative.InternalDerivative; -import org.elasticsearch.search.aggregations.pipeline.movavg.MovAvgParser; import org.elasticsearch.search.aggregations.pipeline.movavg.MovAvgPipelineAggregator; +import org.elasticsearch.search.aggregations.pipeline.movavg.MovAvgPipelineAggregatorBuilder; import org.elasticsearch.search.aggregations.pipeline.movavg.models.MovAvgModel; import org.elasticsearch.search.aggregations.pipeline.movavg.models.MovAvgModelParserMapper; import org.elasticsearch.search.aggregations.pipeline.serialdiff.SerialDiffPipelineAggregator; @@ -511,7 +511,9 @@ public class SearchModule extends AbstractModule { registerPipelineAggregation(ExtendedStatsBucketPipelineAggregatorBuilder::new, new ExtendedStatsBucketParser(), ExtendedStatsBucketPipelineAggregatorBuilder.AGGREGATION_NAME_FIELD); registerPipelineParser(new PercentilesBucketParser()); - registerPipelineParser(new MovAvgParser(movAvgModelParserMapper)); + registerPipelineAggregation(MovAvgPipelineAggregatorBuilder::new, + (n, c) -> MovAvgPipelineAggregatorBuilder.parse(movAvgModelParserMapper, n, c), + MovAvgPipelineAggregatorBuilder.AGGREGATION_FIELD_NAME); registerPipelineAggregation(CumulativeSumPipelineAggregatorBuilder::new, CumulativeSumPipelineAggregatorBuilder::parse, CumulativeSumPipelineAggregatorBuilder.AGGREGATION_NAME_FIELD); registerPipelineAggregation(BucketScriptPipelineAggregatorBuilder::new, BucketScriptPipelineAggregatorBuilder::parse, diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/movavg/MovAvgParser.java b/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/movavg/MovAvgParser.java deleted file mode 100644 index 1c63099c745..00000000000 --- a/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/movavg/MovAvgParser.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * 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.search.aggregations.pipeline.movavg; - -import org.elasticsearch.common.ParseField; -import org.elasticsearch.common.ParsingException; -import org.elasticsearch.common.inject.Inject; -import org.elasticsearch.common.xcontent.XContentParser; -import org.elasticsearch.index.query.QueryParseContext; -import org.elasticsearch.search.aggregations.pipeline.BucketHelpers.GapPolicy; -import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator; -import org.elasticsearch.search.aggregations.pipeline.movavg.models.MovAvgModel; -import org.elasticsearch.search.aggregations.pipeline.movavg.models.MovAvgModelParserMapper; - -import java.io.IOException; -import java.text.ParseException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -public class MovAvgParser implements PipelineAggregator.Parser { - - public static final ParseField MODEL = new ParseField("model"); - public static final ParseField WINDOW = new ParseField("window"); - public static final ParseField SETTINGS = new ParseField("settings"); - public static final ParseField PREDICT = new ParseField("predict"); - public static final ParseField MINIMIZE = new ParseField("minimize"); - - private final MovAvgModelParserMapper movAvgModelParserMapper; - - @Inject - public MovAvgParser(MovAvgModelParserMapper movAvgModelParserMapper) { - this.movAvgModelParserMapper = movAvgModelParserMapper; - } - - @Override - public String type() { - return MovAvgPipelineAggregator.TYPE.name(); - } - - @Override - public MovAvgPipelineAggregatorBuilder parse(String pipelineAggregatorName, QueryParseContext context) throws IOException { - XContentParser parser = context.parser(); - XContentParser.Token token; - String currentFieldName = null; - String[] bucketsPaths = null; - String format = null; - - GapPolicy gapPolicy = null; - Integer window = null; - Map settings = null; - String model = null; - Integer predict = null; - Boolean minimize = null; - - while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { - if (token == XContentParser.Token.FIELD_NAME) { - currentFieldName = parser.currentName(); - } else if (token == XContentParser.Token.VALUE_NUMBER) { - if (context.getParseFieldMatcher().match(currentFieldName, WINDOW)) { - window = parser.intValue(); - if (window <= 0) { - throw new ParsingException(parser.getTokenLocation(), "[" + currentFieldName + "] value must be a positive, " - + "non-zero integer. Value supplied was [" + predict + "] in [" + pipelineAggregatorName + "]."); - } - } else if (context.getParseFieldMatcher().match(currentFieldName, PREDICT)) { - predict = parser.intValue(); - if (predict <= 0) { - throw new ParsingException(parser.getTokenLocation(), "[" + currentFieldName + "] value must be a positive integer." - + " Value supplied was [" + predict + "] in [" + pipelineAggregatorName + "]."); - } - } else { - throw new ParsingException(parser.getTokenLocation(), - "Unknown key for a " + token + " in [" + pipelineAggregatorName + "]: [" + currentFieldName + "]."); - } - } else if (token == XContentParser.Token.VALUE_STRING) { - if (context.getParseFieldMatcher().match(currentFieldName, FORMAT)) { - format = parser.text(); - } else if (context.getParseFieldMatcher().match(currentFieldName, BUCKETS_PATH)) { - bucketsPaths = new String[] { parser.text() }; - } else if (context.getParseFieldMatcher().match(currentFieldName, GAP_POLICY)) { - gapPolicy = GapPolicy.parse(context, parser.text(), parser.getTokenLocation()); - } else if (context.getParseFieldMatcher().match(currentFieldName, MODEL)) { - model = parser.text(); - } else { - throw new ParsingException(parser.getTokenLocation(), - "Unknown key for a " + token + " in [" + pipelineAggregatorName + "]: [" + currentFieldName + "]."); - } - } else if (token == XContentParser.Token.START_ARRAY) { - if (context.getParseFieldMatcher().match(currentFieldName, BUCKETS_PATH)) { - List paths = new ArrayList<>(); - while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) { - String path = parser.text(); - paths.add(path); - } - bucketsPaths = paths.toArray(new String[paths.size()]); - } else { - throw new ParsingException(parser.getTokenLocation(), - "Unknown key for a " + token + " in [" + pipelineAggregatorName + "]: [" + currentFieldName + "]."); - } - } else if (token == XContentParser.Token.START_OBJECT) { - if (context.getParseFieldMatcher().match(currentFieldName, SETTINGS)) { - settings = parser.map(); - } else { - throw new ParsingException(parser.getTokenLocation(), - "Unknown key for a " + token + " in [" + pipelineAggregatorName + "]: [" + currentFieldName + "]."); - } - } else if (token == XContentParser.Token.VALUE_BOOLEAN) { - if (context.getParseFieldMatcher().match(currentFieldName, MINIMIZE)) { - minimize = parser.booleanValue(); - } else { - throw new ParsingException(parser.getTokenLocation(), - "Unknown key for a " + token + " in [" + pipelineAggregatorName + "]: [" + currentFieldName + "]."); - } - } else { - throw new ParsingException(parser.getTokenLocation(), - "Unexpected token " + token + " in [" + pipelineAggregatorName + "]."); - } - } - - if (bucketsPaths == null) { - throw new ParsingException(parser.getTokenLocation(), "Missing required field [" + BUCKETS_PATH.getPreferredName() - + "] for movingAvg aggregation [" + pipelineAggregatorName + "]"); - } - - MovAvgPipelineAggregatorBuilder factory = - new MovAvgPipelineAggregatorBuilder(pipelineAggregatorName, bucketsPaths[0]); - if (format != null) { - factory.format(format); - } - if (gapPolicy != null) { - factory.gapPolicy(gapPolicy); - } - if (window != null) { - factory.window(window); - } - if (predict != null) { - factory.predict(predict); - } - if (model != null) { - MovAvgModel.AbstractModelParser modelParser = movAvgModelParserMapper.get(model); - if (modelParser == null) { - throw new ParsingException(parser.getTokenLocation(), - "Unknown model [" + model + "] specified. Valid options are:" + movAvgModelParserMapper.getAllNames().toString()); - } - - MovAvgModel movAvgModel; - try { - movAvgModel = modelParser.parse(settings, pipelineAggregatorName, factory.window(), context.getParseFieldMatcher()); - } catch (ParseException exception) { - throw new ParsingException(parser.getTokenLocation(), "Could not parse settings for model [" + model + "].", exception); - } - factory.model(movAvgModel); - } - if (minimize != null) { - factory.minimize(minimize); - } - return factory; - } - - @Override - public MovAvgPipelineAggregatorBuilder getFactoryPrototype() { - return MovAvgPipelineAggregatorBuilder.PROTOTYPE; - } - -} diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/movavg/MovAvgPipelineAggregatorBuilder.java b/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/movavg/MovAvgPipelineAggregatorBuilder.java index 2decd08954e..d9b66aa2175 100644 --- a/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/movavg/MovAvgPipelineAggregatorBuilder.java +++ b/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/movavg/MovAvgPipelineAggregatorBuilder.java @@ -19,28 +19,45 @@ package org.elasticsearch.search.aggregations.pipeline.movavg; +import org.elasticsearch.common.ParseField; +import org.elasticsearch.common.ParsingException; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.index.query.QueryParseContext; import org.elasticsearch.search.DocValueFormat; import org.elasticsearch.search.aggregations.AggregatorFactory; import org.elasticsearch.search.aggregations.bucket.histogram.AbstractHistogramAggregatorFactory; +import org.elasticsearch.search.aggregations.pipeline.BucketHelpers.GapPolicy; import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator; import org.elasticsearch.search.aggregations.pipeline.PipelineAggregatorBuilder; -import org.elasticsearch.search.aggregations.pipeline.BucketHelpers.GapPolicy; import org.elasticsearch.search.aggregations.pipeline.movavg.models.MovAvgModel; import org.elasticsearch.search.aggregations.pipeline.movavg.models.MovAvgModelBuilder; +import org.elasticsearch.search.aggregations.pipeline.movavg.models.MovAvgModelParserMapper; import org.elasticsearch.search.aggregations.pipeline.movavg.models.MovAvgModelStreams; import org.elasticsearch.search.aggregations.pipeline.movavg.models.SimpleModel; import java.io.IOException; +import java.text.ParseException; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; -public class MovAvgPipelineAggregatorBuilder extends PipelineAggregatorBuilder { +import static org.elasticsearch.search.aggregations.pipeline.PipelineAggregator.Parser.BUCKETS_PATH; +import static org.elasticsearch.search.aggregations.pipeline.PipelineAggregator.Parser.FORMAT; +import static org.elasticsearch.search.aggregations.pipeline.PipelineAggregator.Parser.GAP_POLICY; - static final MovAvgPipelineAggregatorBuilder PROTOTYPE = new MovAvgPipelineAggregatorBuilder("", ""); +public class MovAvgPipelineAggregatorBuilder extends PipelineAggregatorBuilder { + public static final String NAME = MovAvgPipelineAggregator.TYPE.name(); + public static final ParseField AGGREGATION_FIELD_NAME = new ParseField(NAME); + + public static final ParseField MODEL = new ParseField("model"); + private static final ParseField WINDOW = new ParseField("window"); + public static final ParseField SETTINGS = new ParseField("settings"); + private static final ParseField PREDICT = new ParseField("predict"); + private static final ParseField MINIMIZE = new ParseField("minimize"); private String format; private GapPolicy gapPolicy = GapPolicy.SKIP; @@ -50,11 +67,35 @@ public class MovAvgPipelineAggregatorBuilder extends PipelineAggregatorBuilder 0) { - builder.field(MovAvgParser.PREDICT.getPreferredName(), predict); + builder.field(PREDICT.getPreferredName(), predict); } if (minimize != null) { - builder.field(MovAvgParser.MINIMIZE.getPreferredName(), minimize); + builder.field(MINIMIZE.getPreferredName(), minimize); } return builder; } - @Override - protected MovAvgPipelineAggregatorBuilder doReadFrom(String name, String[] bucketsPaths, StreamInput in) throws IOException { - MovAvgPipelineAggregatorBuilder factory = new MovAvgPipelineAggregatorBuilder(name, bucketsPaths); - factory.format = in.readOptionalString(); - factory.gapPolicy = GapPolicy.readFrom(in); - factory.window = in.readVInt(); - factory.model = MovAvgModelStreams.read(in); - factory.predict = in.readVInt(); - factory.minimize = in.readOptionalBoolean(); - return factory; - } + public static MovAvgPipelineAggregatorBuilder parse(MovAvgModelParserMapper movAvgModelParserMapper, String pipelineAggregatorName, + QueryParseContext context) throws IOException { + XContentParser parser = context.parser(); + XContentParser.Token token; + String currentFieldName = null; + String[] bucketsPaths = null; + String format = null; - @Override - protected void doWriteTo(StreamOutput out) throws IOException { - out.writeOptionalString(format); - gapPolicy.writeTo(out); - out.writeVInt(window); - model.writeTo(out); - out.writeVInt(predict); - out.writeOptionalBoolean(minimize); + GapPolicy gapPolicy = null; + Integer window = null; + Map settings = null; + String model = null; + Integer predict = null; + Boolean minimize = null; + + while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { + if (token == XContentParser.Token.FIELD_NAME) { + currentFieldName = parser.currentName(); + } else if (token == XContentParser.Token.VALUE_NUMBER) { + if (context.getParseFieldMatcher().match(currentFieldName, WINDOW)) { + window = parser.intValue(); + if (window <= 0) { + throw new ParsingException(parser.getTokenLocation(), "[" + currentFieldName + "] value must be a positive, " + + "non-zero integer. Value supplied was [" + predict + "] in [" + pipelineAggregatorName + "]."); + } + } else if (context.getParseFieldMatcher().match(currentFieldName, PREDICT)) { + predict = parser.intValue(); + if (predict <= 0) { + throw new ParsingException(parser.getTokenLocation(), "[" + currentFieldName + "] value must be a positive integer." + + " Value supplied was [" + predict + "] in [" + pipelineAggregatorName + "]."); + } + } else { + throw new ParsingException(parser.getTokenLocation(), + "Unknown key for a " + token + " in [" + pipelineAggregatorName + "]: [" + currentFieldName + "]."); + } + } else if (token == XContentParser.Token.VALUE_STRING) { + if (context.getParseFieldMatcher().match(currentFieldName, FORMAT)) { + format = parser.text(); + } else if (context.getParseFieldMatcher().match(currentFieldName, BUCKETS_PATH)) { + bucketsPaths = new String[] { parser.text() }; + } else if (context.getParseFieldMatcher().match(currentFieldName, GAP_POLICY)) { + gapPolicy = GapPolicy.parse(context, parser.text(), parser.getTokenLocation()); + } else if (context.getParseFieldMatcher().match(currentFieldName, MODEL)) { + model = parser.text(); + } else { + throw new ParsingException(parser.getTokenLocation(), + "Unknown key for a " + token + " in [" + pipelineAggregatorName + "]: [" + currentFieldName + "]."); + } + } else if (token == XContentParser.Token.START_ARRAY) { + if (context.getParseFieldMatcher().match(currentFieldName, BUCKETS_PATH)) { + List paths = new ArrayList<>(); + while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) { + String path = parser.text(); + paths.add(path); + } + bucketsPaths = paths.toArray(new String[paths.size()]); + } else { + throw new ParsingException(parser.getTokenLocation(), + "Unknown key for a " + token + " in [" + pipelineAggregatorName + "]: [" + currentFieldName + "]."); + } + } else if (token == XContentParser.Token.START_OBJECT) { + if (context.getParseFieldMatcher().match(currentFieldName, SETTINGS)) { + settings = parser.map(); + } else { + throw new ParsingException(parser.getTokenLocation(), + "Unknown key for a " + token + " in [" + pipelineAggregatorName + "]: [" + currentFieldName + "]."); + } + } else if (token == XContentParser.Token.VALUE_BOOLEAN) { + if (context.getParseFieldMatcher().match(currentFieldName, MINIMIZE)) { + minimize = parser.booleanValue(); + } else { + throw new ParsingException(parser.getTokenLocation(), + "Unknown key for a " + token + " in [" + pipelineAggregatorName + "]: [" + currentFieldName + "]."); + } + } else { + throw new ParsingException(parser.getTokenLocation(), + "Unexpected token " + token + " in [" + pipelineAggregatorName + "]."); + } + } + + if (bucketsPaths == null) { + throw new ParsingException(parser.getTokenLocation(), "Missing required field [" + BUCKETS_PATH.getPreferredName() + + "] for movingAvg aggregation [" + pipelineAggregatorName + "]"); + } + + MovAvgPipelineAggregatorBuilder factory = + new MovAvgPipelineAggregatorBuilder(pipelineAggregatorName, bucketsPaths[0]); + if (format != null) { + factory.format(format); + } + if (gapPolicy != null) { + factory.gapPolicy(gapPolicy); + } + if (window != null) { + factory.window(window); + } + if (predict != null) { + factory.predict(predict); + } + if (model != null) { + MovAvgModel.AbstractModelParser modelParser = movAvgModelParserMapper.get(model); + if (modelParser == null) { + throw new ParsingException(parser.getTokenLocation(), + "Unknown model [" + model + "] specified. Valid options are:" + movAvgModelParserMapper.getAllNames().toString()); + } + + MovAvgModel movAvgModel; + try { + movAvgModel = modelParser.parse(settings, pipelineAggregatorName, factory.window(), context.getParseFieldMatcher()); + } catch (ParseException exception) { + throw new ParsingException(parser.getTokenLocation(), "Could not parse settings for model [" + model + "].", exception); + } + factory.model(movAvgModel); + } + if (minimize != null) { + factory.minimize(minimize); + } + return factory; } @Override @@ -298,4 +437,8 @@ public class MovAvgPipelineAggregatorBuilder extends PipelineAggregatorBuilder movAvgParsers; - @Inject public MovAvgModelParserMapper(Set parsers) { Map map = new HashMap<>(); add(map, new SimpleModel.SimpleModelParser()); diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/movavg/models/SimpleModel.java b/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/movavg/models/SimpleModel.java index 61f8c668e1a..7fb3b4e7b99 100644 --- a/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/movavg/models/SimpleModel.java +++ b/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/movavg/models/SimpleModel.java @@ -25,7 +25,7 @@ import org.elasticsearch.common.ParseFieldMatcher; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.search.aggregations.pipeline.movavg.MovAvgParser; +import org.elasticsearch.search.aggregations.pipeline.movavg.MovAvgPipelineAggregatorBuilder; import java.io.IOException; import java.text.ParseException; @@ -90,7 +90,7 @@ public class SimpleModel extends MovAvgModel { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.field(MovAvgParser.MODEL.getPreferredName(), NAME_FIELD.getPreferredName()); + builder.field(MovAvgPipelineAggregatorBuilder.MODEL.getPreferredName(), NAME_FIELD.getPreferredName()); return builder; } @@ -122,7 +122,7 @@ public class SimpleModel extends MovAvgModel { public static class SimpleModelBuilder implements MovAvgModelBuilder { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.field(MovAvgParser.MODEL.getPreferredName(), NAME_FIELD.getPreferredName()); + builder.field(MovAvgPipelineAggregatorBuilder.MODEL.getPreferredName(), NAME_FIELD.getPreferredName()); return builder; }