/** * Licensed 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 io.horizondb.db.parser; import io.horizondb.db.Configuration; import io.horizondb.db.HorizonDBException; import io.horizondb.db.databases.DatabaseManager; import io.horizondb.db.parser.ErrorHandler.SyntaxException; import io.horizondb.db.parser.HqlParser.StatementsContext; import io.horizondb.db.parser.builders.MsgBuilderDispatcher; import io.horizondb.io.serialization.Serializable; import io.horizondb.model.protocol.HqlQueryPayload; import io.horizondb.model.protocol.Msg; import java.io.IOException; import org.antlr.v4.runtime.ANTLRInputStream; import org.antlr.v4.runtime.CharStream; import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.tree.ParseTreeWalker; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * The parser used to parse the HQL queries. */ public final class QueryParser { /** * The logger. */ private static final Logger LOGGER = LoggerFactory.getLogger(QueryParser.class); /** * Parses the specified query string of the specified message and return the corresponding low level message. * * @param configuration the database configuration * @param databaseManager the database manager * @param msg the query message * @return the low level message corresponding to the specified <code>query</code>. * @throws HorizonDBException if a problem occurs while parsing the query. * @throws IOException if an I/O problem occurs while parsing the query */ public static <T extends Serializable> Msg<T> parse(Configuration configuration, DatabaseManager databaseManager, Msg<HqlQueryPayload> msg) throws HorizonDBException, IOException { HqlQueryPayload payload = msg.getPayload(); String databaseName = payload.getDatabaseName(); String query = payload.getQuery(); LOGGER.debug("parsing query: [{}] for database {}.", query, databaseName); try { final ErrorHandler errorHandler = new ErrorHandler(); CharStream stream = new ANTLRInputStream(query); HqlLexer lexer = new HqlLexer(stream); lexer.removeErrorListeners(); lexer.addErrorListener(errorHandler); CommonTokenStream tokens = new CommonTokenStream(lexer); HqlParser parser = new HqlParser(tokens); parser.removeErrorListeners(); parser.addErrorListener(errorHandler); StatementsContext statements = parser.statements(); ParseTreeWalker walker = new ParseTreeWalker(); MsgBuilder msgBuilder = new MsgBuilderDispatcher(configuration, databaseManager, msg.getHeader(), databaseName); walker.walk(msgBuilder, statements); return (Msg<T>) msgBuilder.build(); } catch (SyntaxException e) { throw new BadHqlGrammarException(query, e.getLineNumber(), e.getCharPosition(), e.getMessage()); } } }