/*
* Copyright (c) 2006-2011 Rogério Liesenfeld
* This file is subject to the terms of the MIT license (see LICENSE.txt).
*/
package mockit.emulation.hibernate3.ast;
import java.io.*;
import java.text.*;
import java.util.*;
public final class Tokens
{
private static final DecimalFormat NUM_FORMAT = new DecimalFormat();
private static final List<String> KEYWORDS = Arrays.asList(
"and", "as", "asc", "ascending", "between", "by", "desc", "descending", "distinct", "fetch",
"from", "full", "group", "having", "in", "inner", "join", "left", "like", "member", "new",
"not", "of", "or", "order", "outer", "right", "select", "where");
static {
NUM_FORMAT.setGroupingUsed(false);
DecimalFormatSymbols symbols = new DecimalFormatSymbols();
symbols.setDecimalSeparator('.');
NUM_FORMAT.setDecimalFormatSymbols(symbols);
}
private final String[] tokens;
private int pos;
private int lastParameterIndex;
public Tokens(String ql)
{
tokens = tokens(ql);
pos = -1;
lastParameterIndex = -1;
}
private static String[] tokens(String ql)
{
StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(ql));
tokenizer.ordinaryChar('/');
List<String> tokens = new ArrayList<String>();
try {
while (tokenizer.nextToken() != StreamTokenizer.TT_EOF) {
int ttype = tokenizer.ttype;
char firstChar = (char) ttype;
if (firstChar == '<' || firstChar == '>' || firstChar == '!' || firstChar == '|') {
char secondChar = (char) tokenizer.nextToken();
if (
firstChar == '|' && secondChar == '|' ||
firstChar == '!' && secondChar == '=' ||
firstChar == '>' && secondChar == '=' ||
firstChar == '<' && secondChar == '=' ||
firstChar == '<' && secondChar == '>'
) {
tokens.add(String.valueOf(firstChar) + secondChar);
continue;
}
else {
tokenizer.pushBack();
}
}
String token;
if (ttype == StreamTokenizer.TT_WORD) {
token = tokenizer.sval;
}
else if (ttype == '\'') {
token = '\'' + tokenizer.sval + '\'';
}
else if (ttype == StreamTokenizer.TT_NUMBER) {
token = NUM_FORMAT.format(tokenizer.nval);
// TODO: not needed any more?
// if (token.endsWith(".0")) {
// token = token.substring(0, token.lastIndexOf('.'));
// }
}
else {
token = String.valueOf((char) ttype);
}
tokens.add(token);
}
}
catch (IOException ignore) { /* Won't ever happen */ }
return tokens.toArray(new String[tokens.size()]);
}
public boolean hasNext()
{
return pos + 1 < tokens.length;
}
public char nextChar()
{
return next().charAt(0);
}
public String next() throws QuerySyntaxException
{
pos++;
return token();
}
private String token()
{
if (pos >= tokens.length) {
throw new QuerySyntaxException(this);
}
return tokens[pos];
}
public void next(String expected) throws QuerySyntaxException
{
String token = next();
if (!expected.equalsIgnoreCase(token)) {
throw new QuerySyntaxException(this);
}
}
public void pushback()
{
pos--;
}
public int getPosition()
{
return pos;
}
public void setPosition(int position)
{
pos = position;
}
public int nextParameterIndex()
{
lastParameterIndex++;
return lastParameterIndex;
}
@Override
public String toString()
{
StringBuilder result = new StringBuilder();
for (int i = 0; i < tokens.length; i++) {
String token = tokens[i];
if (i == pos + 1) {
result.append('_');
}
result.append(token).append(' ');
}
return result.toString();
}
public static boolean isIdentifier(String token)
{
char firstChar = token.charAt(0);
return Character.isJavaIdentifierStart(firstChar) && !KEYWORDS.contains(token);
}
}