/*
 * Copyright (c) 2006, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation
//
package org.eclipse.persistence.jpa.jpql;

/**
 * This "parser/scanner" holds onto the string version of the JPQL query that is parsed into a
 * parsed tree. It uses a cursor that lets the current {@link
 * org.eclipse.persistence.jpa.jpql.parser.Expression Expression} object to parse its fragment of the query.
 * <p>
 * Provisional API: This interface is part of an interim API that is still under development and
 * expected to change significantly before reaching stability. It is available at this early stage
 * to solicit feedback from pioneering adopters on the understanding that any code that uses this
 * API will almost certainly be broken (repeatedly) as the API evolves.
 *
 * @version 2.5.1
 * @since 2.3
 * @author Pascal Filion
 */
public final class WordParser {

    /**
     * The current position of the cursor within the JPQL query.
     */
    private int cursor;

    /**
     * The length of the JPQL query.
     */
    private final int length;

    /**
     * The string representation of the JPQL query.
     */
    private final CharSequence text;

    /**
     * When {@link WordParser#word()}, {@link WordParser#wordEndPosition()}, or {@link
     * WordParser#wordEndPosition(int)} is called, this is updated to reflect the type of word that
     * is scanned.
     *
     * @since 2.4
     */
    private WordType wordType;

    /**
     * Creates a new <code>WordParser</code>.
     *
     * @param text The string representation of the JPQL query
     */
    public WordParser(CharSequence text) {
        super();
        this.cursor   = 0;
        this.text     = text;
        this.length   = text.length();
        this.wordType = WordType.UNDEFINED;
    }

    /**
     * Retrieves the character at the current cursor position.
     *
     * @return The character retrieved from the string at the current cursor position or '\0' if the
     * position is beyond the end of the text
     */
    public char character() {
        return character(cursor);
    }

    /**
     * Retrieves the character at the given cursor position.
     *
     * @param position The position of the character to return
     * @return The character retrieved from the string at the given position or '\0' if the position
     * is beyond the end of the text
     */
    public char character(int position) {
        return (position >= length) ? '\0' : text.charAt(position);
    }

    /**
     * Determines whether the query ends with the given suffix and the end position is the end of the
     * range for testing.
     *
     * @param endPosition The position where the check stops
     * @param suffix The suffix is the text that is used to match it with the substring within the text
     * @return <code>true</code> if the character sequence represented by the argument is a suffix of
     * the query; <code>false</code> otherwise
     */
    public boolean endsWith(int endPosition, String suffix) {
        return startsWith(suffix, endPosition - suffix.length());
    }

    /**
     * Determines whether the query ends with the given suffix and the end position is the end of the
     * range for testing. The case of the character is ignored.
     *
     * @param endPosition The position where the check stops
     * @param suffix The suffix is the text that is used to match it with the substring within the text
     * @return <code>true</code> if the character sequence represented by the argument is a suffix of
     * the query; <code>false</code> otherwise
     * @since 2.5
     */
    public boolean endsWithIgnoreCase(int endPosition, String suffix) {
        return startsWithIgnoreCase(suffix, endPosition - suffix.length());
    }

    /**
     * Retrieves a word starting at the current position. The text before and after the position will
     * be part of the returned value.
     * <p>
     * For instance, "<b>SELECT</b> <b>AVG</b>(e.age) <b>FROM</b> Employee e":
     * <ul>
     * <li>Position 3, result is "SELECT";
     * <li>Position 6, result is "SELECT";
     * <li>Position 7, result is an empty string.
     * <li>Position 11, result is an empty string.
     * <li>Position 13, result is "e.".
     * </ul>
     *
     * @return The word in which the cursor is
     */
    public String entireWord() {
        return entireWord(cursor);
    }

    /**
     * Retrieves a word starting at the given position. The text before and after the position will
     * be part of the returned value.
     * <p>
     * For instance, "<b>SELECT</b> <b>AVG</b>(e.age) <b>FROM</b> Employee e":
     * <ul>
     * <li>Position 3, result is "SELECT";
     * <li>Position 6, result is "SELECT";
     * <li>Position 7, result is an empty string.
     * <li>Position 11, result is an empty string.
     * <li>Position 13, result is "e.".
     * </ul>
     *
     * @param position The position where to retrieve the word
     * @return The word in which the cursor is
     */
    public String entireWord(int position) {
        int startPosition = partialWordStartPosition(position);
        int endPosition   = wordEndPosition(position);
        return substring(startPosition, endPosition);
    }

