/*
 * Copyright (c) 2006, 2020 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.tools;

import static org.eclipse.persistence.jpa.jpql.parser.Expression.BETWEEN;
import static org.eclipse.persistence.jpa.jpql.parser.Expression.DELETE_FROM;
import static org.eclipse.persistence.jpa.jpql.parser.Expression.IN;
import static org.eclipse.persistence.jpa.jpql.parser.Expression.INNER_JOIN;
import static org.eclipse.persistence.jpa.jpql.parser.Expression.INNER_JOIN_FETCH;
import static org.eclipse.persistence.jpa.jpql.parser.Expression.IS_EMPTY;
import static org.eclipse.persistence.jpa.jpql.parser.Expression.IS_NOT_EMPTY;
import static org.eclipse.persistence.jpa.jpql.parser.Expression.IS_NOT_NULL;
import static org.eclipse.persistence.jpa.jpql.parser.Expression.IS_NULL;
import static org.eclipse.persistence.jpa.jpql.parser.Expression.JOIN;
import static org.eclipse.persistence.jpa.jpql.parser.Expression.JOIN_FETCH;
import static org.eclipse.persistence.jpa.jpql.parser.Expression.LEFT_JOIN;
import static org.eclipse.persistence.jpa.jpql.parser.Expression.LEFT_JOIN_FETCH;
import static org.eclipse.persistence.jpa.jpql.parser.Expression.LEFT_OUTER_JOIN;
import static org.eclipse.persistence.jpa.jpql.parser.Expression.LEFT_OUTER_JOIN_FETCH;
import static org.eclipse.persistence.jpa.jpql.parser.Expression.MEMBER;
import static org.eclipse.persistence.jpa.jpql.parser.Expression.MEMBER_OF;
import static org.eclipse.persistence.jpa.jpql.parser.Expression.NOT_BETWEEN;
import static org.eclipse.persistence.jpa.jpql.parser.Expression.NOT_IN;
import static org.eclipse.persistence.jpa.jpql.parser.Expression.NOT_MEMBER;
import static org.eclipse.persistence.jpa.jpql.parser.Expression.NOT_MEMBER_OF;
import static org.eclipse.persistence.jpa.jpql.parser.Expression.SELECT;
import static org.eclipse.persistence.jpa.jpql.parser.Expression.UPDATE;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.persistence.jpa.jpql.ExpressionTools;
import org.eclipse.persistence.jpa.jpql.WordParser;
import org.eclipse.persistence.jpa.jpql.parser.IdentifierRole;
import org.eclipse.persistence.jpa.jpql.parser.JPQLGrammar;
import org.eclipse.persistence.jpa.jpql.tools.spi.IEntity;
import org.eclipse.persistence.jpa.jpql.tools.spi.IMapping;
import org.eclipse.persistence.jpa.jpql.tools.spi.IType;
import org.eclipse.persistence.jpa.jpql.tools.utility.XmlEscapeCharacterConverter;
import org.eclipse.persistence.jpa.jpql.tools.utility.iterable.SnapshotCloneIterable;

/**
 * The default implementation of {@link ContentAssistProposals} which stores the valid proposals.
 * <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
 * @since 2.3
 * @author Pascal Filion
 */
@SuppressWarnings("nls")
public final class DefaultContentAssistProposals implements ContentAssistProposals {

    /**
     * The prefix that is used to filter the list of class names.
     *
     * @since 2.5
     */
    private String classNamePrefix;

    /**
     * The class type helps to filter the various types of classes, i.e. anonymous, member, interface
     * are never allowed.
     *
     * @since 2.5
     */
    private ClassType classType;

    /**
     * TODO
     *
     * @since 2.5
     */
    private String columnNamePrefix;

    /**
     * The set of possible abstract schema types.
     */
    private Set<IEntity> entities;

    /**
     * TODO
     *
     * @since 2.5
     */
    private Map<IType, DefaultEnumProposals> enumProposals;

