KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > refactoring > java > plugins > SafeDeleteRefactoringPlugin


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.plugins;
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.io.IOException JavaDoc;
26 import java.net.MalformedURLException JavaDoc;
27 import java.util.ArrayList JavaDoc;
28 import java.util.Arrays JavaDoc;
29 import java.util.Collection JavaDoc;
30 import java.util.Collections JavaDoc;
31 import java.util.HashSet JavaDoc;
32 import java.util.Iterator JavaDoc;
33 import java.util.Set JavaDoc;
34 import javax.lang.model.element.Element;
35 import javax.swing.Action JavaDoc;
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.CompilationInfo;
40 import org.netbeans.api.java.source.JavaSource;
41 import org.netbeans.api.java.source.JavaSource.Phase;
42 import org.netbeans.api.java.source.ModificationResult;
43 import org.netbeans.api.java.source.TreePathHandle;
44 import org.netbeans.api.java.source.WorkingCopy;
45 import org.netbeans.modules.refactoring.java.DiffElement;
46 import org.netbeans.modules.refactoring.api.AbstractRefactoring;
47 import org.netbeans.modules.refactoring.api.Problem;
48 import org.netbeans.modules.refactoring.api.RefactoringElement;
49 import org.netbeans.modules.refactoring.api.RefactoringSession;
50 import org.netbeans.modules.refactoring.api.SafeDeleteRefactoring;
51 import org.netbeans.modules.refactoring.api.WhereUsedQuery;
52 import org.netbeans.modules.refactoring.spi.ui.UI;
53 import org.netbeans.modules.refactoring.java.api.WhereUsedQueryConstants;
54 import org.netbeans.modules.refactoring.spi.ProblemDetailsFactory;
55 import org.netbeans.modules.refactoring.spi.ProblemDetailsImplementation;
56 import org.netbeans.modules.refactoring.spi.RefactoringElementImplementation;
57 import org.netbeans.modules.refactoring.spi.RefactoringElementsBag;
58 import org.netbeans.modules.refactoring.spi.SimpleRefactoringElementImpl;
59 import org.netbeans.modules.refactoring.spi.ui.RefactoringUI;
60 import org.netbeans.modules.refactoring.java.ui.SafeDeleteUI;
61 import org.netbeans.modules.refactoring.java.ui.WhereUsedQueryUI;
62 import org.netbeans.modules.refactoring.java.ui.tree.ElementGrip;
63 import org.netbeans.modules.refactoring.java.ui.tree.ElementGripFactory;
64 import org.openide.ErrorManager;
65 import org.openide.filesystems.FileObject;
66 import org.openide.text.PositionBounds;
67 import org.openide.util.Cancellable;
68 import org.openide.util.NbBundle;
69 import org.openide.util.lookup.Lookups;
70
71
72 /**
73  * The plugin that carries out Safe Delete refactoring.
74  * @author Bharath Ravikumar, Jan Becicka
75  */

