package io.ebeaninternal.server.querydefn; public class SimpleTextParser { private final String oql; private final char[] chars; private final int eof; private int pos; private String word; private String lowerWord; public SimpleTextParser(String oql) { this.oql = oql; this.chars = oql.toCharArray(); this.eof = oql.length(); } public boolean isEmpty() { return oql.isEmpty(); } public int getPos() { return pos; } String getOql() { return oql; } public String getWord() { return word; } private String peekNextWord() { int origPos = pos; String nw = nextWordInternal(); pos = origPos; return nw; } /** * Match the current and the next word. */ public boolean isMatch(String lowerMatch, String nextWordMatch) { if (isMatch(lowerMatch)) { String nw = peekNextWord(); if (nw != null) { nw = nw.toLowerCase(); return nw.equals(nextWordMatch); } } return false; } public boolean isFinished() { return word == null; } public int findWordLower(String lowerMatch, int afterPos) { this.pos = afterPos; return findWordLower(lowerMatch); } public int findWordLower(String lowerMatch) { do { if (nextWord() == null) { return -1; } if (lowerMatch.equals(lowerWord)) { return pos - lowerWord.length(); } } while (true); } /** * Match the current word. */ public boolean isMatch(String lowerMatch) { return lowerMatch.equals(lowerWord); } public String nextWord() { word = nextWordInternal(); if (word != null) { lowerWord = word.toLowerCase(); } return word; } private String nextWordInternal() { trimLeadingWhitespace(); if (pos >= eof) { return null; } int start = pos; if (chars[pos] == '(') { moveToClose(); } else { moveToEndOfWord(); } return oql.substring(start, pos); } private void moveToClose() { pos++; int openParenthesisCount = 0; for (; pos < eof; pos++) { char c = chars[pos]; if (c == '(') { // count nested parenthesis openParenthesisCount++; } else if (c == ')') { if (openParenthesisCount > 0) { // still in nested parenthesis --openParenthesisCount; } else { // we have found the end pos++; return; } } } } private void moveToEndOfWord() { char c = chars[pos]; boolean isOperator = isOperator(c); for (; pos < eof; pos++) { c = chars[pos]; if (isWordTerminator(c, isOperator)) { return; } } } private boolean isWordTerminator(char c, boolean isOperator) { return Character.isWhitespace(c) || (isOperator(c) ? !isOperator : c == '(' || isOperator); } private boolean isOperator(char c) { switch (c) { case '<': return true; case '>': return true; case '=': return true; case '!': return true; default: return false; } } private void trimLeadingWhitespace() { for (; pos < eof; pos++) { char c = chars[pos]; if (!Character.isWhitespace(c)) { break; } } } }