/**
* OpenSpotLight - Open Source IT Governance Platform
*
* Copyright (c) 2009, CARAVELATECH CONSULTORIA E TECNOLOGIA EM INFORMATICA LTDA
* or third-party contributors as indicated by the @author tags or express
* copyright attribution statements applied by the authors. All third-party
* contributions are distributed under license by CARAVELATECH CONSULTORIA E
* TECNOLOGIA EM INFORMATICA LTDA.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
***********************************************************************
* OpenSpotLight - Plataforma de Governança de TI de Código Aberto
*
* Direitos Autorais Reservados (c) 2009, CARAVELATECH CONSULTORIA E TECNOLOGIA
* EM INFORMATICA LTDA ou como contribuidores terceiros indicados pela etiqueta
* @author ou por expressa atribuição de direito autoral declarada e atribuída pelo autor.
* Todas as contribuições de terceiros estão distribuídas sob licença da
* CARAVELATECH CONSULTORIA E TECNOLOGIA EM INFORMATICA LTDA.
*
* Este programa é software livre; você pode redistribuí-lo e/ou modificá-lo sob os
* termos da Licença Pública Geral Menor do GNU conforme publicada pela Free Software
* Foundation.
*
* Este programa é distribuído na expectativa de que seja útil, porém, SEM NENHUMA
* GARANTIA; nem mesmo a garantia implícita de COMERCIABILIDADE OU ADEQUAÇÃO A UMA
* FINALIDADE ESPECÍFICA. Consulte a Licença Pública Geral Menor do GNU para mais detalhes.
*
* Você deve ter recebido uma cópia da Licença Pública Geral Menor do GNU junto com este
* programa; se não, escreva para:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.openspotlight.graph.query;
import java.util.ArrayList;
import java.util.List;
import org.antlr.runtime.EarlyExitException;
import org.antlr.runtime.FailedPredicateException;
import org.antlr.runtime.MismatchedNotSetException;
import org.antlr.runtime.MismatchedSetException;
import org.antlr.runtime.MismatchedTokenException;
import org.antlr.runtime.MismatchedTreeNodeException;
import org.antlr.runtime.NoViableAltException;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.Token;
import org.openspotlight.graph.query.parser.SLQLLexer;
/**
* Helper class that generates SLQueryLanguageParserException with user friendly error messages.
*
* @author porcelli
* @see InvalidQuerySyntaxException
*/
public class InvalidQuerySyntaxExceptionFactory {
/** The Constant EARLY_EXIT_MESSAGE. */
private final static String EARLY_EXIT_MESSAGE =
"Line %1$d:%2$d required (...)+ loop did not match anything at input '%3$s'";
/** The Constant FAILED_PREDICATE_MESSAGE. */
private final static String FAILED_PREDICATE_MESSAGE = "Line %1$d:%2$d rule '%3$s' failed predicate: {%4$s}?";
/** The Constant MISMATCHED_NOT_SET_MESSAGE. */
private final static String MISMATCHED_NOT_SET_MESSAGE =
"Line %1$d:%2$d mismatched input '%3$' expecting set '%4$s'";
/** The Constant MISMATCHED_SET_MESSAGE. */
private final static String MISMATCHED_SET_MESSAGE =
"Line %1$d:%2$d mismatched input '%3$' expecting set '%4$s'.";
/** The Constant MISMATCHED_TOKEN_MESSAGE_COMPLETE. */
private final static String MISMATCHED_TOKEN_MESSAGE_COMPLETE = "Line %1$d:%2$d mismatched input '%3$s' expecting '%4$s'";
/** The Constant MISMATCHED_TOKEN_MESSAGE_PART. */
private final static String MISMATCHED_TOKEN_MESSAGE_PART = "Line %1$d:%2$d mismatched input '%3$s'";
/** The Constant MISMATCHED_TREE_NODE_MESSAGE_COMPLETE. */
private final static String MISMATCHED_TREE_NODE_MESSAGE_COMPLETE =
"Line %1$d:%2$d mismatched tree node '%3$s' expecting '%4$s'";
/** The Constant MISMATCHED_TREE_NODE_MESSAGE_PART. */
private final static String MISMATCHED_TREE_NODE_MESSAGE_PART = "Line %1$d:%2$d mismatched tree node '%3$s'";
/** The Constant NO_VIABLE_ALT_MESSAGE. */
private final static String NO_VIABLE_ALT_MESSAGE = "Line %1$d:%2$d no viable alternative at input '%3$s'";
/** The token names. */
private String[] tokenNames = null;
/**
* InvalidQuerySyntaxExceptionFactory constructor.
*
* @param tokenNames tokenNames generated by ANTLR
*/
public InvalidQuerySyntaxExceptionFactory(
final String[] tokenNames) {
this.tokenNames = tokenNames;
}
/**
* This will take a RecognitionException, and create a sensible error message out of it.
*
* @param e the e
* @return the list< string>
*/
private List<String> createErrorMessage(final RecognitionException e) {
final List<String> codeAndMessage = new ArrayList<String>(2);
String message = "";
if (e instanceof MismatchedTokenException) {
final MismatchedTokenException mte = (MismatchedTokenException) e;
if (tokenNames != null && mte.expecting >= 0 && mte.expecting < tokenNames.length) {
message = String.format(InvalidQuerySyntaxExceptionFactory.MISMATCHED_TOKEN_MESSAGE_COMPLETE, e.line,
e.charPositionInLine, getBetterToken(e.token), getBetterToken(mte.expecting));
codeAndMessage.add(message);
codeAndMessage.add("ERR 101");
} else {
message = String.format(InvalidQuerySyntaxExceptionFactory.MISMATCHED_TOKEN_MESSAGE_PART, e.line,
e.charPositionInLine, getBetterToken(e.token));
codeAndMessage.add(message);
codeAndMessage.add("ERR 101");
}
} else if (e instanceof MismatchedTreeNodeException) {
final MismatchedTreeNodeException mtne = (MismatchedTreeNodeException) e;
if (mtne.expecting >= 0 && mtne.expecting < tokenNames.length) {
message = String.format(InvalidQuerySyntaxExceptionFactory.MISMATCHED_TREE_NODE_MESSAGE_COMPLETE, e.line,
e.charPositionInLine, getBetterToken(e.token), getBetterToken(mtne.expecting));
codeAndMessage.add(message);
codeAndMessage.add("ERR 102");
} else {
message = String.format(InvalidQuerySyntaxExceptionFactory.MISMATCHED_TREE_NODE_MESSAGE_PART, e.line,
e.charPositionInLine, getBetterToken(e.token));
codeAndMessage.add(message);
codeAndMessage.add("ERR 102");
}
} else if (e instanceof NoViableAltException) {
// NoViableAltException nvae = (NoViableAltException) e;
message = String.format(InvalidQuerySyntaxExceptionFactory.NO_VIABLE_ALT_MESSAGE, e.line, e.charPositionInLine,
getBetterToken(e.token));
codeAndMessage.add(message);
codeAndMessage.add("ERR 103");
} else if (e instanceof EarlyExitException) {
// EarlyExitException eee = (EarlyExitException) e;
message = String.format(InvalidQuerySyntaxExceptionFactory.EARLY_EXIT_MESSAGE, e.line, e.charPositionInLine,
getBetterToken(e.token));
codeAndMessage.add(message);
codeAndMessage.add("ERR 104");
} else if (e instanceof MismatchedSetException) {
final MismatchedSetException mse = (MismatchedSetException) e;
message = String.format(InvalidQuerySyntaxExceptionFactory.MISMATCHED_SET_MESSAGE, e.line, e.charPositionInLine,
getBetterToken(e.token), mse.expecting);
codeAndMessage.add(message);
codeAndMessage.add("ERR 105");
} else if (e instanceof MismatchedNotSetException) {
final MismatchedNotSetException mse = (MismatchedNotSetException) e;
message = String.format(InvalidQuerySyntaxExceptionFactory.MISMATCHED_NOT_SET_MESSAGE, e.line,
e.charPositionInLine, getBetterToken(e.token), mse.expecting);
codeAndMessage.add(message);
codeAndMessage.add("ERR 106");
} else if (e instanceof FailedPredicateException) {
final FailedPredicateException fpe = (FailedPredicateException) e;
message = String.format(InvalidQuerySyntaxExceptionFactory.FAILED_PREDICATE_MESSAGE, e.line, e.charPositionInLine,
fpe.ruleName, fpe.predicateText);
codeAndMessage.add(message);
codeAndMessage.add("ERR 107");
}
if (codeAndMessage.get(0).length() == 0) {
codeAndMessage.add("?????");
}
return codeAndMessage;
}
/**
* Helper method that creates a user friendly token definition.
*
* @param tokenType token type
* @return user friendly token definition
*/
private String getBetterToken(final int tokenType) {
return getBetterToken(tokenType, null);
}
/**
* Helper method that creates a user friendly token definition.
*
* @param tokenType token type
* @param defaultValue default value for identifier token, may be null
* @return user friendly token definition
*/
private String getBetterToken(final int tokenType,
final String defaultValue) {
switch (tokenType) {
case SLQLLexer.INT:
return defaultValue == null ? "int" : defaultValue;
case SLQLLexer.DEC:
return defaultValue == null ? "decimal" : defaultValue;
case SLQLLexer.STRING:
return defaultValue == null ? "string" : defaultValue;
case SLQLLexer.SEMICOLON:
return ";";
case SLQLLexer.STAR:
return "*";
case SLQLLexer.DOUBLE_STAR:
return "**";
case SLQLLexer.EQUALS:
return "=";
case SLQLLexer.NOT_EQUALS:
return "!=";
case SLQLLexer.GREATER:
return ">";
case SLQLLexer.GREATER_OR_EQUALS:
return ">=";
case SLQLLexer.LESSER:
return "<";
case SLQLLexer.LESSER_OR_EQUALS:
return "<=";
case SLQLLexer.ID:
return defaultValue == null ? "identifier" : defaultValue;
case SLQLLexer.LEFT_PAREN:
return "(";
case SLQLLexer.RIGHT_PAREN:
return ")";
case SLQLLexer.LEFT_SQUARE:
return "[";
case SLQLLexer.RIGHT_SQUARE:
return "]";
case SLQLLexer.COMMA:
return ",";
case SLQLLexer.DOT:
return ".";
case SLQLLexer.OR_OPERATOR:
return "||";
case SLQLLexer.AND_OPERATOR:
return "&&";
case SLQLLexer.EOF:
return "<eof>";
default:
return tokenType > tokenNames.length ? "unknown" : tokenNames[tokenType];
}
}
/**
* Helper method that creates a user friendly token definition.
*
* @param token token
* @return user friendly token definition
*/
private String getBetterToken(final Token token) {
if (token == null) { return ""; }
return getBetterToken(token.getType(), token.getText());
}
/**
* Creates a new InvalidQuerySyntaxException object.
*
* @return the SL invalid query syntax exception
*/
public InvalidQuerySyntaxException createByLinkWithoutDefineTargetException() {
return new InvalidQuerySyntaxException("ERR 113", "invalid use of double star (**)", -1, -1, -1, null);
}
/**
* Creates a new InvalidQuerySyntaxException object.
*
* @return the SL invalid query syntax exception
*/
public InvalidQuerySyntaxException createCannotUseWhereWithByLInkException() {
return new InvalidQuerySyntaxException("ERR 114", "invalid use of double star (**)", -1, -1, -1, null);
}
/**
* Creates a new InvalidQuerySyntaxException object.
*
* @return the SL invalid query syntax exception
*/
public InvalidQuerySyntaxException createDefineTargetWithByLinkException() {
return new InvalidQuerySyntaxException("ERR 115", "invalid use of by link in define target", -1, -1, -1, null);
}
/**
* Creates a new InvalidQuerySyntaxException object.
*
* @return the SL invalid query syntax exception
*/
public InvalidQuerySyntaxException createDefineTargetWithoutByLinkException() {
return new InvalidQuerySyntaxException("ERR 112", "invalid use of double star (**)", -1, -1, -1, null);
}
/**
* Creates a new InvalidQuerySyntaxException object.
*
* @return the SL invalid query syntax exception
*/
public InvalidQuerySyntaxException createDuplicatedDefineDomainException() {
return new InvalidQuerySyntaxException("ERR 111", "invalid use of double star (**)", -1, -1, -1, null);
}
/**
* Creates a new InvalidQuerySyntaxException object.
*
* @return the SL invalid query syntax exception
*/
public InvalidQuerySyntaxException createDuplicatedDefineMessageException() {
return new InvalidQuerySyntaxException("ERR 110", "invalid use of double star (**)", -1, -1, -1, null);
}
/**
* Creates a new InvalidQuerySyntaxException object.
*
* @return the SL invalid query syntax exception
*/
public InvalidQuerySyntaxException createInvalidDoubleStarException() {
return new InvalidQuerySyntaxException("ERR 109", "invalid use of double star (**)", -1, -1, -1, null);
}
/**
* Creates a new InvalidQuerySyntaxException object.
*
* @return the SL invalid query syntax exception
*/
public InvalidQuerySyntaxException createInvalidExecutingException() {
return new InvalidQuerySyntaxException("ERR 108", "invalid use of executing times", -1, -1, -1, null);
}
/**
* Creates a new InvalidQuerySyntaxException object.
*
* @return the SL invalid query syntax exception
*/
public InvalidQuerySyntaxException createSLQueryLanguageException() {
return new InvalidQuerySyntaxException("");
}
/**
* This method creates a InvalidQuerySyntaxException full of information.
*
* @param e original exception
* @return InvalidQuerySyntaxException filled.
*/
public InvalidQuerySyntaxException createSLQueryLanguageException(final RecognitionException e) {
final List<String> codeAndMessage = createErrorMessage(e);
return new InvalidQuerySyntaxException(codeAndMessage.get(1), codeAndMessage.get(0), e.line, e.charPositionInLine,
e.index, e);
}
}