    /**
     * This extension can be used to provide additional support to JPQL content assist that is
     * outside the scope of providing proposals related to JPA metadata. It adds support for
     * providing suggestions related to class names, enum constants, table names, column names.
     *
     * @since 2.5
     */
    private ContentAssistExtension extension;

    /**
     * The set of possible identification variables.
     */
    private Set<String> identificationVariables;

    /**
     * The set of possible JPQL identifiers.
     */
    private Set<String> identifiers;

    /**
     * The {@link JPQLGrammar} that defines how the JPQL query was parsed.
     */
    private JPQLGrammar jpqlGrammar;

    /**
     * The set of possible {@link IMapping mappings}, which can be state fields, association fields
     * and/or collection fields.
     */
    private Set<IMapping> mappings;

    /**
     * The identification variables mapped to their abstract schema types.
     */
    private Map<String, IEntity> rangeIdentificationVariables;

    /**
     * TODO
     *
     * @since 2.5
     */
    private String tableName;

    /**
     * TODO
     *
     * @since 2.5
     */
    private String tableNamePrefix;

    /**
     * A JPQL identifier that is mapped to its longest counterpart.
     */
    private static final Map<String, String> LONGUEST_IDENTIFIERS = buildLonguestIdentifiers();

    /**
     * A JPQL identifier that is mapped to the list of counterparts used to find them in the query.
     */
    private static final Map<String, List<String>> ORDERED_IDENTIFIERS = buildOrderedIdentifiers();

    /**
     * Creates a new <code>DefaultContentAssistProposals</code>.
     *
     * @param jpqlGrammar The {@link JPQLGrammar} that defines how the JPQL query was parsed
     * @param extension This extension can be used to provide additional support to JPQL content
     * assist that is outside the scope of providing proposals related to JPA metadata. It adds
     * support for providing suggestions related to class names, enum constants, table names, column
     * names
     */
    public DefaultContentAssistProposals(JPQLGrammar jpqlGrammar, ContentAssistExtension extension) {
        super();
        initialize(jpqlGrammar, extension);
    }

    private static Map<String, String> buildLonguestIdentifiers() {

        Map<String, String> identifiers = new HashMap<String, String>();

        identifiers.put(IS_EMPTY,         IS_NOT_EMPTY);
        identifiers.put(IS_NULL,          IS_NOT_NULL);
        identifiers.put(IN,               NOT_IN);
        identifiers.put(BETWEEN,          NOT_BETWEEN);
        identifiers.put(MEMBER,           NOT_MEMBER_OF);
        identifiers.put(MEMBER_OF,        NOT_MEMBER_OF);
        identifiers.put(NOT_MEMBER,       NOT_MEMBER_OF);
        identifiers.put(JOIN,             LEFT_OUTER_JOIN_FETCH);
        identifiers.put(JOIN_FETCH,       LEFT_OUTER_JOIN_FETCH);
        identifiers.put(LEFT_JOIN,        LEFT_OUTER_JOIN_FETCH);
        identifiers.put(LEFT_JOIN_FETCH,  LEFT_OUTER_JOIN_FETCH);
        identifiers.put(LEFT_OUTER_JOIN,  LEFT_OUTER_JOIN_FETCH);
        identifiers.put(INNER_JOIN,       LEFT_OUTER_JOIN_FETCH);
        identifiers.put(INNER_JOIN_FETCH, LEFT_OUTER_JOIN_FETCH);

        identifiers.put(SELECT, DELETE_FROM);
        identifiers.put(UPDATE, DELETE_FROM);

        return identifiers;
    }

