KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ant > internal > ui > editor > AntEditorCompletionProcessor


1 /*******************************************************************************
2  * Copyright (c) 2002, 2006 GEBIT Gesellschaft fuer EDV-Beratung
3  * und Informatik-Technologien mbH,
4  * Berlin, Duesseldorf, Frankfurt (Germany) and others.
5  * All rights reserved. This program and the accompanying materials
6  * are made available under the terms of the Eclipse Public License v1.0
7  * which accompanies this distribution, and is available at
8  * http://www.eclipse.org/legal/epl-v10.html
9  *
10  * Contributors:
11  * GEBIT Gesellschaft fuer EDV-Beratung und Informatik-Technologien mbH - initial API and implementation
12  * IBM Corporation - bug fixes
13  * John-Mason P. Shackelford (john-mason.shackelford@pearson.com) - bug 49383, 56299, 59024
14  * Brock Janiczak (brockj_eclipse@ihug.com.au ) - bug 78028, 78030
15  *******************************************************************************/

16
17 package org.eclipse.ant.internal.ui.editor;
18
19 import java.io.File JavaDoc;
20 import java.io.IOException JavaDoc;
21 import java.io.InputStream JavaDoc;
22 import java.io.InputStreamReader JavaDoc;
23 import java.io.Reader JavaDoc;
24 import java.lang.reflect.InvocationTargetException JavaDoc;
25 import java.util.ArrayList JavaDoc;
26 import java.util.Arrays JavaDoc;
27 import java.util.Collections JavaDoc;
28 import java.util.Comparator JavaDoc;
29 import java.util.Enumeration JavaDoc;
30 import java.util.HashMap JavaDoc;
31 import java.util.Iterator JavaDoc;
32 import java.util.List JavaDoc;
33 import java.util.Map JavaDoc;
34 import java.util.Set JavaDoc;
35
36 import org.apache.tools.ant.BuildException;
37 import org.apache.tools.ant.ComponentHelper;
38 import org.apache.tools.ant.IntrospectionHelper;
39 import org.apache.tools.ant.Project;
40 import org.apache.tools.ant.Target;
41 import org.apache.tools.ant.taskdefs.MacroDef;
42 import org.apache.tools.ant.taskdefs.MacroInstance;
43 import org.apache.tools.ant.types.EnumeratedAttribute;
44 import org.apache.tools.ant.types.Reference;
45 import org.eclipse.ant.internal.ui.AntUIImages;
46 import org.eclipse.ant.internal.ui.AntUIPlugin;
47 import org.eclipse.ant.internal.ui.IAntUIConstants;
48 import org.eclipse.ant.internal.ui.dtd.IAttribute;
49 import org.eclipse.ant.internal.ui.dtd.IDfm;
50 import org.eclipse.ant.internal.ui.dtd.IElement;
51 import org.eclipse.ant.internal.ui.dtd.ISchema;
52 import org.eclipse.ant.internal.ui.dtd.ParseError;
53 import org.eclipse.ant.internal.ui.dtd.Parser;
54 import org.eclipse.ant.internal.ui.editor.templates.AntContext;
55 import org.eclipse.ant.internal.ui.editor.templates.AntTemplateAccess;
56 import org.eclipse.ant.internal.ui.editor.templates.AntTemplateInformationControlCreator;
57 import org.eclipse.ant.internal.ui.editor.templates.AntTemplateProposal;
58 import org.eclipse.ant.internal.ui.editor.templates.BuildFileContextType;
59 import org.eclipse.ant.internal.ui.editor.templates.TargetContextType;
60 import org.eclipse.ant.internal.ui.editor.templates.TaskContextType;
61 import org.eclipse.ant.internal.ui.model.AntDefiningTaskNode;
62 import org.eclipse.ant.internal.ui.model.AntElementNode;
63 import org.eclipse.ant.internal.ui.model.AntModel;
64 import org.eclipse.ant.internal.ui.model.AntProjectNode;
65 import org.eclipse.ant.internal.ui.model.AntTargetNode;
66 import org.eclipse.ant.internal.ui.model.AntTaskNode;
67 import org.eclipse.core.commands.Command;
68 import org.eclipse.core.commands.ParameterizedCommand;
69 import org.eclipse.core.runtime.IProgressMonitor;
70 import org.eclipse.jface.bindings.TriggerSequence;
71 import org.eclipse.jface.operation.IRunnableWithProgress;
72 import org.eclipse.jface.text.BadLocationException;
73 import org.eclipse.jface.text.IDocument;
74 import org.eclipse.jface.text.IRegion;
75 import org.eclipse.jface.text.ITextSelection;
76 import org.eclipse.jface.text.ITextViewer;
77 import org.eclipse.jface.text.Position;
78 import org.eclipse.jface.text.Region;
79 import org.eclipse.jface.text.contentassist.ContentAssistEvent;
80 import org.eclipse.jface.text.contentassist.ICompletionListener;
81 import org.eclipse.jface.text.contentassist.ICompletionProposal;
82 import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
83 import org.eclipse.jface.text.contentassist.IContentAssistant;
84 import org.eclipse.jface.text.contentassist.IContentAssistantExtension2;
85 import org.eclipse.jface.text.contentassist.IContextInformation;
86 import org.eclipse.jface.text.contentassist.IContextInformationValidator;
87 import org.eclipse.jface.text.templates.Template;
88 import org.eclipse.jface.text.templates.TemplateCompletionProcessor;
89 import org.eclipse.jface.text.templates.TemplateContext;
90 import org.eclipse.jface.text.templates.TemplateContextType;
91 import org.eclipse.jface.text.templates.TemplateException;
92 import org.eclipse.jface.text.templates.TemplateProposal;
93 import org.eclipse.swt.graphics.Image;
94 import org.eclipse.swt.graphics.Point;
95 import org.eclipse.ui.IEditorPart;
96 import org.eclipse.ui.IWorkbenchPage;
97 import org.eclipse.ui.PlatformUI;
98 import org.eclipse.ui.commands.ICommandService;
99 import org.eclipse.ui.keys.IBindingService;
100 import org.eclipse.ui.part.FileEditorInput;
101 import org.eclipse.ui.progress.IProgressService;
102 import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
103 import org.w3c.dom.Element JavaDoc;
104 import org.w3c.dom.Node JavaDoc;
105 import org.w3c.dom.NodeList JavaDoc;
106
107 import com.ibm.icu.text.MessageFormat;
108
109 /**
110  * The completion processor for the Ant Editor.
111  */

