/** * Constructs the AggregatorParsers out of all the given parsers * * @param parsers The available aggregator parsers (dynamically injected by the {@link * org.elasticsearch.search.aggregations.AggregationModule}). */ @Inject public AggregatorParsers(Set<Aggregator.Parser> parsers) { MapBuilder<String, Aggregator.Parser> builder = MapBuilder.newMapBuilder(); for (Aggregator.Parser parser : parsers) { builder.put(parser.type(), parser); } this.parsers = builder.immutableMap(); }
private AggregatorFactories parseAggregators( XContentParser parser, SearchContext context, int level) throws IOException { Matcher validAggMatcher = VALID_AGG_NAME.matcher(""); AggregatorFactories.Builder factories = new AggregatorFactories.Builder(); XContentParser.Token token = null; while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token != XContentParser.Token.FIELD_NAME) { throw new SearchParseException( context, "Unexpected token " + token + " in [aggs]: aggregations definitions must start with the name of the aggregation."); } final String aggregationName = parser.currentName(); if (!validAggMatcher.reset(aggregationName).matches()) { throw new SearchParseException( context, "Invalid aggregation name [" + aggregationName + "]. Aggregation names must be alpha-numeric and can only contain '_' and '-'"); } token = parser.nextToken(); if (token != XContentParser.Token.START_OBJECT) { throw new SearchParseException( context, "Aggregation definition for [" + aggregationName + " starts with a [" + token + "], expected a [" + XContentParser.Token.START_OBJECT + "]."); } AggregatorFactory factory = null; AggregatorFactories subFactories = null; while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token != XContentParser.Token.FIELD_NAME) { throw new SearchParseException( context, "Expected [" + XContentParser.Token.FIELD_NAME + "] under a [" + XContentParser.Token.START_OBJECT + "], but got a [" + token + "] in [" + aggregationName + "]"); } final String fieldName = parser.currentName(); token = parser.nextToken(); if ("aggregations_binary".equals(fieldName)) { if (subFactories != null) { throw new SearchParseException( context, "Found two sub aggregation definitions under [" + aggregationName + "]"); } XContentParser binaryParser = null; if (token == XContentParser.Token.VALUE_STRING || token == XContentParser.Token.VALUE_EMBEDDED_OBJECT) { byte[] source = parser.binaryValue(); binaryParser = XContentFactory.xContent(source).createParser(source); } else { throw new SearchParseException( context, "Expected [" + XContentParser.Token.VALUE_STRING + " or " + XContentParser.Token.VALUE_EMBEDDED_OBJECT + "] for [" + fieldName + "], but got a [" + token + "] in [" + aggregationName + "]"); } XContentParser.Token binaryToken = binaryParser.nextToken(); if (binaryToken != XContentParser.Token.START_OBJECT) { throw new SearchParseException( context, "Expected [" + XContentParser.Token.START_OBJECT + "] as first token when parsing [" + fieldName + "], but got a [" + binaryToken + "] in [" + aggregationName + "]"); } subFactories = parseAggregators(binaryParser, context, level + 1); } else if (token == XContentParser.Token.START_OBJECT) { switch (fieldName) { case "aggregations": case "aggs": if (subFactories != null) { throw new SearchParseException( context, "Found two sub aggregation definitions under [" + aggregationName + "]"); } subFactories = parseAggregators(parser, context, level + 1); break; default: if (factory != null) { throw new SearchParseException( context, "Found two aggregation type definitions in [" + aggregationName + "]: [" + factory.type + "] and [" + fieldName + "]"); } Aggregator.Parser aggregatorParser = parser(fieldName); if (aggregatorParser == null) { throw new SearchParseException( context, "Could not find aggregator type [" + fieldName + "] in [" + aggregationName + "]"); } factory = aggregatorParser.parse(aggregationName, parser, context); } } else { throw new SearchParseException( context, "Expected [" + XContentParser.Token.START_OBJECT + "] under [" + fieldName + "], but got a [" + token + "] in [" + aggregationName + "]"); } } if (factory == null) { throw new SearchParseException( context, "Missing definition for aggregation [" + aggregationName + "]"); } if (subFactories != null) { factory.subFactories(subFactories); } if (level == 0) { factory.validate(); } factories.add(factory); } return factories.build(); }