/*******************************************************************************
* Copyright (c) 2008 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is made available under the terms of the
* Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.smooks.contentassist;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.ListIterator;
import org.eclipse.core.resources.IProject;
import org.eclipse.jface.fieldassist.IContentProposal;
import org.eclipse.jface.fieldassist.IContentProposalProvider;
import org.eclipse.swt.graphics.Image;
/**
* @author Dart
*
*/
public class TypeContentProposalProvider extends TypePackageCompletionProcessor implements
IContentProposalProvider {
public static final char F_DOT = '.';
private IProject fProject;
private int fTypeScope;
private ArrayList<Object> fInitialContentProposals;
private String fInitialContent;
private Comparator<Object> fComparator;
/**
*
*/
public TypeContentProposalProvider(IProject project, int scope) {
fProject = project;
fTypeScope = scope;
fComparator = new TypeComparator();
reset();
}
/**
* TypeComparator
*
*/
private static class TypeComparator implements Comparator<Object> {
/**
*
*/
public TypeComparator() {
// NO-OP
}
/*
* (non-Javadoc)
*
* @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
*/
public int compare(Object arg0, Object arg1) {
String proposalSortKey1 = ((IContentProposal) arg0).getLabel();
String proposalSortKey2 = ((IContentProposal) arg1).getLabel();
return proposalSortKey1.compareToIgnoreCase(proposalSortKey2);
}
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.jface.fieldassist.IContentProposalProvider#getProposals(java
* .lang.String, int)
*/
public IContentProposal[] getProposals(String contents, int position) {
// Generate a list of proposals based on the current contents
ArrayList<Object> currentContentProposals = null;
// Determine method to obtain proposals based on current field contents
if (position == 0) {
// If the document offset is at the 0 position (i.e. no input
// entered),
// do not perform content assist. The operation is too expensive
// because all classes and interfaces (depending on the specified
// scope)
// will need to be resolved as proposals
currentContentProposals = null;
} else if ((fInitialContentProposals == null) || (contents.length() < fInitialContent.length())
|| (endsWithDot(contents))) {
// Generate new proposals if the content assist session was just
// started
// Or generate new proposals if the current contents of the field
// is less than the initial contents of the field used to
// generate the original proposals; thus, widening the search
// scope. This can occur when the user types backspace
// Or generate new proposals if the current contents ends with a
// dot
currentContentProposals = generateContentProposals(contents);
} else {
// Filter existing proposals from a prevous search; thus, narrowing
// the search scope. This can occur when the user types additional
// characters in the field causing new characters to be appended to
// the initial field contents
currentContentProposals = filterContentProposals(contents);
}
return convertResultsToSortedProposals(currentContentProposals);
}
/**
*
*/
public void reset() {
fInitialContentProposals = null;
}
/*
* (non-Javadoc)
*
* @seeorg.eclipse.pde.internal.ui.editor.contentassist.
* TypePackageCompletionProcessor
* #addProposalToCollection(java.util.Collection, int, int,
* java.lang.String, java.lang.String, org.eclipse.swt.graphics.Image)
*/
protected void addProposalToCollection(Collection<Object> collection, int startOffset, int length, String label,
String content, Image image) {
// Create content proposals for field assist
// start offset and length not required
IContentProposal proposal = new TypeContentProposal(label, content, null, image);
// Add the proposal to the list of proposals
collection.add(proposal);
}
/**
* @param string
* @return
*/
private boolean endsWithDot(String string) {
int index = string.lastIndexOf(F_DOT);
if ((index + 1) == string.length()) {
return true;
}
return false;
}
/**
* @param currentContent
* @return
*/
private ArrayList<Object> generateContentProposals(String currentContent) {
fInitialContentProposals = new ArrayList<Object>();
// Store the initial field contents to determine if we need to
// widen the scope later
fInitialContent = currentContent;
generateTypePackageProposals(currentContent, fProject, fInitialContentProposals, 0, fTypeScope, true);
return fInitialContentProposals;
}
/**
* @param list
* @return
*/
private IContentProposal[] convertResultsToSortedProposals(ArrayList<Object> list) {
IContentProposal[] proposals = null;
if ((list != null) && (list.size() != 0)) {
// Convert the results array list into an array of completion
// proposals
proposals = (IContentProposal[]) list.toArray(new IContentProposal[list.size()]);
// Sort the proposals alphabetically
Arrays.sort(proposals, fComparator);
} else {
proposals = new IContentProposal[0];
}
return proposals;
}
/**
* @param currentContent
* @return
*/
private ArrayList<Object> filterContentProposals(String currentContent) {
String lowerCaseCurrentContent = currentContent.toLowerCase();
ListIterator<Object> iterator = fInitialContentProposals.listIterator();
// Maintain a list of filtered search results
ArrayList<Object> filteredContentProposals = new ArrayList<Object>();
// Iterate over the initial search results
while (iterator.hasNext()) {
Object object = iterator.next();
IContentProposal proposal = (IContentProposal) object;
String compareString = null;
if (lowerCaseCurrentContent.indexOf(F_DOT) == -1) {
// Use only the type name
compareString = proposal.getLabel().toLowerCase();
} else {
// Use the fully qualified type name
compareString = proposal.getContent().toLowerCase();
}
// Filter out any proposal not matching the current contents
// except for the edge case where the proposal is identical to the
// current contents
if (compareString.startsWith(lowerCaseCurrentContent, 0)) {
filteredContentProposals.add(proposal);
}
}
return filteredContentProposals;
}
}