    /**
     * Returns what the type of word {@link #word()} returns.
     *
     * @return The category of the word returned by {@link #word()}
     * @since 2.4
     */
    public WordType getWordType() {
        return wordType;
    }

    /**
     * Determines whether the given character is an arithmetic symbol, which is one of the following:
     * { {@literal '>', '<', '/', '*', '-', '+', '=', '{'} }.
     *
     * @param character The character to test if it's a math symbol
     * @return <code>true</code> if the given character is one of the valid math symbols;
     * <code>false</code> otherwise
     */
    public boolean isArithmeticSymbol(char character) {
        return character == '>' ||
               character == '!' ||
               character == '<' ||
               character == '/' ||
               character == '*' ||
               character == '-' ||
               character == '+' ||
               character == '=' ||
               character == '{';
    }

    /**
     * Determines whether the given character is a delimiter. The delimiter are '(', ')' and ','.
     *
     * @param character The character to test
     * @return <code>true</code> if the given character is a delimiter; <code>false</code> otherwise
     */
    public boolean isDelimiter(char character) {
        return character == '(' ||
               character == ')' ||
               character == ',';
    }

    /**
     * Determines whether the given character is a character that can be used in a number. This only
     * includes the numeric characters [0, 9] and the period character. This method should only be
     * used to determine if a word starts with a digit character.
     *
     * @param character The character to test if it's a digit
     * @return <code>true</code> if the given character is a digit; <code>false</code> otherwise
     */
    public boolean isDigit(char character) {
        return (character == '.') || Character.isDigit(character);
    }

    /**
     * Determines whether the position of the cursor is at the end of the text.
     *
     * @return <code>true</code> if the position of the cursor is at the end of the text;
     * <code>false</code> otherwise
     */
    public boolean isTail() {
        return cursor >= length;
    }

    /**
     * Determines whether the given character is not considered to be part of a word (which is
     * usually comprise of alphanumeric characters).
     *
     * @param character The character used to determine if it should be part of a word or not
     * @return <code>true</code> if the character can be part of a word; <code>false</code> if it is
     * not an alphanumeric character, which usually means is a whitespace, a delimiter or an
     * arithmetic symbol
     * @see Character#isWhitespace(char)
     * @see #isArithmeticSymbol(char)
     * @see #isDelimiter(char)
     */
    public boolean isWordSeparator(char character) {
        return Character.isWhitespace(character) ||
               isDelimiter(character)            ||
               isArithmeticSymbol(character);
    }

    /**
     * Returns the length of the string value.
     *
     * @return The total count of characters
     */
    public int length() {
        return length;
    }

    /**
     * Moves the position of the cursor by the length of the given word.
     *
     * @param word The word used to determine how much to move the position forward
     */
    public void moveBackward(CharSequence word) {
        cursor -= word.length();
    }

    /**
     * Moves backward the position of the cursor by the given amount.
     *
     * @param position The amount to remove from the current position
     */
    public void moveBackward(int position) {
        cursor -= position;
    }

    /**
     * Moves the position of the cursor by the length of the given word.
     *
     * @param word The word used to determine how much to move the position forward
     * @return The actual portion of the text that was skipped
     */
    public String moveForward(CharSequence word) {
        return moveForward(word.length());
    }

    /**
     * Moves forward the position of the cursor by the given amount.
     *
     * @param position The amount to add to the current position
     * @return The actual portion of the text that was skipped
     */
    public String moveForward(int position) {
        String word = substring(cursor, cursor + position);
        cursor += position;
        return word;
    }

    /**
     * Moves the position of the cursor by the length of the given word and ignore any different in
     * whitespace count. If the text has more than one whitespace and the given word usually has one,
     * then only one will be part of the returned substring.
     *
     * @param word The word used to determine how much to move the position forward
     * @return The actual portion of the text that was skipped
     * @since 2.4.3
     */
    public String moveForwardIgnoreWhitespace(CharSequence word) {

        StringBuilder sb = new StringBuilder();
        int pc = word.length();
        int po = 0;

        while (--pc >= 0) {

            char c1 = text.charAt(cursor++);
            char c2 = word.charAt(po++);

            // Handle testing
            // 1. "... GROUP    BY" and "GROUP BY"
            // 2. "... GROUP\nBY" and "GROUP BY"
            if (Character.isWhitespace(c1)) {

                if (Character.isWhitespace(c2)) {
                    sb.append(' ');
                    continue;
                }

                pc++;
                po--;
                continue;
            }

            sb.append(c1);
        }

        return sb.toString();
    }

