001: package jimm.datavision.source.sql;
002:
003: /**
004: * A helper class used by a SQL query while parsing the WHERE clause.
005: *
006: * @author Jim Menard, <a href="mailto:jimm@io.com">jimm@io.com</a>
007: * @see SQLQuery
008: */
009: public class ParserHelper {
010:
011: protected String str;
012: protected int startPos;
013: protected String prevToken;
014: protected int prevTokenStartPos;
015: protected int endBeforeToken;
016:
017: public ParserHelper(String s, int pos) {
018: str = s;
019: startPos = pos;
020:
021: findPreviousSQLToken();
022: }
023:
024: /**
025: * Finds the token before the one that starts at <var>startPos</var> in
026: * <var>str</var>. The token will not include the whitespace surrounding
027: * it, if any.
028: */
029: protected void findPreviousSQLToken() {
030: if (startPos == 0) {
031: prevToken = "";
032: prevTokenStartPos = 0;
033: endBeforeToken = 0;
034: return;
035: }
036:
037: // Move backwards, skipping whitespace, to the end of the previous token.
038: prevTokenStartPos = startPos - 1;
039: while (prevTokenStartPos >= 0
040: && Character.isSpaceChar(str.charAt(prevTokenStartPos)))
041: --prevTokenStartPos;
042:
043: int tokenEnd = prevTokenStartPos + 1;
044:
045: char c = str.charAt(prevTokenStartPos);
046: boolean prevWordIsAlpha = (Character.isLetterOrDigit(c) || c == '_');
047:
048: // Continue moving backwards, stopping when we get to whitespace or '}'
049: // or a char that is not of the same type.
050: while (prevTokenStartPos >= 0
051: && !Character.isSpaceChar(c = str
052: .charAt(prevTokenStartPos))
053: && !(c == '}') // Always stop at '}'
054: && (prevWordIsAlpha ? (Character.isLetterOrDigit(c) || c == '_')
055: : !(Character.isLetterOrDigit(c) || c == '_')))
056: --prevTokenStartPos;
057: ++prevTokenStartPos;
058:
059: // Set flag which tells us if there is a space before the previous token
060: // spaceBeforePrevToken = prevTokenStartPos > 0
061: // && Character.isSpaceChar(str.charAt(prevTokenStartPos - 1));
062:
063: // Find the index of the character after the token before this token.
064: // That's the same as the beginning of this whitespace before this
065: // token or, if none, the beginning of this token.
066: if (prevTokenStartPos == 0)
067: endBeforeToken = 0;
068: else {
069: endBeforeToken = prevTokenStartPos - 1;
070: while (endBeforeToken >= 0
071: && Character
072: .isSpaceChar(str.charAt(endBeforeToken)))
073: --endBeforeToken;
074: ++endBeforeToken;
075: }
076:
077: // Finally, grab the token itself, sans whitespace.
078: prevToken = str.substring(prevTokenStartPos, tokenEnd);
079: }
080:
081: /**
082: * Returns the previous token, sans whitespace.
083: *
084: * @return a possibly empty string
085: */
086: public String getPrevToken() {
087: return prevToken;
088: }
089:
090: /**
091: * Returns the starting position of the previous token in the original
092: * string, not including any leading whitespace.
093: *
094: * @return a string index pointing to the start of the previous token
095: */
096: public int getPrevTokenStartPos() {
097: return prevTokenStartPos;
098: }
099:
100: public int getEndBeforeToken() {
101: return endBeforeToken;
102: }
103:
104: }
|