KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > junit > GoToOppositeAction


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-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.junit;
21
22 import com.sun.source.tree.Tree;
23 import com.sun.source.util.TreePath;
24 import java.awt.EventQueue JavaDoc;
25 import java.io.IOException JavaDoc;
26 import java.util.Collections JavaDoc;
27 import java.util.logging.Level JavaDoc;
28 import java.util.logging.Logger JavaDoc;
29 import javax.lang.model.element.Element;
30 import javax.swing.Action JavaDoc;
31 import javax.swing.JEditorPane JavaDoc;
32 import javax.swing.text.Document JavaDoc;
33 import org.netbeans.api.java.classpath.ClassPath;
34 import org.netbeans.api.java.project.JavaProjectConstants;
35 import org.netbeans.api.java.queries.UnitTestForSourceQuery;
36 import org.netbeans.api.java.source.CancellableTask;
37 import org.netbeans.api.java.source.ClasspathInfo;
38 import org.netbeans.api.java.source.CompilationController;
39 import org.netbeans.api.java.source.JavaSource;
40 import org.netbeans.api.java.source.JavaSource.Phase;
41 import org.netbeans.api.project.FileOwnerQuery;
42 import org.netbeans.api.project.Project;
43 import org.netbeans.api.project.ProjectUtils;
44 import org.netbeans.api.project.SourceGroup;
45 import org.netbeans.modules.junit.plugin.JUnitPlugin;
46 import org.netbeans.modules.junit.plugin.JUnitPlugin.Location;
47 import org.netbeans.spi.java.classpath.support.ClassPathSupport;
48 import org.openide.NotifyDescriptor;
49 import org.openide.filesystems.FileObject;
50 import org.openide.loaders.DataObject;
51 import org.openide.nodes.Node;
52 import org.openide.text.CloneableEditorSupport;
53 import org.openide.util.HelpCtx;
54 import org.openide.util.NbBundle;
55 import org.openide.util.RequestProcessor;
56 import org.openide.util.actions.CallableSystemAction;
57 import org.openide.windows.TopComponent;
58
59 /**
60  * Jumps to the opposite class or method.
61  * If the cursor is currently in a source method, this action will jump to the
62  * corresponding test method and vice versa. If the cursor is currently in a
63  * source class but not in any method, this action will switch to the beginning
64  * of the corresponding class.
65  *
66  * @see OpenTestAction
67  * @author Marian Petras
68  */

