class Fields {
        static final String STMT = "stmt";
        static final String ARGS = "args";
        static final String BULK_ARGS = "bulk_args";
    }

    private static final Map<String, SQLParseElement> ELEMENT_PARSERS = Map.of(
        Fields.STMT, new SQLStmtParseElement(),
        Fields.ARGS, new SQLArgsParseElement(),
        Fields.BULK_ARGS, new SQLBulkArgsParseElement()
    );

    private SQLRequestParser() {
    }

    private static void validate(SQLRequestParseContext parseContext) throws SQLParseSourceException {
        if (parseContext.stmt() == null) {
            throw new SQLParseSourceException("Field [stmt] was not defined");
        }
    }

    public static SQLRequestParseContext parseSource(BytesReference source) throws IOException {
        if (source.length() == 0) {
            throw new SQLParseException("Missing request body");
        }
        XContentParser parser = null;
        try {
            SQLRequestParseContext parseContext = new SQLRequestParseContext();
            parser = XContentType.JSON.xContent().createParser(
                NamedXContentRegistry.EMPTY, DeprecationHandler.THROW_UNSUPPORTED_OPERATION, source.streamInput());
            parse(parseContext, parser);
            validate(parseContext);
            return parseContext;
        } catch (Exception e) {
            String sSource = "_na_";
            try {
                sSource = source.utf8ToString();
            } catch (Throwable e1) {
                // ignore
            }
            throw new SQLParseException("Failed to parse source [" + sSource + "]", e);
        } finally {
            if (parser != null) {
                parser.close();
            }
        }
    }

    public static void parse(SQLRequestParseContext parseContext, XContentParser parser) throws Exception {<FILL_FUNCTION_BODY>

        XContentParser.Token token;
        while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
            if (token == XContentParser.Token.FIELD_NAME) {
                String fieldName = parser.currentName();
                parser.nextToken();
                SQLParseElement element = ELEMENT_PARSERS.get(fieldName);
                if (element == null) {
                    throw new SQLParseException("No parser for element [" + fieldName + "]");
                }
                element.parse(parser, parseContext);
            } else if (token == null) {
                break;
            }
        }
    
<no_super_class>