112 public class AntEditorCompletionProcessor extends TemplateCompletionProcessor implements IContentAssistProcessor, ICompletionListener {
113  
114     private static final class ProposalComparator implements Comparator JavaDoc {
115         public int compare(Object JavaDoc o1, Object JavaDoc o2) {
116             return ((TemplateProposal) o2).getRelevance() - ((TemplateProposal) o1).getRelevance();
117         }
118     }
119
120     private static final Comparator JavaDoc fgProposalComparator= new ProposalComparator();
121     
122     private Comparator JavaDoc proposalComparator= new Comparator JavaDoc() {
123         public int compare(Object JavaDoc o1, Object JavaDoc o2) {
124             
125             int type1= getProposalType(o1);
126             int type2= getProposalType(o2);
127             if (type1 != type2) {
128                 if (type1 > type2) {
129                     return 1;
130                 }
131                 return -1;
132             }
133             String JavaDoc string1 = ((ICompletionProposal)o1).getDisplayString();
134             String JavaDoc string2 = ((ICompletionProposal)o2).getDisplayString();
135             return string1.compareToIgnoreCase(string2);
136         }
137         private int getProposalType(Object JavaDoc o){
138             if(o instanceof AntCompletionProposal){
139                 return ((AntCompletionProposal) o).getType();
140             }
141             return AntCompletionProposal.TASK_PROPOSAL;
142         }
143     };
144     
145     protected final static int PROPOSAL_MODE_NONE = 0;
146     protected final static int PROPOSAL_MODE_BUILDFILE = 1;
147     protected final static int PROPOSAL_MODE_TASK_PROPOSAL = 2;
148     protected final static int PROPOSAL_MODE_PROPERTY_PROPOSAL = 3;
149     protected final static int PROPOSAL_MODE_ATTRIBUTE_PROPOSAL = 4;
150     protected final static int PROPOSAL_MODE_TASK_PROPOSAL_CLOSING = 5;
151     protected final static int PROPOSAL_MODE_ATTRIBUTE_VALUE_PROPOSAL = 6;
152     protected final static int PROPOSAL_MODE_NESTED_ELEMENT_PROPOSAL = 7;
153     
154     private final static ICompletionProposal[] NO_PROPOSALS= new ICompletionProposal[0];
155     
156     /**
157      * The line where the cursor sits now.
158      * <P>
159      * The first line has index '1'.
160      */

161     protected int lineNumber = -1;
162
163     /**
164      * The startingColumn where the cursor sits now.
165      * <P>
166      * The first startingColumn has index '1'.
167      */

168     protected int columnNumber = -1;
169     
170     /**
171      * The additional offset required from a required attribute to
172      * place the cursor for the current proposal
173      */

174     private int additionalProposalOffset = -1;
175     
176     private static final String JavaDoc ANT_DTD_FILENAME = "/org/eclipse/ant/internal/ui/editor/ant1.6.2.dtd"; //$NON-NLS-1$
177

178     /**
179      * The dtd.
180      */

181     private static ISchema fgDtd;
182
183     /**
184      * Cursor position, counted from the beginning of the document.
185      * <P>
186      * The first position has index '0'.
187      */

188     protected int cursorPosition = -1;
189     
190     /**
191      * The text viewer.
192      */

193     private ITextViewer viewer;
194     
195     /**
196      * The set of characters that will trigger the activation of the
197      * completion proposal computation.
198      */

199     private char[] autoActivationChars= null;
200     
201     private String JavaDoc errorMessage;
202     
203     protected AntModel antModel;
204     
205     /**
206      * The proposal mode for the current content assist
207      * @see #determineProposalMode(IDocument, int, String)
208      */

209     private int currentProposalMode= -1;
210     
211     /**
212      * The prefix for the current content assist
213      */

214     protected String JavaDoc currentPrefix= null;
215     
216     /**
217      * The current task string for content assist
218      * @see #determineProposalMode(IDocument, int, String)
219      */

220     protected String JavaDoc currentTaskString= null;
221
222     private boolean fTemplatesOnly= false;
223     protected IContentAssistantExtension2 fContentAssistant;
224     
225     public AntEditorCompletionProcessor(AntModel model) {
226         super();
227         antModel= model;
228     }
229
230     /**
231      * Parses the dtd.
232      */

233     private ISchema parseDtd() throws ParseError, IOException JavaDoc {
234         InputStream JavaDoc stream= null;
235         Reader JavaDoc reader= null;
236         try {
237             stream= getClass().getResourceAsStream(ANT_DTD_FILENAME);
238             reader=new InputStreamReader JavaDoc(stream, "UTF-8"); //$NON-NLS-1$
239
Parser parser = new Parser();
240             ISchema schema= parser.parseDTD(reader, "project"); //$NON-NLS-1$
241
return schema;
242         } finally {
243             if (reader != null) {
244                 reader.close();
245             }
246             if (stream != null) {
247                 stream.close();
248             }
249         }
250     }
251     
252     /* (non-Javadoc)
253      * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeCompletionProposals(org.eclipse.jface.text.ITextViewer, int)
254      */

255     public ICompletionProposal[] computeCompletionProposals(ITextViewer refViewer, int documentOffset) {
256         this.viewer = refViewer;
257         try {
258             if (fTemplatesOnly) {
259                 fContentAssistant.setStatusMessage(getIterationGestureMessage(AntEditorMessages.getString("AntEditorCompletionProcessor.0"))); //$NON-NLS-1$
260
fContentAssistant.setEmptyMessage(AntEditorMessages.getString("AntEditorCompletionProcessor.60")); //$NON-NLS-1$
261
ICompletionProposal[] templates= determineTemplateProposals(refViewer, documentOffset);
262                 Arrays.sort(templates, proposalComparator);
263                 return templates;
264             }
265             fContentAssistant.setStatusMessage(getIterationGestureMessage(AntEditorMessages.getString("AntEditorCompletionProcessor.61"))); //$NON-NLS-1$
266
fContentAssistant.setEmptyMessage(AntEditorMessages.getString("AntEditorCompletionProcessor.62")); //$NON-NLS-1$
267
ICompletionProposal[] matchingProposals= determineProposals();
268             ICompletionProposal[] matchingTemplateProposals = determineTemplateProposals(refViewer, documentOffset);
269             return mergeProposals(matchingProposals, matchingTemplateProposals);
270         } finally {
271             currentPrefix= null;
272             currentProposalMode= -1;
273             fTemplatesOnly= !fTemplatesOnly;
274         }
275     }
276     
277     protected ICompletionProposal[] determineTemplateProposals(ITextViewer refViewer, int documentOffset) {
278         this.viewer= refViewer;
279         String JavaDoc prefix = getCurrentPrefix();
280         ICompletionProposal[] matchingTemplateProposals;
281         if (prefix.length() == 0) {
282             matchingTemplateProposals = determineTemplateProposalsForContext(documentOffset);
283         } else {
284             ICompletionProposal[] templateProposals = determineTemplateProposalsForContext(documentOffset);
285             List JavaDoc templateProposalList = new ArrayList JavaDoc(templateProposals.length);
286             for (int i = 0; i < templateProposals.length; i++) {
287                 if (templateProposals[i].getDisplayString().toLowerCase().startsWith(prefix)) {
288                     templateProposalList.add(templateProposals[i]);
289                 }
290             }
291             matchingTemplateProposals =
292                 (ICompletionProposal[]) templateProposalList.toArray(new ICompletionProposal[templateProposalList.size()]);
293         }
294         return matchingTemplateProposals;
295     }
296
297     //essentially a copy of super.computeCompletionProposals but we need to have both context types work
298
//for target (task and target) context type in a backwards compatible way
299
private ICompletionProposal[] determineTemplateProposalsForContext(int offset) {
300         ITextSelection selection= (ITextSelection) viewer.getSelectionProvider().getSelection();
301
302         // adjust offset to end of normalized selection
303
if (selection.getOffset() == offset) {
304             offset= selection.getOffset() + selection.getLength();
305         }
306
307         String JavaDoc prefix= extractPrefix(viewer, offset);
308         Region region= new Region(offset - prefix.length(), prefix.length());
309         TemplateContext context= createContext(viewer, region);
310         if (context == null) {
311             return new ICompletionProposal[0];
312         }
313         
314         context.setVariable("selection", selection.getText()); // name of the selection variables {line, word}_selection //$NON-NLS-1$
315

316         Template[] templates;
317         String JavaDoc contextTypeId = context.getContextType().getId();
318         boolean isTargetContextType = contextTypeId.equals(TargetContextType.TARGET_CONTEXT_TYPE);
319         if (isTargetContextType) {
320             Template[] tasks = AntTemplateAccess.getDefault().getTemplateStore().getTemplates(TaskContextType.TASK_CONTEXT_TYPE);
321             Template[] targets = getTemplates(contextTypeId);
322             templates = new Template[tasks.length + targets.length];
323             System.arraycopy(tasks, 0, templates, 0, tasks.length);
324             System.arraycopy(targets, 0, templates, tasks.length, targets.length);
325         } else {
326             templates = getTemplates(contextTypeId);
327         }
328
329         List JavaDoc matches= new ArrayList JavaDoc();
330         for (int i= 0; i < templates.length; i++) {
331             Template template= templates[i];
332             try {
333                 context.getContextType().validate(template.getPattern());
334             } catch (TemplateException e) {
335                 continue;
336             }
337             if (template.matches(prefix, contextTypeId) || (isTargetContextType && template.matches(prefix, TaskContextType.TASK_CONTEXT_TYPE))) {
338                 matches.add(createProposal(template, context, (IRegion) region, getRelevance(template, prefix)));
339             }
340         }
341
342         Collections.sort(matches, fgProposalComparator);
343
344         return (ICompletionProposal[]) matches.toArray(new ICompletionProposal[matches.size()]);
345     }
346     
347     private ICompletionProposal[] mergeProposals(ICompletionProposal[] proposals1, ICompletionProposal[] proposals2) {
348
349         ICompletionProposal[] combinedProposals = new ICompletionProposal[proposals1.length + proposals2.length];
350                 
351         System.arraycopy(proposals1, 0, combinedProposals, 0, proposals1.length);
352         System.arraycopy(proposals2, 0, combinedProposals, proposals1.length, proposals2.length);
353
354         Arrays.sort(combinedProposals, proposalComparator);
355         return combinedProposals;
356     }
357
358     /**
359      * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeContextInformation(ITextViewer, int)
360      */

361     public IContextInformation[] computeContextInformation(ITextViewer refViewer, int documentOffset) {
362         return new IContextInformation[0];
363     }
364
365     /**
366      * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getCompletionProposalAutoActivationCharacters()
367      */

368     public char[] getCompletionProposalAutoActivationCharacters() {
369         return autoActivationChars;
370     }
371
372     /**
373      * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationAutoActivationCharacters()
374      */

375     public char[] getContextInformationAutoActivationCharacters() {
376         return null;
377     }
378
379     /**
380      * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationValidator()
381      */

382     public IContextInformationValidator getContextInformationValidator() {
383         return null;
384     }
385
386     /**
387      * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getErrorMessage()
388      */

389     public String JavaDoc getErrorMessage() {
390         return errorMessage;
391     }
392     
393     /**
394      * Returns the new determined proposals.
395      */

396     private ICompletionProposal[] determineProposals() {
397         ITextSelection selection= (ITextSelection)viewer.getSelectionProvider().getSelection();
398         cursorPosition = selection.getOffset() + selection.getLength();
399         
400         IDocument doc = viewer.getDocument();
401         try {
402             lineNumber = doc.getLineOfOffset(cursorPosition);
403             columnNumber = cursorPosition - doc.getLineOffset(lineNumber);
404         } catch (BadLocationException e) {
405             AntUIPlugin.log(e);
406         }
407         
408         String JavaDoc prefix = getCurrentPrefix();
409         if (prefix == null || cursorPosition == -1) {
410             AntUIPlugin.getStandardDisplay().beep();
411             return NO_PROPOSALS;
412         }
413     
414         ICompletionProposal[] proposals = getProposalsFromDocument(doc, prefix);
415         currentTaskString= null;
416         return proposals;
417     }
418
419     /**
420      * Returns the proposals for the specified document.
421      */

422     protected ICompletionProposal[] getProposalsFromDocument(IDocument document, String JavaDoc prefix) {
423         ICompletionProposal[] proposals= null;
424         currentProposalMode= determineProposalMode(document, cursorPosition, prefix);
425         switch (currentProposalMode) {
426             case PROPOSAL_MODE_ATTRIBUTE_PROPOSAL:
427                 proposals= getAttributeProposals(currentTaskString, prefix);
428                 if (proposals.length == 0) {
429                     errorMessage= AntEditorMessages.getString("AntEditorCompletionProcessor.28"); //$NON-NLS-1$
430
}
431                 break;
432             case PROPOSAL_MODE_TASK_PROPOSAL:
433                 String JavaDoc parentName= getParentName(document, lineNumber, columnNumber);
434                 if (parentName == null || parentName.length() == 0) { //outside of any parent element
435
proposals= NO_PROPOSALS;
436                      currentProposalMode= PROPOSAL_MODE_NONE;
437                 } else {
438                     proposals= getTaskProposals(document, parentName, prefix);
439                 }
440                 if (proposals.length == 0) {
441                     errorMessage= AntEditorMessages.getString("AntEditorCompletionProcessor.29"); //$NON-NLS-1$
442
}
443                 break;
444             case PROPOSAL_MODE_BUILDFILE:
445                 proposals= getBuildFileProposals(document, prefix);
446                 if (proposals.length == 0) {
447                    errorMessage= AntEditorMessages.getString("AntEditorCompletionProcessor.29"); //$NON-NLS-1$
448
}
449                 break;
450             case PROPOSAL_MODE_TASK_PROPOSAL_CLOSING:
451                 ICompletionProposal proposal= getClosingTaskProposal(getOpenElementName(), prefix, true);
452                 if (proposal == null) {
453                    errorMessage= AntEditorMessages.getString("AntEditorCompletionProcessor.30"); //$NON-NLS-1$
454
proposals= NO_PROPOSALS;
455                 } else {
456                     proposals= new ICompletionProposal[]{proposal};
457                 }
458                 break;
459             case PROPOSAL_MODE_ATTRIBUTE_VALUE_PROPOSAL:
460                 String JavaDoc textToSearch= document.get().substring(0, cursorPosition-prefix.length());
461                 String JavaDoc attributeString = getAttributeStringFromDocumentStringToPrefix(textToSearch);
462                 if ("target".equalsIgnoreCase(currentTaskString)) { //$NON-NLS-1$
463
proposals= getTargetAttributeValueProposals(document, textToSearch, prefix, attributeString);
464                 } else if ("antcall".equalsIgnoreCase(currentTaskString)) { //$NON-NLS-1$
465
proposals= getAntCallAttributeValueProposals(document, prefix, attributeString);
466                 } else if ("project".equalsIgnoreCase(currentTaskString)) { //$NON-NLS-1$
467
proposals= getProjectAttributeValueProposals(prefix, attributeString);
468                 } else if ("refid".equalsIgnoreCase(attributeString) || "classpathref".equalsIgnoreCase(attributeString) //$NON-NLS-1$//$NON-NLS-2$
469
|| "sourcepathref".equalsIgnoreCase(attributeString) || "bootpathref".equalsIgnoreCase(attributeString)) { //$NON-NLS-1$ //$NON-NLS-2$
470
proposals= getReferencesValueProposals(prefix);
471                 } else {
472                     proposals= getAttributeValueProposals(currentTaskString, attributeString, prefix);
473                 }
474                 if (proposals.length == 0) {
475                    errorMessage= AntEditorMessages.getString("AntEditorCompletionProcessor.31"); //$NON-NLS-1$
476
}
477                 break;
478             case PROPOSAL_MODE_PROPERTY_PROPOSAL:
479                 proposals= getPropertyProposals(document, prefix, cursorPosition);
480                 if (proposals.length == 0) {
481                    errorMessage= AntEditorMessages.getString("AntEditorCompletionProcessor.32"); //$NON-NLS-1$
482
}
483                 break;
484             case PROPOSAL_MODE_NONE :
485             default :
486                 proposals= NO_PROPOSALS;
487                 errorMessage= AntEditorMessages.getString("AntEditorCompletionProcessor.33"); //$NON-NLS-1$
488
}
489         
490         if (proposals.length > 0) {
491             errorMessage= ""; //$NON-NLS-1$
492
}
493         return proposals;
494
495     }
496     
497     private ICompletionProposal[] getProjectAttributeValueProposals(String JavaDoc prefix, String JavaDoc attributeName) {
498         if (attributeName.equalsIgnoreCase("default")) { //$NON-NLS-1$
499
return getDefaultValueProposals(prefix);
500         }
501
502         return NO_PROPOSALS;
503     }
504
505     private ICompletionProposal[] getDefaultValueProposals(String JavaDoc prefix) {
506         Map JavaDoc targets = getTargets();
507         List JavaDoc defaultProposals = new ArrayList JavaDoc(targets.size());
508         Iterator JavaDoc itr = targets.values().iterator();
509
510         Target target;
511         String JavaDoc targetName;
512         while (itr.hasNext()) {
513             target = (Target) itr.next();
514             targetName= target.getName();
515             if (targetName.toLowerCase().startsWith(prefix) && targetName.length() > 0) {
516                 defaultProposals.add(new AntCompletionProposal(targetName, cursorPosition - prefix.length(), prefix.length(), targetName.length(), null, targetName, target.getDescription(), AntCompletionProposal.TASK_PROPOSAL));
517             }
518         }
519
520         ICompletionProposal[] proposals = new ICompletionProposal[defaultProposals.size()];
521         return (ICompletionProposal[])defaultProposals.toArray(proposals);
522     }
523     
524     private ICompletionProposal[] getReferencesValueProposals(String JavaDoc prefix) {
525         Project project= antModel.getProjectNode().getProject();
526         Map JavaDoc references= project.getReferences();
527         if (references.isEmpty()) {
528             return NO_PROPOSALS;
529         }
530         Set JavaDoc refIds= references.keySet();
531         AntElementNode node= antModel.getNode(cursorPosition, false);
532         if (node == null) {
533             return NO_PROPOSALS;
534         }
535         while (node.getParentNode() instanceof AntTaskNode) {
536             node= node.getParentNode();
537         }
538         String JavaDoc id= null;
539         if (node instanceof AntTaskNode) {
540             id= ((AntTaskNode)node).getId();
541         }
542         List JavaDoc proposals= new ArrayList JavaDoc(refIds.size());
543         int i= 0;
544         String JavaDoc refId;
545         ICompletionProposal proposal;
546         int prefixLength= prefix.length();
547         int replacementOffset= cursorPosition - prefixLength;
548         for (Iterator JavaDoc iter = refIds.iterator(); iter.hasNext(); i++) {
549             refId= (String JavaDoc) iter.next();
550             if (!refId.equals(id) && (prefixLength == 0 || refId.toLowerCase().startsWith(prefix))) {
551                 proposal= new AntCompletionProposal(refId, replacementOffset, prefixLength, refId.length(), null, refId, null, AntCompletionProposal.TASK_PROPOSAL);
552                 proposals.add(proposal);
553             }
554         }
555         return (ICompletionProposal[])proposals.toArray(new ICompletionProposal[proposals.size()]);
556     }
557
558     protected ICompletionProposal[] getTargetAttributeValueProposals(IDocument document, String JavaDoc textToSearch, String JavaDoc prefix, String JavaDoc attributeName) {
559         if (attributeName.equalsIgnoreCase("depends")) { //$NON-NLS-1$
560
return getDependsValueProposals(document, prefix);
561         } else if (attributeName.equalsIgnoreCase("if") || attributeName.equalsIgnoreCase("unless")) { //$NON-NLS-1$ //$NON-NLS-2$
562
if (!textToSearch.trim().endsWith(",")) { //$NON-NLS-1$
563
return getPropertyProposals(document, prefix, cursorPosition);
564             }
565         }
566         
567         return NO_PROPOSALS;
568     }
569     
570     protected ICompletionProposal[] getAntCallAttributeValueProposals(IDocument document, String JavaDoc prefix, String JavaDoc attributeName) {
571         if (attributeName.equalsIgnoreCase("target")) { //$NON-NLS-1$
572
return getTargetProposals(document, prefix);
573         }
574         
575         return NO_PROPOSALS;
576     }
577     
578     private ICompletionProposal[] getTargetProposals(IDocument document, String JavaDoc prefix) {
579         String JavaDoc currentTargetName= getEnclosingTargetName(document, lineNumber, columnNumber);
580         if(currentTargetName == null) {
581             return NO_PROPOSALS;
582         }
583             
584         Map JavaDoc targets= getTargets();
585         Set JavaDoc targetNames= targets.keySet();
586         List JavaDoc proposals= new ArrayList JavaDoc(targets.size() - 2); //current target and implicit target
587
int index= 0;
588         Iterator JavaDoc itr= targetNames.iterator();
589         while (itr.hasNext()) {
590             String JavaDoc targetName = (String JavaDoc) itr.next();
591             if (targetName.equals(currentTargetName)) {
592                 continue;
593             }
594             if (targetName.toLowerCase().startsWith(prefix) && targetName.length() > 0){
595                 ICompletionProposal proposal = new AntCompletionProposal(targetName, cursorPosition - prefix.length(), prefix.length(), targetName.length(), null, targetName, ((Target)targets.get(targetName)).getDescription(), AntCompletionProposal.TASK_PROPOSAL);
596                 proposals.add(proposal);
597                 index++;
598             }
599         }
600         return (ICompletionProposal[])proposals.toArray(new ICompletionProposal[proposals.size()]);
601     }
602
603     private ICompletionProposal[] getDependsValueProposals(IDocument document, String JavaDoc prefix) {
604         List JavaDoc possibleDependencies = new ArrayList JavaDoc();
605         String JavaDoc currentTargetName= getEnclosingTargetName(document, lineNumber, columnNumber);
606         if(currentTargetName == null) {
607             return NO_PROPOSALS;
608         }
609             
610         Map JavaDoc targets= getTargets();
611         Set JavaDoc targetNames= targets.keySet();
612         Iterator JavaDoc itr= targetNames.iterator();
613         Enumeration JavaDoc dependencies= null;
614         while (itr.hasNext()) {
615             String JavaDoc targetName = (String JavaDoc) itr.next();
616             if (targetName.equals(currentTargetName)) {
617                 Target currentTarget= (Target)targets.get(targetName);
618                 dependencies= currentTarget.getDependencies();
619                 continue;
620             }
621             if (targetName.toLowerCase().startsWith(prefix) && targetName.length() > 0){
622                 possibleDependencies.add(targetName);
623             }
624         }
625         
626         if (dependencies != null) {
627             while (dependencies.hasMoreElements()) {
628                 possibleDependencies.remove(dependencies.nextElement());
629             }
630         }
631         
632         ICompletionProposal[] proposals= new ICompletionProposal[possibleDependencies.size()];
633         int i= 0;
634         for (Iterator JavaDoc iter = possibleDependencies.iterator(); iter.hasNext(); i++) {
635             String JavaDoc targetName = (String JavaDoc) iter.next();
636             ICompletionProposal proposal = new AntCompletionProposal(targetName, cursorPosition - prefix.length(), prefix.length(), targetName.length(), null, targetName, ((Target)targets.get(targetName)).getDescription(), AntCompletionProposal.TASK_PROPOSAL);
637             proposals[i]= proposal;
638         }
639         return proposals;
640     }
641
642     /**
643      * Returns all possible attributes for the specified task.
644      *
645      * @param taskName the name of the task for that the attribute shall be
646      * completed
647      * @param prefix prefix, that all proposals should start with. The prefix
648      * may be an empty string.
649      */

650     protected ICompletionProposal[] getAttributeProposals(String JavaDoc taskName, String JavaDoc prefix) {
651         List JavaDoc proposals = new ArrayList JavaDoc();
652         IElement element = getDtd().getElement(taskName);
653         if (element != null) {
654             Iterator JavaDoc keys = element.getAttributes().keySet().iterator();
655             while (keys.hasNext()) {
656                 String JavaDoc attrName = (String JavaDoc) keys.next();
657                 if (prefix.length() == 0 || attrName.toLowerCase().startsWith(prefix)) {
658                     IAttribute dtdAttributes = (IAttribute) element.getAttributes().get(attrName);
659                     String JavaDoc replacementString = attrName+"=\"\""; //$NON-NLS-1$
660
String JavaDoc displayString = attrName;
661                     String JavaDoc[] items = dtdAttributes.getEnum();
662                     if (items != null) {
663                         if(items.length > 1) {
664                             displayString += " - ("; //$NON-NLS-1$
665
}
666                         for (int i = 0; i < items.length; i++) {
667                             displayString += items[i];
668                             if(i+1 < items.length) {
669                                 displayString += " | "; //$NON-NLS-1$
670
} else {
671                                 displayString += ")"; //$NON-NLS-1$
672
}
673                         }
674                     }
675                     
676                     addAttributeProposal(taskName, prefix, proposals, attrName, replacementString, displayString, true);
677                 }
678             }
679         } else { //possibly a user defined task or type
680
Class JavaDoc taskClass= getTaskClass(taskName);
681             if (taskClass != null) {
682                 if (taskClass == MacroInstance.class) {
683                     addMacroDefAttributeProposals(taskName, prefix, proposals);
684                 } else {
685                     IntrospectionHelper helper= getIntrospectionHelper(taskClass);
686                     if (helper != null) {
687                         addAttributeProposals(helper, taskName, prefix, proposals);
688                     }
689                 }
690             } else { //nested user defined element
691
Class JavaDoc nestedType= getNestedType();
692                 if (nestedType != null) {
693                     IntrospectionHelper helper= getIntrospectionHelper(nestedType);
694                     if (helper != null) {
695                         addAttributeProposals(helper, taskName, prefix, proposals);
696                     }
697                 }
698             }
699         }
700         return (ICompletionProposal[])proposals.toArray(new ICompletionProposal[proposals.size()]);
701     }
702     
703     private void addAttributeProposals(IntrospectionHelper helper, String JavaDoc taskName, String JavaDoc prefix, List JavaDoc proposals) {
704         Enumeration JavaDoc attributes= helper.getAttributes();
705         while (attributes.hasMoreElements()) {
706             String JavaDoc attribute = (String JavaDoc) attributes.nextElement();
707             if (prefix.length() == 0 || attribute.toLowerCase().startsWith(prefix)) {
708                 String JavaDoc replacementString = attribute + "=\"\""; //$NON-NLS-1$
709
addAttributeProposal(taskName, prefix, proposals, attribute, replacementString, attribute, false);
710             }
711         }
712     }
713
714     private Class JavaDoc getNestedType() {
715         AntElementNode currentNode= antModel.getNode(cursorPosition, false);
716         if (currentNode == null) {
717             return null;
718         }
719         AntElementNode parent= currentNode.getParentNode();
720         if (parent instanceof AntTaskNode) {
721             String JavaDoc parentName= parent.getName();
722             if (hasNestedElements(parentName)) {
723                 Class JavaDoc taskClass= getTaskClass(parentName);
724                 if (taskClass != null) {
725                     IntrospectionHelper helper= getIntrospectionHelper(taskClass);
726                     if (helper != null) {
727                         Class JavaDoc nestedType= null;
728                         try {
729                             nestedType= helper.getElementType(currentNode.getName());
730                         } catch (BuildException be) {
731                         }
732                         return nestedType;
733                     }
734                 }
735             }
736         }
737         return null;
738     }
739     
740     private IntrospectionHelper getIntrospectionHelper(Class JavaDoc taskClass) {
741         IntrospectionHelper helper= null;
742         try {
743             helper= IntrospectionHelper.getHelper(antModel.getProjectNode().getProject(), taskClass);
744         } catch (NoClassDefFoundError JavaDoc e) {
745             //ignore as a task may require additional classpath components
746
}
747         return helper;
748     }
749
750     private void addMacroDefAttributeProposals(String JavaDoc taskName, String JavaDoc prefix, List JavaDoc proposals) {
751         currentProposalMode= PROPOSAL_MODE_ATTRIBUTE_PROPOSAL;
752         AntDefiningTaskNode node= antModel.getDefininingTaskNode(taskName);
753         Object JavaDoc task= node.getRealTask();
754         if (!(task instanceof MacroDef)) {
755             return;
756         }
757         List JavaDoc attributes= ((MacroDef)task).getAttributes();
758         Iterator JavaDoc itr= attributes.iterator();
759         while (itr.hasNext()) {
760             MacroDef.Attribute attribute = (MacroDef.Attribute) itr.next();
761             String JavaDoc attributeName= attribute.getName();
762             if (!(prefix.length() == 0 || attributeName.toLowerCase().startsWith(prefix))) {
763                 continue;
764             }
765             String JavaDoc replacementString = attributeName + "=\"\""; //$NON-NLS-1$
766
String JavaDoc proposalInfo = null;
767             
768             String JavaDoc description = attribute.getDescription();
769             if(description != null) {
770                 proposalInfo= description;
771             }
772             String JavaDoc deflt = attribute.getDefault();
773             if(deflt != null && deflt.length() > 0) {
774                 proposalInfo= (proposalInfo == null ? "<BR><BR>" : (proposalInfo += "<BR><BR>")); //$NON-NLS-1$ //$NON-NLS-2$
775
proposalInfo+= MessageFormat.format(AntEditorMessages.getString("AntEditorCompletionProcessor.59"), new String JavaDoc[]{deflt}); //$NON-NLS-1$
776
}
777             
778             ICompletionProposal proposal = new AntCompletionProposal(replacementString, cursorPosition - prefix.length(), prefix.length(), attributeName.length() + 2, null, attributeName, proposalInfo, AntCompletionProposal.TASK_PROPOSAL);
779             proposals.add(proposal);
780         }
781     }
782     
783     private void addMacroDefElementProposals(String JavaDoc taskName, String JavaDoc prefix, List JavaDoc proposals) {
784         AntDefiningTaskNode node= antModel.getDefininingTaskNode(taskName);
785         Object JavaDoc task= node.getRealTask();
786         if (!(task instanceof MacroDef)) {
787             return;
788         }
789         Map JavaDoc elements= ((MacroDef)task).getElements();
790         Iterator JavaDoc itr= elements.keySet().iterator();
791         int prefixLength= prefix.length();
792         int replacementOffset= cursorPosition - prefixLength;
793         while (itr.hasNext()) {
794             String JavaDoc elementName = (String JavaDoc) itr.next();
795             if (!(prefixLength == 0 || elementName.toLowerCase().startsWith(prefix))) {
796                 continue;
797             }
798             MacroDef.TemplateElement element = (MacroDef.TemplateElement) elements.get(elementName);
799             String JavaDoc replacementString = MessageFormat.format("<{0}>\n</{1}>", new String JavaDoc[]{elementName, elementName}); //$NON-NLS-1$
800
String JavaDoc proposalInfo = null;
801             
802             String JavaDoc description = element.getDescription();
803             if(description != null) {
804                 proposalInfo= description;
805             }
806             proposalInfo= (proposalInfo == null ? "<BR><BR>" : (proposalInfo += "<BR><BR>")); //$NON-NLS-1$ //$NON-NLS-2$
807

808             if(element.isOptional()) {
809                 proposalInfo+= AntEditorMessages.getString("AntEditorCompletionProcessor.1"); //$NON-NLS-1$
810
} else {
811                 proposalInfo+= AntEditorMessages.getString("AntEditorCompletionProcessor.2"); //$NON-NLS-1$
812
}
813             
814             ICompletionProposal proposal = new AntCompletionProposal(replacementString, replacementOffset, prefixLength, elementName.length() + 2, null, elementName, proposalInfo, AntCompletionProposal.TASK_PROPOSAL);
815             proposals.add(proposal);
816         }
817     }
818
819     private void addAttributeProposal(String JavaDoc taskName, String JavaDoc prefix, List JavaDoc proposals, String JavaDoc attrName, String JavaDoc replacementString, String JavaDoc displayString, boolean lookupDescription) {
820         
821         String JavaDoc proposalInfo = null;
822         if (lookupDescription) {
823             String JavaDoc required = getDescriptionProvider().getRequiredAttributeForTaskAttribute(taskName, attrName);
824             if(required != null && required.length() > 0) {
825                 proposalInfo = AntEditorMessages.getString("AntEditorCompletionProcessor.Required___4") + required; //$NON-NLS-1$
826
proposalInfo += "<BR><BR>"; //$NON-NLS-1$
827
}
828             String JavaDoc description = getDescriptionProvider().getDescriptionForTaskAttribute(taskName, attrName);
829             if(description != null) {
830                 proposalInfo = (proposalInfo == null ? "" : proposalInfo); //$NON-NLS-1$
831
proposalInfo += description;
832             }
833         }
834         
835         ICompletionProposal proposal = new AntCompletionProposal(replacementString, cursorPosition - prefix.length(), prefix.length(), attrName.length()+2, null, displayString, proposalInfo, AntCompletionProposal.TASK_PROPOSAL);
836         proposals.add(proposal);
837     }
838
839     /**
840      * Returns all possible values for the specified attribute of the specified
841      * task.
842      *
843      * @param aTaskName the name of the task that the specified attribute
844      * belongs to.
845      *
846      * @param anAttributeName the name of the attribute for that the value
847      * shall be completed
848      *
849      * @param prefix the prefix that all proposals should start with. The prefix
850      * may be an empty string.
851      */

852     private ICompletionProposal[] getAttributeValueProposals(String JavaDoc taskName, String JavaDoc attributeName, String JavaDoc prefix) {
853         List JavaDoc proposals = new ArrayList JavaDoc();
854         IElement taskElement = getDtd().getElement(taskName);
855         if (taskElement != null) {
856             IAttribute attribute = (IAttribute) taskElement.getAttributes().get(attributeName);
857             if (attribute != null) {
858                 String JavaDoc[] items = attribute.getEnum();
859                 if (items != null) {
860                     String JavaDoc item;
861                     for (int i = 0; i < items.length; i++) {
862                         item= items[i];
863                         if(prefix.length() ==0 || item.toLowerCase().startsWith(prefix)) {
864                             proposals.add(
865                                 new AntCompletionProposal(item, cursorPosition - prefix.length(), prefix.length(), item.length(), null, item, null, AntCompletionProposal.TASK_PROPOSAL));
866                         }
867                     }
868                 }
869             }
870         } else { //possibly a user defined task or type
871
Class JavaDoc taskClass= getTaskClass(taskName);
872             if (taskClass != null) {
873                 IntrospectionHelper helper= getIntrospectionHelper(taskClass);
874                 if (helper != null) {
875                     addAttributeValueProposals(helper, attributeName, prefix, proposals);
876                 }
877             } else { //nested user defined element
878
Class JavaDoc nestedType= getNestedType();
879                 if (nestedType != null) {
880                     IntrospectionHelper helper= getIntrospectionHelper(nestedType);
881                     if (helper != null) {
882                         addAttributeValueProposals(helper, attributeName, prefix, proposals);
883                     }
884                 }
885             }
886         }
887         return (ICompletionProposal[])proposals.toArray(new ICompletionProposal[proposals.size()]);
888     }
889
890     private void addAttributeValueProposals(IntrospectionHelper helper, String JavaDoc attributeName, String JavaDoc prefix, List JavaDoc proposals) {
891         Enumeration JavaDoc attributes= helper.getAttributes();
892         while (attributes.hasMoreElements()) {
893             String JavaDoc attribute= (String JavaDoc) attributes.nextElement();
894             if (attribute.equals(attributeName)) {
895                 Class JavaDoc attributeType= helper.getAttributeType(attribute);
896                 addAttributeValueProposalsForAttributeType(attributeType, prefix, proposals);
897                 break;
898             }
899         }
900     }
901
902     private void addAttributeValueProposalsForAttributeType(Class JavaDoc attributeType, String JavaDoc prefix, List JavaDoc proposals) {
903         if ((attributeType == Boolean.TYPE || attributeType == Boolean JavaDoc.class) && prefix.length() <= 5) {
904             addBooleanAttributeValueProposals(prefix, proposals);
905         } else if (EnumeratedAttribute.class.isAssignableFrom(attributeType)) {
906             try {
907                 addEnumeratedAttributeValueProposals(attributeType, prefix, proposals);
908             } catch (InstantiationException JavaDoc e) {
909             } catch (IllegalAccessException JavaDoc e) {
910             }
911         } else if (Reference.class == attributeType) {
912             proposals.addAll(Arrays.asList(getReferencesValueProposals(prefix)));
913         }
914     }
915     
916     private void addEnumeratedAttributeValueProposals(Class JavaDoc type, String JavaDoc prefix, List JavaDoc proposals) throws InstantiationException JavaDoc, IllegalAccessException JavaDoc {
917         EnumeratedAttribute ea= (EnumeratedAttribute) type.newInstance();
918         String JavaDoc[] values = ea.getValues();
919         String JavaDoc enumerated;
920         for (int i = 0; i < values.length; i++) {
921             enumerated= values[i].toLowerCase();
922             if (prefix.length() == 0 || enumerated.startsWith(prefix)) {
923                 proposals.add(new AntCompletionProposal(enumerated, cursorPosition - prefix.length(), prefix.length(), enumerated.length(), null, enumerated, null, AntCompletionProposal.TASK_PROPOSAL));
924             }
925         }
926     }
927
928     private void addBooleanAttributeValueProposals(String JavaDoc prefix, List JavaDoc proposals) {
929         String JavaDoc[] booleanValues = new String JavaDoc[]{"true","false","on","off","yes","no"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
930
String JavaDoc booleanAssist;
931         for (int i = 0; i < booleanValues.length; i++) {
932             booleanAssist= booleanValues[i].toLowerCase();
933             if (prefix.length() == 0 || booleanAssist.startsWith(prefix)) {
934                 proposals.add(new AntCompletionProposal(booleanAssist, cursorPosition -prefix.length(),
935                         prefix.length(), booleanAssist.length(), null, booleanAssist,
936                         null, AntCompletionProposal.TASK_PROPOSAL));
937             }
938         }
939     }
940
941     /**
942      * Returns all possible properties for the specified prefix.
943      * <P>
944      * Note that the completion mode must be property mode, otherwise it is not
945      * safe to call this method.
946      */

947     protected ICompletionProposal[] getPropertyProposals(IDocument document, String JavaDoc prefix, int aCursorPosition) {
948         List JavaDoc proposals = new ArrayList JavaDoc();
949         Map JavaDoc displayStringToProposals= new HashMap JavaDoc();
950         Map JavaDoc properties = findPropertiesFromDocument();
951         
952         Image image = AntUIImages.getImage(IAntUIConstants.IMG_PROPERTY);
953         // Determine replacement length and offset
954
// String from beginning to the beginning of the prefix
955
int replacementLength = prefix.length();
956        int replacementOffset = 0;
957        String JavaDoc text= document.get();
958        String JavaDoc stringToPrefix = text.substring(0, aCursorPosition - prefix.length());
959        // Property proposal
960
String JavaDoc lastTwoCharacters = stringToPrefix.substring(stringToPrefix.length()-2, stringToPrefix.length());
961        boolean appendBraces= true;
962        if(lastTwoCharacters.equals("${")) { //$NON-NLS-1$
963
replacementLength += 2;
964            replacementOffset = aCursorPosition - prefix.length() - 2;
965        } else if(lastTwoCharacters.endsWith("$")) { //$NON-NLS-1$
966
replacementLength += 1;
967            replacementOffset = aCursorPosition - prefix.length() - 1;
968        } else {
969             //support for property proposals for the if/unless attributes of targets
970
replacementOffset= aCursorPosition - prefix.length();
971             appendBraces= false;
972        }
973        
974        if(text.length() > aCursorPosition && text.charAt(aCursorPosition) == '}') {
975            replacementLength += 1;
976        }
977        String JavaDoc propertyName;
978        for(Iterator JavaDoc i=properties.keySet().iterator(); i.hasNext(); ) {
979             propertyName= (String JavaDoc)i.next();
980             if(prefix.length() == 0 || propertyName.toLowerCase().startsWith(prefix)) {
981                 String JavaDoc additionalPropertyInfo = (String JavaDoc)properties.get(propertyName);
982                 
983                 StringBuffer JavaDoc replacementString = new StringBuffer JavaDoc();
984                 if (appendBraces) {
985                     replacementString.append("${"); //$NON-NLS-1$
986
}
987                 replacementString.append(propertyName);
988                 if (appendBraces) {
989                     replacementString.append('}');
990                 }
991                 
992                 if (displayStringToProposals.get(propertyName) == null) {
993                     ICompletionProposal proposal =
994                         new AntCompletionProposal(
995                             replacementString.toString(), replacementOffset, replacementLength,
996                             replacementString.length(), image, propertyName,
997                             additionalPropertyInfo, AntCompletionProposal.PROPERTY_PROPOSAL);
998                     proposals.add(proposal);
999                     displayStringToProposals.put(propertyName, proposal);
1000                }
1001            }
1002        }
1003        return (ICompletionProposal[])proposals.toArray(new ICompletionProposal[proposals.size()]);
1004    }
1005
1006
1007    /**
1008     * Returns all possible proposals for the specified parent name.
1009     * <P>
1010     * No completions will be returned if <code>parentName</code> is
1011     * not known.
1012     *
1013     * @param document the entire document
1014     * @param parentName name of the parent (surrounding) element.
1015     * @param prefix the prefix that all proposals should start with. The prefix
1016     * may be an empty string.
1017     */

1018    protected ICompletionProposal[] getTaskProposals(IDocument document, String JavaDoc parentName, String JavaDoc prefix) {
1019       List JavaDoc proposals = new ArrayList JavaDoc(250);
1020       ICompletionProposal proposal;
1021       if (areTasksOrTypesValidChildren(parentName)) {
1022            //use the definitions in the project as that includes more than what is defined in the DTD
1023
Project project= antModel.getProjectNode().getProject();
1024            Map JavaDoc tasksAndTypes= ComponentHelper.getComponentHelper(project).getAntTypeTable();
1025            createProposals(document, prefix, proposals, tasksAndTypes);
1026            if (parentName.equals("project") && "target".startsWith(prefix)) { //$NON-NLS-1$ //$NON-NLS-2$
1027
proposals.add(newCompletionProposal(document, prefix, "target")); //$NON-NLS-1$
1028
}
1029        } else {
1030            IElement parent = getDtd().getElement(parentName);
1031            if (parent != null) {
1032                IDfm dfm = parent.getDfm();
1033                String JavaDoc[] accepts = dfm.getAccepts();
1034                if (accepts.length == 0) {
1035                    currentProposalMode= PROPOSAL_MODE_NONE;
1036                }
1037                String JavaDoc elementName;
1038                for (int i = 0; i < accepts.length; i++) {
1039                    elementName = accepts[i];
1040                    if(prefix.length() == 0 || elementName.toLowerCase().startsWith(prefix)) {
1041                        proposal = newCompletionProposal(document, prefix, elementName);
1042                        proposals.add(proposal);
1043                    }
1044                }
1045            } else {
1046                //a nested element of a user defined task/type?
1047
Class JavaDoc taskClass= getTaskClass(parentName);
1048                if (taskClass != null) {
1049                    if (taskClass == MacroInstance.class) {
1050                        currentProposalMode= PROPOSAL_MODE_ATTRIBUTE_PROPOSAL;
1051                        addMacroDefElementProposals(parentName, prefix, proposals);
1052                    } else {
1053                        currentProposalMode= PROPOSAL_MODE_NESTED_ELEMENT_PROPOSAL;
1054                        IntrospectionHelper helper= getIntrospectionHelper(taskClass);
1055                        if (helper != null) {
1056                            Enumeration JavaDoc nested= helper.getNestedElements();
1057                            String JavaDoc nestedElement;
1058                            while (nested.hasMoreElements()) {
1059                                nestedElement = (String JavaDoc) nested.nextElement();
1060                                if (prefix.length() == 0 || nestedElement.toLowerCase().startsWith(prefix)) {
1061                                    proposal = newCompletionProposal(document, prefix, nestedElement);
1062                                    proposals.add(proposal);
1063                                }
1064                            }
1065                        }
1066                    }
1067                }
1068            }
1069        }
1070        
1071        proposal= getClosingTaskProposal(getOpenElementName(), prefix, false);
1072        if (proposal != null) {
1073            proposals.add(proposal);
1074        }
1075        
1076        return (ICompletionProposal[])proposals.toArray(new ICompletionProposal[proposals.size()]);
1077   }
1078    
1079    private boolean areTasksOrTypesValidChildren(String JavaDoc parentName) {
1080        return parentName == "project" || parentName == "target" || parentName == "sequential" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1081
|| parentName == "presetdef" || parentName == "parallel" || parentName == "daemons"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1082
}
1083
1084    /**
1085    * Returns proposals that define the structure of a buildfile.
1086    *
1087    * Note that template proposals which define the structure of a buildfile
1088    * are handled by {@link #determineTemplateProposals(ITextViewer, int)}
1089    * which limits proposals by context type.
1090
1091    * @param document the entire document
1092    * @param prefix the prefix that all proposals should start with. The prefix
1093    * may be an empty string.
1094    */

1095   protected ICompletionProposal[] getBuildFileProposals(IDocument document, String JavaDoc prefix) {
1096       String JavaDoc rootElementName= "project"; //$NON-NLS-1$
1097
IElement rootElement = getDtd().getElement(rootElementName);
1098       if (rootElement != null && rootElementName.toLowerCase().startsWith(prefix)) {
1099            ICompletionProposal proposal = newCompletionProposal(document, prefix, rootElementName);
1100            return new ICompletionProposal[] {proposal};
1101        }
1102       
1103       return NO_PROPOSALS;
1104   }
1105
1106    private void createProposals(IDocument document, String JavaDoc prefix, List JavaDoc proposals, Map JavaDoc tasks) {
1107        Iterator JavaDoc keys= tasks.keySet().iterator();
1108        ICompletionProposal proposal;
1109        String JavaDoc key;
1110        while (keys.hasNext()) {
1111            key= antModel.getUserNamespaceCorrectName((String JavaDoc) keys.next());
1112            if (prefix.length() == 0 || key.toLowerCase().startsWith(prefix)) {
1113                proposal = newCompletionProposal(document, prefix, key);
1114                proposals.add(proposal);
1115            }
1116        }
1117    }
1118    
1119    private ICompletionProposal newCompletionProposal(IDocument document, String JavaDoc aPrefix, String JavaDoc elementName) {
1120        additionalProposalOffset= 0;
1121        Image proposalImage = AntUIImages.getImage(IAntUIConstants.IMG_TASK_PROPOSAL);
1122        String JavaDoc proposalInfo = getDescriptionProvider().getDescriptionForTask(elementName);
1123        boolean hasNestedElements= hasNestedElements(elementName);
1124        String JavaDoc replacementString = getTaskProposalReplacementString(elementName, hasNestedElements);
1125        int replacementOffset = cursorPosition - aPrefix.length();
1126        int replacementLength = aPrefix.length();
1127        if (replacementOffset > 0 && document.get().charAt(replacementOffset - 1) == '<') {
1128            replacementOffset--;
1129            replacementLength++;
1130        }
1131        int proposalCursorPosition;
1132        if (hasNestedElements) {
1133            proposalCursorPosition= elementName.length() + 2 + additionalProposalOffset;
1134        } else {
1135            if (additionalProposalOffset > 0) {
1136                additionalProposalOffset+=2; //<antstructure output="|"/>
1137
} else {
1138                additionalProposalOffset+=1; //<arg|/>
1139
}
1140            proposalCursorPosition= elementName.length() + additionalProposalOffset;
1141        }
1142        return new AntCompletionProposal(replacementString, replacementOffset,
1143            replacementLength, proposalCursorPosition, proposalImage, elementName, proposalInfo, AntCompletionProposal.TASK_PROPOSAL);
1144    }
1145
1146    /**
1147     * Returns the one possible completion for the specified unclosed task .
1148     *
1149     * @param openElementName the task that hasn't been closed
1150     * last
1151     * @param prefix The prefix that the one possible proposal should start
1152     * with. The prefix may be an empty string.
1153     * @return the proposal or <code>null</code> if no closing proposal available
1154     */

1155    private ICompletionProposal getClosingTaskProposal(String JavaDoc openElementName, String JavaDoc prefix, boolean closingMode) {
1156        char previousChar = getPreviousChar();
1157        ICompletionProposal proposal= null;
1158        if(openElementName != null) {
1159            if(prefix.length() == 0 || openElementName.toLowerCase().startsWith(prefix)) {
1160                StringBuffer JavaDoc replaceString = new StringBuffer JavaDoc();
1161                if (!closingMode) {
1162                    if (previousChar != '/') {
1163                        if (previousChar != '<') {
1164                            replaceString.append('<');
1165                        }
1166                        replaceString.append('/');
1167                    }
1168                }
1169                replaceString.append(openElementName);
1170                replaceString.append('>');
1171                StringBuffer JavaDoc displayString= new StringBuffer JavaDoc("</"); //$NON-NLS-1$
1172
displayString.append(openElementName);
1173                displayString.append('>');
1174                proposal= new AntCompletionProposal(replaceString.toString(), cursorPosition - prefix.length(), prefix.length(), replaceString.length(), null, displayString.toString(), AntEditorMessages.getString("AntEditorCompletionProcessor.39"), AntCompletionProposal.TAG_CLOSING_PROPOSAL); //$NON-NLS-1$
1175
}
1176        }
1177
1178        return proposal;
1179    }
1180
1181    protected char getPreviousChar() {
1182        ITextSelection selection = (ITextSelection)viewer.getSelectionProvider().getSelection();
1183        int offset= selection.getOffset();
1184        char previousChar= '?';
1185        try {
1186            previousChar= viewer.getDocument().getChar(offset-1);
1187        } catch (BadLocationException e) {
1188            
1189        }
1190        return previousChar;
1191    }
1192
1193    /**
1194     * Returns the replacement string for the specified task name.
1195     */

1196    private String JavaDoc getTaskProposalReplacementString(String JavaDoc aTaskName, boolean hasNested) {
1197        StringBuffer JavaDoc replacement = new StringBuffer JavaDoc("<"); //$NON-NLS-1$
1198
replacement.append(aTaskName);
1199        Node attributeNode= getDescriptionProvider().getAttributesNode(aTaskName);
1200        
1201        if (attributeNode != null) {
1202            appendRequiredAttributes(replacement, attributeNode);
1203        }
1204        
1205        if (hasNested) {
1206            replacement.append("></"); //$NON-NLS-1$
1207
replacement.append(aTaskName);
1208            replacement.append('>');
1209        } else {
1210            replacement.append("/>"); //$NON-NLS-1$
1211
}
1212        return replacement.toString();
1213    }
1214
1215    private void appendRequiredAttributes(StringBuffer JavaDoc replacement, Node attributeNode) {
1216        boolean requiredAdded= false;
1217        NodeList JavaDoc attributes= attributeNode.getChildNodes();
1218        String JavaDoc required;
1219        Node attribute;
1220        for (int i = 0; i < attributes.getLength(); i++) {
1221            attribute = attributes.item(i);
1222            required= getDescriptionProvider().getRequiredOfNode(attribute);
1223            if (required.equalsIgnoreCase("yes")) { //$NON-NLS-1$
1224
String JavaDoc attributeName= getDescriptionProvider().getTaskAttributeName(attribute);
1225                replacement.append(' ');
1226                replacement.append(attributeName);
1227                replacement.append("=\"\""); //$NON-NLS-1$
1228
if (!requiredAdded){
1229                    additionalProposalOffset= attributeName.length() + 2;
1230                    requiredAdded= true;
1231                }
1232            }
1233        }
1234    }
1235
1236    /**
1237     * Returns whether the named element supports nested elements.
1238     */

1239    private boolean hasNestedElements(String JavaDoc elementName) {
1240        IElement element = getDtd().getElement(elementName);
1241        if (element != null) {
1242            return !element.isEmpty();
1243        }
1244        Class JavaDoc taskClass= getTaskClass(elementName);
1245        if (taskClass != null) {
1246            IntrospectionHelper helper= getIntrospectionHelper(taskClass);
1247            if (helper != null) {
1248                Enumeration JavaDoc nested= helper.getNestedElements();
1249                return nested.hasMoreElements();
1250            }
1251        }
1252        return false;
1253    }
1254    
1255    /**
1256     * Finds a direct child element with <code>aChildElementName</code> of
1257     * <code>anElement</code>.
1258     * <P>
1259     * The child will not be searched for in the whole hierarchy but only in
1260     * the hierarchy step below.
1261     *
1262     * @return the found child or <code>null</code> if not found.
1263     */

1264    protected Element findChildElementNamedOf(Element anElement, String JavaDoc aChildElementName) {
1265        NodeList JavaDoc nodeList = anElement.getChildNodes();
1266        for (int i = 0; i < nodeList.getLength(); i++) {
1267            Node childNode = nodeList.item(i);
1268            if(childNode.getNodeType() == Node.ELEMENT_NODE) {
1269                if(childNode.getNodeName().equals(aChildElementName)) {
1270                    return (Element)childNode;
1271                }
1272            }
1273        }
1274        return null;
1275    }
1276
1277    /**
1278     * Determines the current prefix that should be used for completion.
1279     */

1280    private String JavaDoc getCurrentPrefix() {
1281        if (currentPrefix != null) {
1282            return currentPrefix;
1283        }
1284        ITextSelection selection = (ITextSelection)viewer.getSelectionProvider().getSelection();
1285        IDocument doc = viewer.getDocument();
1286        return getPrefixFromDocument(doc.get(), selection.getOffset() + selection.getLength()).toLowerCase();
1287    }
1288
1289
1290    /**
1291     * Returns the prefix in the specified document text with respect to the
1292     * specified offset.
1293     *
1294     * @param aDocumentText the whole content of the edited file as String
1295     * @param anOffset the cursor position
1296     */

1297    protected String JavaDoc getPrefixFromDocument(String JavaDoc aDocumentText, int anOffset) {
1298        if (currentPrefix != null) {
1299            return currentPrefix;
1300        }
1301        int startOfWordToken = anOffset;
1302        
1303        char token= 'a';
1304        if (startOfWordToken > 0) {
1305            token= aDocumentText.charAt(startOfWordToken - 1);
1306        }
1307        
1308        while (startOfWordToken > 0
1309                && (Character.isJavaIdentifierPart(token)
1310                    || '.' == token
1311                    || '-' == token
1312                    || ';' == token)
1313                && !('$' == token)) {
1314            startOfWordToken--;
1315            if (startOfWordToken == 0) {
1316                break; //word goes right to the beginning of the doc
1317
}
1318            token= aDocumentText.charAt(startOfWordToken - 1);
1319        }
1320        
1321        if (startOfWordToken != anOffset) {
1322            currentPrefix= aDocumentText.substring(startOfWordToken, anOffset).toLowerCase();
1323        } else {
1324            currentPrefix= ""; //$NON-NLS-1$
1325
}
1326        return currentPrefix;
1327    }
1328 
1329 
1330    /**
1331     * Returns the current proposal mode.
1332     */

1333    protected int determineProposalMode(IDocument document, int aCursorPosition, String JavaDoc aPrefix) {
1334        if (currentProposalMode != -1) {
1335            return currentProposalMode;
1336        }
1337        if (document.getLength() == 0 || (document.getLength() == 1 && document.get().equals("<"))) { //$NON-NLS-1$
1338
return PROPOSAL_MODE_BUILDFILE;
1339        }
1340        
1341        //String from beginning of document to the beginning of the prefix
1342
String JavaDoc text= document.get();
1343        String JavaDoc stringToPrefix = text.substring(0, aCursorPosition - aPrefix.length());
1344        if (stringToPrefix.length() == 0) {
1345            return PROPOSAL_MODE_BUILDFILE;
1346        }
1347        //Is trimmable from behind
1348
String JavaDoc trimmedString = stringToPrefix.trim();
1349        if (antModel != null && antModel.getProjectNode() == null) {
1350            currentTaskString= getTaskStringFromDocumentStringToPrefix(trimmedString);
1351            if ("project".equals(currentTaskString)) { //$NON-NLS-1$
1352
return PROPOSAL_MODE_ATTRIBUTE_PROPOSAL;
1353            }
1354            return PROPOSAL_MODE_BUILDFILE;
1355        }
1356        
1357        char lastChar = 0;
1358        if(trimmedString.length() > 0) {
1359            lastChar = trimmedString.charAt(trimmedString.length()-1);
1360        } else {
1361            return PROPOSAL_MODE_TASK_PROPOSAL;
1362        }
1363        if(stringToPrefix.charAt(stringToPrefix.length()-1) != lastChar && lastChar != '>' && lastChar != ',') {
1364            /*
1365             * Substring must be trimmable from behind in case of attribute
1366             * proposal because a space or a new line must be used as delimiter
1367             * between task name and attribute or attribute and attribute.
1368             * Example: '<property id="bla" name="hups"'
1369             */

1370             
1371            // Attribute proposal
1372
if(lastChar != '>' && lastChar != '<') {
1373               currentTaskString= getTaskStringFromDocumentStringToPrefix(trimmedString);
1374                if(currentTaskString != null && isKnownElement(currentTaskString)) {
1375                    return PROPOSAL_MODE_ATTRIBUTE_PROPOSAL;
1376                }
1377            }
1378        } else if(stringToPrefix.charAt(stringToPrefix.length() - 1) == '"' || trimmedString.charAt(trimmedString.length() - 1) == ',') {
1379            // Attribute value proposal
1380
currentTaskString= getTaskStringFromDocumentStringToPrefix(trimmedString);
1381            if (currentTaskString != null && isKnownElement(currentTaskString)) {
1382                return PROPOSAL_MODE_ATTRIBUTE_VALUE_PROPOSAL;
1383            }
1384        } else { // Possibly a Task proposal
1385
int spaceIndex = stringToPrefix.lastIndexOf(' ');
1386            int lessThanIndex = stringToPrefix.lastIndexOf('<');
1387            int greaterThanIndex = stringToPrefix.lastIndexOf('>');
1388            
1389            // Task proposal
1390
if(lessThanIndex > spaceIndex && greaterThanIndex < lessThanIndex) {
1391                int slashIndex = stringToPrefix.lastIndexOf('/');
1392                if(slashIndex == lessThanIndex +1) {
1393                    return PROPOSAL_MODE_TASK_PROPOSAL_CLOSING; // ... </
1394
}
1395                return PROPOSAL_MODE_TASK_PROPOSAL;
1396            }
1397            if(lessThanIndex < greaterThanIndex) {
1398                if (isPropertyProposalMode(stringToPrefix)) {
1399                   return PROPOSAL_MODE_PROPERTY_PROPOSAL;
1400               }
1401               return PROPOSAL_MODE_TASK_PROPOSAL;
1402            }
1403        }
1404
1405        // Property proposal
1406
if (isPropertyProposalMode(stringToPrefix)) {
1407            return PROPOSAL_MODE_PROPERTY_PROPOSAL;
1408        }
1409                        
1410        return PROPOSAL_MODE_NONE;
1411    }
1412
1413
1414    private boolean isPropertyProposalMode(String JavaDoc stringToPrefix) {
1415        if(stringToPrefix.length() >= 2) {
1416            String JavaDoc lastTwoChars = stringToPrefix.substring(stringToPrefix.length()-2, stringToPrefix.length());
1417            if(lastTwoChars.equals("${") || //$NON-NLS-1$
1418
stringToPrefix.charAt(stringToPrefix.length()-1) == '$') {
1419                    return true;
1420            }
1421        }
1422        return false;
1423    }
1424    /**
1425     * Returns the last occuring task string in the specified string.
1426     * <P>
1427     * The returned string must not necessarily be a valid Ant task string.
1428     * This can be tested with the method <code>inNamedTaskKnown(String)</code>
1429     * after invoking this method.
1430     *
1431     * @param aDocumentStringToPrefix the String that contains the whole string
1432     * of the currently edited file from the beginning up to the prefix for code
1433     * completion. Example: '<project default="name"><property '.
1434     *
1435     * @return the extracted task string or <code>null</code> if no string could
1436     * be extracted.
1437     */

1438    private String JavaDoc getTaskStringFromDocumentStringToPrefix(String JavaDoc aDocumentStringToPrefix) {
1439            
1440        int lessThanIndex = aDocumentStringToPrefix.lastIndexOf('<');
1441
1442        if(lessThanIndex > -1) {
1443            String JavaDoc taskString = aDocumentStringToPrefix.trim();
1444            taskString = taskString.substring(lessThanIndex+1, taskString.length());
1445            int index = taskString.indexOf(' ');
1446            if(index > 0) {
1447                taskString = taskString.substring(0, index);
1448            }
1449            index = taskString.indexOf('\n');
1450            if(index > 0) {
1451                taskString = taskString.substring(0, index);
1452            }
1453            index = taskString.indexOf('\r');
1454            if(index > 0) {
1455                taskString = taskString.substring(0, index);
1456            }
1457            return taskString;
1458        }
1459        
1460        return null;
1461    }
1462    
1463
1464    /**
1465     * Returns the last occuring attribute string in the specified string.
1466     * <code>null</code> is returned if no attribute string is available.
1467     * <P>
1468     * Calling this method is only safe if the current proposal mode is really
1469     * <code>PROPOSAL_MODE_ATTRIBUTE_VALUE_PROPOSAL</code>.
1470     */

1471    public static String JavaDoc getAttributeStringFromDocumentStringToPrefix(String JavaDoc docStringToPrefix) {
1472        int index = docStringToPrefix.lastIndexOf('=');
1473        if (index == -1) {
1474            return null;
1475        }
1476        String JavaDoc subString = docStringToPrefix.substring(0, index);
1477        subString = subString.trim();
1478        
1479        index = subString.lastIndexOf(' ');
1480        if(index > 0) {
1481            subString = subString.substring(index+1, subString.length());
1482        }
1483        index = subString.lastIndexOf('\n');
1484        if(index > 0) {
1485            subString = subString.substring(index+1, subString.length());
1486        }
1487        index = subString.lastIndexOf('\r');
1488        if(index > 0) {
1489            subString = subString.substring(index+1, subString.length());
1490        }
1491        return trimBeginning(subString);
1492    }
1493    
1494    private static String JavaDoc trimBeginning(String JavaDoc toBeTrimmed) {
1495        int i= 0;
1496        while ((i != toBeTrimmed.length()) && Character.isWhitespace(toBeTrimmed.charAt(i))) {
1497            i++;
1498        }
1499        return toBeTrimmed.substring(i);
1500    }
1501
1502
1503    /**
1504     * Returns whether the specified element name is known
1505     */

1506    protected boolean isKnownElement(String JavaDoc elementName) {
1507        if (elementName.equals("target") || elementName.equals("project")) { //$NON-NLS-1$ //$NON-NLS-2$
1508
return true;
1509        }
1510        AntProjectNode node= antModel.getProjectNode();
1511        if (node != null) {
1512            Project antProject= node.getProject();
1513            ComponentHelper helper= ComponentHelper.getComponentHelper(antProject);
1514            if (helper.getDefinition(elementName) != null) {
1515                return true;
1516            }
1517            if (helper.getDefinition(antModel.getNamespaceCorrectName(elementName)) != null) {
1518                return true;
1519            }
1520            //not everything is a task or type (nested elements)
1521
if (getDtd().getElement(elementName) != null) {
1522                return true;
1523            }
1524            
1525            if (getNestedType() != null) {
1526                return true;
1527            }
1528        }
1529        
1530        return false;
1531    }
1532
1533    private Class JavaDoc getTaskClass(String JavaDoc taskName) {
1534        Class JavaDoc clss= null;
1535        AntProjectNode node= antModel.getProjectNode();
1536        if (node != null) {
1537            Project antProject= node.getProject();
1538            Map JavaDoc tasksAndTypes= ComponentHelper.getComponentHelper(antProject).getAntTypeTable();
1539            clss= (Class JavaDoc)tasksAndTypes.get(taskName);
1540            if (clss == null) {
1541                clss= (Class JavaDoc)tasksAndTypes.get(antModel.getNamespaceCorrectName(taskName));
1542            }
1543        }
1544        return clss;
1545    }
1546
1547    /**
1548     * Finds the parent task element in respect to the cursor position.
1549     *
1550     * @return the parent task element or <code>null</code> if not found.
1551     */

1552    protected String JavaDoc getParentName(IDocument document, int aLineNumber, int aColumnNumber) {
1553        if (document.getLength() == 0) {
1554            return null;
1555        }
1556        AntProjectNode project= antModel.getProjectNode();
1557        if (project == null) {
1558            return null;
1559        }
1560        int offset= getOffset(document, aLineNumber, aColumnNumber);
1561        if (offset == -1) {
1562            return null;
1563        }
1564        AntElementNode node= project.getNode(offset);
1565        if (node == null) {
1566            node= antModel.getOpenElement();
1567        }
1568        if (node == null) {
1569            return ""; //$NON-NLS-1$
1570
} else if (node instanceof AntTaskNode) {
1571            String JavaDoc name= node.getName();
1572            if (offset <= node.getOffset() + name.length() - 1) {
1573                //not really the enclosing node as the offset is within the name of the node
1574
node= node.getParentNode();
1575            } else {
1576                return name;
1577            }
1578        }
1579        if (node instanceof AntTaskNode) {
1580            return node.getName();
1581        } else if (node instanceof AntTargetNode) {
1582            return "target"; //$NON-NLS-1$
1583
} else {
1584            return "project"; //$NON-NLS-1$
1585
}
1586    }
1587
1588    /**
1589     * Return the properties as defined in the entire buildfile
1590     *
1591     * @return a map with all the found properties
1592     */

1593    private Map JavaDoc findPropertiesFromDocument() {
1594        Project project= antModel.getProjectNode().getProject();
1595        return project.getProperties();
1596    }
1597    
1598    private Map JavaDoc getTargets() {
1599        Project project = antModel.getProjectNode().getProject();
1600        return project.getTargets();
1601    }
1602
1603    protected File JavaDoc getEditedFile() {
1604        IWorkbenchPage page= AntUIPlugin.getActivePage();
1605        if (page == null) {
1606            return null;
1607        }
1608        IEditorPart editor= page.getActiveEditor();
1609        if (editor == null) {
1610            return null;
1611        }
1612        FileEditorInput input = (FileEditorInput) editor.getEditorInput();
1613        String JavaDoc projectPath = input.getFile().getProject().getLocation().toFile().getAbsolutePath();
1614        String JavaDoc projectRelativeFilePath = input.getFile().getFullPath().removeFirstSegments(1).makeRelative().toString();
1615        return new File JavaDoc(projectPath + File.separator + projectRelativeFilePath);
1616    }
1617    
1618    private String JavaDoc getOpenElementName() {
1619        AntElementNode node= antModel.getOpenElement();
1620        if (node == null) {
1621            return null;
1622        }
1623        return node.getName();
1624    }
1625
1626    /**
1627     * Finds the enclosing target in respect to the cursor position and returns its name
1628     *
1629     * @return the name of the enclosing target or <code>null</code> if not found
1630     * or the element is not contained in a target.
1631     */

1632    private String JavaDoc getEnclosingTargetName(IDocument document, int aLineNumber, int aColumnNumber) {
1633
1634       AntProjectNode project= antModel.getProjectNode();
1635       int offset= getOffset(document, aLineNumber, aColumnNumber);
1636       if(offset == -1) {
1637            return null;
1638       }
1639       AntElementNode node= project.getNode(offset);
1640       if (node instanceof AntTaskNode) {
1641            node= node.getParentNode();
1642            if (!(node instanceof AntTargetNode)) {
1643                //top level task
1644
node= null;
1645            }
1646       } else if (node instanceof AntProjectNode) {
1647            node= null;
1648       }
1649       String JavaDoc targetName = null;
1650       if(node == null
1651            || (targetName = ((AntTargetNode)node).getTarget().getName()) == null
1652            || targetName.length() == 0) {
1653            return null;
1654       }
1655       return targetName;
1656    }
1657    
1658    private int getOffset(IDocument document, int line, int column) {
1659        try {
1660            return document.getLineOffset(line ) + column - 1;
1661        } catch (BadLocationException e) {
1662            return -1;
1663        }
1664    }
1665    
1666    /**
1667     * Sets this processor's set of characters triggering the activation of the
1668     * completion proposal computation.
1669     *
1670     * @param activationSet the activation set
1671     */

1672    public void setCompletionProposalAutoActivationCharacters(char[] activationSet) {
1673        autoActivationChars= activationSet;
1674    }
1675
1676    /* (non-Javadoc)
1677     * @see org.eclipse.jface.text.templates.TemplateCompletionProcessor#extractPrefix(org.eclipse.jface.text.ITextViewer, int)
1678     */

1679    protected String JavaDoc extractPrefix(ITextViewer textViewer, int offset) {
1680        return getPrefixFromDocument(textViewer.getDocument().get(), offset);
1681    }
1682
1683    /**
1684     * Cut out angular brackets for relevance sorting, since the template name
1685     * does not contain the brackets.
1686     */

1687    protected int getRelevance(Template template, String JavaDoc prefix) {
1688        if (prefix.startsWith("<")) //$NON-NLS-1$
1689
prefix= prefix.substring(1);
1690        if (template.getName().startsWith(prefix))
1691            return 90;
1692        return 0;
1693    }
1694
1695    /* (non-Javadoc)
1696     * @see org.eclipse.jface.text.templates.TemplateCompletionProcessor#getTemplates(java.lang.String)
1697     */

1698    protected Template[] getTemplates(String JavaDoc contextTypeId) {
1699        return AntTemplateAccess.getDefault().getTemplateStore().getTemplates(contextTypeId);
1700    }
1701
1702    /* (non-Javadoc)
1703     * @see org.eclipse.jface.text.templates.TemplateCompletionProcessor#getContextType(org.eclipse.jface.text.ITextViewer, org.eclipse.jface.text.IRegion)
1704     */

1705    protected TemplateContextType getContextType(ITextViewer textViewer, IRegion region) {
1706         switch (determineProposalMode(textViewer.getDocument(), cursorPosition, getCurrentPrefix())) {
1707            case PROPOSAL_MODE_TASK_PROPOSAL:
1708                if (getEnclosingTargetName(textViewer.getDocument(), lineNumber, columnNumber) == null) {
1709                    return AntTemplateAccess.getDefault().getContextTypeRegistry().getContextType(TargetContextType.TARGET_CONTEXT_TYPE);
1710                }
1711                return AntTemplateAccess.getDefault().getContextTypeRegistry().getContextType(TaskContextType.TASK_CONTEXT_TYPE);
1712            case PROPOSAL_MODE_BUILDFILE:
1713                return AntTemplateAccess.getDefault().getContextTypeRegistry().getContextType(BuildFileContextType.BUILDFILE_CONTEXT_TYPE);
1714            case PROPOSAL_MODE_NONE:
1715            case PROPOSAL_MODE_ATTRIBUTE_PROPOSAL:
1716            case PROPOSAL_MODE_TASK_PROPOSAL_CLOSING:
1717            case PROPOSAL_MODE_ATTRIBUTE_VALUE_PROPOSAL:
1718            case PROPOSAL_MODE_PROPERTY_PROPOSAL:
1719            case PROPOSAL_MODE_NESTED_ELEMENT_PROPOSAL:
1720            default :
1721                return null;
1722        }
1723    }
1724
1725    /* (non-Javadoc)
1726     * @see org.eclipse.jface.text.templates.TemplateCompletionProcessor#getImage(org.eclipse.jface.text.templates.Template)
1727     */

1728    protected Image getImage(Template template) {
1729        return AntUIImages.getImage(IAntUIConstants.IMG_TEMPLATE_PROPOSAL);
1730    }
1731    
1732    /* (non-Javadoc)
1733     * @see org.eclipse.jface.text.templates.TemplateCompletionProcessor#createContext(org.eclipse.jface.text.ITextViewer, org.eclipse.jface.text.IRegion)
1734     */

1735    protected TemplateContext createContext(ITextViewer contextViewer, IRegion region) {
1736        TemplateContextType contextType= getContextType(contextViewer, region);
1737        if (contextType != null) {
1738            Point selection= contextViewer.getSelectedRange();
1739            Position position;
1740            if (selection.y > 0) {
1741                position= new Position(selection.x, selection.y);
1742            } else {
1743                position= new Position(region.getOffset(), region.getLength());
1744            }
1745            
1746            IDocument document= contextViewer.getDocument();
1747            return new AntContext(contextType, document, antModel, position);
1748        }
1749        return null;
1750    }
1751    
1752    /* (non-Javadoc)
1753     * @see org.eclipse.jface.text.templates.TemplateCompletionProcessor#createProposal(org.eclipse.jface.text.templates.Template, org.eclipse.jface.text.templates.TemplateContext, org.eclipse.jface.text.Region, int)
1754     */

1755    protected ICompletionProposal createProposal(Template template,TemplateContext context, IRegion region, int relevance) {
1756        AntTemplateProposal proposal= new AntTemplateProposal(template, context, region, getImage(template), relevance);
1757        proposal.setInformationControlCreator(new AntTemplateInformationControlCreator());
1758        return proposal;
1759    }
1760
1761    protected ISchema getDtd() {
1762        if (fgDtd == null) {
1763            IRunnableWithProgress runnable= new IRunnableWithProgress() {
1764                public void run(IProgressMonitor monitor)
1765                        throws InvocationTargetException JavaDoc, InterruptedException JavaDoc {
1766                    try {
1767                        fgDtd= parseDtd();
1768                    } catch (IOException JavaDoc e) {
1769                        AntUIPlugin.log(e);
1770                    } catch (ParseError e) {
1771                        AntUIPlugin.log(e);
1772                    }
1773                }
1774            };
1775            
1776            IProgressService service= PlatformUI.getWorkbench().getProgressService();
1777            try {
1778                service.busyCursorWhile(runnable);
1779            } catch (InvocationTargetException JavaDoc e) {
1780            } catch (InterruptedException JavaDoc e) {
1781            }
1782        }
1783        return fgDtd;
1784    }
1785
1786    /**
1787     * The provider for all task and attribute descriptions.
1788     */

1789    private TaskDescriptionProvider getDescriptionProvider() {
1790        return TaskDescriptionProvider.getDefault();
1791    }
1792    
1793    protected static void resetCodeCompletionDataStructures() {
1794        fgDtd= null;
1795        TaskDescriptionProvider.reset();
1796    }
1797
1798    /* (non-Javadoc)
1799     * @see org.eclipse.jface.text.contentassist.ICompletionListener#assistSessionStarted(org.eclipse.jface.text.contentassist.ContentAssistEvent)
1800     */

1801    public void assistSessionStarted(ContentAssistEvent event) {
1802        IContentAssistant assistant= event.assistant;
1803        if (assistant instanceof IContentAssistantExtension2) {
1804            fContentAssistant= (IContentAssistantExtension2) assistant;
1805        }
1806    }
1807
1808    /* (non-Javadoc)
1809     * @see org.eclipse.jface.text.contentassist.ICompletionListener#assistSessionEnded(org.eclipse.jface.text.contentassist.ContentAssistEvent)
1810     */

1811    public void assistSessionEnded(ContentAssistEvent event) {
1812        fContentAssistant= null;
1813        fTemplatesOnly= false;
1814    }
1815
1816    /* (non-Javadoc)
1817     * @see org.eclipse.jface.text.contentassist.ICompletionListener#selectionChanged(org.eclipse.jface.text.contentassist.ICompletionProposal, boolean)
1818     */

1819    public void selectionChanged(ICompletionProposal proposal, boolean smartToggle) {
1820    }
1821    
1822    private String JavaDoc getIterationGestureMessage(String JavaDoc showMessage) {
1823        final IBindingService bindingSvc= (IBindingService) PlatformUI.getWorkbench().getAdapter(IBindingService.class);
1824        TriggerSequence[] triggers= bindingSvc.getActiveBindingsFor(getContentAssistCommand());
1825        String JavaDoc message;
1826        if (triggers.length > 0) {
1827            message= MessageFormat.format(AntEditorMessages.getString("AntEditorCompletionProcessor.63"), new Object JavaDoc[] { triggers[0].format(), showMessage }); //$NON-NLS-1$
1828
} else {
1829            message= MessageFormat.format(AntEditorMessages.getString("AntEditorCompletionProcessor.64"), new String JavaDoc[] {showMessage}); //$NON-NLS-1$
1830
}
1831        return message;
1832    }
1833
1834    private ParameterizedCommand getContentAssistCommand() {
1835        final ICommandService commandSvc= (ICommandService) PlatformUI.getWorkbench().getAdapter(ICommandService.class);
1836        final Command command= commandSvc.getCommand(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
1837        ParameterizedCommand pCmd= new ParameterizedCommand(command, null);
1838        return pCmd;
1839    }
1840}
Popular Tags