    private static Map<String, List<String>> buildOrderedIdentifiers() {

        Map<String, List<String>> identifiers = new HashMap<String, List<String>>();

        identifiers.put(IS_NOT_EMPTY, Collections.singletonList(IS_NOT_EMPTY));
        identifiers.put(IS_NOT_NULL,  Collections.singletonList(IS_NOT_NULL));
        identifiers.put(NOT_IN,       Collections.singletonList(NOT_IN));
        identifiers.put(NOT_BETWEEN,  Collections.singletonList(NOT_BETWEEN));

        List<String> members = new ArrayList<String>();
        members.add(MEMBER_OF);
        members.add(NOT_MEMBER);
        members.add(MEMBER);
        identifiers.put(NOT_MEMBER_OF, members);

        List<String> joins = new ArrayList<String>();
        joins.add(LEFT_OUTER_JOIN);
        joins.add(LEFT_JOIN_FETCH);
        joins.add(LEFT_JOIN);
        joins.add(INNER_JOIN_FETCH);
        joins.add(INNER_JOIN);
        joins.add(JOIN_FETCH);
        joins.add(JOIN);
        identifiers.put(LEFT_OUTER_JOIN_FETCH, joins);

        List<String> clauses = new ArrayList<String>();
        clauses.add(SELECT);
        clauses.add(UPDATE);
        identifiers.put(DELETE_FROM, clauses);

        return identifiers;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Iterable<IEntity> abstractSchemaTypes() {
        return new SnapshotCloneIterable<IEntity>(entities);
    }

    /**
     * Adds the given {@link IEntity} as a possible abstract schema type.
     *
     * @param abstractSchemaType The abstract schema type that is a valid proposal
     */
    public void addEntity(IEntity abstractSchemaType) {
        entities.add(abstractSchemaType);
    }

    /**
     * Adds the constants of the given enum constant as a valid proposal.
     *
     * @param enumType The {@link IType} of the enum type
     * @param enumConstant The enum constant to be added as a valid proposal
     *
     * @since 2.5
     */
    public void addEnumConstant(IType enumType, String enumConstant) {

        DefaultEnumProposals proposal = enumProposals.get(enumType);

        if (proposal == null) {
            proposal = new DefaultEnumProposals(enumType);
            enumProposals.put(enumType, proposal);
        }

        proposal.constants.add(enumConstant);
    }

    /**
     * Adds the given identification variable as a proposal.
     *
     * @param identificationVariable The identification variable that is a valid proposal
     */
    public void addIdentificationVariable(String identificationVariable) {
        identificationVariables.add(identificationVariable);
    }

    /**
     * Adds the given JPQL identifier as a proposal.
     *
     * @param identifier The JPQL identifier that is a valid proposal
     */
    public void addIdentifier(String identifier) {
        identifiers.add(identifier);
    }

    /**
     * Adds the given {@link IMapping mapping} (state field, association field or collection field)
     * as a valid proposal.
     *
     * @param mapping The {@link IMapping} of the state field, association field or collection field
     */
    public void addMapping(IMapping mapping) {
        mappings.add(mapping);
    }

    /**
     * Adds the given {@link IMapping mappings} (state fields, association fields or collection fields)
     * as valid proposals.
     *
     * @param mappings The {@link IMapping mappings} of the state fields, association fields or
     * collection fields
     */
    public void addMappings(Collection<IMapping> mappings) {
        this.mappings.addAll(mappings);
    }

    /**
     * Adds the given range identification variable that is mapping the given abstract schema type.
     *
     * @param identificationVariable The range identification variable mapping the abstract schema name
     * @param entity The abstract type name that identifies the type of the variable
     */
    public void addRangeIdentificationVariable(String identificationVariable, IEntity entity) {
        rangeIdentificationVariables.put(identificationVariable, entity);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Result buildEscapedQuery(String jpqlQuery, String proposal, int position, boolean insert) {

        Result result = buildQuery(jpqlQuery, proposal, position, insert);

        // Escape the JPQL query and adjust the position accordingly
        int[] positions = { result.position };
        result.jpqlQuery = ExpressionTools.escape(result.jpqlQuery, positions);
        result.position  = positions[0];

        return result;
    }

    /**
     * Calculates the start and end position for correctly inserting the proposal into the query.
     *
     * @param wordParser This parser can be used to retrieve words from the cursor position
     * @param proposal The proposal to be inserted into the query
     * @param insert Flag that determines if the proposal is simply inserted or it should also replace
     * the partial word following the position of the cursor
     * @return The start and end positions
     */
    public int[] buildPositions(WordParser wordParser, String proposal, boolean insert) {

        int index;
        String wordsToReplace = null;

        // Special case for arithmetic symbol (<, <=, =, <>, >, >=, +, -, *, /)
        if (wordParser.isArithmeticSymbol(proposal.charAt(0))) {
            int startIndex = wordParser.position();
            int endIndex   = startIndex;
            char character;

            // Now look for the start index
            do {
                character = wordParser.character(--startIndex);
            }
            while (wordParser.isArithmeticSymbol(character));

            // Now look for the end index
            do {
                character = wordParser.character(endIndex++);
            }
            while (wordParser.isArithmeticSymbol(character));

            // Increment the start index because the loop always decrements it by one before stopping
            // and decrement the end position because it's always incremented by one before stopping
            index = ++startIndex;
            wordsToReplace = wordParser.substring(index, --endIndex);
        }
        else {
            // Always try to find the start position using the longest JPQL identifier
            // if the proposal has more than one word
            wordsToReplace = longuestIdentifier(proposal);
            index = startPosition(wordParser, wordsToReplace);

            // Now check with the other possibilities
            if ((index == -1) && ORDERED_IDENTIFIERS.containsKey(wordsToReplace)) {
                for (String identifier : ORDERED_IDENTIFIERS.get(wordsToReplace)) {
                    wordsToReplace = identifier;
                    index = startPosition(wordParser, wordsToReplace);
                    if (index > -1) {
                        break;
                    }
                }
            }
        }

        // Now calculate the start position
        int startPosition;

        if (index > -1) {
            startPosition = index;
        }
        else {
            // Check for path expression (which uses a dot) and update the wordToReplace
            // and startPosition accordingly
            String partialWord = wordParser.partialWord();
            String entireWord = wordParser.entireWord();
            int dotIndex = -1;

            if (isMappingName(proposal)  ||
                isEnumConstant(proposal) ||
                isColumnName(proposal)) {

                dotIndex = partialWord.lastIndexOf('.');
            }

            if (dotIndex > 0) {
                wordsToReplace = entireWord.substring(dotIndex + 1);
                startPosition = wordParser.position() - partialWord.length() + dotIndex + 1;
            }
            else if (insert) {
                wordsToReplace = wordParser.word();
                startPosition = wordParser.position() - partialWord.length();
            }
            else {
                wordsToReplace = entireWord;
                startPosition = wordParser.position() - partialWord.length();
            }
        }

        // Now calculate the end position
        int length;

        // Only the partial word to the left of the cursor will be replaced and
        // the partial word to the right of the cursor will stay
        if (insert) {
            String partialWord = wordParser.substring(startPosition, wordParser.position());
            length = partialWord.length();
        }
        else if (proposal != wordsToReplace) {
            length = wordsToReplace.length();
        }
        else {
            index = 0;

            for (int charIndex = 0, wordLength = wordParser.length(), count = wordsToReplace.length();
                 startPosition + index < wordLength && charIndex < count;
                 index++, charIndex++) {

                // Find the end position by matching the proposal with the content of the query by
                // scanning every character starting at the start position, the end position will be
                // the position of the first character that is different or at the end of the query
                if (wordParser.character(startPosition + charIndex) !=
                     wordsToReplace.charAt(charIndex)) {

                    break;
                }
            }

            length = index;
        }

        return new int[] { startPosition, startPosition + length };
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Result buildQuery(String jpqlQuery, String proposal, int position, boolean insert) {

        // Nothing to replace
        if (ExpressionTools.stringIsEmpty(proposal)) {
            return new Result(jpqlQuery, position);
        }

        WordParser wordParser = new WordParser(jpqlQuery);
        wordParser.setPosition(position);

        // Calculate the start and end positions
        int[] positions = buildPositions(wordParser, proposal, insert);

        // Create the new query
        StringBuilder sb = new StringBuilder(jpqlQuery);
        sb.replace(positions[0], positions[1], proposal);

        // Return the result
        return new Result(sb.toString(), positions[0] + proposal.length());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ResultQuery buildXmlQuery(String jpqlQuery, String proposal, int position, boolean insert) {

        // Nothing to replace
        if (ExpressionTools.stringIsEmpty(proposal)) {
            return new Result(jpqlQuery, position);
        }

        int[] positions = { position };

        // First convert the escape characters into their unicode characters
        String query = XmlEscapeCharacterConverter.unescape(jpqlQuery, positions);

        // Calculate the start and end positions
        WordParser wordParser = new WordParser(query);
        wordParser.setPosition(positions[0]);
        int[] proposalPositions = buildPositions(wordParser, proposal, insert);

        // Escape the proposal
        proposal = XmlEscapeCharacterConverter.escape(proposal, new int[1]);

        // Adjust the positions so it's in the original JPQL query, which may contain escaped characters
        XmlEscapeCharacterConverter.reposition(jpqlQuery, proposalPositions);

        // Create the new JPQL query
        StringBuilder sb = new StringBuilder(jpqlQuery);
        sb.replace(proposalPositions[0], proposalPositions[1], proposal);

        // Return the result
        return new Result(sb.toString(), proposalPositions[0] + proposal.length());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Iterable<String> classNames() {
        if (classNamePrefix == null) {
            return Collections.emptyList();
        }
        return extension.classNames(classNamePrefix, classType);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Iterable<String> columnNames() {
        if (tableName == null) {
            return Collections.emptyList();
        }
        return extension.columnNames(tableName, columnNamePrefix);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Iterable<EnumProposals> enumConstant() {
        return new SnapshotCloneIterable<EnumProposals>(enumProposals.values());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public IEntity getAbstractSchemaType(String identificationVariable) {
        return rangeIdentificationVariables.get(identificationVariable);
    }

    /**
     * Returns the prefix that will be used to filter the list of possible class names.
     *
     * @return The prefix that is used to filter the list of class names or <code>null</code> if it
     * was not set for the cursor position within the JPQL query
     * @since 2.5
     */
    public String getClassNamePrefix() {
        return classNamePrefix;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ClassType getClassType() {
        return classType;
    }

    /**
     * Returns the prefix that will be used by {@link ContentAssistExtension} to filter the column
     * names if the table name is not <code>null</code>.
     *
     * @return The prefix that is used to filter the list of columns names, which is <code>null</code>
     * if it has not been set along with the table name
     * @since 2.5
     */
    public String getColumnNamePrefix() {
        return columnNamePrefix;
    }

    /**
     * Returns the {@link JPQLGrammar} that defines how the JPQL query was parsed.
     *
     * @return The {@link JPQLGrammar} that was used to parse this {@link org.eclipse.persistence.jpa.jpql.parser.Expression Expression}
     */
    public JPQLGrammar getGrammar() {
        return jpqlGrammar;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public IdentifierRole getIdentifierRole(String identifier) {
        return jpqlGrammar.getExpressionRegistry().getIdentifierRole(identifier);
    }

    /**
     * Returns the table name that will be used by {@link ContentAssistExtension} to retrieve the
     * column names.
     *
     * @return The name of the table for which its column names should be retrieve as possible proposals
     * @since 2.5
     */
    public String getTableName() {
        return tableName;
    }

    /**
     * Returns the prefix that will be used to filter the list of possible table names.
     *
     * @return The prefix that is used to filter the list of table names or <code>null</code> if it
     * was not set for the cursor position within the JPQL query
     * @since 2.5
     */
    public String getTableNamePrefix() {
        return tableNamePrefix;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean hasProposals() {
        return !mappings.isEmpty()                ||
               !entities.isEmpty()                ||
               !identifiers.isEmpty()             ||
               !enumProposals.isEmpty()           ||
               !identificationVariables.isEmpty() ||
                classNames().iterator().hasNext() ||
                tableNames().iterator().hasNext() ||
               columnNames().iterator().hasNext() ||
               !rangeIdentificationVariables.isEmpty();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Iterable<String> identificationVariables() {
        List<String> variables = new ArrayList<String>(identificationVariables.size() + rangeIdentificationVariables.size());
        variables.addAll(identificationVariables);
        variables.addAll(rangeIdentificationVariables.keySet());
        return new SnapshotCloneIterable<String>(variables);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Iterable<String> identifiers() {
        return new SnapshotCloneIterable<String>(identifiers);
    }

    protected void initialize(JPQLGrammar jpqlGrammar, ContentAssistExtension extension) {

        this.extension                    = extension;
        this.jpqlGrammar                  = jpqlGrammar;
        this.mappings                     = new HashSet<IMapping>();
        this.identifiers                  = new HashSet<String>();
        this.entities                     = new HashSet<IEntity>();
        this.identificationVariables      = new HashSet<String>();
        this.rangeIdentificationVariables = new HashMap<String, IEntity>();
        this.enumProposals                = new HashMap<IType, DefaultEnumProposals>();
    }


    /**
     * Determines whether the given proposal is a column name (which should be unqualified).
     *
     * @param proposal The proposal that is being inserted into the JPQL query
     * @return <code>true</code> if the given proposal is a column name; <code>false</code> otherwise
     * @since 2.5
     */
    public boolean isColumnName(String proposal) {

        for (String columName : columnNames()) {
            if (columName.equals(proposal)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Determines whether the given proposal is an enum constant name (which should be unqualified).
     *
     * @param proposal The proposal that is being inserted into the JPQL query
     * @return <code>true</code> if the given proposal is a unqualified enum constant name;
     * <code>false</code> otherwise
     * @since 2.5
     */
    public boolean isEnumConstant(String proposal) {

        for (EnumProposals enumProposal : enumProposals.values()) {
            for (String enumConstant : enumProposal.enumConstants()) {
                if (enumConstant.equals(proposal)) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * Determines whether the given proposal is a mapping name.
     *
     * @param proposal The proposal that is being inserted into the JPQL query
     * @return <code>true</code> if the given proposal is a mapping name; <code>false</code> otherwise
     * @since 2.5
     */
    public boolean isMappingName(String proposal) {

        for (IMapping mapping : mappings) {
            if (mapping.getName().equals(proposal)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Returns the longest possible JPQL identifier that is related to the given proposal if the
     * proposal is a JPQL identifier and contains multiple words. For instance, the longest form of
     * <code>JOIN</code> or <code>JOIN FETCH</code> is <code>LEFT OUTER JOIN FETCH</code>.
     *
     * @param proposal The proposal to retrieve its longest form if one is associated with it
     * @return Either the given proposal if it's not a JPQL identifier or it does not have a longer
     * form or the longest version of the JPQL identifier
     */
    public String longuestIdentifier(String proposal) {
        return LONGUEST_IDENTIFIERS.containsKey(proposal) ? LONGUEST_IDENTIFIERS.get(proposal) : proposal;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Iterable<IMapping> mappings() {
        return new SnapshotCloneIterable<IMapping>(mappings);
    }

    /**
     * Removes the given JPQL identifier.
     *
     * @param identifier The identifier that was added but actually needs to be removed
     */
    protected void removeIdentifier(String identifier) {
        identifiers.remove(identifier);
    }

    /**
     * Adds the given prefix that will be used to filter the list of possible class names.
     *
     * @param prefix The prefix that is used to filter the list of class names
     * @param classType Determines how to filter the various types of classes
     * @since 2.5
     */
    public void setClassNamePrefix(String prefix, ClassType classType) {
        this.classNamePrefix = prefix;
        this.classType = classType;
    }

    /**
     * Sets the table name and a prefix that will be used to filter the names of the table's columns.
     *
     * @param tableName The name of the table for which its column names should be retrieve as
     * possible proposals
     * @param prefix The prefix that is used to filter the list of columns names, which is never
     * <code>null</code> but can be an empty string
     * @since 2.5
     */
    public void setTableName(String tableName, String prefix) {
        this.tableName = tableName;
        this.columnNamePrefix = prefix;
    }

    /**
     * Adds the given prefix that will be used to filter the list of possible columns names.
     *
     * @param tableNamePrefix The prefix that is used to filter the list of columns names
     * @since 2.5
     */
    public void setTableNamePrefix(String tableNamePrefix) {
        this.tableNamePrefix = tableNamePrefix;
    }

    public int startPosition(WordParser wordParser, String proposal) {

        int index = wordParser.position();
        int maxMoveLength = proposal.length();

        while (index >= 0 && maxMoveLength > 0) {
            if (wordParser.startsWithIgnoreCase(proposal, index)) {
                return index;
            }
            index--;
            maxMoveLength--;
        }

        return -1;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Iterable<String> tableNames() {
        if (tableNamePrefix == null) {
            return Collections.emptyList();
        }
        return extension.tableNames(tableNamePrefix);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString() {

        StringBuilder sb = new StringBuilder();

        // JPQL identifiers
        if (!identifiers.isEmpty()) {
            sb.append(identifiers);
        }

        // Entity names
        if (!entities.isEmpty()) {
            if (sb.length() > 0) {
                sb.append(", ");
            }
            sb.append(entities);
        }

        // Identification variables
        if (!identificationVariables.isEmpty()) {
            if (sb.length() > 0) {
                sb.append(", ");
            }
            sb.append(identificationVariables);
        }

        // Range identification variables
        if (!rangeIdentificationVariables.isEmpty()) {
            if (sb.length() > 0) {
                sb.append(", ");
            }
            sb.append(rangeIdentificationVariables);
        }

        // Mappings
        if (!mappings.isEmpty()) {
            if (sb.length() > 0) {
                sb.append(", ");
            }
            sb.append(mappings);
        }

        // Class names
        for (String className : classNames()) {
            if (sb.length() > 0) {
                sb.append(", ");
            }
            sb.append(className);
        }

        // Table names
        for (String tableName : tableNames()) {
            if (sb.length() > 0) {
                sb.append(", ");
            }
            sb.append(tableName);
        }

        // Column names
        for (String columnName : columnNames()) {
            if (sb.length() > 0) {
                sb.append(", ");
            }
            sb.append(columnName);
        }

        // Enum constant names
        for (EnumProposals enumProposals : enumConstant()) {
            for (String enumConstant : enumProposals.enumConstants()) {
                if (sb.length() > 0) {
                    sb.append(", ");
                }
                sb.append(enumConstant);
            }
        }

        // No proposals
        if (sb.length() == 0) {
            sb.append("<No Default Proposals>");
        }

        return sb.toString();
    }

    private static final class DefaultEnumProposals implements EnumProposals {

        private Set<String> constants;
        private IType enumType;

        DefaultEnumProposals(IType enumType) {
            super();
            this.enumType  = enumType;
            this.constants = new HashSet<String>();
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public Iterable<String> enumConstants() {
            return new SnapshotCloneIterable<String>(constants);
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public IType enumType() {
            return enumType;
        }
    }

    /**
     * This contains the result of inserting a proposal into a JPQL query at a given position.
     *
     * @see ContentAssistProposals#buildEscapedQuery(String, String, int, boolean)
     * @see ContentAssistProposals#buildQuery(String, String, int, boolean)
     */
    private static final class Result implements ResultQuery {

        /**
         * The new JPQL query after insertion of the proposal.
         */
        private String jpqlQuery;

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

        /**
         * Creates a new <code>Result</code>.
         *
         * @param jpqlQuery The new JPQL query after insertion of the proposal
         * @param position The position of the cursor within the new query
         */
        public Result(String jpqlQuery, int position) {
            super();
            this.jpqlQuery = jpqlQuery;
            this.position  = position;
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public int getPosition() {
            return position;
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public String getQuery() {
            return jpqlQuery;
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append("Query=[").append(jpqlQuery);
            sb.append("], position=").append(position);
            return sb.toString();
        }
    }
}