76 public class SafeDeleteRefactoringPlugin extends JavaRefactoringPlugin {
77     private SafeDeleteRefactoring refactoring;
78     private WhereUsedQuery[] whereUsedQueries;
79     
80     /**
81      * Creates the a new instance of the Safe Delete refactoring
82      * plugin.
83      * @param refactoring The refactoring to be used by this plugin
84      */

85     public SafeDeleteRefactoringPlugin(SafeDeleteRefactoring refactoring) {
86         this.refactoring = refactoring;
87     }
88     
89     /**
90      * For each element to be refactored, the corresponding
91      * prepare method of the underlying WhereUsed query is
92      * invoked to check for usages. If none is present, a
93      * <CODE>SafeDeleteRefactoringElement</CODE> is created
94      * with the corresponding element.
95      * @param refactoringElements
96      * @return
97      */

98     public Problem prepare(RefactoringElementsBag refactoringElements) {
99         RefactoringSession inner = RefactoringSession.create("delete"); // NOI18N
100
Set JavaDoc refactoredObjects = new HashSet JavaDoc();
101         fireProgressListenerStart(AbstractRefactoring.PARAMETERS_CHECK, whereUsedQueries.length + 1);
102         for(int i = 0;i < whereUsedQueries.length; ++i) {
103             Object JavaDoc refactoredObject = whereUsedQueries[i].getRefactoringSource().lookup(Object JavaDoc.class);
104             refactoredObjects.add(refactoredObject);
105
106             whereUsedQueries[i].prepare(inner);
107             
108             JavaSource javaSource = JavaSource.forFileObject(grips.get(i).getFileObject());
109             try {
110                 final ModificationResult result = javaSource.runModificationTask(new FindTask(refactoringElements, grips.get(i)));
111                 refactoringElements.registerTransaction(new RetoucheCommit(Collections.singleton(result)));
112                 for (FileObject jfo : result.getModifiedFileObjects()) {
113                     for (ModificationResult.Difference dif: result.getDifferences(jfo)) {
114                         refactoringElements.add(refactoring,DiffElement.create(dif, jfo, result));
115                     }
116                 }
117             } catch (MalformedURLException JavaDoc ex) {
118                 ex.printStackTrace();
119             } catch (IOException JavaDoc ex) {
120                 ex.printStackTrace();
121             }
122             
123             fireProgressListenerStep();
124         }
125         
126         Collection JavaDoc importStmts = new ArrayList JavaDoc();
127         
128         for (Iterator JavaDoc iter = inner.getRefactoringElements().iterator(); iter.hasNext(); ) {
129             ElementGrip elem = (ElementGrip) ((RefactoringElement) iter.next()).getComposite();
130             ElementGrip comp = elem;
131             boolean isOuterRef = true;
132 // //Check if this usage is an import statement & ignore it if so.
133
// boolean isUsageImport = false;
134
// Import importStmt = null;
135
// if(comp instanceof Resource){
136
// //An Import shows up as a Resource - not as an Import object.
137
// //Hence, we go through the hassle of checking the set of import
138
// //statements. This is not a reliable way of verifying if the import is
139
// //accounting for a usage. But there's no better option currently.
140
// Iterator importIterator = ((Resource)comp).getImports().iterator();
141
// while(importIterator.hasNext()){
142
// importStmt = (Import) importIterator.next();
143
// if(refactoredObjects.contains(importStmt.getImportedNamespace())){
144
// isUsageImport = true;
145
// break;
146
// }
147
// }
148
// }
149
//
150
// //If the usage is an import, we'd have to store away the standalone
151
// //import to be deleted later
152
// if(isUsageImport){
153
// importStmts.add(new ImportRefDeleteElement(importStmt));
154
// //Go no further in this iteration. Move on to the next usage.
155
// continue;
156
// }
157
//
158
// while (comp != null && !(comp instanceof Resource)) {
159
// if (refactoredObjects.contains(comp)) {
160
// isOuterRef = false;
161
// break;
162
// }
163
// comp = (Element) comp.refImmediateComposite();
164
// }
165
if (isOuterRef) {
166                 fireProgressListenerStop();
167                 return new Problem(false, getString("ERR_ReferencesFound"), ProblemDetailsFactory.createProblemDetails(new ProblemDetailsImplemen(new WhereUsedQueryUI(elem.getHandle(), "!!!TODO!!!", refactoring), inner)));
168             }
169         }
170         
171         //If there we no non-import usages, delete the import statements as well.
172
if(importStmts.size() > 0){
173             for (Iterator JavaDoc it = importStmts.iterator(); it.hasNext();) {
174                 RefactoringElementImplementation refacElem =
175                         (RefactoringElementImplementation) it.next();
176                 refactoringElements.add(refactoring, refacElem);
177             }
178         }
179         
180         fireProgressListenerStop();
181         return null;
182     }
183     
184     private class ProblemDetailsImplemen implements ProblemDetailsImplementation {
185         
186         private RefactoringUI ui;
187         private RefactoringSession rs;
188         
189         public ProblemDetailsImplemen(RefactoringUI ui, RefactoringSession rs) {
190             this.ui = ui;
191             this.rs = rs;
192         }
193         
194         public void showDetails(Action JavaDoc callback, Cancellable parent) {
195             parent.cancel();
196             UI.openRefactoringUI(ui, rs, callback);
197         }
198         
199         public String JavaDoc getDetailsHint() {
200             return getString("LBL_ShowUsages");
201         }
202         
203     }
204     
205     /**
206      * Checks whether the element being refactored is a valid Method/Field/Class
207      * @return Problem returns a generic problem message if the check fails
208      */

209     public Problem preCheck() {
210 // Element[] refElements = refactoring.getRefactoredObjects();
211
// for(int i = 0;i < refElements.length; ++i) {
212
// Element refactoredObject = refElements[i];
213
// boolean validType = refactoredObject instanceof ClassMember
214
// || refactoredObject instanceof LocalVariable
215
// || refactoredObject instanceof Resource;
216
// if(!validType) {
217
// String errMsg = NbBundle.getMessage(SafeDeleteRefactoringPlugin.class,
218
// "ERR_SafeDel_InvalidType"); // NOI18N
219
// return new Problem(true,errMsg);
220
// }
221
//
222
// if (!CheckUtils.isElementInOpenProject(refactoredObject)) {
223
// return new Problem(true, NbBundle.getMessage(JavaRefactoringPlugin.class, "ERR_ProjectNotOpened"));
224
// }
225
// }
226
return null;
227     }
228     
229     /**
230      * A No-op for this particular refactoring.
231      */

232     public Problem fastCheckParameters() {
233         //Nothing to be done for Safe Delete
234
return null;
235     }
236     
237     private ArrayList JavaDoc<TreePathHandle> grips = new ArrayList JavaDoc();
238     /**
239      * Invokes the checkParameters of each of the underlying
240      * WhereUsed refactorings and returns a Problem (if any)
241      * returned by any of these queries.
242      */

243     public Problem checkParameters() {
244         //This class expects too many details from SafeDeleteRefactoring
245
//But there's no other go I guess.
246
grips.clear();
247         final ArrayList JavaDoc<ClasspathInfo> controllers = new ArrayList JavaDoc();
248         for (final FileObject f:refactoring.getRefactoringSource().lookupAll(FileObject.class)) {
249             JavaSource source = JavaSource.forFileObject(f);
250             try {
251                 source.runUserActionTask(new CancellableTask<CompilationController>() {
252                     public void cancel() {
253                         
254                     }
255                     public void run(CompilationController co) throws Exception JavaDoc {
256                         co.toPhase(Phase.ELEMENTS_RESOLVED);
257                         CompilationUnitTree cut = co.getCompilationUnit();
258                         for (Tree t: cut.getTypeDecls()) {
259                             grips.add(TreePathHandle.create(TreePath.getPath(cut, t), co));
260                         }
261                         controllers.add(co.getClasspathInfo());
262                     }
263                 }, true);
264             } catch (IllegalArgumentException JavaDoc ex) {
265                 ex.printStackTrace();
266             } catch (IOException JavaDoc ex) {
267                 ex.printStackTrace();
268             }
269         }
270
271         grips.addAll(refactoring.getRefactoringSource().lookupAll(TreePathHandle.class));
272
273         whereUsedQueries = new WhereUsedQuery[grips.size()];
274         for(int i = 0;i < whereUsedQueries.length; ++i) {
275             if (!controllers.isEmpty()) {
276                 refactoring.getContext().add(controllers.get(i));
277             }
278             whereUsedQueries[i] = createQuery(grips.get(i));
279             
280             whereUsedQueries[i].putValue(WhereUsedQuery.SEARCH_IN_COMMENTS, refactoring.isCheckInComments());
281             if(Tree.Kind.METHOD.equals(grips.get(i).getKind())){
282                 whereUsedQueries[i].putValue(WhereUsedQueryConstants.FIND_OVERRIDING_METHODS,true);
283             }
284         }
285         
286         Problem problemFromUsage = null;
287         for(int i = 0;i < whereUsedQueries.length; ++i) {
288 // Fix for issue 63050. Doesn't make sense to check usages of a Resource.Ignore it.
289
// if(whereUsedQueries[i].getRefactoredObject() instanceof Resource)
290
// continue;
291
if((problemFromUsage = whereUsedQueries[i].checkParameters()) != null)
292                 return problemFromUsage;
293         }
294         return null;
295     }
296     
297     private WhereUsedQuery createQuery(TreePathHandle tph) {
298         WhereUsedQuery q = new WhereUsedQuery(Lookups.singleton(tph));
299         for (Object JavaDoc o:refactoring.getContext().lookupAll(Object JavaDoc.class)) {
300             q.getContext().add(o);
301         }
302         return q;
303     }
304     
305     
306     //Private Helper methods
307
private static String JavaDoc getString(String JavaDoc key) {
308         return NbBundle.getMessage(SafeDeleteRefactoringPlugin.class, key);
309     }
310     
311     /**
312      *Returns the default critical error message for this refactoring
313      *
314      */

315     private Problem getProblemMessage(Object JavaDoc refactoredObject) {
316         String JavaDoc errorMsg = NbBundle.getMessage(SafeDeleteUI.class,
317                 "DSC_SafeDelProblem", refactoredObject);// NOI18N
318
return new Problem(true,errorMsg);
319     }
320  
321     private static class ImportRefDeleteElement extends SimpleRefactoringElementImpl{
322         
323 // private final Import importStmt;
324
private final String JavaDoc text = "todo";
325         
326 // private ImportRefDeleteElement(Import importStmt){
327
// this.importStmt = importStmt;
328
// text = NbBundle.getMessage(ImportRefDeleteElement.class,
329
// "TXT_SafeDel_Delete_Ref_Import", importStmt.getName());
330
// }
331

332         public String JavaDoc getText() {
333             return text;
334         }
335
336         public String JavaDoc getDisplayText() {
337             return getText();
338         }
339
340         public void performChange() {
341 // importStmt.refDelete();
342
}
343
344         public Element getComposite() {
345 // return importStmt.getResource();
346
return null;
347         }
348
349         public FileObject getParentFile() {
350             //return JavaMetamodel.getManager().getFileObject(importStmt.getResource());
351
return null;
352         }
353
354         public PositionBounds getPosition() {
355             //return JavaMetamodel.getManager().getElementPosition(importStmt);
356
return null;
357         }
358     }
359     
360     private class FindTask implements CancellableTask<WorkingCopy> {
361
362         private RefactoringElementsBag elements;
363         private TreePathHandle jmiObject;
364
365         public FindTask(RefactoringElementsBag elements, TreePathHandle element) {
366             super();
367             this.elements = elements;
368             this.jmiObject = element;
369         }
370
371         public void cancel() {
372         }
373
374         public void run(WorkingCopy compiler) throws IOException JavaDoc {
375             compiler.toPhase(Phase.RESOLVED);
376             CompilationUnitTree cu = compiler.getCompilationUnit();
377             if (cu == null) {
378                 ErrorManager.getDefault().log(ErrorManager.ERROR, "compiler.getCompilationUnit() is null " + compiler);
379                 return;
380             }
381             Element el = jmiObject.resolveElement(compiler);
382             assert el != null;
383
384             DeleteTransformer findVisitor = new DeleteTransformer(compiler);
385             findVisitor.scan(compiler.getCompilationUnit(), el);
386
387             for (TreePath tree : findVisitor.getUsages()) {
388                 ElementGripFactory.getDefault().put(compiler.getFileObject(), tree, compiler);
389             }
390         }
391     }
392 }
393
Popular Tags