    /**
     * Retrieves the numeric literal that should be the current word to parse.
     *
     * @return The numeric literal value
     */
    public String numericLiteral() {
        return substring(cursor, scanNumericLiteral(cursor));
    }

    /**
     * Retrieves a word before the current position of the cursor, which determines when the parsing
     * stop.
     * <p>
     * For instance, "<b>SELECT</b> <b>AVG</b>(e.age) <b>FROM</b> Employee e":
     * <ul>
     * <li>Position 3, result is "SEL";
     * <li>Position 6, result is "SELECT";
     * <li>Position 7, result is an empty string.
     * <li>Position 11, result is an empty string.
     * <li>Position 13, result is "e.".
     * </ul>
     *
     * @return The sub-string that is before the position
     */
    public String partialWord() {
        int startIndex = partialWordStartPosition(cursor);
        return substring(startIndex, cursor);
    }

    /**
     * Retrieves a word before the specified position, which determines when the parsing stop.
     * <p>
     * For instance, "<b>SELECT</b> <b>AVG</b>(e.age) <b>FROM</b> Employee e":
     * <ul>
     * <li>Position 3, result is "SEL";
     * <li>Position 6, result is "SELECT";
     * <li>Position 7, result is an empty string.
     * <li>Position 11, result is an empty string.
     * <li>Position 13, result is "e.".
     * </ul>
     *
     * @param position The position of the cursor
     * @return The sub-string that is before the position
     */
    public String partialWord(int position) {
        int startIndex = partialWordStartPosition(position);
        return substring(startIndex, position);
    }

    /**
     * Finds the beginning of the word and the given position is within that word.
     * <p>
     * For instance, "<b>SELECT</b> <b>AVG</b>(e.age) <b>FROM</b> Employee e":
     * <ul>
     * <li>Position 3, result is 0;
     * <li>Position 8, result is 7;
     * </ul>
     *
     * @param position The position from which the search ends
     * @return The position, which is a smaller number or equal, than the given position
     */
    public int partialWordStartPosition(int position) {

        int startIndex = position;

        for (int index = position; --index >= 0; ) {
            char character = text.charAt(index);

            if (Character.isWhitespace(character) ||
                isDelimiter(character) ||
                isArithmeticSymbol(character)) {

                break;
            }

            startIndex--;
        }

        return startIndex;
    }

    /**
     * Returns the current position of the cursor.
     *
     * @return The current position of the cursor
     */
    public int position() {
        return cursor;
    }

    private int scanNumericLiteral(int startPosition) {

        int endIndex = startPosition;
        boolean digitParsed = false;
        boolean dotParsed = false;

        for (; endIndex < length; endIndex++) {
            char character = text.charAt(endIndex);

            // Usual digit
            if (character >= '0' && character <= '9') {
                digitParsed = true;
            }
            // The arithmetic sign before the number
            else if ((character == '+' || character == '-')) {

                // '+' or '-' is only valid at the beginning of the literal
                if (endIndex > startPosition) {
                    break;
                }
            }
            // The separator of integer and decimal values
            else if (character == '.') {

                // A '.' was already parsed, it is not a valid numeric literal
                if (dotParsed) {
                    endIndex = startPosition + 1;
                    wordType = WordType.WORD;
                    break;
                }

                dotParsed = true;
            }
            // Hexadecimal value
            else if (character == 'x') {
                boolean powerParsed = false;

                for (; endIndex < length; endIndex++) {
                    character = text.charAt(endIndex);

                    if (character == 'p' || character == 'P') {
                        powerParsed = true;
                    }
                    else if (powerParsed && (character == '+' || character == '-')) {
                        continue;
                    }
                    else if (isWordSeparator(character)) {
                        break;
                    }
                }

                break;
            }
            // Parse the exponent
            else if (character == 'e' || character == 'E') {

                if (!digitParsed) {
                    wordType = WordType.WORD;
                    break;
                }

                for (int index = ++endIndex; index < length; index++) {
                    character = text.charAt(index);

                    // The first character can be '+', '-' or a number
                    if ((index == endIndex) && (character == '-' || character == '+') ||
                        character >= '0' && character <= '9') {

                        endIndex++;
                        continue;
                    }

                    if (character == '.') {
                        wordType = WordType.WORD;
                    }

                    // If it is not a character like '(', then it's not a valid number
                    if (isWordSeparator(character)) {
                        break;
                    }

                    endIndex++;
                }

                break;
            }
            // A float/double or long number
            else if (character == 'f' || character == 'F' ||
                     character == 'd' || character == 'D' ||
                     character == 'l' || character == 'L') {

                // A single arithmetic symbol
                // Example: "-LENGTH..." -> "-"
                if (!digitParsed) {
                    wordType = WordType.WORD;
                    break;
                }

                endIndex++;

                // End of the text
                if (endIndex == length) {
                    break;
                }

                character = text.charAt(endIndex);

                // Done parsing the numeric literal
                if (isWordSeparator(character)) {
                    break;
                }
            }
            // Example: "-AVG..." -> "-"
            else if (!digitParsed && Character.isJavaIdentifierPart(character)) {
                wordType = WordType.WORD;
                break;
            }
            // Done parsing the numeric literal
            else if (isWordSeparator(character)) {
                break;
            }
        }

        return endIndex;
    }

