KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > refactoring > java > ui > RefactoringActionsProvider


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.modules.refactoring.java.ui;
21
22 import com.sun.source.tree.CompilationUnitTree;
23 import com.sun.source.tree.Tree;
24 import com.sun.source.util.TreePath;
25 import java.awt.datatransfer.Transferable JavaDoc;
26 import java.io.IOException JavaDoc;
27 import java.util.Arrays JavaDoc;
28 import java.util.Collection JavaDoc;
29 import java.util.Dictionary JavaDoc;
30 import java.util.Enumeration JavaDoc;
31 import java.util.HashSet JavaDoc;
32 import java.util.List JavaDoc;
33 import java.util.Set JavaDoc;
34 import javax.lang.model.element.Element;
35 import javax.lang.model.element.ElementKind;
36 import javax.swing.JOptionPane JavaDoc;
37 import javax.swing.text.JTextComponent JavaDoc;
38 import org.netbeans.api.fileinfo.NonRecursiveFolder;
39 import org.netbeans.api.java.source.CancellableTask;
40 import org.netbeans.api.java.source.CompilationController;
41 import org.netbeans.api.java.source.CompilationInfo;
42 import org.netbeans.api.java.source.JavaSource;
43 import org.netbeans.api.java.source.JavaSource.Phase;
44 import org.netbeans.api.java.source.SourceUtils;
45 import org.netbeans.api.java.source.TreePathHandle;
46 import org.netbeans.modules.refactoring.java.RetoucheUtils;
47 import org.netbeans.modules.refactoring.spi.ui.UI;
48 import org.netbeans.modules.refactoring.spi.ui.ActionsImplementationProvider;
49 import org.netbeans.modules.refactoring.spi.ui.RefactoringUI;
50 import org.openide.ErrorManager;
51 import org.openide.cookies.EditorCookie;
52 import org.openide.filesystems.FileObject;
53 import org.openide.loaders.DataFolder;
54 import org.openide.loaders.DataObject;
55 import org.openide.loaders.DataObjectNotFoundException;
56 import org.openide.nodes.Node;
57 import org.openide.text.CloneableEditorSupport;
58 import org.openide.util.Lookup;
59 import org.openide.util.NbBundle;
60 import org.openide.util.datatransfer.PasteType;
61 import org.openide.windows.TopComponent;
62
63 /**
64  *
65  * @author Jan Becicka
66  * TODO: avoid Runnables
67  */

