@Override
 protected XContentBuilder internalXContent(XContentBuilder builder, Params params)
     throws IOException {
   builder.field(BUCKETS_PATH.getPreferredName(), bucketsPathsMap);
   builder.field(ScriptField.SCRIPT.getPreferredName(), script);
   builder.field(GAP_POLICY.getPreferredName(), gapPolicy.getName());
   return builder;
 }
 @Override
 public void doXContent(XContentBuilder builder, Params params) throws IOException {
   builder.startObject(getName());
   builder.field(ScriptField.SCRIPT.getPreferredName(), script);
   builder.endObject();
 }
  public static BucketSelectorPipelineAggregationBuilder parse(
      String reducerName, QueryParseContext context) throws IOException {
    XContentParser parser = context.parser();
    XContentParser.Token token;
    Script script = null;
    String currentFieldName = null;
    Map<String, String> bucketsPathsMap = null;
    GapPolicy gapPolicy = null;

    while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
      if (token == XContentParser.Token.FIELD_NAME) {
        currentFieldName = parser.currentName();
      } else if (token == XContentParser.Token.VALUE_STRING) {
        if (context.getParseFieldMatcher().match(currentFieldName, BUCKETS_PATH)) {
          bucketsPathsMap = new HashMap<>();
          bucketsPathsMap.put("_value", parser.text());
        } else if (context.getParseFieldMatcher().match(currentFieldName, GAP_POLICY)) {
          gapPolicy = GapPolicy.parse(context, parser.text(), parser.getTokenLocation());
        } else if (context.getParseFieldMatcher().match(currentFieldName, ScriptField.SCRIPT)) {
          script = Script.parse(parser, context.getParseFieldMatcher());
        } else {
          throw new ParsingException(
              parser.getTokenLocation(),
              "Unknown key for a "
                  + token
                  + " in ["
                  + reducerName
                  + "]: ["
                  + currentFieldName
                  + "].");
        }
      } else if (token == XContentParser.Token.START_ARRAY) {
        if (context.getParseFieldMatcher().match(currentFieldName, BUCKETS_PATH)) {
          List<String> paths = new ArrayList<>();
          while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
            String path = parser.text();
            paths.add(path);
          }
          bucketsPathsMap = new HashMap<>();
          for (int i = 0; i < paths.size(); i++) {
            bucketsPathsMap.put("_value" + i, paths.get(i));
          }
        } else {
          throw new ParsingException(
              parser.getTokenLocation(),
              "Unknown key for a "
                  + token
                  + " in ["
                  + reducerName
                  + "]: ["
                  + currentFieldName
                  + "].");
        }
      } else if (token == XContentParser.Token.START_OBJECT) {
        if (context.getParseFieldMatcher().match(currentFieldName, ScriptField.SCRIPT)) {
          script = Script.parse(parser, context.getParseFieldMatcher());
        } else if (context.getParseFieldMatcher().match(currentFieldName, BUCKETS_PATH)) {
          Map<String, Object> map = parser.map();
          bucketsPathsMap = new HashMap<>();
          for (Map.Entry<String, Object> entry : map.entrySet()) {
            bucketsPathsMap.put(entry.getKey(), String.valueOf(entry.getValue()));
          }
        } else {
          throw new ParsingException(
              parser.getTokenLocation(),
              "Unknown key for a "
                  + token
                  + " in ["
                  + reducerName
                  + "]: ["
                  + currentFieldName
                  + "].");
        }
      } else {
        throw new ParsingException(
            parser.getTokenLocation(), "Unexpected token " + token + " in [" + reducerName + "].");
      }
    }

    if (bucketsPathsMap == null) {
      throw new ParsingException(
          parser.getTokenLocation(),
          "Missing required field ["
              + BUCKETS_PATH.getPreferredName()
              + "] for bucket_selector aggregation ["
              + reducerName
              + "]");
    }

    if (script == null) {
      throw new ParsingException(
          parser.getTokenLocation(),
          "Missing required field ["
              + ScriptField.SCRIPT.getPreferredName()
              + "] for bucket_selector aggregation ["
              + reducerName
              + "]");
    }

    BucketSelectorPipelineAggregationBuilder factory =
        new BucketSelectorPipelineAggregationBuilder(reducerName, bucketsPathsMap, script);
    if (gapPolicy != null) {
      factory.gapPolicy(gapPolicy);
    }
    return factory;
  }