    /**
     * Retrieves the first word from the given text starting at the specified position.
     *
     * @param startPosition the current position that will be used to parse the literal
     * @return The first word contained in the text, if none could be found, then an empty string is
     * returned
     */
    private int scanStringLiteral(int startPosition) {

        int endIndex = startPosition;
        char startQuote = text.charAt(endIndex);

        for (endIndex++; endIndex < length; endIndex++) {

            char character = text.charAt(endIndex);

            if (character == startQuote) {
                endIndex++;

                // Verify the single quote is escaped with another single quote
                if ((startQuote == '\'') && (endIndex < length)) {
                    char nextCharacter = text.charAt(endIndex);

                    // The single quote is escaped, continue
                    if (nextCharacter == '\'') {
                        continue;
                    }
                }
                // Verify the double quote is escaped with backslash
                else if ((startQuote == '\"') && (endIndex - 2 > startPosition)) {
                    char previousCharacter = text.charAt(endIndex - 2);

                    // The double quote is escaped, continue
                    if (previousCharacter == '\\') {
                        continue;
                    }
                }

                // Reached the end of the string literal
                break;
            }
        }

        return endIndex;
    }

    /**
     * Manually sets the position of the cursor within the string. If the position is a negative
     * number, the position will be 0.
     *
     * @param position The new position of the cursor
     */
    public void setPosition(int position) {
        this.cursor = (position < 0) ? 0 : position;
    }

    /**
     * Removes the whitespace that starts the given text.
     *
     * @return The number of whitespace removed
     */
    public int skipLeadingWhitespace() {

        int count = 0;

        while (cursor < length) {

            char character = text.charAt(cursor);
            if (!Character.isWhitespace(character)) {
                break;
            }

            cursor++;
            count++;
        }

        return count;
    }

    /**
     * Determines whether the text starts with the given character. The case of the character is not
     * ignored.
     *
     * @param possibleCharacter The possible character at the current position
     * @return <code>true</code> if the text starts with the given character at the current position;
     * <code>false</code> otherwise
     */
    public boolean startsWith(char possibleCharacter) {
        return possibleCharacter == character();
    }

    /**
     * Tests whether the query starts with the specified prefix from the current position.
     *
     * @param prefix The prefix
     * @return <code>true</code> if the character sequence represented by the argument is a prefix of
     * the text; <code>false</code> otherwise
     */
    public boolean startsWith(CharSequence prefix) {
        return startsWith(prefix, cursor);
    }

    /**
     * Tests whether the substring of the query beginning at the specified index starts with the
     * specified prefix.
     *
     * @param prefix The prefix
     * @param startIndex Where to begin looking in the query
     * @return <code>true</code> if the character sequence represented by the
     * argument is a prefix of the substring of this object starting at index <code>startIndex</code>;
     * <code>false</code> otherwise
     */
    public boolean startsWith(CharSequence prefix, int startIndex) {

        int prefixLength = prefix.length();

        // Note: startIndex might be near -1 >>> 1
        if ((startIndex < 0) || (startIndex > length - prefixLength)) {
            return false;
        }

        int prefixIndex = 0;

        while (--prefixLength >= 0) {
            if (text.charAt(startIndex++) != prefix.charAt(prefixIndex++)) {
                return false;
            }
        }

        return true;
    }

