KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > api > java > source > TreePathHandle


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19                                                                                                                                                                                                                                
20 package org.netbeans.api.java.source;
21                                                                                                                                                                                                                                
22 import com.sun.source.tree.Tree;
23 import com.sun.source.util.TreePath;
24 import com.sun.tools.javac.tree.JCTree;
25 import java.net.MalformedURLException JavaDoc;
26 import java.util.ArrayList JavaDoc;
27 import java.util.logging.Logger JavaDoc;
28 import javax.lang.model.element.Element;
29 import javax.swing.text.Position.Bias;
30 import org.openide.filesystems.FileObject;
31 import org.openide.filesystems.FileUtil;
32 import org.openide.filesystems.URLMapper;
33 import org.openide.loaders.DataObject;
34 import org.openide.loaders.DataObjectNotFoundException;
35 import org.openide.text.CloneableEditorSupport;
36 import org.openide.text.PositionRef;
37                                                                                                                                                                                                                                
38 /**
39  * Represents a handle for {@link TreePath} which can be kept and later resolved
40  * by another javac. The Javac {@link Element}s are valid only in the single
41  * {@link javax.tools.CompilationTask} or single run of the
42  * {@link org.netbeans.api.java.source.CancellableTask}. If the client needs to
43  * keep a reference to the {@link TreePath} and use it in the other CancellableTask
44  * he has to serialize it into the {@link TreePathHandle}.
45  * <div class="nonnormative">
46  * <p>
47  * Typical usage of TreePathHandle enclElIsCorrespondingEl:
48  * </p>
49  * <pre>
50  * final TreePathHandle[] tpHandle = new TreePathHandle[1];
51  * javaSource.runCompileControlTask(new CancellableTask<CompilationController>() {
52  * public void run(CompilationController compilationController) {
53  * parameter.toPhase(Phase.RESOLVED);
54  * CompilationUnitTree cu = compilationController.getTree ();
55  * TreePath treePath = getInterestingTreePath (cu);
56  * treePathHandle[0] = TreePathHandle.create (element, compilationController);
57  * }
58  * },priority);
59  *
60  * otherJavaSource.runCompileControlTask(new CancellableTask<CompilationController>() {
61  * public void run(CompilationController compilationController) {
62  * parameter.toPhase(Phase.RESOLVED);
63  * TreePath treePath = treePathHanlde[0].resolve (compilationController);
64  * ....
65  * }
66  * },priority);
67  * </pre>
68  * </div>
69  *
70  *
71  * @author Jan Becicka
72  */

