1 /***********************************************************************************************************************************
2 * Copyright (c) 2000, 2004 IBM Corporation and others. All rights reserved. This program and the accompanying materials are made
3 * available under the terms of the Common Public License v1.0 which accompanies this distribution, and is available at
4 * http://www.eclipse.org/legal/cpl-v10.html
6 * Contributors: IBM Corporation - initial API and implementation
7 **********************************************************************************************************************************/
8 package net.sourceforge.phpeclipse.wiki.editor;
10 import java.util.ArrayList;
11 import java.util.Arrays;
12 import java.util.Collections;
13 import java.util.Comparator;
14 import java.util.List;
16 import net.sourceforge.phpeclipse.wiki.editor.model.WikipediaSection;
17 import net.sourceforge.phpeclipse.wiki.editor.model.WikipediaText;
18 import net.sourceforge.phpeclipse.wiki.sql.WikipediaDB;
20 import org.eclipse.jface.resource.ImageDescriptor;
21 import org.eclipse.jface.resource.ImageRegistry;
22 import org.eclipse.jface.text.BadLocationException;
23 import org.eclipse.jface.text.IDocument;
24 import org.eclipse.jface.text.IRegion;
25 import org.eclipse.jface.text.ITextSelection;
26 import org.eclipse.jface.text.ITextViewer;
27 import org.eclipse.jface.text.Region;
28 import org.eclipse.jface.text.TextUtilities;
29 import org.eclipse.jface.text.contentassist.CompletionProposal;
30 import org.eclipse.jface.text.contentassist.ICompletionProposal;
31 import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
32 import org.eclipse.jface.text.contentassist.IContextInformation;
33 import org.eclipse.jface.text.contentassist.IContextInformationValidator;
34 import org.eclipse.jface.text.templates.DocumentTemplateContext;
35 import org.eclipse.jface.text.templates.Template;
36 import org.eclipse.jface.text.templates.TemplateContext;
37 import org.eclipse.jface.text.templates.TemplateContextType;
38 import org.eclipse.jface.text.templates.TemplateException;
39 import org.eclipse.jface.text.templates.TemplateProposal;
40 import org.eclipse.swt.graphics.Image;
42 public class WikiCompletionProcessor implements IContentAssistProcessor {
44 static class StringComparator implements Comparator {
45 public int compare(Object o1, Object o2) {
46 String s1 = (String) o1;
47 String s2 = (String) o2;
48 return s1.compareTo(s2);
49 // return s1.toUpperCase().compareTo(s2.toUpperCase());
52 public boolean equals(Object o) {
53 // String s = (String) o;
54 return compare(this, o) == 0;
58 private static final String TEMPLATE_ICON = "icons/template.gif";
60 // private static TreeSet TITLES_SET = null;
61 private static final String WIKIPEDIA_TEMPLATE_CTX = "net.sourceforge.phpeclipse.wiki.editor.templates";
63 private static final class ProposalComparator implements Comparator {
64 public int compare(Object o1, Object o2) {
65 return ((TemplateProposal) o2).getRelevance() - ((TemplateProposal) o1).getRelevance();
69 private static final Comparator fgProposalComparator = new ProposalComparator();
71 private final WikiEditor fEditor;
73 public WikiCompletionProcessor(WikiEditor editor) {
77 // private static void readFile(String filename) {
78 // TITLES_SET = new TreeSet(new StringComparator());
79 // FileReader fileReader;
81 // fileReader = new FileReader(filename);
82 // BufferedReader bufferedReader = new BufferedReader(fileReader);
83 // LineTokenizer lineTokenizer = new LineTokenizer();
84 // StringBuffer line = new StringBuffer(1024);
85 // while (lineTokenizer.getToken(line, bufferedReader)) {
86 // if (line.length() == 0) {
87 // // this should not happen
89 // TITLES_SET.add(line.toString());
90 // line.delete(0, line.length());
93 // bufferedReader.close();
94 // } catch (FileNotFoundException e) {
96 // // TODO DialogBox which asks the user if she/he likes to build new index?
97 // } catch (IOException e) {
98 // // TODO Auto-generated catch block
99 // e.printStackTrace();
103 public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
104 WikipediaSection section = fEditor.getSection();
108 ITextSelection selection = (ITextSelection) viewer.getSelectionProvider().getSelection();
109 // adjust offset to start of normalized selection:
110 if (selection.getOffset() != offset)
111 offset = selection.getOffset();
113 String prefix = getPrefix(viewer, offset);
114 Region region = new Region(offset - prefix.length(), prefix.length() + selection.getLength());
115 List result = new ArrayList();
117 if (prefix.length() > 2) {
118 if (WikiEditorPlugin.fWikiDB == null) {
120 WikiEditorPlugin.fWikiDB = new WikipediaDB();
121 } catch (Exception ex1) {
122 // ex1.printStackTrace(); // could not start db
123 WikiEditorPlugin.fWikiDB = null;
126 if (WikiEditorPlugin.fWikiDB != null) {
128 ArrayList list = WikiEditorPlugin.fWikiDB.queryPrefix(prefix);
129 ICompletionProposal[] titleProposals = computeTitleProposals(list, region, viewer);
130 result.addAll(Arrays.asList(titleProposals));
131 } catch (Exception ex1) {
132 // ex1.printStackTrace(); // could not start db
133 WikiEditorPlugin.fWikiDB = null;
137 // if (TITLES_SET==null) {
138 // TODO make this a preference
139 // readFile("c:\\temp\\titles.txt");
141 // if (TITLES_SET.size()>0 && prefix.length()>3) {
142 // SortedSet subSet = TITLES_SET.subSet(prefix, prefix + '\255');
143 // Iterator iter = subSet.iterator();
146 // int maxProposals = 200;
147 // while (iter.hasNext()) {
148 // title = (String) iter.next();
149 // if (title.toLowerCase().startsWith(prefix.toLowerCase())) {
150 // result.add(title);
152 // if (maxProposals-- < 0) {
158 ICompletionProposal[] templateProposals = computeTemplateProposals(viewer, region, section, prefix);
159 // ICompletionProposal[] ingredientProposals = computeIngredientsProposals(viewer, region, recipe, prefix);
160 // ICompletionProposal[] titleProposals = computeTitleProposals(viewer, region, recipe, prefix);
162 // result.addAll(Arrays.asList(ingredientProposals));
163 result.addAll(Arrays.asList(templateProposals));
164 // result.addAll(Arrays.asList(titleProposals));
166 return (ICompletionProposal[]) result.toArray(new ICompletionProposal[result.size()]);
169 private ICompletionProposal[] computeTitleProposals(ArrayList list, IRegion region, ITextViewer viewer) {
170 ICompletionProposal[] arr = new ICompletionProposal[list.size()];
171 // String lineDelimiter = TextUtilities.getDefaultLineDelimiter(viewer.getDocument());
173 for (int i = 0; i < arr.length; i++) {
174 temp = (String) list.get(i);
175 arr[i] = new CompletionProposal(temp, region.getOffset(), region.getLength(), region.getOffset() + temp.length(), null, temp,
181 private TemplateContextType getContextType(WikipediaSection section, int offset) {
182 return WikiEditorPlugin.getDefault().getContextTypeRegistry().getContextType(WIKIPEDIA_TEMPLATE_CTX);
186 * Creates a concrete template context for the given region in the document. This involves finding out which context fType is
187 * valid at the given location, and then creating a context of this fType. The default implementation returns a
188 * <code>DocumentTemplateContext</code> for the context fType at the given location.
191 * the viewer for which the context is created
193 * the region into <code>document</code> for which the context is created
194 * @return a template context that can handle template insertion at the given location, or <code>null</code>
196 private TemplateContext createContext(ITextViewer viewer, IRegion region, WikipediaSection recipe) {
197 TemplateContextType contextType = getContextType(recipe, region.getOffset());
198 if (contextType != null) {
199 IDocument document = viewer.getDocument();
200 return new DocumentTemplateContext(contextType, document, region.getOffset(), region.getLength());
205 private ICompletionProposal[] computeTemplateProposals(ITextViewer viewer, IRegion region, WikipediaSection recipe, String prefix) {
206 TemplateContext context = createContext(viewer, region, recipe);
208 return new ICompletionProposal[0];
210 ITextSelection selection = (ITextSelection) viewer.getSelectionProvider().getSelection();
211 context.setVariable("selection", selection.getText()); // name of the selection variables {line, word}_selection
213 String id = context.getContextType().getId();
214 Template[] templates = WikiEditorPlugin.getDefault().getTemplateStore().getTemplates(id);
216 List matches = new ArrayList();
217 for (int i = 0; i < templates.length; i++) {
218 Template template = templates[i];
220 context.getContextType().validate(template.getPattern());
221 } catch (TemplateException e) {
224 // int relevance = getRelevance(template, prefix);
225 // if (relevance > 0) {
226 matches.add(new TemplateProposal(template, context, region, getImage(template), 1));
230 Collections.sort(matches, fgProposalComparator);
232 return (ICompletionProposal[]) matches.toArray(new ICompletionProposal[matches.size()]);
236 * Returns the relevance of a template given a prefix. The default implementation returns a number greater than zero if the
237 * template name starts with the prefix, and zero otherwise.
240 * the template to compute the relevance for
242 * the prefix after which content assist was requested
243 * @return the relevance of <code>template</code>
244 * @see #getPrefix(ITextViewer, int)
246 private int getRelevance(Template template, String prefix) {
247 if (template.getName().startsWith(prefix))
252 private String getPrefix(ITextViewer viewer, int offset) {
254 IDocument document = viewer.getDocument();
255 if (i > document.getLength())
260 char ch = document.getChar(i - 1);
261 if (!Character.isLetterOrDigit(ch) && (ch != ':') && (ch != '_'))
266 return document.get(i, offset - i);
267 } catch (BadLocationException e) {
273 * Always return the default image.
275 private Image getImage(Template template) {
276 ImageRegistry registry = WikiEditorPlugin.getDefault().getImageRegistry();
277 Image image = registry.get(TEMPLATE_ICON);
279 ImageDescriptor desc = WikiEditorPlugin.imageDescriptorFromPlugin("net.sourceforge.phpeclipse.wiki.editor", TEMPLATE_ICON);
280 registry.put(TEMPLATE_ICON, desc);
281 image = registry.get(TEMPLATE_ICON);
286 public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) {
290 public char[] getCompletionProposalAutoActivationCharacters() {
294 public char[] getContextInformationAutoActivationCharacters() {
298 public String getErrorMessage() {
302 public IContextInformationValidator getContextInformationValidator() {