    /**
     * Determines whether the character at the current position is one of the arithmetic operators:
     * { '+', '-', '*', '/' },
     *
     * @return <code>true</code> if the character at the current position is an arithmetic operator;
     * <code>false</code> otherwise
     */
    public boolean startsWithArithmeticOperator() {

        char character = text.charAt(cursor);

        return (character == '+') ||
               (character == '/') ||
               (character == '-') ||
               (character == '*');
    }

    /**
     * Determines if the text starts with a digit (<code>true</code>), an arithmetic term
     * (<code>false</code>) or anything else (<code>null</code>).
     *
     * @return <code>true</code> if the text starts with a digit (we'll assume it is a digit if the
     * text starts with a digit or an arithmetic sign followed by a digit), <code>false</code> if it
     * starts with an arithmetic term (we'll assume it is a digit followed by a non-digit character);
     * otherwise returns <code>null</code>
     */
    public Boolean startsWithDigit() {

        char character = character();

        // Check if the first character is either '+' or '-' and make sure it's not used for a numeric
        // value, which in that case, a numeric value will be created
        if (character == '-' ||
            character == '+') {

            moveForward(1);
            int count = skipLeadingWhitespace();
            character = character(cursor);
            moveBackward(count + 1);

            if (isDigit(character)) {
                return Boolean.TRUE;
            }

            if (character == '-' ||
                character == '+' ||
                character == '*' ||
                character == '/') {

                return null;
            }

            return Boolean.FALSE;
        }

        if (character == '.') {
            return isDigit(character(cursor + 1));
        }

        if (isDigit(character)) {
            return Boolean.TRUE;
        }

        return null;
    }

    /**
     * Determines whether the text at the current position start with the following identifier.
     *
     * @param identifier The JPQL identifier to match with the text at the current position
     * @return <code>true</code> if the text starts with the given text (case is ignored) and the
     * cursor is at the end of the text or is following by a word separator character; <code>false</code>
     * otherwise
     */
    public boolean startsWithIdentifier(CharSequence identifier) {
        return startsWithIdentifier(identifier, cursor);
    }

    /**
     * Determines whether the text at the current position start with the following identifier.
     *
     * @param identifier The JPQL identifier to match with the text at the current position
     * @param position The position to start matching the characters
     * @return <code>true</code> if the text starts with the given text (case is ignored) and the
     * cursor is at the end of the text or is following by a word separator character; <code>false</code>
     * otherwise
     */
    public boolean startsWithIdentifier(CharSequence identifier, int position) {

        int pc = identifier.length();

        // Note: offset might be near -1 >>> 1
        if ((position < 0) || (position > length - pc)) {
            return false;
        }

        int po = 0;
        int to = position;

        while (--pc >= 0) {

            char c1 = text.charAt(to++);
            char c2 = identifier.charAt(po++);

            if (c1 == c2) {
                continue;
            }

            // Handle testing
            // 1. "... GROUP    BY" and "GROUP BY"
            // 2. "... GROUP\nBY" and "GROUP BY"
            if (Character.isWhitespace(c1)) {

                if (Character.isWhitespace(c2)) {
                    continue;
                }

                if (to == length) {
                    return false;
                }

                pc++;
                po--;
                continue;
            }

            // If characters don't match but case may be ignored, try converting
            // both characters to uppercase. If the results match, then the
            // comparison scan should continue
            char u1 = Character.toUpperCase(c1);
            char u2 = Character.toUpperCase(c2);

            if (u1 != u2) {
                return false;
            }

            // Unfortunately, conversion to uppercase does not work properly for
            // the Georgian alphabet, which has strange rules about case
            // conversion. So we need to make one last check before exiting
            if (Character.toLowerCase(u1) != Character.toLowerCase(u2)) {
                return false;
            }
        }

        // End of the text
        if (to == length) {
            return true;
        }

        // Check to see if the next character is a word separator
        char character = text.charAt(to);
        return isWordSeparator(character);
    }