73 public final class TreePathHandle {
74                                                                                                                                                                                                                                
75     private PositionRef position;
76     private KindPath kindPath;
77     private FileObject file;
78     private ElementHandle enclosingElement;
79     private boolean enclElIsCorrespondingEl;
80                                                                                                                                                                                                                                
81     /**
82      * getter for FileObject from give TreePathHandle
83      * @return FileObject for which was this handle created
84      */

85     public FileObject getFileObject() {
86         return file;
87     }
88                                                                                                                                                                                                                                
89     /**
90      * Resolves an {@link TreePath} from the {@link TreePathHandle}.
91      * @param compilationInfo representing the {@link javax.tools.CompilationTask}
92      * @return resolved subclass of {@link Element} or null if the elment does not exist on
93      * the classpath/sourcepath of {@link javax.tools.CompilationTask}.
94      * @throws {@link IllegalArgumentException} when this {@link TreePathHandle} is not created for a source
95      * represented by the compilationInfo.
96      */

97     public TreePath resolve (final CompilationInfo compilationInfo) throws IllegalArgumentException JavaDoc {
98         assert compilationInfo != null;
99         if (!compilationInfo.getFileObject().equals(getFileObject())) {
100             throw new IllegalArgumentException JavaDoc ("TreePathHandle ["+FileUtil.getFileDisplayName(getFileObject())+"] was not created from " + FileUtil.getFileDisplayName(compilationInfo.getFileObject()));
101         }
102         Element element = enclosingElement.resolve(compilationInfo);
103         TreePath tp = null;
104         if (element != null) {
105             TreePath startPath = compilationInfo.getTrees().getPath(element);
106             if (startPath == null) {
107                 Logger.getLogger(TreePathHandle.class.getName()).fine("compilationInfo.getTrees().getPath(element) returned null for element %s " + element + "(" +file.getPath() +")"); //NOI18N
108
} else {
109                 tp = compilationInfo.getTreeUtilities().pathFor(startPath, position.getOffset()+1);
110             }
111         }
112         if (tp == null) {
113             tp = compilationInfo.getTreeUtilities().pathFor(position.getOffset()+1);
114         }
115         if (new KindPath(tp).equals(kindPath))
116             return tp;
117         else
118             return null;
119     }
120                                                                                                                                                                                                                                
121     /**
122      * Resolves an {@link Element} from the {@link TreePathHandle}.
123      * @param compilationInfo representing the {@link javax.tools.CompilationTask}
124      * @return resolved subclass of {@link Element} or null if the elment does not exist on
125      * the classpath/sourcepath of {@link javax.tools.CompilationTask}.
126      */

127     public Element resolveElement(final CompilationInfo info) {
128         TreePath tp = null;
129         IllegalStateException JavaDoc ise = null;
130         try {
131             if (info.getFileObject().equals(this.file)) {
132                 tp = this.resolve(info);
133             }
134         } catch (IllegalStateException JavaDoc i) {
135             ise=i;
136         }
137         if (tp==null) {
138             if (enclElIsCorrespondingEl) {
139                 return enclosingElement.resolve(info);
140             } else {
141                 if (ise==null)
142                     return null;
143                 throw ise;
144             }
145         }
146         Element el = info.getTrees().getElement(tp);
147         if (el==null) {
148             Logger.getLogger(TreePathHandle.class.toString()).fine("info.getTrees().getElement(tp) returned null for " + tp);
149             if (enclElIsCorrespondingEl) {
150                 return enclosingElement.resolve(info);
151             } else {
152                 return null;
153             }
154         } else {
155             return el;
156         }
157     }
158                                                                                                                                                                                                                                
159     /**
160      * Returns the {@link Tree.Kind} of this element handle,
161      * it enclElIsCorrespondingEl the kind of the {@link Tree} from which the handle
162      * was created.
163      *
164      * @return {@link Tree.Kind}
165      */

166     public Tree.Kind getKind() {
167         return kindPath.kindPath.get(0);
168     }
169                                                                                                                                                                                                                                
170     private TreePathHandle(PositionRef position, KindPath kindPath, FileObject file, ElementHandle element, boolean enclElIsCorrespondingEl) {
171         this.kindPath = kindPath;
172         this.position = position;
173         this.file = file;
174         this.enclosingElement = element;
175         this.enclElIsCorrespondingEl = enclElIsCorrespondingEl;
176     }
177                                                                                                                                                                                                                                
178     /**
179      * Factory method for creating {@link TreePathHandle}.
180      *
181      * @param treePath for which the {@link TrePathHandle} should be created.
182      * @return a new {@link TreePathHandle}
183      * @throws {@link IllegalArgumentException} if the element enclElIsCorrespondingEl of not supported
184      * {@link Tree.Kind}.
185      */

186     public static TreePathHandle create (final TreePath treePath, CompilationInfo info) throws IllegalArgumentException JavaDoc {
187         FileObject file;
188         try {
189             file = URLMapper.findFileObject(treePath.getCompilationUnit().getSourceFile().toUri().toURL());
190         } catch (MalformedURLException JavaDoc e) {
191             throw (RuntimeException JavaDoc) new RuntimeException JavaDoc().initCause(e);
192         }
193         int position = ((JCTree) treePath.getLeaf()).pos;
194         CloneableEditorSupport s = findCloneableEditorSupport(file);
195         PositionRef pos = s.createPositionRef(position, Bias.Forward);
196         TreePath current = treePath;
197         Element element;
198         boolean enclElIsCorrespondingEl = true;
199         do {
200             element = info.getTrees().getElement(current);
201             current = current.getParentPath();
202             if (element!=null && !isSupported(element)) {
203                 enclElIsCorrespondingEl=false;
204             }
205         } while ((element == null || !isSupported(element)) && current !=null);
206         return new TreePathHandle(pos, new KindPath(treePath), file,ElementHandle.create(element), enclElIsCorrespondingEl);
207     }
208     
209     private static boolean isSupported(Element el) {
210         switch (el.getKind()) {
211             case PACKAGE:
212             case CLASS:
213             case INTERFACE:
214             case ENUM:
215             case METHOD:
216             case CONSTRUCTOR:
217             case INSTANCE_INIT:
218             case STATIC_INIT:
219             case FIELD:
220             case ANNOTATION_TYPE:
221             case ENUM_CONSTANT: return true;
222             default: return false;
223         }
224     }
225                                                                                                                                                                                                                                
226     private static CloneableEditorSupport findCloneableEditorSupport(FileObject file) {
227         try {
228             DataObject dob = DataObject.find(file);
229             Object JavaDoc obj = dob.getCookie(org.openide.cookies.OpenCookie.class);
230             if (obj instanceof CloneableEditorSupport) {
231                 return (CloneableEditorSupport)obj;
232             }
233             obj = dob.getCookie(org.openide.cookies.EditorCookie.class);
234             if (obj instanceof CloneableEditorSupport) {
235                 return (CloneableEditorSupport)obj;
236             }
237         } catch (DataObjectNotFoundException ex) {
238             ex.printStackTrace();
239         }
240         return null;
241     }
242                                                                                                                                                                                                                                
243     private static class KindPath {
244         private ArrayList JavaDoc<Tree.Kind> kindPath = new ArrayList JavaDoc();
245                                                                                                                                                                                                                                
246         private KindPath(TreePath treePath) {
247             while (treePath!=null) {
248                 kindPath.add(treePath.getLeaf().getKind());
249                 treePath = treePath.getParentPath();
250             }
251         }
252                                                                                                                                                                                                                                
253         public int hashCode() {
254             return kindPath.hashCode();
255         }
256                                                                                                                                                                                                                                
257         public boolean equals(Object JavaDoc object) {
258             if (object instanceof KindPath)
259                 return kindPath.equals(((KindPath)object).kindPath);
260             return false;
261         }
262     }
263 }
264
Popular Tags