/* * 12/21/2008 * * AbstractCompletionProvider.java - Base class for completion providers. * * This library is distributed under a modified BSD license. See the included * AutoComplete.License.txt file for details. */ package org.fife.ui.autocomplete; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import javax.swing.text.JTextComponent; /** * A base class for completion providers. {@link Completion}s are kept in * a sorted list. To get the list of completions that match a given input, * a binary search is done to find the first matching completion, then all * succeeding completions that also match are also returned. * * @author Robert Futrell * @version 1.0 */ public abstract class AbstractCompletionProvider extends CompletionProviderBase { /** * The completions this provider is aware of. Subclasses should ensure * that this list is sorted alphabetically (case-insensitively). */ protected List completions; /** * Compares a {@link Completion} against a String. */ protected CaseInsensitiveComparator comparator; /** * Constructor. */ public AbstractCompletionProvider() { comparator = new CaseInsensitiveComparator(); clearParameterizedCompletionParams(); completions = new ArrayList(); } /** * Adds a single completion to this provider. If you are adding multiple * completions to this provider, for efficiency reasons please consider * using {@link #addCompletions(List)} instead. * * @param c The completion to add. * @throws IllegalArgumentException If the completion's provider isn't * this CompletionProvider. * @see #addCompletions(List) * @see #removeCompletion(Completion) * @see #clear() */ public void addCompletion(Completion c) { checkProviderAndAdd(c); Collections.sort(completions); } /** * Adds {@link Completion}s to this provider. * * @param completions The completions to add. This cannot be * null. * @throws IllegalArgumentException If a completion's provider isn't * this CompletionProvider. * @see #addCompletion(Completion) * @see #removeCompletion(Completion) * @see #clear() */ public void addCompletions(List completions) { //this.completions.addAll(completions); for (Completion c : completions) { checkProviderAndAdd(c); } Collections.sort(this.completions); } /** * Adds simple completions for a list of words. * * @param words The words. * @see BasicCompletion */ protected void addWordCompletions(String[] words) { int count = words==null ? 0 : words.length; for (int i=0; iCompletionProvider, if there is one. * * @see #addCompletion(Completion) * @see #addCompletions(List) * @see #removeCompletion(Completion) */ public void clear() { completions.clear(); } /** * Returns a list of Completions in this provider with the * specified input text. * * @param inputText The input text to search for. * @return A list of {@link Completion}s, or null if there * are no matching Completions. */ @SuppressWarnings("unchecked") public List getCompletionByInputText(String inputText) { // Find any entry that matches this input text (there may be > 1). int end = Collections.binarySearch(completions, inputText, comparator); if (end<0) { return null; } // There might be multiple entries with the same input text. int start = end; while (start>0 && comparator.compare(completions.get(start-1), inputText)==0) { start--; } int count = completions.size(); while (++end getCompletionsImpl(JTextComponent comp) { List retVal = new ArrayList(); String text = getAlreadyEnteredText(comp); if (text!=null) { int index = Collections.binarySearch(completions, text, comparator); if (index<0) { // No exact match index = -index - 1; } else { // If there are several overloads for the function being // completed, Collections.binarySearch() will return the index // of one of those overloads, but we must return all of them, // so search backward until we find the first one. int pos = index - 1; while (pos>0 && comparator.compare(completions.get(pos), text)==0) { retVal.add(completions.get(pos)); pos--; } } while (indextrue if this provider contained the specified * completion. * @see #clear() * @see #addCompletion(Completion) * @see #addCompletions(List) */ public boolean removeCompletion(Completion c) { // Don't just call completions.remove(c) as it'll be a linear search. int index = Collections.binarySearch(completions, c); if (index<0) { return false; } completions.remove(index); return true; } /** * A comparator that compares the input text of a {@link Completion} * against a String lexicographically, ignoring case. */ @SuppressWarnings("rawtypes") public static class CaseInsensitiveComparator implements Comparator, Serializable { @Override public int compare(Object o1, Object o2) { String s1 = o1 instanceof String ? (String)o1 : ((Completion)o1).getInputText(); String s2 = o2 instanceof String ? (String)o2 : ((Completion)o2).getInputText(); return String.CASE_INSENSITIVE_ORDER.compare(s1, s2); } } }