    /**
     * Determines whether the text starts with the given character. The case of the character is ignored.
     *
     * @param possibleCharacter The possible character at the current position
     * @return <code>true</code> if the text starts with the given character at the current position;
     * <code>false</code> otherwise
     */
    public boolean startsWithIgnoreCase(char possibleCharacter) {

        char character = character();

        return possibleCharacter == character ||
               possibleCharacter == Character.toUpperCase(character);
    }

    /**
     * Tests if the string starts with the specified prefix. The case of the character is ignored.
     *
     * @param prefix The prefix to test against
     * @return <code>true</code> if the character sequence represented by the argument is a prefix of
     * the character sequence represented by this string; <code>false</code> otherwise. Note also
     * that <code>true</code> will be returned if the argument is an empty string or is equal to this
     * <code>String</code> object as determined by the {@link #equals(Object)} method
     */
    public boolean startsWithIgnoreCase(CharSequence prefix) {
        return startsWithIgnoreCase(prefix, cursor);
    }

    /**
     * Tests if the string starts with the specified prefix. The case of the character is ignored.
     *
     * @param prefix The prefix to test against
     * @param offset Where to begin looking in this string
     * @return <code>true</code> if the character sequence represented by the argument is a prefix of
     * the character sequence represented by this string; <code>false</code> otherwise
     */
    public boolean startsWithIgnoreCase(CharSequence prefix, int offset) {

        int pc = prefix.length();

        // Note: offset might be near -1 >>> 1
        if ((offset < 0) || (offset > length - pc)) {
            return false;
        }

        int po = 0;
        int to = offset;

        while (--pc >= 0) {

            char c1 = text.charAt(to++);
            char c2 = prefix.charAt(po++);

            if (c1 == c2) {
                continue;
            }

            // If characters don't match but case may be ignored, try converting
            // both characters to uppercase. If the results match, then the
            // comparison scan should continue
            char u1 = Character.toUpperCase(c1);
            char u2 = Character.toUpperCase(c2);

            if (u1 != u2) {
                return false;
            }

            // Unfortunately, conversion to uppercase does not work properly for
            // the Georgian alphabet, which has strange rules about case
            // conversion. So we need to make one last check before exiting
            if (Character.toLowerCase(u1) != Character.toLowerCase(u2)) {
                return false;
            }
        }

        return true;
    }

    /**
     * Returns a substring that is within the current position of the cursor and the end of the text.
     *
     * @return The remain of the string starting at the current position
     */
    public String substring() {
        return substring(cursor);
    }

    /**
     * Returns a substring that is within the given position and the end of the text.
     *
     * @param startIndex The beginning of the substring, inclusive
     * @return The remain of the string starting at the given position
     */
    public String substring(int startIndex) {
        return substring(startIndex, length);
    }

    /**
     * Returns a substring that is within the given positions.
     *
     * @param startIndex The beginning of the substring, inclusive
     * @param endIndex The end of the substring, exclusive
     * @return The remain of the string that is within the given positions
     */
    public String substring(int startIndex, int endIndex) {
        return text.subSequence(startIndex, endIndex).toString();
    }

    @Override
    public String toString() {
        return isTail() ? ExpressionTools.EMPTY_STRING : substring();
    }

    /**
     * Calculates the number of whitespace that are in the query. The check starts at the current position.
     *
     * @return The count of consecutive whitespace found from the current position
     */
    public int whitespaceCount() {
        return whitespaceCount(cursor);
    }

    /**
     * Calculates the number of whitespace that are in the query. The check starts at the current position.
     *
     * @param position The position from where the scan starts
     * @return The count of consecutive whitespace found from the given position
     */
    public int whitespaceCount(int position) {

        for (int index = position; index < length; index++) {
            char character = text.charAt(index);

            if (!Character.isWhitespace(character)) {
                return index - position;
            }
        }

        return 0;
    }

    /**
     * Retrieves the first word starting at the current position.
     *
     * @return The first word contained in the text, if none could be found,
     * then an empty string is returned
     */
    public String word() {
        return substring(cursor, wordEndPosition());
    }

    /**
     * Returns the position a word would end based on the current cursor position. {@link #getWordType()}
     * can be used to determine the type of word that was scanned.
     *
     * @return The position where the current word ends
     * @see #word() WordParser.word()
     * @see WordType
     */
    public int wordEndPosition() {
        return wordEndPosition(cursor);
    }

