KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ant > internal > ui > model > AntElementNode


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 49445
14  *******************************************************************************/

15
16 package org.eclipse.ant.internal.ui.model;
17
18 import java.io.File JavaDoc;
19 import java.net.MalformedURLException JavaDoc;
20 import java.net.URL JavaDoc;
21 import com.ibm.icu.text.MessageFormat;
22 import java.util.ArrayList JavaDoc;
23 import java.util.Iterator JavaDoc;
24 import java.util.List JavaDoc;
25
26 import org.eclipse.ant.internal.ui.AntImageDescriptor;
27 import org.eclipse.ant.internal.ui.AntUIImages;
28 import org.eclipse.ant.internal.ui.AntUtil;
29 import org.eclipse.ant.internal.ui.IAntUIConstants;
30 import org.eclipse.core.resources.IFile;
31 import org.eclipse.core.runtime.IAdaptable;
32 import org.eclipse.core.runtime.Path;
33 import org.eclipse.core.runtime.Platform;
34 import org.eclipse.jface.resource.ImageDescriptor;
35 import org.eclipse.jface.text.IRegion;
36 import org.eclipse.swt.graphics.Image;
37
38 /**
39  * General representation of an Ant buildfile element.
40  *
41  */

42 public class AntElementNode implements IAdaptable {
43     
44     /**
45      * The offset of the corresponding source.
46      * @see #getOffset()
47      */

48     protected int fOffset= -1;
49     
50     /**
51      * The length of the corresponding source.
52      * @see #getLength()
53      */

54     protected int fLength= -1;
55     
56     /**
57      * The length of the source to select for this node
58      */

59     protected int fSelectionLength;
60     
61     /**
62      * The parent node.
63      */

64     protected AntElementNode fParent;
65     
66     /**
67      * The import node that "imported" this element
68      */

69     private AntElementNode fImportNode;
70
71     /**
72      * The child nodes.
73      */

74     protected List JavaDoc fChildNodes= null;
75
76     /**
77      * The (tag-)name of the element.
78      */

79     protected String JavaDoc fName;
80
81     /**
82      * Whether this element has been generated as part of an element hierarchy
83      * this has problems. This is the severity of the problem.
84      * @see XMLProblem#NO_PROBLEM
85      * @see XMLProblem#SEVERITY_ERROR
86      * @see XMLProblem#SEVERITY_WARNING
87      * @see XMLProblem#SEVERITY_FATAL_ERROR
88      */

89     private int fProblemSeverity= AntModelProblem.NO_PROBLEM;
90     
91     private String JavaDoc fProblemMessage= null;
92     
93     /**
94      * The absolute file system path of the file this element is
95      * defined within.
96      */

97     private String JavaDoc fFilePath;
98     
99     /**
100      * Whether this element has been generated from an external entity definition
101      */

102     private boolean fIsExternal = false;
103     
104     /**
105      * The unique (in the corresponding element tree) path of this element.
106      */

107     private String JavaDoc fElementPath;
108     
109     /**
110      * The (not necessarily unique) identifier of this element.
111      */

112     private String JavaDoc fElementIdentifier;
113
114     /**
115      * The problem associated with this node. May be <code>null</code>.
116      */

117     private IProblem fProblem;
118     
119     /**
120      * The unique index of this element in it's parents child collection
121      */

122     private int fIndex= 0;
123     
124     /**
125      * Only used when opening an import element to indicate the location in the imported file
126      */

127     private int fLine;
128     private int fColumn;
129
130     /**
131      * Creates an instance with the specified name.
132      */

133     public AntElementNode(String JavaDoc aName) {
134        fName = aName;
135     }
136     
137     public AntElementNode() {
138     }
139     
140     /**
141      * Returns the name.
142      */

143     public String JavaDoc getName() {
144         return fName;
145     }
146     
147     /**
148      * Returns the label that is used for display.
149      * <P>
150      * The default implementation returns just the same as the method <code>getName()</code>.
151      * Override this method in your own subclass for special elements in order to provide a
152      * custom label.
153      */

154     public String JavaDoc getLabel() {
155         return getName();
156     }
157     
158     /**
159      * Returns the child nodes.
160      */

161     public List JavaDoc getChildNodes() {
162         return fChildNodes;
163     }
164
165     /**
166      * Returns the parent <code>AntElementNode</code>.
167      *
168      * @return the parent or <code>null</code> if this element has no parent.
169      */

170     public AntElementNode getParentNode() {
171         return fParent;
172     }
173     
174     public AntProjectNode getProjectNode() {
175         AntElementNode projectParent= getParentNode();
176         while (projectParent != null && !(projectParent instanceof AntProjectNode)) {
177             projectParent= projectParent.getParentNode();
178         }
179         return (AntProjectNode)projectParent;
180     }
181     
182     /**
183      * Adds the specified element as a child.
184      * <P>
185      * The specified element will have this assigned as its parent.
186      */

187     public void addChildNode(AntElementNode childElement) {
188         childElement.setParent(this);
189         synchronized (this) {
190             if (fChildNodes == null) {
191                 fChildNodes= new ArrayList JavaDoc();
192             }
193             fChildNodes.add(childElement);
194             childElement.setIndex(fChildNodes.size() - 1);
195         }
196     }
197     
198     private void setIndex(int index) {
199         fIndex= index;
200     }
201
202     protected void setParent(AntElementNode node) {
203         fParent= node;
204     }
205
206     /**
207      * Sets the absolute file system path of the file this element is defined
208      * within.
209      */

210     public void setFilePath(String JavaDoc path) {
211         if (path == null) {
212             return;
213         }
214         URL JavaDoc url= null;
215         try {
216             url= new URL JavaDoc(path);
217         } catch (MalformedURLException JavaDoc e) {
218             fFilePath= path;
219             return;
220         }
221         fFilePath = new Path(new File JavaDoc(url.getPath()).getAbsolutePath()).toString();
222     }
223     
224     /**
225      * Returns the absolute file system path of the file this element is defined
226      * within. Only relevant for nodes that are external
227      * @see #isExternal()
228      */

229     public String JavaDoc getFilePath() {
230         return fFilePath;
231     }
232
233     /**
234      * Returns the 0-based index of the first character of the source code for this element,
235      * relative to the source buffer in which this element is contained.
236      *
237      * @return the 0-based index of the first character of the source code for this element,
238      * relative to the source buffer in which this element is contained
239      */

240     public int getOffset() {
241         return fOffset;
242     }
243     
244     /**
245      * Sets the offset.
246      *
247      * @see #getOffset()
248      */

249     public void setOffset(int anOffset) {
250         fOffset = anOffset;
251     }
252     
253     /**
254      * Returns the number of characters of the source code for this element,
255      * relative to the source buffer in which this element is contained.
256      *
257      * @return the number of characters of the source code for this element,
258      * relative to the source buffer in which this element is contained
259      */

260     public int getLength() {
261         return fLength;
262     }
263
264     /**
265      * Sets the length.
266      *
267      * @see #getLength()
268      */

269     public void setLength(int aLength) {
270         fLength = aLength;
271         if (fProblem != null && fProblem instanceof AntModelProblem) {
272             ((AntModelProblem)fProblem).setLength(aLength);
273         }
274     }
275
276     /**
277      * Returns a string representation of this element.
278      */

279     public String JavaDoc toString() {
280         return "Ant Element Node: " + getLabel() + " Offset: " + getOffset() + " Length: " + getLength(); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
281
}
282     
283     /**
284      * Returns whether this element has been generated as part of an element
285      * hierarchy that has error(s) associated with it
286      */

287     public boolean isErrorNode() {
288         return fProblemSeverity == AntModelProblem.SEVERITY_ERROR || fProblemSeverity == AntModelProblem.SEVERITY_FATAL_ERROR;
289     }
290     
291     /**
292      * Returns whether this element has been generated as part of an element
293      * hierarchy that has warning(s) associated with it
294      */

295     public boolean isWarningNode() {
296         return fProblemSeverity == AntModelProblem.SEVERITY_WARNING;
297     }
298     
299     /**
300      * Sets whether this element has been generated as part of an element
301      * hierarchy that has problems. The severity of the problem is provided.
302      */

303     public void setProblemSeverity(int severity) {
304         fProblemSeverity= severity;
305     }
306     
307     /**
308      * Returns whether this xml element is defined in an external entity.
309      *
310      * @return boolean
311      */

312     public boolean isExternal() {
313         return fIsExternal;
314     }
315
316     /**
317      * Sets whether this xml element is defined in an external entity.
318      */

319     public void setExternal(boolean isExternal) {
320         fIsExternal = isExternal;
321     }
322     
323     /**
324      * Returns a unique string representation of this element. The format of
325      * the string is not specified.
326      *
327      * @return the string representation
328      */

329     public String JavaDoc getElementPath() {
330         if (fElementPath == null) {
331             StringBuffer JavaDoc buffer= new StringBuffer JavaDoc();
332             String JavaDoc buildFileName= getProjectNode().getBuildFileName();
333             if (buildFileName != null) {
334                 buffer.append(buildFileName);
335             }
336             buffer.append(getParentNode() != null ? getParentNode().getElementPath() : ""); //$NON-NLS-1$
337
buffer.append('/');
338             buffer.append(getElementIdentifier());
339             buffer.append('[');
340             buffer.append(fIndex);
341             buffer.append(']');
342             
343             fElementPath= buffer.toString();
344         }
345         return fElementPath;
346     }
347
348     private String JavaDoc getElementIdentifier() {
349         if (fElementIdentifier == null) {
350             StringBuffer JavaDoc buffer= escape(new StringBuffer JavaDoc(getName() != null ? getName() : ""), '\\', "$/[]\\"); //$NON-NLS-1$ //$NON-NLS-2$
351
buffer.append('$');
352             buffer.append(escape(new StringBuffer JavaDoc(getLabel() != null ? getLabel() : ""), '\\', "$/[]\\").toString()); //$NON-NLS-1$ //$NON-NLS-2$
353

354             fElementIdentifier= buffer.toString();
355         }
356         return fElementIdentifier;
357     }
358
359     private StringBuffer JavaDoc escape(StringBuffer JavaDoc sb, char esc, String JavaDoc special) {
360         for (int i= 0; i < sb.length(); i++) {
361             if (special.indexOf(sb.charAt(i)) >= 0) {
362                 sb.insert(i++, esc);
363             }
364         }
365
366         return sb;
367     }
368
369 // private int getElementIndexOf(AntElementNode child) {
370
// if (getChildNodes() == null) {
371
// return -1;
372
// }
373
//
374
// int result= -1;
375
//
376
// Iterator iter= getChildNodes().iterator();
377
// AntElementNode current= null;
378
// while (current != child && iter.hasNext()) {
379
// current= (AntElementNode) iter.next();
380
// if (child.getElementIdentifier().equals(current.getElementIdentifier()))
381
// result++;
382
// }
383
//
384
// if (current != child) {
385
// return -1;
386
// }
387
//
388
// return result;
389
// }
390

391     /* (non-Javadoc)
392      * @see java.lang.Object#equals(java.lang.Object)
393      */

394     public boolean equals(Object JavaDoc o2) {
395         Object JavaDoc o1= this;
396         
397         if (o1 == o2) {
398             return true;
399         }
400         if (o2 == null) {
401             return false;
402         }
403         if (!(o1 instanceof AntElementNode || o2 instanceof AntElementNode)) {
404             return o2.equals(o1);
405         }
406         if (!(o1 instanceof AntElementNode && o2 instanceof AntElementNode)) {
407             return false;
408         }
409         
410         AntElementNode e1= (AntElementNode) o1;
411         AntElementNode e2= (AntElementNode) o2;
412     
413         return e1.getElementPath().equals(e2.getElementPath());
414     }
415
416     /* (non-Javadoc)
417      * @see java.lang.Object#hashCode()
418      */

419     public int hashCode() {
420         return getElementPath().hashCode();
421     }
422
423     /**
424      * Returns the length of source to select for this node.
425      * @return the length of source to select
426      */

427     public int getSelectionLength() {
428         return fSelectionLength;
429     }
430     
431     public void setSelectionLength(int selectionLength) {
432         this.fSelectionLength= selectionLength;
433     }
434     
435     /**
436      * Returns the node with the narrowest source range that contains the offset.
437      * It may be this node or one of its children or <code>null</code> if the offset is not in the source range of this node.
438      * @param sourceOffset The source offset
439      * @return the node that includes the offset in its source range or <code>null</code>
440      */

441     public AntElementNode getNode(int sourceOffset) {
442         synchronized (this) {
443             if (fChildNodes != null) {
444                 for (Iterator JavaDoc iter = fChildNodes.iterator(); iter.hasNext(); ) {
445                     AntElementNode node = (AntElementNode) iter.next();
446                     AntElementNode containingNode= node.getNode(sourceOffset);
447                     if (containingNode != null) {
448                         return containingNode;
449                     }
450                 }
451             }
452         }
453         if (fLength == -1 && fOffset <= sourceOffset && !isExternal()) { //this is still an open element
454
return this;
455         }
456         if (fOffset <= sourceOffset && sourceOffset <= (fOffset + fLength - 2)) {
457             return this;
458         }
459         
460         return null;
461     }
462     
463     public Image getImage() {
464         int flags = 0;
465         
466         if (isErrorNode()) {
467             flags = flags | AntImageDescriptor.HAS_ERRORS;
468         } else if (isWarningNode()) {
469             flags = flags | AntImageDescriptor.HAS_WARNINGS;
470         }
471         if(fImportNode != null || isExternal()){
472             flags = flags | AntImageDescriptor.IMPORTED;
473         }
474         ImageDescriptor base= getBaseImageDescriptor();
475         return AntUIImages.getImage(new AntImageDescriptor(base, flags));
476     }
477
478     protected ImageDescriptor getBaseImageDescriptor() {
479         return AntUIImages.getImageDescriptor(IAntUIConstants.IMG_TASK_PROPOSAL);
480     }
481     
482     protected IAntModel getAntModel() {
483         AntElementNode parentNode= getParentNode();
484         while (!(parentNode instanceof AntProjectNode)) {
485             parentNode= parentNode.getParentNode();
486         }
487         return parentNode.getAntModel();
488     }
489
490     /**
491      * Sets the problem associated with this element
492      * @param problem The problem associated with this element.
493      */

494     public void associatedProblem(IProblem problem) {
495         fProblem= problem;
496     }
497     
498     public IProblem getProblem() {
499         return fProblem;
500     }
501
502     protected void appendEntityName(StringBuffer JavaDoc displayName) {
503         String JavaDoc path= getFilePath();
504         
505         if (getImportNode() != null) {
506             displayName.append(MessageFormat.format(AntModelMessages.AntElementNode_9, new String JavaDoc[]{getImportNode().getLabel()}));
507         } else {
508             String JavaDoc entityName= getAntModel().getEntityName(path);
509             displayName.append(MessageFormat.format(AntModelMessages.AntElementNode_9, new String JavaDoc[]{entityName}));
510         }
511     }
512     
513     public AntElementNode getImportNode() {
514         return fImportNode;
515     }
516     
517     public void setImportNode(AntElementNode importNode) {
518         fImportNode = importNode;
519     }
520     
521     public boolean hasChildren() {
522         if (fChildNodes == null) {
523             return false;
524         }
525         return !fChildNodes.isEmpty();
526     }
527
528     public void reset() {
529         fChildNodes= null;
530     }
531
532     public void setExternalInfo(int line, int column) {
533         fLine= line;
534         fColumn= column;
535     }
536     
537     public int[] getExternalInfo() {
538         return new int[] {fLine, fColumn};
539     }
540     
541     /**
542      * Return the resource that contains the definition of this
543      * Ant node.
544      * @return The resource that contains the definition of this ant node or <code>null</code>
545      * if that resource could not be determined (a buildfile that is external to the workspace).
546      */

547     public IFile getIFile() {
548         if (isExternal()) {
549             return AntUtil.getFileForLocation(fFilePath, null);
550         }
551         return getBuildFileResource();
552     }
553     
554     /**
555      * Return the resource that is the main build file for this
556      * Ant node.
557      * @return The resource that is the main buildfile for this ant node or <code>null</code>
558      * if that resource could not be determined (a buildfile that is external to the workspace).
559      */

560     public IFile getBuildFileResource() {
561         LocationProvider locationProvider= getAntModel().getLocationProvider();
562         return locationProvider.getFile();
563     }
564
565     /* (non-Javadoc)
566      * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
567      */

568     public Object JavaDoc getAdapter(Class JavaDoc adapter) {
569         return Platform.getAdapterManager().getAdapter(this, adapter);
570     }
571     
572     /**
573      * Returns whether this node is a structural node that should be shown in the buildfile outline.
574      * For example, an AntCommentNode would return <code>false</code>
575      *
576      * @return whether this node is a structural node that should be shown in the buildfile outline
577      */

578     public boolean isStructuralNode() {
579         return true;
580     }
581     
582     /**
583      * Returns whether to collapse the code folding projection (region) represented by this node.
584      * @return whether the user preference is set to collapse the code folding projection (region)
585      * represented by this node
586      */

587     public boolean collapseProjection() {
588         return false;
589     }
590     
591     public void dispose() {
592         getAntModel().dispose();
593     }
594     
595     /**
596      * Returns the name or path of the element referenced at the offset within the declaration of this node or
597      * <code>null</code> if no element is referenced at the offset
598      * @param offset The offset within the declaration of this node
599      * @return <code>null</code> or the name or path of the referenced element
600      */

601     public String JavaDoc getReferencedElement(int offset) {
602         return null;
603     }
604    
605     public String JavaDoc getProblemMessage() {
606         return fProblemMessage;
607     }
608    
609     public void setProblemMessage(String JavaDoc problemMessage) {
610         fProblemMessage = problemMessage;
611     }
612
613     /**
614      * Returns whether this node contains a reference to the supplied identifier
615      *
616      * @param identifier
617      * @return whether this node contains a reference to the supplied identifier
618      */

619     public boolean containsOccurrence(String JavaDoc identifier) {
620         return false;
621     }
622     
623     /**
624      * Returns the identifier to use for matching occurrences in the Ant editor.
625      *
626      * @return the occurrences identifier for this node
627      */

628     public String JavaDoc getOccurrencesIdentifier() {
629         return getLabel();
630     }
631
632     /**
633      * Returns whether the supplied region can be considered as an area in this node containing
634      * a reference.
635      *
636      * @param region the area to consider for finding a reference
637      * @return whether a reference could exist in this node from the supplied region
638      */

639     public boolean isRegionPotentialReference(IRegion region) {
640         return region.getOffset() >= fOffset;
641     }
642
643     public List JavaDoc computeIdentifierOffsets(String JavaDoc identifier) {
644         return null;
645     }
646     
647     /**
648      * Returns whether the supplied region is from within this node's
649      * declaration identifier area
650      * @param region The region to check
651      * @return whether the region is from within this node and is
652      * the declaration of a reference.
653      */

654     public boolean isFromDeclaration(IRegion region) {
655         return false;
656     }
657
658     protected boolean checkReferenceRegion(IRegion region, String JavaDoc textToSearch, String JavaDoc attributeName) {
659         int attributeOffset= textToSearch.indexOf(attributeName);
660         while (attributeOffset > 0 && !Character.isWhitespace(textToSearch.charAt(attributeOffset - 1))) {
661             attributeOffset= textToSearch.indexOf(attributeName, attributeOffset + 1);
662         }
663         if (attributeOffset != -1) {
664             attributeOffset+= attributeName.length();
665             int attributeOffsetEnd = textToSearch.indexOf('"', attributeOffset);
666             attributeOffsetEnd = textToSearch.indexOf('"', attributeOffsetEnd + 1);
667             return region.getOffset() >= getOffset() + attributeOffset && (region.getOffset() + region.getLength()) <= getOffset() + attributeOffsetEnd;
668         }
669         return false;
670     }
671 }
Popular Tags