68 public class RefactoringActionsProvider extends ActionsImplementationProvider{
69     
70     /** Creates a new instance of RefactoringActionsProvider */
71     public RefactoringActionsProvider() {
72     }
73     @Override JavaDoc
74     public void doRename(final Lookup lookup) {
75         EditorCookie ec = lookup.lookup(EditorCookie.class);
76         final Dictionary JavaDoc dictionary = lookup.lookup(Dictionary JavaDoc.class);
77         if (isFromEditor(ec)) {
78             new TextComponentRunnable(ec) {
79                 @Override JavaDoc
80                 protected RefactoringUI createRefactoringUI(TreePathHandle selectedElement,int startOffset,int endOffset, CompilationInfo info) {
81                     Element selected = selectedElement.resolveElement(info);
82                     if (selected==null)
83                         return null;
84                     if (selected.getKind() == ElementKind.CONSTRUCTOR) {
85                         selected = selected.getEnclosingElement();
86                     }
87                     if (selected.getKind() == ElementKind.PACKAGE || selected.getEnclosingElement().getKind() == ElementKind.PACKAGE) {
88                         FileObject f = SourceUtils.getFile(selected, info.getClasspathInfo());
89                         return new RenameRefactoringUI(f==null?info.getFileObject():f);
90                     } else {
91                         return new RenameRefactoringUI(selectedElement, info);
92                     }
93                 }
94             }.run();
95         } else {
96             new NodeToFileObject(lookup.lookupAll(Node.class)) {
97                 @Override JavaDoc
98                 protected RefactoringUI createRefactoringUI(FileObject[] selectedElements) {
99                     String JavaDoc newName = getName(dictionary);
100                     if (newName!=null) {
101                         if (pkg[0]!= null)
102                             return new RenameRefactoringUI(pkg[0], newName);
103                         else
104                             return new RenameRefactoringUI(selectedElements[0], newName);
105                     }
106                     else
107                         if (pkg[0]!= null)
108                             return new RenameRefactoringUI(pkg[0]);
109                         else
110                             return new RenameRefactoringUI(selectedElements[0]);
111                 }
112             }.run();
113         }
114     }
115
116     /**
117      * returns true if exactly one refactorable file is selected
118      */

119     @Override JavaDoc
120     public boolean canRename(Lookup lookup) {
121         Collection JavaDoc<? extends Node> nodes = lookup.lookupAll(Node.class);
122         if (nodes.size() != 1) {
123             return false;
124         }
125         Node n = nodes.iterator().next();
126         DataObject dob = n.getCookie(DataObject.class);
127         if (dob==null) {
128             return false;
129         }
130         FileObject fo = dob.getPrimaryFile();
131         if (RetoucheUtils.isRefactorable(fo)) { //NOI18N
132
return true;
133         }
134         if ((dob instanceof DataFolder) &&
135                 RetoucheUtils.isFileInOpenProject(fo) &&
136                 RetoucheUtils.isOnSourceClasspath(fo) &&
137                 !RetoucheUtils.isClasspathRoot(fo))
138             return true;
139         return false;
140     }
141     
142     @Override JavaDoc
143     public void doCopy(final Lookup lookup) {
144         EditorCookie ec = lookup.lookup(EditorCookie.class);
145         final Dictionary JavaDoc dictionary = lookup.lookup(Dictionary JavaDoc.class);
146 // if (isFromEditor(ec)) {
147
// return new TextComponentRunnable(ec) {
148
// @Override
149
// protected RefactoringUI createRefactoringUI(TreePathHandle selectedElement,int startOffset,int endOffset, CompilationInfo info) {
150
// Element selected = selectedElement.resolveElement(info);
151
// if (selected.getKind() == ElementKind.PACKAGE || selected.getEnclosingElement().getKind() == ElementKind.PACKAGE) {
152
// FileObject f = SourceUtils.getFile(selected, info.getClasspathInfo());
153
// return new RenameRefactoringUI(f==null?info.getFileObject():f);
154
// } else {
155
// return new RenameRefactoringUI(selectedElement, info);
156
// }
157
// }
158
// };
159
// } else {
160
new NodeToFileObject(lookup.lookupAll(Node.class)) {
161                 @Override JavaDoc
162                 protected RefactoringUI createRefactoringUI(FileObject[] selectedElements) {
163                     return new CopyClassRefactoringUI(selectedElements[0], getTarget(dictionary), getPaste(dictionary));
164                 }
165             }.run();
166 // }
167
}
168
169     /**
170      * returns true if exactly one refactorable file is selected
171      */

172     @Override JavaDoc
173     public boolean canCopy(Lookup lookup) {
174         Collection JavaDoc<? extends Node> nodes = lookup.lookupAll(Node.class);
175         if (nodes.size() != 1) {
176             return false;
177         }
178         Node n = nodes.iterator().next();
179         DataObject dob = n.getCookie(DataObject.class);
180         if (dob==null) {
181             return false;
182         }
183         
184         Dictionary JavaDoc dict = lookup.lookup(Dictionary JavaDoc.class);
185         FileObject fob = getTarget(dict);
186         if (dict!=null && dict.get("target") != null && fob==null) { //NOI18N
187
//unknown target
188
return false;
189         }
190         if (fob != null) {
191             if (!fob.isFolder())
192                 return false;
193             FileObject fo = dob.getPrimaryFile();
194             if (RetoucheUtils.isRefactorable(fo)) { //NOI18N
195
return true;
196             }
197
198         } else {
199             FileObject fo = dob.getPrimaryFile();
200             if (RetoucheUtils.isRefactorable(fo)) { //NOI18N
201
return true;
202             }
203         }
204
205         return false;
206     }
207
208     @Override JavaDoc
209     public boolean canFindUsages(Lookup lookup) {
210         Collection JavaDoc<? extends Node> nodes = lookup.lookupAll(Node.class);
211         if (nodes.size() != 1) {
212             return false;
213         }
214         Node n = nodes.iterator().next();
215         DataObject dob = n.getCookie(DataObject.class);
216         if ((dob!=null) && RetoucheUtils.isJavaFile(dob.getPrimaryFile())) { //NOI18N
217
return true;
218         }
219         return false;
220     }
221
222     @Override JavaDoc
223     public void doFindUsages(Lookup lookup) {
224         EditorCookie ec = lookup.lookup(EditorCookie.class);
225         if (isFromEditor(ec)) {
226             new TextComponentRunnable(ec) {
227                 @Override JavaDoc
228                 protected RefactoringUI createRefactoringUI(TreePathHandle selectedElement,int startOffset,int endOffset, CompilationInfo info) {
229                     return new WhereUsedQueryUI(selectedElement, info);
230                 }
231             }.run();
232         } else {
233             new NodeToElement(lookup.lookupAll(Node.class)) {
234                 protected RefactoringUI createRefactoringUI(TreePathHandle selectedElement, CompilationInfo info) {
235                     return new WhereUsedQueryUI(selectedElement, info);
236                 }
237             }.run();
238         }
239     }
240
241     /**
242      * returns true iff all selected file are refactorable java files
243      **/

244
245     @Override JavaDoc
246     public boolean canDelete(Lookup lookup) {
247         Collection JavaDoc<? extends Node> nodes = lookup.lookupAll(Node.class);
248         for (Node n:nodes) {
249             DataObject dob = n.getCookie(DataObject.class);
250             if (dob==null)
251                 return false;
252             
253             if (!RetoucheUtils.isRefactorable(dob.getPrimaryFile())) {
254                 return false;
255             }
256         }
257         return !nodes.isEmpty();
258     }
259
260     @Override JavaDoc
261     public void doDelete(final Lookup lookup) {
262         EditorCookie ec = lookup.lookup(EditorCookie.class);
263         if (isFromEditor(ec)) {
264             new TextComponentRunnable(ec) {
265                 @Override JavaDoc
266                 protected RefactoringUI createRefactoringUI(TreePathHandle selectedElement,int startOffset,int endOffset, CompilationInfo info) {
267                     Element selected = selectedElement.resolveElement(info);
268                     if (selected.getKind() == ElementKind.PACKAGE || selected.getEnclosingElement().getKind() == ElementKind.PACKAGE) {
269                         return new SafeDeleteUI(new FileObject[]{info.getFileObject()});
270                     } else {
271                         return new SafeDeleteUI(new TreePathHandle[]{selectedElement}, info);
272                     }
273                 }
274             }.run();
275         } else {
276             new NodeToFileObject(lookup.lookupAll(Node.class)) {
277                 @Override JavaDoc
278                 protected RefactoringUI createRefactoringUI(FileObject[] selectedElements) {
279                     return new SafeDeleteUI(selectedElements);
280                 }
281                 
282             }.run();
283         }
284     }
285     
286     private FileObject getTarget(Dictionary JavaDoc dict) {
287         if (dict==null)
288             return null;
289         Node n = (Node) dict.get("target"); //NOI18N
290
if (n==null)
291             return null;
292         DataObject dob = n.getCookie(DataObject.class);
293         if (dob!=null)
294             return dob.getPrimaryFile();
295         return null;
296     }
297     
298     private PasteType getPaste(Dictionary JavaDoc dict) {
299         if (dict==null)
300             return null;
301         Transferable JavaDoc orig = (Transferable JavaDoc) dict.get("transferable"); //NOI18N
302
if (orig==null)
303             return null;
304         Node n = (Node) dict.get("target");
305         if (n==null)
306             return null;
307         PasteType[] pt = n.getPasteTypes(orig);
308         return pt[1];
309     }
310     
311     static String JavaDoc getName(Dictionary JavaDoc dict) {
312         if (dict==null)
313             return null;
314         return (String JavaDoc) dict.get("name"); //NOI18N
315
}
316     
317     /**
318      * returns true if there is at least one java file in the selection
319      * and all java files are refactorable
320      */

321     @Override JavaDoc
322     public boolean canMove(Lookup lookup) {
323         Collection JavaDoc<? extends Node> nodes = lookup.lookupAll(Node.class);
324         Dictionary JavaDoc dict = lookup.lookup(Dictionary JavaDoc.class);
325         FileObject fo = getTarget(dict);
326         if (fo != null) {
327             if (!fo.isFolder())
328                 return false;
329             //it is drag and drop
330
Set JavaDoc<DataFolder> folders = new HashSet JavaDoc();
331             boolean jdoFound = false;
332             for (Node n:nodes) {
333                 DataObject dob = n.getCookie(DataObject.class);
334                 if (dob==null) {
335                     return false;
336                 }
337                 if (!RetoucheUtils.isOnSourceClasspath(dob.getPrimaryFile())) {
338                     return false;
339                 }
340                 if (dob instanceof DataFolder) {
341                     folders.add((DataFolder)dob);
342                 } else if (RetoucheUtils.isJavaFile(dob.getPrimaryFile())) {
343                     jdoFound = true;
344                 }
345             }
346             if (jdoFound)
347                 return true;
348             for (DataFolder fold:folders) {
349                 for (Enumeration JavaDoc<DataObject> e = (fold).children(true); e.hasMoreElements();) {
350                     if (RetoucheUtils.isJavaFile(e.nextElement().getPrimaryFile())) {
351                         return true;
352                     }
353                 }
354             }
355             return false;
356         } else {
357             //regular invokation
358
boolean result = false;
359             for (Node n:nodes) {
360                 DataObject dob = n.getCookie(DataObject.class);
361                 if (dob==null) {
362                     return false;
363                 }
364                 if (dob instanceof DataFolder) {
365                     return false;
366                 }
367                 if (!RetoucheUtils.isOnSourceClasspath(dob.getPrimaryFile())) {
368                     return false;
369                 }
370                 if (RetoucheUtils.isJavaFile(dob.getPrimaryFile())) {
371                     result = true;
372                 }
373             }
374             return result;
375         }
376     }
377
378     @Override JavaDoc
379     public void doMove(final Lookup lookup) {
380         EditorCookie ec = lookup.lookup(EditorCookie.class);
381         final Dictionary JavaDoc dictionary = lookup.lookup(Dictionary JavaDoc.class);
382         if (isFromEditor(ec)) {
383             new TextComponentRunnable(ec) {
384                 @Override JavaDoc
385                 protected RefactoringUI createRefactoringUI(TreePathHandle selectedElement,int startOffset,int endOffset, CompilationInfo info) {
386                     if (selectedElement.resolve(info).getLeaf().getKind() == Tree.Kind.COMPILATION_UNIT) {
387                         try {
388                             return new MoveClassUI(DataObject.find(info.getFileObject()));
389                         } catch (DataObjectNotFoundException ex) {
390                             throw (RuntimeException JavaDoc) new RuntimeException JavaDoc().initCause(ex);
391                         }
392                     } else {
393                         try {
394                             return new MoveClassUI(DataObject.find(info.getFileObject()));
395                         } catch (DataObjectNotFoundException ex) {
396                             throw (RuntimeException JavaDoc) new RuntimeException JavaDoc().initCause(ex);
397                         }
398                     }
399                 }
400             }.run();
401         } else {
402             new NodeToFileObject(lookup.lookupAll(Node.class)) {
403                 @Override JavaDoc
404                 protected RefactoringUI createRefactoringUI(FileObject[] selectedElements) {
405                     PasteType paste = getPaste(dictionary);
406                     FileObject tar=getTarget(dictionary);
407                     if (selectedElements.length == 1) {
408                         try {
409                             return new MoveClassUI(DataObject.find(selectedElements[0]), tar, paste);
410                         } catch (DataObjectNotFoundException ex) {
411                             throw (RuntimeException JavaDoc) new RuntimeException JavaDoc().initCause(ex);
412                         }
413                     } else {
414                         Set JavaDoc s = new HashSet JavaDoc();
415                         s.addAll(Arrays.asList(selectedElements));
416                         return new MoveClassesUI(s, tar, paste);
417                     }
418                 }
419                 
420             }.run();
421         }
422     }
423
424     
425     public static abstract class TextComponentRunnable implements Runnable JavaDoc {
426         private JTextComponent JavaDoc textC;
427         private int caret;
428         private int start;
429         private int end;
430         private RefactoringUI ui;
431         
432         public TextComponentRunnable(EditorCookie ec) {
433             this.textC = ec.getOpenedPanes()[0];
434             this.caret = textC.getCaretPosition();
435             this.start = textC.getSelectionStart();
436             this.end = textC.getSelectionEnd();
437             assert caret != -1;
438             assert start != -1;
439             assert end != -1;
440         }
441         
442         public final void run() {
443             try {
444                 JavaSource source = JavaSource.forDocument(textC.getDocument());
445                 source.runUserActionTask(new CancellableTask<CompilationController>() {
446                     public void cancel() {
447                     }
448                     
449                     public void run(CompilationController cc) throws Exception JavaDoc {
450                         TreePath selectedElement = null;
451                         cc.toPhase(Phase.RESOLVED);
452                         selectedElement = cc.getTreeUtilities().pathFor(caret);
453                         //workaround for issue 89064
454
if (selectedElement.getLeaf().getKind() == Tree.Kind.COMPILATION_UNIT) {
455                             List JavaDoc<? extends Tree> decls = cc.getCompilationUnit().getTypeDecls();
456                             if (!decls.isEmpty()) {
457                                 selectedElement = TreePath.getPath(cc.getCompilationUnit(), decls.get(0));
458                             }
459                         }
460                         ui = createRefactoringUI(TreePathHandle.create(selectedElement, cc), start, end, cc);
461                     }
462                 }, false);
463             } catch (IOException JavaDoc ioe) {
464                 ErrorManager.getDefault().notify(ioe);
465                 return ;
466             }
467             TopComponent activetc = TopComponent.getRegistry().getActivated();
468             
469             if (ui!=null) {
470                 UI.openRefactoringUI(ui, activetc);
471             } else {
472                 JOptionPane.showMessageDialog(null,NbBundle.getMessage(RefactoringActionsProvider.class, "ERR_CannotRenameKeyword"));
473             }
474         }
475         
476         protected abstract RefactoringUI createRefactoringUI(TreePathHandle selectedElement,int startOffset,int endOffset, CompilationInfo info);
477     }
478     
479     public static abstract class NodeToElement implements Runnable JavaDoc {
480         private Node node;
481         private RefactoringUI ui;
482         
483         public NodeToElement(Collection JavaDoc<? extends Node> nodes) {
484             assert nodes.size() == 1;
485             this.node = nodes.iterator().next();
486         }
487         
488         public final void run() {
489             DataObject o = node.getCookie(DataObject.class);
490             JavaSource source = JavaSource.forFileObject(o.getPrimaryFile());
491             assert source != null;
492             try {
493                 source.runUserActionTask(new CancellableTask<CompilationController>() {
494                     public void cancel() {
495                     }
496
497                     public void run(CompilationController info) throws Exception JavaDoc {
498                         info.toPhase(Phase.ELEMENTS_RESOLVED);
499                         CompilationUnitTree unit = info.getCompilationUnit();
500                         TreePathHandle representedObject = TreePathHandle.create(TreePath.getPath(unit, unit.getTypeDecls().get(0)),info);
501                         ui = createRefactoringUI(representedObject, info);
502                     }
503                     
504                 }, false);
505             } catch (IllegalArgumentException JavaDoc ex) {
506                 ex.printStackTrace();
507             } catch (IOException JavaDoc ex) {
508                 ex.printStackTrace();
509             }
510             UI.openRefactoringUI(ui);
511         }
512         protected abstract RefactoringUI createRefactoringUI(TreePathHandle selectedElement, CompilationInfo info);
513     }
514     
515     public static abstract class NodeToFileObject implements Runnable JavaDoc {
516         private Collection JavaDoc<? extends Node> nodes;
517         private RefactoringUI ui;
518         public NonRecursiveFolder pkg[];
519         
520         public NodeToFileObject(Collection JavaDoc<? extends Node> nodes) {
521             this.nodes = nodes;
522         }
523         
524         public void run() {
525             FileObject[] fobs = new FileObject[nodes.size()];
526             pkg = new NonRecursiveFolder[fobs.length];
527             int i = 0;
528             for (Node node:nodes) {
529                 DataObject dob = (DataObject) node.getCookie(DataObject.class);
530                 if (dob!=null) {
531                     fobs[i] = dob.getPrimaryFile();
532                     pkg[i++] = node.getLookup().lookup(NonRecursiveFolder.class);
533                 }
534             }
535             UI.openRefactoringUI(createRefactoringUI(fobs));
536         }
537
538         protected abstract RefactoringUI createRefactoringUI(FileObject[] selectedElement);
539     }
540     
541     static boolean isFromEditor(EditorCookie ec) {
542         if (ec != null && ec.getOpenedPanes() != null) {
543             TopComponent activetc = TopComponent.getRegistry().getActivated();
544             if (activetc instanceof CloneableEditorSupport.Pane) {
545                 return true;
546             }
547         }
548         return false;
549     }
550 }
551
Popular Tags