KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ant > internal > ui > editor > outline > AntModel


1 /*******************************************************************************
2  * Copyright (c) 2000, 2004 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  * Nico Seessle - bug 51332
11  *******************************************************************************/

12
13 package org.eclipse.ant.internal.ui.editor.outline;
14
15 import java.io.File JavaDoc;
16 import java.text.MessageFormat JavaDoc;
17 import java.util.ArrayList JavaDoc;
18 import java.util.Collection JavaDoc;
19 import java.util.HashMap JavaDoc;
20 import java.util.Iterator JavaDoc;
21 import java.util.List JavaDoc;
22 import java.util.Map JavaDoc;
23 import java.util.Set JavaDoc;
24 import java.util.Stack JavaDoc;
25
26 import org.apache.tools.ant.AntTypeDefinition;
27 import org.apache.tools.ant.BuildException;
28 import org.apache.tools.ant.ComponentHelper;
29 import org.apache.tools.ant.IntrospectionHelper;
30 import org.apache.tools.ant.Location;
31 import org.apache.tools.ant.Project;
32 import org.apache.tools.ant.Target;
33 import org.apache.tools.ant.Task;
34 import org.apache.tools.ant.TaskAdapter;
35 import org.apache.tools.ant.UnknownElement;
36 import org.eclipse.ant.core.AntCorePlugin;
37 import org.eclipse.ant.core.Type;
38 import org.eclipse.ant.internal.core.IAntCoreConstants;
39 import org.eclipse.ant.internal.ui.editor.model.AntDefiningTaskNode;
40 import org.eclipse.ant.internal.ui.editor.model.AntElementNode;
41 import org.eclipse.ant.internal.ui.editor.model.AntImportNode;
42 import org.eclipse.ant.internal.ui.editor.model.AntProjectNode;
43 import org.eclipse.ant.internal.ui.editor.model.AntPropertyNode;
44 import org.eclipse.ant.internal.ui.editor.model.AntTargetNode;
45 import org.eclipse.ant.internal.ui.editor.model.AntTaskNode;
46 import org.eclipse.ant.internal.ui.editor.model.IAntModelConstants;
47 import org.eclipse.ant.internal.ui.editor.utils.ProjectHelper;
48 import org.eclipse.ant.internal.ui.model.AntUIPlugin;
49 import org.eclipse.ant.internal.ui.preferences.AntEditorPreferenceConstants;
50 import org.eclipse.core.resources.IFile;
51 import org.eclipse.core.resources.ResourcesPlugin;
52 import org.eclipse.core.runtime.IPath;
53 import org.eclipse.core.runtime.Preferences;
54 import org.eclipse.jface.text.BadLocationException;
55 import org.eclipse.jface.text.DocumentEvent;
56 import org.eclipse.jface.text.IDocument;
57 import org.eclipse.jface.text.IDocumentListener;
58 import org.eclipse.jface.text.reconciler.DirtyRegion;
59 import org.xml.sax.Attributes JavaDoc;
60 import org.xml.sax.SAXParseException JavaDoc;
61
62 public class AntModel {
63
64     private static ClassLoader JavaDoc fgClassLoader;
65     private static int fgInstanceCount= 0;
66     
67     private XMLCore fCore;
68     private IDocument fDocument;
69     private IProblemRequestor fProblemRequestor;
70     private LocationProvider fLocationProvider;
71
72     private AntProjectNode fProjectNode;
73     private AntTargetNode fCurrentTargetNode;
74     private AntElementNode fLastNode;
75     private AntElementNode fNodeBeingResolved;
76     
77     private AntTargetNode fIncrementalTarget= null;
78     private boolean fReplaceHasOccurred= false;
79     private int fRemoveLengthOfReplace= 0;
80     private DirtyRegion fDirtyRegion= null;
81     
82      /**
83      * Stack of still open elements.
84      * <P>
85      * On top of the stack is the innermost element.
86      */

87     private Stack JavaDoc fStillOpenElements = new Stack JavaDoc();
88     
89     private Map JavaDoc fTaskToNode= new HashMap JavaDoc();
90
91     private List JavaDoc fTaskNodes= new ArrayList JavaDoc();
92     
93     private Map JavaDoc fEntityNameToPath;
94
95     private final Object JavaDoc fDirtyLock= new Object JavaDoc();
96     private boolean fIsDirty= true;
97     private IDocumentListener fListener;
98     private File JavaDoc fEditedFile= null;
99     private AntEditorMarkerUpdater fMarkerUpdater= null;
100     private Set JavaDoc fNamesOfOldDefiningNodes;
101     
102     private Preferences.IPropertyChangeListener fCorePropertyChangeListener= new Preferences.IPropertyChangeListener() {
103         public void propertyChange(Preferences.PropertyChangeEvent event) {
104             if (event.getProperty().equals(IAntCoreConstants.PREFERENCE_CLASSPATH_CHANGED)) {
105                 if (((Boolean JavaDoc)event.getNewValue()) == Boolean.TRUE) {
106                     reconcileForPropertyChange(true);
107                 }
108             }
109         }
110     };
111     
112     private Preferences.IPropertyChangeListener fUIPropertyChangeListener= new Preferences.IPropertyChangeListener() {
113         public void propertyChange(Preferences.PropertyChangeEvent event) {
114             String JavaDoc property= event.getProperty();
115             if (property.equals(AntEditorPreferenceConstants.PROBLEM)) {
116                 AntUIPlugin.getDefault().getPluginPreferences().removePropertyChangeListener(fUIPropertyChangeListener);
117                 reconcileForPropertyChange(false);
118                 AntUIPlugin.getDefault().getPluginPreferences().setToDefault(AntEditorPreferenceConstants.PROBLEM);
119                 AntUIPlugin.getDefault().getPluginPreferences().addPropertyChangeListener(fUIPropertyChangeListener);
120             } else if (property.equals(AntEditorPreferenceConstants.CODEASSIST_USER_DEFINED_TASKS)) {
121                 if (((Boolean JavaDoc)event.getNewValue()).booleanValue()) {
122                     reconcileForPropertyChange(false);
123                 }
124             }
125         }
126     };
127
128     public AntModel(XMLCore core, IDocument document, IProblemRequestor problemRequestor, LocationProvider locationProvider) {
129         fCore= core;
130         fDocument= document;
131         fProblemRequestor= problemRequestor;
132         fMarkerUpdater= new AntEditorMarkerUpdater();
133         fMarkerUpdater.setModel(this);
134         fLocationProvider= locationProvider;
135         AntCorePlugin.getPlugin().getPluginPreferences().addPropertyChangeListener(fCorePropertyChangeListener);
136         AntUIPlugin.getDefault().getPluginPreferences().addPropertyChangeListener(fUIPropertyChangeListener);
137         AntDefiningTaskNode.setJavaClassPath();
138         fgInstanceCount++;
139     }
140
141     private void reconcileForPropertyChange(boolean classpathChanged) {
142         if (classpathChanged) {
143             fgClassLoader= null;
144             AntDefiningTaskNode.setJavaClassPath();
145         }
146         fIsDirty= true;
147         reconcile(null);
148         fCore.notifyDocumentModelListeners(new DocumentModelChangeEvent(this, true));
149         fMarkerUpdater.updateMarkers();
150     }
151
152     public void install() {
153         fListener= new IDocumentListener() {
154             public void documentAboutToBeChanged(DocumentEvent event) {
155                 synchronized (fDirtyLock) {
156                     fIsDirty= true;
157                 }
158             }
159             public void documentChanged(DocumentEvent event) {}
160         };
161         fDocument.addDocumentListener(fListener);
162     }
163     
164     public void dispose() {
165         synchronized (this) {
166             if (fDocument != null) {
167                 fDocument.removeDocumentListener(fListener);
168             }
169             fDocument= null;
170             fCore= null;
171             ProjectHelper.setAntModel(null);
172         }
173         
174         AntCorePlugin.getPlugin().getPluginPreferences().removePropertyChangeListener(fCorePropertyChangeListener);
175         AntUIPlugin.getDefault().getPluginPreferences().removePropertyChangeListener(fUIPropertyChangeListener);
176         fgInstanceCount--;
177         if (fgInstanceCount == 0) {
178             fgClassLoader= null;
179         }
180         if (getProjectNode() != null) {
181             //cleanup the introspection helpers that may have been generated
182
IntrospectionHelper.getHelper(getProjectNode().getProject(), AntModel.class);
183             getProjectNode().getProject().fireBuildFinished(null);
184         }
185     }
186     
187     public void reconcile(DirtyRegion region) {
188         //TODO turn off incremental as it is deferred to post 3.0
189
region= null;
190         fDirtyRegion= region;
191         synchronized (fDirtyLock) {
192             if (!fIsDirty) {
193                 return;
194             }
195             if (fReplaceHasOccurred && region != null) {
196                 //this is the removed part of a replace
197
//the insert region will be along shortly
198
fRemoveLengthOfReplace= region.getLength();
199                 fReplaceHasOccurred= false;
200                 return;
201             }
202             fIsDirty= false;
203         }
204
205         synchronized (this) {
206             if (fCore == null) {
207                 // disposed
208
return;
209             }
210             
211             if (fDocument == null) {
212                 fProjectNode= null;
213             } else {
214                 reset(region);
215                 parseDocument(fDocument, region);
216                 fRemoveLengthOfReplace= 0;
217                 fDirtyRegion= null;
218                 reconcileTaskAndTypes();
219             }
220     
221             fCore.notifyDocumentModelListeners(new DocumentModelChangeEvent(this));
222         }
223     }
224
225     private void reset(DirtyRegion region) {
226         //TODO this could be better for incremental parsing
227
//cleaning up the task to node map (do when a target is reset)
228
fCurrentTargetNode= null;
229         
230         if (region == null ) {
231             fStillOpenElements= new Stack JavaDoc();
232             fTaskToNode= new HashMap JavaDoc();
233             fTaskNodes= new ArrayList JavaDoc();
234             fNodeBeingResolved= null;
235             fLastNode= null;
236         }
237     }
238
239     public AntElementNode[] getRootElements() {
240         reconcile(null);
241         if (fProjectNode == null) {
242             return new AntElementNode[0];
243         }
244             return new AntElementNode[] {fProjectNode};
245         }
246
247     private void parseDocument(IDocument input, DirtyRegion region) {
248         boolean parsed= true;
249         if (input.getLength() == 0) {
250             fProjectNode= null;
251             parsed= false;
252             return;
253         }
254         ClassLoader JavaDoc parsingClassLoader= getClassLoader();
255         ClassLoader JavaDoc originalClassLoader= Thread.currentThread().getContextClassLoader();
256         Thread.currentThread().setContextClassLoader(parsingClassLoader);
257         boolean incremental= false;
258         Project project= null;
259         try {
260             String JavaDoc textToParse= null;
261             ProjectHelper projectHelper= null;
262             if (region == null || fProjectNode == null) { //full parse
263
if (fProjectNode == null || !fProjectNode.hasChildren()) {
264                     fProjectNode= null;
265                     project = new AntModelProject();
266                     projectHelper= prepareForFullParse(project, parsingClassLoader);
267                     textToParse= input.get(); //the entire document
268
} else {
269                     project= fProjectNode.getProject();
270                     projectHelper= (ProjectHelper)project.getReference("ant.projectHelper"); //$NON-NLS-1$
271
textToParse= prepareForFullIncremental(input);
272                 }
273             } else { //incremental
274
project= fProjectNode.getProject();
275                 textToParse= prepareForIncrementalParse(project, region, input);
276                 if (textToParse == null) {
277                     parsed= false;
278                     return;
279                 }
280                 incremental= true;
281                 projectHelper= (ProjectHelper)project.getReference("ant.projectHelper"); //$NON-NLS-1$
282
}
283             beginReporting();
284             Map JavaDoc references= project.getReferences();
285             references.remove("ant.parsing.context"); //$NON-NLS-1$
286
ProjectHelper.setAntModel(this);
287             projectHelper.parse(project, textToParse);
288             
289         } catch(BuildException e) {
290             handleBuildException(e, null);
291         } finally {
292             Thread.currentThread().setContextClassLoader(originalClassLoader);
293             if (parsed) {
294                 if (incremental) {
295                     updateAfterIncrementalChange(region, true);
296                 }
297                 resolveBuildfile();
298                 endReporting();
299                 project.fireBuildFinished(null); //cleanup (IntrospectionHelper)
300
fIncrementalTarget= null;
301             }
302         }
303     }
304     
305     private void updateAfterIncrementalChange(DirtyRegion region, boolean updateProjectLength) {
306         if (fProjectNode == null) {
307             return;
308         }
309         int editAdjustment= determineEditAdjustment(region);
310         if (editAdjustment == 0) {
311             return;
312         }
313         if (updateProjectLength) { //edit within the project
314
fProjectNode.setLength(fProjectNode.getLength() + editAdjustment);
315         } else {
316             fProjectNode.setOffset(fProjectNode.getOffset() + editAdjustment);
317         }
318         if ((fIncrementalTarget != null || !updateProjectLength) && fProjectNode.hasChildren()) {
319             List JavaDoc children= fProjectNode.getChildNodes();
320             int index= children.indexOf(fIncrementalTarget) + 1;
321             updateNodesForIncrementalParse(editAdjustment, children, index);
322         }
323     }
324
325     private void updateNodesForIncrementalParse(int editAdjustment, List JavaDoc children, int index) {
326         AntElementNode node;
327         for (int i = index; i < children.size(); i++) {
328             node= (AntElementNode)children.get(i);
329             node.setOffset(node.getOffset() + editAdjustment);
330             if (node.hasChildren()) {
331                 updateNodesForIncrementalParse(editAdjustment, node.getChildNodes(), 0);
332             }
333         }
334     }
335
336     private ProjectHelper prepareForFullParse(Project project, ClassLoader JavaDoc parsingClassLoader) {
337         initializeProject(project, parsingClassLoader);
338         // Ant's parsing facilities always works on a file, therefore we need
339
// to determine the actual location of the file. Though the file
340
// contents will not be parsed. We parse the passed document string
341
File JavaDoc file = getEditedFile();
342         String JavaDoc filePath= ""; //$NON-NLS-1$
343
if (file != null) {
344             filePath= file.getAbsolutePath();
345         }
346         project.setUserProperty("ant.file", filePath); //$NON-NLS-1$
347

348         ProjectHelper projectHelper= new ProjectHelper(this);
349         projectHelper.setBuildFile(file);
350         project.addReference("ant.projectHelper", projectHelper); //$NON-NLS-1$
351
return projectHelper;
352     }
353     
354     private String JavaDoc prepareForIncrementalParse(Project project, DirtyRegion region, IDocument input) {
355         String JavaDoc textToParse= null;
356         AntElementNode node= fProjectNode.getNode(region.getOffset());
357         if (node == null) {
358             if (fProjectNode.getLength() > 0) {
359                 //outside of any element
360
if (region.getOffset() < fProjectNode.getOffset()) {
361                     updateAfterIncrementalChange(region, false);
362                 }
363                 return null;
364             }
365             //nodes don't know their lengths due to parsing error --> full parse
366
textToParse = prepareForFullIncremental(input);
367             return textToParse;
368         }
369         
370         while (node != null && !(node instanceof AntTargetNode)) {
371             node= node.getParentNode();
372         }
373         if (node == null) { //no enclosing target node found
374
if (region.getText() != null && region.getText().trim().length() == 0) {
375                 return null; //no need to parse for whitespace additions
376
}
377             textToParse= prepareForFullIncremental(input);
378         } else {
379             fIncrementalTarget= (AntTargetNode)node;
380             if (fIncrementalTarget.hasChildren()) {
381                 Collection JavaDoc nodes= fTaskToNode.values();
382                 nodes.removeAll(fIncrementalTarget.getDescendents());
383             }
384             
385             markHierarchy(node, XMLProblem.NO_PROBLEM);
386             
387             StringBuffer JavaDoc temp = createIncrementalContents(project);
388             fIncrementalTarget.reset();
389             try {
390                 int editAdjustment = determineEditAdjustment(region) + 1;
391                 String JavaDoc targetString= input.get(node.getOffset() - 1, node.getLength() + editAdjustment);
392                 temp.append(targetString);
393                 temp.append("\n</project>"); //$NON-NLS-1$
394
textToParse= temp.toString();
395             } catch (BadLocationException e) {
396                 textToParse= input.get();
397             }
398         }
399         return textToParse;
400     }
401
402     private String JavaDoc prepareForFullIncremental(IDocument input) {
403         String JavaDoc textToParse= input.get();
404         fProjectNode.reset();
405         fTaskToNode= new HashMap JavaDoc();
406         fTaskNodes= new ArrayList JavaDoc();
407         return textToParse;
408     }
409
410     private StringBuffer JavaDoc createIncrementalContents(Project project) {
411         int offset= fIncrementalTarget.getOffset();
412         int line= getLine(offset) - 1;
413         
414         StringBuffer JavaDoc temp= new StringBuffer JavaDoc("<project");//$NON-NLS-1$
415
String JavaDoc defltTarget= project.getDefaultTarget();
416         if (defltTarget != null) {
417             temp.append(" default=\""); //$NON-NLS-1$
418
temp.append(defltTarget);
419             temp.append("\""); //$NON-NLS-1$
420
}
421         temp.append(">"); //$NON-NLS-1$
422
while (line > 0) {
423             temp.append("\n"); //$NON-NLS-1$
424
line--;
425         }
426         return temp;
427     }
428
429     private int determineEditAdjustment(DirtyRegion region) {
430         int editAdjustment= 0;
431         if (region.getType().equals(DirtyRegion.INSERT)) {
432             editAdjustment+= region.getLength() - fRemoveLengthOfReplace;
433         } else {
434             editAdjustment-= region.getLength();
435         }
436         return editAdjustment;
437     }
438
439     private void initializeProject(Project project, ClassLoader JavaDoc loader) {
440         project.init();
441         setTasks(project, loader);
442         setTypes(project, loader);
443     }
444     
445     private void setTasks(Project project, ClassLoader JavaDoc loader) {
446         List JavaDoc tasks = AntCorePlugin.getPlugin().getPreferences().getTasks();
447         for (Iterator JavaDoc iterator = tasks.iterator(); iterator.hasNext();) {
448             org.eclipse.ant.core.Task task = (org.eclipse.ant.core.Task) iterator.next();
449             AntTypeDefinition def= new AntTypeDefinition();
450             def.setName(task.getTaskName());
451             def.setClassName(task.getClassName());
452             def.setClassLoader(loader);
453             def.setAdaptToClass(Task.class);
454             def.setAdapterClass(TaskAdapter.class);
455             ComponentHelper.getComponentHelper(project).addDataTypeDefinition(def);
456         }
457     }
458         
459     private void setTypes(Project project, ClassLoader JavaDoc loader) {
460         List JavaDoc types = AntCorePlugin.getPlugin().getPreferences().getTypes();
461         for (Iterator JavaDoc iterator = types.iterator(); iterator.hasNext();) {
462             Type type = (Type) iterator.next();
463              AntTypeDefinition def = new AntTypeDefinition();
464              def.setName(type.getTypeName());
465              def.setClassName(type.getClassName());
466              def.setClassLoader(loader);
467              ComponentHelper.getComponentHelper(project).addDataTypeDefinition(def);
468         }
469     }
470
471     private void resolveBuildfile() {
472         Collection JavaDoc nodeCopy= new ArrayList JavaDoc(fTaskNodes.size());
473         nodeCopy.addAll(fTaskNodes);
474         Iterator JavaDoc iter= nodeCopy.iterator();
475         while (iter.hasNext()) {
476             AntTaskNode node = (AntTaskNode) iter.next();
477             fNodeBeingResolved= node;
478             if (node.configure(false)) {
479                 //resolve any new elements that may have been added
480
resolveBuildfile();
481             }
482         }
483         fNodeBeingResolved= null;
484         
485         checkTargets();
486     }
487
488     /**
489      * Check that we have a default target defined and that the
490      * target dependencies exist.
491      */

492     private void checkTargets() {
493         if (fProjectNode == null) {
494             return;
495         }
496         String JavaDoc defaultTargetName= fProjectNode.getProject().getDefaultTarget();
497         if (defaultTargetName == null || fProjectNode.getProject().getTargets().get(defaultTargetName) == null) {
498             //no default target
499
String JavaDoc message;
500             if (defaultTargetName == null) {
501                 message= AntOutlineMessages.getString("AntModel.0"); //$NON-NLS-1$
502
} else {
503                 message= MessageFormat.format(AntOutlineMessages.getString("AntModel.43"), new String JavaDoc[]{defaultTargetName}); //$NON-NLS-1$
504
}
505             IProblem problem= createProblem(message, fProjectNode.getOffset(), fProjectNode.getSelectionLength(), XMLProblem.SEVERITY_ERROR);
506             acceptProblem(problem);
507             markHierarchy(fProjectNode, XMLProblem.SEVERITY_ERROR);
508         }
509         if (!fProjectNode.hasChildren()) {
510             return;
511         }
512         List JavaDoc children= fProjectNode.getChildNodes();
513         Iterator JavaDoc iter= children.iterator();
514         while (iter.hasNext()) {
515             AntElementNode node = (AntElementNode) iter.next();
516             AntElementNode originalNode= node;
517             if (node instanceof AntTargetNode) {
518                 String JavaDoc missing= ((AntTargetNode)node).checkDependencies();
519                 if (missing != null) {
520                     String JavaDoc message= MessageFormat.format(AntOutlineMessages.getString("AntModel.44"), new String JavaDoc[]{missing}); //$NON-NLS-1$
521
AntElementNode importNode= node.getImportNode();
522                     if (importNode != null) {
523                         node= importNode;
524                     }
525                     IProblem problem= createProblem(message, node.getOffset(), node.getSelectionLength(), XMLProblem.SEVERITY_ERROR);
526                     acceptProblem(problem);
527                     markHierarchy(originalNode, XMLProblem.SEVERITY_ERROR);
528                 }
529             }
530         }
531         
532     }
533
534     public void handleBuildException(BuildException e, AntElementNode node, int severity) {
535         try {
536             if (node != null) {
537                 markHierarchy(node, severity);
538             }
539             Location location= e.getLocation();
540             int line= 0;
541             int originalOffset= 0;
542             int nonWhitespaceOffset= 0;
543             int length= 0;
544             if (location == Location.UNKNOWN_LOCATION && node != null) {
545                 nonWhitespaceOffset= node.getOffset();
546                 length= node.getLength();
547             } else {
548                 line= location.getLineNumber();
549                 if (line == 0) {
550                     if (getProjectNode() != null) {
551                         length= getProjectNode().getSelectionLength();
552                         nonWhitespaceOffset= getProjectNode().getOffset();
553                         if (severity == XMLProblem.SEVERITY_ERROR) {
554                             getProjectNode().setProblemSeverity(XMLProblem.NO_PROBLEM);
555                         }
556                     } else {
557                         return;
558                     }
559                 } else {
560                     if (node == null) {
561                         originalOffset= getOffset(line, 1);
562                         nonWhitespaceOffset= originalOffset;
563                         try {
564                             nonWhitespaceOffset= getNonWhitespaceOffset(line, 1);
565                         } catch (BadLocationException be) {
566                         }
567                             length= getLastCharColumn(line) - (nonWhitespaceOffset - originalOffset);
568                         } else {
569                             nonWhitespaceOffset= node.getOffset();
570                             length= node.getLength();
571                     }
572                 }
573             }
574             notifyProblemRequestor(e, nonWhitespaceOffset, length, severity);
575         } catch (BadLocationException e1) {
576         }
577     }
578
579     public void handleBuildException(BuildException e, AntElementNode node) {
580         handleBuildException(e, node, XMLProblem.SEVERITY_ERROR);
581     }
582
583     public File JavaDoc getEditedFile() {
584         if (fLocationProvider != null && fEditedFile == null) {
585             fEditedFile= fLocationProvider.getLocation().toFile();
586         }
587         return fEditedFile;
588     }
589
590     private void markHierarchy(AntElementNode openElement, int severity) {
591         while (openElement != null) {
592             openElement.setProblemSeverity(severity);
593             openElement= openElement.getParentNode();
594         }
595     }
596     
597     public LocationProvider getLocationProvider() {
598         return fLocationProvider;
599     }
600
601     public void addTarget(Target newTarget, int line, int column) {
602         if (fIncrementalTarget != null) {
603             fCurrentTargetNode= fIncrementalTarget;
604             fCurrentTargetNode.setTarget(newTarget);
605             fStillOpenElements.push(fCurrentTargetNode);
606         } else {
607             AntTargetNode targetNode= new AntTargetNode(newTarget);
608             fProjectNode.addChildNode(targetNode);
609             fCurrentTargetNode= targetNode;
610             fStillOpenElements.push(targetNode);
611             computeOffset(targetNode, line, column);
612             if (fNodeBeingResolved instanceof AntImportNode) {
613                 targetNode.setImportNode(fNodeBeingResolved);
614             }
615         }
616     }
617     
618     public void addProject(Project project, int line, int column) {
619         if (fIncrementalTarget != null) {
620             return;
621         }
622         fProjectNode= new AntProjectNode((AntModelProject)project, this);
623         fStillOpenElements.push(fProjectNode);
624         computeOffset(fProjectNode, line, column);
625     }
626
627     public void addTask(Task newTask, Task parentTask, Attributes JavaDoc attributes, int line, int column) {
628         AntTaskNode taskNode= null;
629         if (parentTask == null) {
630             taskNode= newTaskNode(newTask, attributes);
631             if (fCurrentTargetNode == null) {
632                 fProjectNode.addChildNode(taskNode);
633             } else {
634                 fCurrentTargetNode.addChildNode(taskNode);
635                 if (taskNode.isExternal()) {
636                     fCurrentTargetNode.setExternal(true);
637                     fCurrentTargetNode.setFilePath(taskNode.getFilePath());
638             }
639             }
640         } else {
641             taskNode= newNotWellKnownTaskNode(newTask, attributes);
642             ((AntTaskNode)fTaskToNode.get(parentTask)).addChildNode(taskNode);
643         }
644         fTaskToNode.put(newTask, taskNode);
645         
646         fStillOpenElements.push(taskNode);
647         computeOffset(taskNode, line, column);
648         if (fNodeBeingResolved instanceof AntImportNode) {
649             taskNode.setImportNode(fNodeBeingResolved);
650             //place the node in the collection right after the import node
651
int index= fTaskNodes.indexOf(fNodeBeingResolved) + 1;
652             fTaskNodes.add(index, taskNode);
653         } else {
654             fTaskNodes.add(taskNode);
655         }
656     }
657     
658     public void addEntity(String JavaDoc entityName, String JavaDoc entityPath) {
659         if (fEntityNameToPath == null) {
660             fEntityNameToPath= new HashMap JavaDoc();
661         }
662         fEntityNameToPath.put(entityName, entityPath);
663     }
664
665     private AntTaskNode newTaskNode(Task newTask, Attributes JavaDoc attributes) {
666         AntTaskNode newNode= null;
667         String JavaDoc taskName= newTask.getTaskName();
668         if (isPropertySettingTask(taskName)) { //$NON-NLS-1$
669
newNode= new AntPropertyNode(newTask, attributes);
670         } else if (taskName.equalsIgnoreCase("import")) { //$NON-NLS-1$
671
newNode= new AntImportNode(newTask, attributes);
672         } else if (taskName.equalsIgnoreCase("macrodef") //$NON-NLS-1$
673
|| taskName.equalsIgnoreCase("presetdef") //$NON-NLS-1$
674
|| taskName.equalsIgnoreCase("typedef") //$NON-NLS-1$
675
|| taskName.equalsIgnoreCase("taskdef")) { //$NON-NLS-1$
676
String JavaDoc name = attributes.getValue(IAntModelConstants.ATTR_NAME);
677                     newNode= new AntDefiningTaskNode(newTask, name);
678         } else if(taskName.equalsIgnoreCase("antcall")) { //$NON-NLS-1$
679