public static ScriptedMetricAggregationBuilder parse(
      String aggregationName, QueryParseContext context) throws IOException {
    Script initScript = null;
    Script mapScript = null;
    Script combineScript = null;
    Script reduceScript = null;
    Map<String, Object> params = null;
    XContentParser.Token token;
    String currentFieldName = null;
    Set<String> scriptParameters = new HashSet<>();
    scriptParameters.add(INIT_SCRIPT_FIELD.getPreferredName());
    scriptParameters.add(MAP_SCRIPT_FIELD.getPreferredName());
    scriptParameters.add(COMBINE_SCRIPT_FIELD.getPreferredName());
    scriptParameters.add(REDUCE_SCRIPT_FIELD.getPreferredName());

    XContentParser parser = context.parser();
    while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
      if (token == XContentParser.Token.FIELD_NAME) {
        currentFieldName = parser.currentName();
      } else if (token == XContentParser.Token.START_OBJECT
          || token == XContentParser.Token.VALUE_STRING) {
        if (context.getParseFieldMatcher().match(currentFieldName, INIT_SCRIPT_FIELD)) {
          initScript =
              Script.parse(
                  parser, context.getParseFieldMatcher(), context.getDefaultScriptLanguage());
        } else if (context.getParseFieldMatcher().match(currentFieldName, MAP_SCRIPT_FIELD)) {
          mapScript =
              Script.parse(
                  parser, context.getParseFieldMatcher(), context.getDefaultScriptLanguage());
        } else if (context.getParseFieldMatcher().match(currentFieldName, COMBINE_SCRIPT_FIELD)) {
          combineScript =
              Script.parse(
                  parser, context.getParseFieldMatcher(), context.getDefaultScriptLanguage());
        } else if (context.getParseFieldMatcher().match(currentFieldName, REDUCE_SCRIPT_FIELD)) {
          reduceScript =
              Script.parse(
                  parser, context.getParseFieldMatcher(), context.getDefaultScriptLanguage());
        } else if (token == XContentParser.Token.START_OBJECT
            && context.getParseFieldMatcher().match(currentFieldName, PARAMS_FIELD)) {
          params = parser.map();
        } else {
          throw new ParsingException(
              parser.getTokenLocation(),
              "Unknown key for a "
                  + token
                  + " in ["
                  + aggregationName
                  + "]: ["
                  + currentFieldName
                  + "].");
        }
      } else {
        throw new ParsingException(
            parser.getTokenLocation(),
            "Unexpected token " + token + " in [" + aggregationName + "].");
      }
    }

    if (mapScript == null) {
      throw new ParsingException(
          parser.getTokenLocation(), "map_script field is required in [" + aggregationName + "].");
    }

    ScriptedMetricAggregationBuilder factory =
        new ScriptedMetricAggregationBuilder(aggregationName);
    if (initScript != null) {
      factory.initScript(initScript);
    }
    if (mapScript != null) {
      factory.mapScript(mapScript);
    }
    if (combineScript != null) {
      factory.combineScript(combineScript);
    }
    if (reduceScript != null) {
      factory.reduceScript(reduceScript);
    }
    if (params != null) {
      factory.params(params);
    }
    return factory;
  }