/*
*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.usergrid.persistence.index.query;
import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.Token;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.commons.lang.StringUtils;
import org.apache.usergrid.persistence.index.exceptions.QueryParseException;
import org.apache.usergrid.persistence.index.query.tree.CpQueryFilterLexer;
import org.apache.usergrid.persistence.index.query.tree.CpQueryFilterParser;
/**
* A utility class that will parse our query, then return it's parsed representation
*/
public class ParsedQueryBuilder {
private static final Logger logger = LoggerFactory.getLogger( ParsedQueryBuilder.class );
/**
* Generate a parsedQuery from the ql
*/
public static ParsedQuery build( final String ql ) throws QueryParseException {
if ( StringUtils.isEmpty( ql ) ) {
return null;
}
if (logger.isTraceEnabled()) {
logger.trace("Processing raw query: {}", ql);
}
final String trimmedLowercaseQuery = ql.trim().toLowerCase();
//the output query after post processing
final String outputQuery;
//it doesn't start with select, rewrite it to be a correct query grammar
if ( !trimmedLowercaseQuery.startsWith( "select" ) ) {
//just an order by, add the select
//just starts with a where, add the select
if ( trimmedLowercaseQuery.startsWith( "order by" ) || trimmedLowercaseQuery.startsWith( "where" )) {
outputQuery = "select * " + trimmedLowercaseQuery;
}
//junk, bail
else {
outputQuery = "select * where " + trimmedLowercaseQuery;
}
}
else {
outputQuery = trimmedLowercaseQuery;
}
ANTLRStringStream in = new ANTLRStringStream( outputQuery );
CpQueryFilterLexer lexer = new CpQueryFilterLexer( in );
CommonTokenStream tokens = new CommonTokenStream( lexer );
CpQueryFilterParser parser = new CpQueryFilterParser( tokens );
try {
final ParsedQuery query = parser.ql().parsedQuery;
query.setOriginalQuery( ql );
return query;
}
catch ( RecognitionException e ) {
logger.error( "Unable to parse \"{}\"", ql, e );
int index = e.index;
int lineNumber = e.line;
Token token = e.token;
String message = String.format(
"The query cannot be parsed. The token '%s' at " + "column %d on line %d cannot be " + "parsed",
token.getText(), index, lineNumber );
throw new QueryParseException( message, e );
}
}
}