    /**
     * Returns the position a word would end based on the given start position. {@link #getWordType()}
     * can be used to determine the type of word that was scanned.
     *
     * @param position The position to start scanning the text
     * @return The position where the current word ends
     * @see #word() WordParser.word()
     * @see WordType
     */
    public int wordEndPosition(int position) {

        if (position >= length) {
            wordType = WordType.UNDEFINED;
            return position;
        }

        char character = text.charAt(position);
        int endIndex = position + 1;
        wordType = WordType.WORD;

        // Parse a string literal
        if (ExpressionTools.isQuote(character)) {
            wordType = WordType.STRING_LITERAL;

            // The quote is the end quote
            if (position > 1) {
                character = character(position - 1);
                if (ExpressionTools.isQuote(character)) {
                    return endIndex;
                }
            }

            return scanStringLiteral(position);
        }

        // Parse an input parameter
        if (ExpressionTools.isParameter(character)) {
            wordType = WordType.INPUT_PARAMETER;

            for (; endIndex < length; endIndex++) {
                character = text.charAt(endIndex);

                // Special case for '!='
                if ((character == '!') && (endIndex + 1 < length)) {
                    character = text.charAt(endIndex + 1);

                    if (character == '=') {
                        break;
                    }

                    endIndex++;
                    continue;
                }

                if (isWordSeparator(character)) {
                    break;
                }
            }

            return endIndex;
        }

        // Parse an arithmetic symbol
        if (character == '/' ||
            character == '*' ||
            character == '+' ||
            character == '-') {

            return endIndex;
        }

        // Parse JDBC date
        if (character == '{') {
            // TODO
            return endIndex;
        }

        // Parse a numeric literal
        if (isDigit(character)) {

            wordType = WordType.NUMERIC_LITERAL;
            endIndex = scanNumericLiteral(position);

            // The word is a valid numeric literal, stop now,
            // otherwise scan for the entire word
            if (wordType == WordType.NUMERIC_LITERAL) {
                return endIndex;
            }
        }

        // '='
        else if (character == '=') {
            return endIndex;
        }

        // <, <>, <=
        else if (character == '<') {

            if (endIndex < length) {
                character = text.charAt(endIndex);

                if (character == '>' ||
                    character == '=') {

                    return endIndex + 1;
                }

                return endIndex;
            }
        }

        // >, >=, !=
        else if (character == '>' ||
                 character == '!') {

            // End of the text
            if (endIndex == length) {
                return endIndex;
            }

            // Scan the next character
            char nextCharacter = text.charAt(endIndex);

            if (nextCharacter == '=') {
                return ++endIndex;
            }

            if (character == '>') {
                return endIndex;
            }
        }

        // Done scanning
        else if (isWordSeparator(character)) {
            return --endIndex;
        }

        // Scan for an entire word
        for (int index = endIndex; index < length; index++) {
            character = text.charAt(index);

            // Special case for '!='
            if ((character == '!') && (endIndex + 1 < length)) {
                character = text.charAt(index + 1);

                if (character == '=') {
                    return endIndex;
                }

                endIndex++;
                continue;
            }

            if (Character.isWhitespace(character) ||
                isDelimiter(character) ||
                character == '>' ||
               character == '<' ||
               character == '/' ||
               character == '*' ||
               character == '-' ||
               character == '+' ||
               character == '=') {

                break;
            }

            // Continue to the next character
            endIndex++;
        }

        return endIndex;
    }

    /**
     * This enumeration determines the type of word that was scanned. It will be set by {@link
     * WordParser#word()}, {@link WordParser#wordEndPosition()}, {@link WordParser#wordEndPosition(int)}.
     */
    public enum WordType {

        /**
         * The word being scanned is an input parameter, it starts with either ':' or '?'.
         */
        INPUT_PARAMETER,

        /**
         * The word being scanned is a numeric literal (decimal or hexadecimal number).
         */
        NUMERIC_LITERAL,

        /**
         * The word being scanned is a string literal, it starts with either ''' or '"'.
         */
        STRING_LITERAL,

        /**
         * No word was scanned, this is usually set when the cursor is at the end of the text.
         */
        UNDEFINED,

        /**
         * The word being scanned anything else other than an input parameter, numeric literal or
         * string literal.
         */
        WORD
    }
}
