package tk.eclipse.plugin.jspeditor.editors;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IFile;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.internal.core.DefaultWorkingCopyOwner;
import org.eclipse.jdt.internal.ui.text.java.AbstractJavaCompletionProposal;
import org.eclipse.jdt.ui.text.java.CompletionProposalCollector;
import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.contentassist.CompletionProposal;
import org.eclipse.jface.text.contentassist.ContextInformation;
import org.eclipse.jface.text.contentassist.ContextInformationValidator;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.text.contentassist.IContextInformationValidator;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IFileEditorInput;
import tk.eclipse.plugin.htmleditor.HTMLPlugin;
import tk.eclipse.plugin.htmleditor.HTMLUtil;
/**
* Provides code completion for JSP directives.
*
* @author Naoki Takezoe
*/
public class JSPDirectiveAssistProcessor implements IContentAssistProcessor {
private Image tagImage;
private Image attrImage;
private Image valueImage;
private IFile file;
private static final String DIRECTIVES[] = {
"include", "page", "taglib"
};
private static final Map<String, String[]> ATTRIBUTES = new HashMap<String, String[]>();
static {
ATTRIBUTES.put("include", new String[]{"file"});
ATTRIBUTES.put("page", new String[]{"language","extends","import","session","buffer","autoFlush","isThreadSafe",
"info","errorPage","isErrorPage","contentType","pageEncoding"});
ATTRIBUTES.put("taglib", new String[]{"prefix","tagdir","uri"});
}
public JSPDirectiveAssistProcessor(){
tagImage = HTMLPlugin.getDefault().getImageRegistry().get(HTMLPlugin.ICON_TAG);
attrImage = HTMLPlugin.getDefault().getImageRegistry().get(HTMLPlugin.ICON_ATTR);
valueImage = HTMLPlugin.getDefault().getImageRegistry().get(HTMLPlugin.ICON_VALUE);
}
public void update(JSPSourceEditor editor){
IEditorInput input = editor.getEditorInput();
if(input instanceof IFileEditorInput){
this.file = ((IFileEditorInput)input).getFile();
}
}
public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
String text = viewer.getDocument().get().substring(0, offset);
int flag = 0;
StringBuffer sb = new StringBuffer();
String directive = "";
String attrName = "";
//String attrValue = "";
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
if(c=='<'){
directive = "";
flag = 1;
} else if(flag==1 && c=='%'){
flag = 2;
} else if(flag==2 && c=='@'){
flag = 3;
} else if(flag==3 && c=='%'){
sb.setLength(0);
flag = 0;
} else if(flag==3 && (c==' ' || c=='\t' || c=='\r' || c=='\n' || c=='=')){
if(directive.equals("")){
directive = sb.toString().trim();
} else {
attrName = sb.toString().trim();
if(!attrName.equals("")){
flag = 4;
}
}
sb.setLength(0);
} else if(flag==4 && c=='"'){
sb.append(c);
flag = 5;
} else if(flag==5 && c=='"'){
sb.setLength(0);
flag = 3;
} else if(flag==3 || flag==5){
sb.append(c);
}
}
String lastWord = sb.toString().trim();
if(directive.equals("")){
return getDirectives(lastWord, offset);
} else if(directive.equals("page") && attrName.equals("import") && lastWord.startsWith("\"")){
return getImportValues(lastWord, offset);
} else if(lastWord.startsWith("\"")){
return getAttributeValues(directive,attrName,lastWord,offset);
} else {
return getAttributes(directive, lastWord, offset);
}
}
/**
* Returns import completion proposals.
*/
private ICompletionProposal[] getImportValues(String lastWord, int offset){
try {
if(this.file != null){
IJavaProject project = JavaCore.create(file.getProject());
CompletionProposalCollector collector = new CompletionProposalCollector(project);
ICompilationUnit unit = HTMLUtil.getTemporaryCompilationUnit(project);
String matchString = lastWord.replaceFirst("^\"", "");
int lastIndex = matchString.lastIndexOf(',');
if(lastIndex >= 0){
//offset = offset + lastIndex;
matchString = matchString.substring(lastIndex + 1);
}
String value = "import " + matchString;
System.out.println(value); // TODO Debug
HTMLUtil.setContentsToCU(unit, value);
unit.codeComplete(value.length(), collector, DefaultWorkingCopyOwner.PRIMARY);
IJavaCompletionProposal[] proposals = collector.getJavaCompletionProposals();
List<ICompletionProposal> result = new ArrayList<ICompletionProposal>();
for(int i=0;i<proposals.length;i++){
if(proposals[i] instanceof AbstractJavaCompletionProposal){
AbstractJavaCompletionProposal proposal = (AbstractJavaCompletionProposal)proposals[i];
proposal.setReplacementOffset(offset - matchString.trim().length());
proposal.setReplacementLength(matchString.length());
proposal.setReplacementString(proposal.getReplacementString().replaceFirst(";$", ""));
proposal.setCursorPosition(proposal.getReplacementString().length());
result.add(proposal);
}
}
return result.toArray(new ICompletionProposal[result.size()]);
}
} catch(Exception ex){
HTMLPlugin.logException(ex);
}
return new ICompletionProposal[0];
}
/**
* Returns attribute value completion prosposals.
*/
private ICompletionProposal[] getAttributeValues(String directive,String attr,String lastWord,int offset){
List<String> values = new ArrayList<String>();
if(directive.equals("page")){
if(attr.equals("autoFlush") || attr.equals("session") ||
attr.equals("isThreadSafe") || attr.equals("isErrorPage")){
values.add("true");
values.add("false");
}
}
if(directive.equals("taglib")){
if(attr.equals("uri")){
Map<String, String> innerTLD = HTMLPlugin.getInnerTLD();
Iterator<String> ite = innerTLD.keySet().iterator();
while(ite.hasNext()){
values.add(ite.next());
}
IPreferenceStore store = HTMLPlugin.getDefault().getPreferenceStore();
String[] uri = store.getString(HTMLPlugin.PREF_TLD_URI).split("\n");
for(int i=0;i<uri.length;i++){
values.add(uri[i]);
}
}
}
lastWord = lastWord.substring(1);
List<ICompletionProposal> assistInfos = new ArrayList<ICompletionProposal>();
for(int i=0;i<values.size();i++){
String value = values.get(i);
if(value.startsWith(lastWord)){
assistInfos.add(new CompletionProposal(
value,
offset-lastWord.length(),
lastWord.length(),
value.length(),
valueImage,
value,
null,null));
}
}
return assistInfos.toArray(new ICompletionProposal[assistInfos.size()]);
}
/**
* Returns JSP direcive completion proposals.
*/
private ICompletionProposal[] getDirectives(String lastWord,int offset){
List<ICompletionProposal> assistInfos = new ArrayList<ICompletionProposal>();
for(int i=0;i<DIRECTIVES.length;i++){
String directive = DIRECTIVES[i];
if(directive.startsWith(lastWord)){
assistInfos.add(new CompletionProposal(
directive,
offset-lastWord.length(),
lastWord.length(),
directive.length(),
tagImage,
directive,
null,null));
}
}
return assistInfos.toArray(new ICompletionProposal[assistInfos.size()]);
}
/**
* Returns directive attribute completion proposals.
*/
private ICompletionProposal[] getAttributes(String directive,String lastWord,int offset){
String attrs[] = ATTRIBUTES.get(directive);
if(attrs==null){
return new ICompletionProposal[0];
}
List<ICompletionProposal> assistInfos = new ArrayList<ICompletionProposal>();
for(int i=0;i<attrs.length;i++){
String attrName = attrs[i];
String replace = attrName + "=\"\"";
if(attrName.startsWith(lastWord)){
assistInfos.add(new CompletionProposal(
replace,
offset-lastWord.length(),
lastWord.length(),
replace.length() - 1,
attrImage,
attrName,
null,null));
}
}
return assistInfos.toArray(new ICompletionProposal[assistInfos.size()]);
}
public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) {
ContextInformation[] info = new ContextInformation[0];
return info;
}
public char[] getCompletionProposalAutoActivationCharacters() {
return new char[0];
}
public char[] getContextInformationAutoActivationCharacters() {
return new char[0];
}
public IContextInformationValidator getContextInformationValidator() {
return new ContextInformationValidator(this);
}
public String getErrorMessage() {
return "Error";
}
}