69 @SuppressWarnings JavaDoc("serial")
70 public final class GoToOppositeAction extends CallableSystemAction {
71     
72     /**
73      *
74      */

75     public GoToOppositeAction() {
76         super();
77         putValue("noIconInMenu", Boolean.TRUE); //NOI18N
78
String JavaDoc trimmedName = NbBundle.getMessage(
79                                         getClass(),
80                                         "LBL_Action_GoToTest_trimmed"); //NOI18N
81
putValue("PopupMenuText", trimmedName); //NOI18N
82
putValue("trimmed-text", trimmedName); //NOI18N
83
}
84     
85     /**
86      */

87     @Override JavaDoc
88     public void performAction() {
89         assert EventQueue.isDispatchThread();
90         
91         TopComponent comp;
92         JEditorPane JavaDoc editorPane;
93         FileObject fileObj;
94         ClassPath srcCP;
95         FileObject fileObjRoot;
96         Project project;
97         
98         boolean sourceToTest = true;
99         comp = TopComponent.getRegistry().getActivated();
100         if (comp == null) {
101             return;
102         }
103
104         if (comp instanceof CloneableEditorSupport.Pane) {
105             editorPane = ((CloneableEditorSupport.Pane) comp).getEditorPane();
106             if (editorPane == null) {
107                 return;
108             }
109             
110             fileObj = getFileObject(editorPane.getDocument());
111         } else {
112             editorPane = null;
113             
114             Node[] selectedNodes = comp.getActivatedNodes();
115             if ((selectedNodes == null) || (selectedNodes.length != 1)) {
116                 return;
117             }
118             
119             DataObject dataObj = selectedNodes[0].getLookup().lookup(DataObject.class);
120             if (dataObj == null) {
121                 return;
122             }
123             
124             fileObj = dataObj.getPrimaryFile();
125         }
126         
127         boolean isJavaFile = false;
128         if ((fileObj == null)
129           || !fileObj.isFolder() && !(isJavaFile = TestUtil.isJavaFile(fileObj))
130           || ((srcCP = ClassPath.getClassPath(fileObj, ClassPath.SOURCE)) == null)
131           || ((fileObjRoot = srcCP.findOwnerRoot(fileObj)) == null)
132           || ((project = FileOwnerQuery.getOwner(fileObjRoot)) == null)
133           || (UnitTestForSourceQuery.findUnitTests(fileObjRoot).length == 0)
134               && !(sourceToTest = false) //side effect - assignment
135
&& (!isJavaFile || (UnitTestForSourceQuery.findSources(fileObjRoot).length == 0))) {
136             return;
137         }
138         
139         JUnitPlugin plugin = TestUtil.getPluginForProject(project);
140         assert plugin != null;
141         
142         SourceGroup[] srcGroups;
143         FileObject[] srcRoots;
144         srcGroups = ProjectUtils.getSources(project)
145                     .getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
146         srcRoots = new FileObject[srcGroups.length];
147         for (int i = 0; i < srcGroups.length; i++) {
148             srcRoots[i] = srcGroups[i].getRootFolder();
149         }
150         ClassPath srcClassPath = ClassPathSupport.createClassPath(srcRoots);
151
152         /*
153         ClasspathInfo cpInfo = ClasspathInfo.create(
154                         ClassPath.getClassPath(fileObj, ClassPath.BOOT),
155                         ClassPath.getClassPath(fileObj, ClassPath.COMPILE),
156                         srcClassPath);
157         int caretPos = editorPane.getCaretPosition();
158         boolean fromSourceToTest = sourceToTest;
159         
160         JavaSource javaSource = JavaSource.create(
161                 cpInfo,
162                 Collections.<FileObject>singleton(fileObj));
163         
164         ElementFinder elementFinder = new ElementFinder(caretPos);
165         try {
166             javaSource.runUserActionTask(elementFinder, true);
167         } catch (IOException ex) {
168             Logger.getLogger("global").log(Level.SEVERE, null, ex); //NOI18N
169         }
170         Element element = elementFinder.getElement();
171         */

172         RequestProcessor.getDefault().post(
173                 new ActionImpl(plugin,
174                                new Location(fileObj/*, element*/),
175                                sourceToTest,
176                                srcClassPath));
177     }
178     
179     /**
180      * Determines an element at the current cursor position.
181      */

182     private class ElementFinder implements CancellableTask<CompilationController> {
183         
184         /** */
185         private final int caretPosition;
186         /** */
187         private volatile boolean cancelled;
188         /** */
189         private Element element = null;
190         
191         /**
192          */

193         private ElementFinder(int caretPosition) {
194             this.caretPosition = caretPosition;
195         }
196     
197         /**
198          */

199         public void run(CompilationController controller) throws IOException JavaDoc {
200             controller.toPhase(Phase.RESOLVED); //cursor position needed
201
if (cancelled) {
202                 return;
203             }
204
205             TreePath treePath = controller.getTreeUtilities()
206                                           .pathFor(caretPosition);
207             if (treePath != null) {
208                 if (cancelled) {
209                     return;
210                 }
211                 
212                 TreePath parent = treePath.getParentPath();
213                 while (parent != null) {
214                     Tree.Kind parentKind = parent.getLeaf().getKind();
215                     if ((parentKind == Tree.Kind.CLASS)
216                             || (parentKind == Tree.Kind.COMPILATION_UNIT)) {
217                         break;
218                     }
219                     treePath = parent;
220                     parent = treePath.getParentPath();
221                 }
222
223             }
224
225             if (treePath != null) {
226                 if (cancelled) {
227                     return;
228                 }
229
230                 try {
231                     element = controller.getTrees().getElement(treePath);
232                 } catch (IllegalArgumentException JavaDoc ex) {
233                     Logger.getLogger("global").log(Level.WARNING, null, ex);
234                 }
235             }
236         }
237         
238         /**
239          */

240         public void cancel() {
241             cancelled = true;
242         }
243         
244         /**
245          */

246         Element getElement() {
247             return element;
248         }
249
250     }
251     
252     /**
253      *
254      */

255     private class ActionImpl implements Runnable JavaDoc {
256         
257         private final JUnitPlugin plugin;
258         private final Location currLocation;
259         private final boolean sourceToTest;
260         private final ClassPath srcClassPath;
261         
262         private Location oppoLocation;
263         
264         ActionImpl(JUnitPlugin plugin,
265                    Location currLocation,
266                    boolean sourceToTest,
267                    ClassPath srcClassPath) {
268             this.plugin = plugin;
269             this.currLocation = currLocation;
270             this.sourceToTest = sourceToTest;
271             this.srcClassPath = srcClassPath;
272         }
273         
274         public void run() {
275             if (!EventQueue.isDispatchThread()) {
276                 findOppositeLocation();
277                 if ((oppoLocation != null) || sourceToTest) {
278                     EventQueue.invokeLater(this);
279                 }
280             } else {
281                 if (oppoLocation != null) {
282                     goToOppositeLocation();
283                 } else if (sourceToTest) {
284                     displayNoOppositeLocationFound();
285                 }
286             }
287         }
288         
289         /**
290          */

291         private void findOppositeLocation() {
292             oppoLocation = sourceToTest
293                   ? JUnitPluginTrampoline.DEFAULT.getTestLocation(plugin,
294                                                                   currLocation)
295                   : JUnitPluginTrampoline.DEFAULT.getTestedLocation(plugin,
296                                                                   currLocation);
297         }
298         
299         /**
300          */

301         private void goToOppositeLocation() {
302             assert oppoLocation != null;
303             assert oppoLocation.getFileObject() != null;
304
305             final FileObject oppoFile = oppoLocation.getFileObject();
306 // final ElementHandle<Element> elementHandle
307
// = oppoLocation.getElementHandle();
308
// if (elementHandle != null) {
309
// OpenTestAction.openFileAtElement(oppoFile, elementHandle);
310
// } else {
311
OpenTestAction.openFile(oppoFile);
312 // }
313
}
314         
315         /**
316          */

317         private void displayNoOppositeLocationFound() {
318             String JavaDoc sourceClsName;
319             FileObject fileObj = currLocation.getFileObject();
320             sourceClsName = srcClassPath.getResourceName(fileObj, '.', false);
321             String JavaDoc msgKey = !fileObj.isFolder()
322                             ? "MSG_test_class_not_found" //NOI18N
323
: (sourceClsName.length() != 0)
324                               ? "MSG_testsuite_class_not_found" //NOI18N
325
: "MSG_testsuite_class_not_found_def_pkg";//NOI18N
326
TestUtil.notifyUser(
327                     NbBundle.getMessage(getClass(), msgKey, sourceClsName),
328                     NotifyDescriptor.INFORMATION_MESSAGE);
329         }
330
331     }
332     
333     /**
334      */

335     @Override JavaDoc
336     public boolean isEnabled() {
337         assert EventQueue.isDispatchThread();
338         
339         return checkDirection() != null;
340     }
341     
342     /**
343      */

344     public String JavaDoc getName() {
345         return NbBundle.getMessage(getClass(),
346                                    checkDirection() == Boolean.FALSE
347                                         ? "LBL_Action_GoToSource" //NOI18N
348
: "LBL_Action_GoToTest"); //NOI18N
349
}
350     
351     /**
352      * Checks whether this action should be enabled for &quot;Go To Test&quot;
353      * or for &quot;Go To Tested Class&quot or whether it should be disabled.
354      *
355      * @return {@code Boolean.TRUE} if this action should be enabled for
356      * &quot;Go To Test&quot;,<br />
357      * {@code Boolean.FALSE} if this action should be enabled for
358      * &quot;Go To Tested Class&quot;,<br />
359      * {@code null} if this action should be disabled
360      */

361     private Boolean JavaDoc checkDirection() {
362         TopComponent comp = TopComponent.getRegistry().getActivated();
363         if (comp == null) {
364             return null;
365         }
366
367         FileObject fileObj = null;
368         
369         if (comp instanceof CloneableEditorSupport.Pane) {
370             JEditorPane JavaDoc editorPane = ((CloneableEditorSupport.Pane) comp).getEditorPane();
371             if (editorPane != null) {
372                 fileObj = getFileObject(editorPane.getDocument());
373             }
374         } else {
375             Node[] selectedNodes = comp.getActivatedNodes();
376             if ((selectedNodes != null) && (selectedNodes.length == 1)) {
377                 DataObject dataObj = selectedNodes[0].getLookup().lookup(DataObject.class);
378                 if (dataObj != null) {
379                     fileObj = dataObj.getPrimaryFile();
380                 }
381             }
382         }
383         
384         ClassPath srcCP;
385         FileObject fileObjRoot;
386         
387         boolean isJavaFile = false;
388         boolean sourceToTest = true;
389         boolean enabled = (fileObj != null)
390           && (fileObj.isFolder() || (isJavaFile = TestUtil.isJavaFile(fileObj)))
391           && ((srcCP = ClassPath.getClassPath(fileObj, ClassPath.SOURCE)) != null)
392           && ((fileObjRoot = srcCP.findOwnerRoot(fileObj)) != null)
393           && ((UnitTestForSourceQuery.findUnitTests(fileObjRoot).length != 0)
394               || (sourceToTest = false) //side effect - assignment
395
|| isJavaFile && (UnitTestForSourceQuery.findSources(fileObjRoot).length != 0));
396         
397         return enabled ? Boolean.valueOf(sourceToTest)
398                        : null;
399     }
400     
401     /**
402      */

403     public HelpCtx getHelpCtx() {
404         return HelpCtx.DEFAULT_HELP;
405     }
406     
407     /**
408      */

409     protected void initialize () {
410     super.initialize ();
411         putProperty(Action.SHORT_DESCRIPTION,
412                     NbBundle.getMessage(getClass(),
413                                         "HINT_Action_GoToTest")); //NOI18N
414
}
415
416     /**
417      */

418     @Override JavaDoc
419     protected boolean asynchronous() {
420         return false;
421     }
422     
423     /**
424      */

425     private static FileObject getFileObject(Document JavaDoc document) {
426         
427         /* copied from org.netbeans.modules.editor.NbEditorUtilities */
428         
429         Object JavaDoc sdp = document.getProperty(Document.StreamDescriptionProperty);
430         if (sdp instanceof FileObject) {
431             return (FileObject) sdp;
432         }
433         if (sdp instanceof DataObject) {
434             return ((DataObject) sdp).getPrimaryFile();
435         }
436         return null;
437     }
438
439 }
440
Popular Tags