📄 whereclausetokenizer.java
字号:
package com.esri.solutions.jitk.web.wfs.data.query.sql;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class WhereClauseTokenizer {
protected int _currentIndex = 0;
protected String _wc;
protected List<String> _logicalOps = new ArrayList<String>();
protected List<String> _comparisonOps = new ArrayList<String>();
public WhereClauseTokenizer(String clause) {
_wc = clause;
buildLogicalOpsTable();
buildComparisonOpsTable();
_currentIndex = 0;
}
protected void buildLogicalOpsTable() {
_logicalOps.add("AND");
_logicalOps.add("OR");
_logicalOps.add("NOT");
}
protected void buildComparisonOpsTable() {
_comparisonOps.add("<>");
_comparisonOps.add("<=");
_comparisonOps.add(">=");
_comparisonOps.add(">");
_comparisonOps.add("<");
_comparisonOps.add("=");
_comparisonOps.add("LIKE");
_comparisonOps.add("BETWEEN");
}
/**
* Parses out the next token in the SQL WHERE clause. When no more tokens are available,
* null is returned.
*
* NOTE: No support for mathmatical operations as left-hand values or aggregate functions.
*
* @return Next token returned from this stateful tokenizer.
* @throws InvalidTokenException - Exception thrown if invalid token encountered
*/
public WhereClauseToken getNextToken() throws InvalidTokenException {
String token = "";
WhereClauseTokenType tokenType = WhereClauseTokenType.Whitespace;
if (_currentIndex >= _wc.length()) {
token = null;
} else {
tokenType = getStartTokenType(_wc.substring(_currentIndex));
while ((tokenType == WhereClauseTokenType.Whitespace) &&
((_currentIndex + 1) < _wc.length())) {
_currentIndex++;
tokenType = getStartTokenType(_wc.substring(_currentIndex));
}
token = parseOutToken(tokenType);
}
if (token == null) {
//End of parse string encountered
return null;
} else {
_currentIndex += token.length();
return new WhereClauseToken(token, tokenType);
}
}
protected String parseOutToken(WhereClauseTokenType tokenType)
throws InvalidTokenException {
String token = "";
switch (tokenType) {
case Whitespace:
//End of string encountered
token = null;
break;
case FieldName:
token = parseOutFieldName();
break;
case Literal:
token = parseOutLiteral();
break;
case LogicalOperator:
token = parseOutLogicalOperator();
break;
case Parenthesis:
token = _wc.substring(_currentIndex, _currentIndex + 1);
break;
case RelationalOperator:
token = parseOutRelationOperator();
break;
default:
String unparsedClause = _wc.substring(_currentIndex);
throw new InvalidTokenException("Invalid parse state encounted for unparsed clause section " + unparsedClause);
}
return token;
}
protected String parseOutFieldName() throws InvalidTokenException {
int index = 0;
String unparsedClause = _wc.substring(_currentIndex);
char nextChar = unparsedClause.charAt(index);
for (; index < unparsedClause.length(); index++) {
nextChar = unparsedClause.charAt(index);
if (!(Character.isLetterOrDigit(nextChar) || (nextChar == '.') || (nextChar == '_'))) {
break;
}
}
return unparsedClause.substring(0, index);
}
protected String parseOutLiteral() throws InvalidTokenException {
String unparsedClause = _wc.substring(_currentIndex);
int index = 0;
char nextChar = unparsedClause.charAt(index);
//If string literal
if (nextChar == '\'') {
index++;
for (; index < unparsedClause.length(); index++) {
nextChar = unparsedClause.charAt(index);
if (nextChar == '\'') {
return unparsedClause.substring(0, index + 1);
}
}
throw new InvalidTokenException("Closing \' expected in string literal within " + unparsedClause);
}
//else literal is a number
else {
for (; index < unparsedClause.length(); index++) {
nextChar = unparsedClause.charAt(index);
if (!(Character.isDigit(nextChar) || nextChar == '.')) {
break;
}
}
return unparsedClause.substring(0, index);
}
}
protected String parseOutLogicalOperator() throws InvalidTokenException {
String unparsedClause = _wc.substring(_currentIndex);
Collection<String> ops = _logicalOps;
for (String op : ops) {
int endIndex = op.length();
if (unparsedClause.toUpperCase().substring(0, endIndex).equals(op)) {
return op;
}
}
throw new InvalidTokenException(unparsedClause + " " +
"did not contain a valid logical operator in the beginning of the sting");
}
protected String parseOutRelationOperator() throws InvalidTokenException {
String unparsedClause = _wc.substring(_currentIndex);
Collection<String> ops = _comparisonOps;
for (String op : ops) {
int endIndex = op.length();
//Ensure string comparison does not go out of range
if (unparsedClause.length() >= op.length()) {
if (unparsedClause.toUpperCase().substring(0, endIndex).equals(op)) {
return op;
}
}
}
throw new InvalidTokenException(unparsedClause + " " +
"did not contain a valid relational operator in the beginning of the sting");
}
protected boolean isRelationalOperatorStart(String unparsedClause) {
char c = unparsedClause.charAt(0);
boolean isLogicalOp = (c == '=') || (c == '<') || (c == '>');
if (!isLogicalOp &&(unparsedClause.length() >= 5)) {
isLogicalOp = unparsedClause.toUpperCase().substring(0, 5).equals("LIKE ");
}
if (!isLogicalOp &&(unparsedClause.length() >= 8)) {
isLogicalOp = unparsedClause.toUpperCase().substring(0, 8).equals("BETWEEN ");
}
return isLogicalOp;
}
protected boolean isLogicalOperator(String unparsedClause) {
Collection<String> ops = _logicalOps;
boolean isLogicOp = false;
// Logical operators are delimited at the end by a space or (
for (String op : ops) {
String logicalOp = op + " ";
int endIndex = logicalOp.length();
//Don't attempt unsafe comparison due to length of string
if (unparsedClause.length() >= logicalOp.length()) {
if (unparsedClause.toUpperCase().substring(0, endIndex).equals(logicalOp)) {
isLogicOp = true;
break;
}
}
logicalOp = op + "(";
//Don't attempt unsafe comparison due to length of string
if (unparsedClause.length() >= logicalOp.length()) {
if (unparsedClause.toUpperCase().substring(0, endIndex).equals(logicalOp)) {
isLogicOp = true;
break;
}
}
}
return isLogicOp;
}
protected WhereClauseTokenType getStartTokenType(String unparsedClause)
throws InvalidTokenException {
char c = unparsedClause.charAt(0);
WhereClauseTokenType type = WhereClauseTokenType.Whitespace;
if (c == '(' || c == ')') {
type = WhereClauseTokenType.Parenthesis;
}
else if (Character.isDigit(c) || c == '\'') {
type = WhereClauseTokenType.Literal;
}
else if (isRelationalOperatorStart(unparsedClause)) {
type = WhereClauseTokenType.RelationalOperator;
}
else if (isLogicalOperator(unparsedClause)) {
type = WhereClauseTokenType.LogicalOperator;
}
else if (Character.isLetter(c)) {
type = WhereClauseTokenType.FieldName;
}
else if (Character.isWhitespace(c)) {
type = WhereClauseTokenType.Whitespace;
}
else {
throw new InvalidTokenException(String.valueOf(c) + " was deteremined to be invalid at it's location");
}
return type;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -