KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > refactoring > experimental > plugins > IntroduceVariableRefactoringPlugin


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 package org.netbeans.modules.refactoring.experimental.plugins;
20
21 import java.text.MessageFormat JavaDoc;
22 import java.util.*;
23 import org.netbeans.jmi.javamodel.*;
24 import org.netbeans.jmi.javamodel.ClassDefinition;
25 import org.netbeans.jmi.javamodel.LocalVariable;
26 import org.netbeans.modules.javacore.internalapi.JavaModelUtil;
27 import org.netbeans.modules.javacore.internalapi.ProgressListener;
28 import org.netbeans.modules.javacore.internalapi.JavaMetamodel;
29 import org.netbeans.modules.refactoring.api.*;
30 import org.openide.filesystems.FileObject;
31 import org.openide.text.PositionBounds;
32 import org.openide.util.NbBundle;
33 import org.netbeans.modules.refactoring.spi.RefactoringElementsBag;
34 import org.netbeans.modules.refactoring.plugins.*;
35 import org.netbeans.modules.refactoring.experimental.IntroduceVariableRefactoring;
36 import org.netbeans.modules.refactoring.spi.SimpleRefactoringElementImpl;
37
38 /**
39  *
40  * @author Daniel Prusa
41  */

42 public class IntroduceVariableRefactoringPlugin extends JavaRefactoringPlugin implements ProgressListener {
43     private Expression expression;
44     private String JavaDoc variableName;
45     private Type variableType;
46     private boolean replaceAll;
47     private boolean declareFinal;
48     private BehavioralFeature enclosingMethod = null;
49     private Set localVariables = null;
50     
51     private IntroduceVariableRefactoring refactoring;
52     
53     public IntroduceVariableRefactoringPlugin(IntroduceVariableRefactoring introduce) {
54         this.refactoring = introduce;
55         expression = introduce.getExpression();
56     }
57     
58     public Problem checkParameters() {
59         return setParameters(
60             refactoring.getVariableName(),
61             refactoring.getVariableType(),
62             refactoring.isReplaceAll(),
63             refactoring.isFinal()
64         );
65     }
66     
67     public Problem fastCheckParameters() {
68         String JavaDoc name = refactoring.getVariableName();
69         if (name == null || name.length() == 0) {
70             return new Problem(true, getString("ERR_EmptyIdentifier"));
71         }
72         if (!org.openide.util.Utilities.isJavaIdentifier(name)) {
73             String JavaDoc msg = new MessageFormat JavaDoc(NbBundle.getMessage(RenameRefactoring.class, "ERR_InvalidIdentifier")).format(new Object JavaDoc[] {name}); //NOI18N
74
return new Problem(true, msg);
75         }
76         return null;
77     }
78     
79     public Problem preCheck() {
80         fireProgressListenerStart(refactoring.PRE_CHECK, 2);
81         Problem problem = null;
82         try {
83             if (expression == null || ((expression instanceof ElementReference) && ((ElementReference) expression).getElement() instanceof PrimitiveType)) {
84                 problem = new Problem(true, getString("ERR_ExpressionNotSelected"));
85                 fireProgressListenerStep();
86             } else {
87                 BehavioralFeature method = getMethod();
88                 fireProgressListenerStep();
89                 if (method == null) {
90                     problem = new Problem(true, getString("ERR_NotInBehavioralFeature"));
91                 } else {
92                     Object JavaDoc comp = expression.refImmediateComposite();
93                     if ((comp instanceof ExpressionStatement) ||
94                         (!(comp instanceof Expression) && expression instanceof TypeReference) ||
95                         (comp instanceof NewClassExpression) || (comp instanceof NewArrayExpression)) {
96                             problem = new Problem(true, getString("ERR_CannotReplaceExpression"));
97                     }
98                 }
99             }
100             fireProgressListenerStep();
101         } finally {
102             fireProgressListenerStop();
103         }
104         return problem;
105     }
106     
107     private Problem checkParameters(String JavaDoc name, Type type, boolean replaceAll, boolean isFinal) {
108         collectLocalVariables();
109         if (localVariables.contains(name)) {
110             String JavaDoc msg = new MessageFormat JavaDoc(getString("ERR_NameClashes")).format(new Object JavaDoc[] {name});
111             return new Problem(true, msg);
112         }
113         return null;
114     }
115     
116     private Problem setParameters(String JavaDoc name, Type type, boolean replaceAll, boolean isFinal) {
117         fireProgressListenerStart(refactoring.PARAMETERS_CHECK, 1);
118         try {
119             fireProgressListenerStep();
120             
121             variableName = name;
122             variableType = type;
123             this.replaceAll = replaceAll;
124             declareFinal = isFinal;
125             
126             Problem result = checkParameters(name, type, replaceAll, isFinal);
127             return result;
128         } finally {
129             fireProgressListenerStop();
130         }
131     }
132     
133     public Problem prepare(RefactoringElementsBag elements) {
134         JavaModelPackage modelPackage = (JavaModelPackage) expression.refOutermostPackage();
135         IntroduceVariableElement elem = new IntroduceVariableElement(expression, variableName, variableType, declareFinal);
136         elements.add(refactoring, elem);
137         if (refactoring.isReplaceAll()) {
138             BehavioralFeature method = getMethod();
139             collectOccurrences(elements, method, refactoring.getVariableName());
140         } else {
141             ReplaceExpressionElement replaceElem = new ReplaceExpressionElement(expression, refactoring.getVariableName());
142             elements.add(refactoring, replaceElem);
143         }
144         return null;
145     }
146     
147     // helper methods ..........................................................
148

149     private BehavioralFeature getMethod() {
150         if (enclosingMethod == null) {
151             Element elem = expression;
152             while (!(elem instanceof BehavioralFeature) && (elem != null)) {
153                 elem = (Element)elem.refImmediateComposite();
154             }
155             enclosingMethod = (BehavioralFeature)elem;
156         }
157         return enclosingMethod;
158     }
159     
160     private void collectLocalVariables() {
161         localVariables = new HashSet();
162         BehavioralFeature method = getMethod();
163         if (method != null) {
164             collectLocalVariables(localVariables, method);
165         }
166     }
167     
168     private void collectLocalVariables(Set localVars, Element elem) {
169         /*
170         if (elem instanceof VariableAccess) {
171             NamedElement nelem = ((VariableAccess) elem).getElement();
172             if (nelem instanceof Field) {
173                 localVars.add(nelem.getName());
174             }
175         } else */
if (elem instanceof LocalVariable) {
176             LocalVariable localVar = (LocalVariable) elem;
177             localVars.add(localVar.getName());
178             InitialValue initValue = localVar.getInitialValue();
179             if (initValue != null) {
180                 collectLocalVariables(localVars, initValue);
181             }
182         } else {
183             for (Iterator iter = elem.getChildren().iterator(); iter.hasNext(); ) {
184                 collectLocalVariables(localVars, (Element)iter.next());
185             }
186         }
187     }
188     
189     private void collectOccurrences(RefactoringElementsBag elements, Element root, String JavaDoc name) {
190         for (Iterator iter = root.getChildren().iterator(); iter.hasNext(); ) {
191             Element elem = (Element) iter.next();
192             if (elem instanceof Expression) {
193                 findMatchingExpressions(elements, (Expression) elem, name);
194             } else if (!(elem instanceof ClassDefinition)) {
195                 collectOccurrences(elements, elem, name);
196             }
197         } // for
198
}
199
200     private void findMatchingExpressions(RefactoringElementsBag elements, Expression root, String JavaDoc name) {
201         // [TODO] exclude all anonymous classes
202
if (compareExpressions(root, expression)) {
203             ReplaceExpressionElement replaceElem = new ReplaceExpressionElement(root, name);
204             elements.add(refactoring, replaceElem);
205             return;
206         }
207         for (Iterator iter = root.getChildren().iterator(); iter.hasNext(); ) {
208             Element elem = (Element) iter.next();
209             if (elem instanceof Expression) {
210                 findMatchingExpressions(elements, (Expression) elem, name);
211             } else {
212                 return;
213             }
214         } // for
215
}
216     
217     public static boolean compareExpressions(Expression expr_1, Expression expr_2) {
218         if (expr_1 == null) {
219             return expr_2 == null;
220         }
221         if (expr_2 == null) {
222             return false; // the previous condition ensures that expr_1 is not null
223
}
224         if (expr_1.getClass() != expr_2.getClass()) {
225             return false;
226         }
227         if (expr_1 instanceof NullLiteral) {
228             return true;
229         } else if (expr_1 instanceof BooleanLiteral) {
230             return ((BooleanLiteral) expr_1).isValue() == ((BooleanLiteral) expr_2).isValue();
231         } else if (expr_1 instanceof StringLiteral) {
232             return ((StringLiteral) expr_1).getValue().equals(((StringLiteral) expr_2).getValue());
233         } else if (expr_1 instanceof IntLiteral) {
234             return ((IntLiteral) expr_1).getValue() == ((IntLiteral) expr_2).getValue();
235         } else if (expr_1 instanceof DoubleLiteral) {
236             return ((DoubleLiteral) expr_1).getValue() == ((DoubleLiteral) expr_2).getValue();
237         } else if (expr_1 instanceof LongLiteral) {
238             return ((LongLiteral) expr_1).getValue() == ((LongLiteral) expr_2).getValue();
239         } else if (expr_1 instanceof CharLiteral) {
240             return ((CharLiteral) expr_1).getValue() == ((CharLiteral) expr_2).getValue();
241         } else if (expr_1 instanceof FloatLiteral) {
242             return ((FloatLiteral) expr_1).getValue() == ((FloatLiteral) expr_2).getValue();
243         } else if (expr_1 instanceof MultipartId) {
244             NamedElement elem_1 = ((MultipartId) expr_1).getElement();
245             NamedElement elem_2 = ((MultipartId) expr_2).getElement();
246             if (!(elem_1 instanceof UnresolvedClass)) {
247                 return elem_1 == elem_2;
248             }
249             if (!(elem_2 instanceof UnresolvedClass)) {
250                 return false;
251             }
252             return elem_1.getName().equals(elem_2.getName());
253         } else if (expr_1 instanceof ArrayReference) {
254             if (((ArrayReference) expr_1).getDimCount() != ((ArrayReference) expr_2).getDimCount()) {
255                 return false;
256             }
257             NamedElement elem_1 = ((TypeReference) expr_1).getElement();
258             NamedElement elem_2 = ((TypeReference) expr_2).getElement();
259             if (!(elem_1 instanceof UnresolvedClass)) {
260                 return elem_1 == elem_2;
261             }
262             if (!(elem_2 instanceof UnresolvedClass)) {
263                 return false;
264             }
265             return elem_1.getName().equals(elem_2.getName());
266         } else if (expr_1 instanceof PrefixExpression) {
267             Operator op_1 = ((PrefixExpression) expr_1).getOperator();
268             Operator op_2 = ((PrefixExpression) expr_2).getOperator();
269             if (!op_1.equals(op_2)) {
270                 return false;
271             }
272         } else if (expr_1 instanceof InfixExpression) {
273             Operator op_1 = ((InfixExpression) expr_1).getOperator();
274             Operator op_2 = ((InfixExpression) expr_2).getOperator();
275             if (!op_1.equals(op_2)) {
276                 return false;
277             }
278         } else if (expr_1 instanceof MethodInvocation) {
279             String JavaDoc name_1 = ((MethodInvocation) expr_1).getName();
280             String JavaDoc name_2 = ((MethodInvocation) expr_2).getName();
281             if (!name_1.equals(name_2)) {
282                 return false;
283             }
284         } else if (expr_1 instanceof VariableAccess) {
285             return ((VariableAccess) expr_1).getName().equals(((VariableAccess) expr_2).getName());
286         }
287         List list_1 = expr_1.getChildren();
288         List list_2 = expr_2.getChildren();
289         if (list_1.size() != list_2.size()) {
290             return false;
291         }
292         Iterator iter_1 = list_1.iterator();
293         Iterator iter_2 = list_2.iterator();
294         while (iter_1.hasNext()) {
295             if (!compareExpressions((Expression) iter_1.next(), (Expression) iter_2.next())) {
296                 return false;
297             }
298         }
299         return true;
300     }
301     
302     private static final String JavaDoc getString(String JavaDoc key) {
303         return NbBundle.getMessage(IntroduceVariableRefactoringPlugin.class, key);
304     }
305     
306     public void start(org.netbeans.modules.javacore.internalapi.ProgressEvent event) {
307         fireProgressListenerStart(event.getOperationType(), event.getCount());
308     }
309     
310     public void step(org.netbeans.modules.javacore.internalapi.ProgressEvent event) {
311         fireProgressListenerStep();
312     }
313     
314     public void stop(org.netbeans.modules.javacore.internalapi.ProgressEvent event) {
315         fireProgressListenerStop();
316     }
317
318     // IntroduceVariableElement .................................................
319
private class IntroduceVariableElement extends SimpleRefactoringElementImpl {
320         
321         private final String JavaDoc text;
322         private PositionBounds bounds = null;
323         
324         private Expression initialExpr;
325         private String JavaDoc name;
326         private Type type;
327         private boolean isFinal;
328         
329         public IntroduceVariableElement(Expression expr, String JavaDoc name, Type type, boolean isFinal) {
330             initialExpr = expr;
331             this.name = name;
332             this.type = type;
333             this.isFinal = isFinal;
334             text = MessageFormat.format(getString("TXT_IntroduceVariable"), new Object JavaDoc[] {name});
335         }
336             
337         private BehavioralFeature getMethod() {
338             Element elem = initialExpr;
339             while (!(elem instanceof BehavioralFeature) && (elem != null)) {
340                 elem = (Element)elem.refImmediateComposite();
341             }
342             return (BehavioralFeature)elem;
343         }
344         
345         public String JavaDoc getDisplayText() {
346             return text;
347         }
348         
349         public Element getJavaElement() {
350             return JavaModelUtil.getDeclaringFeature(initialExpr);
351         }
352         
353         public PositionBounds getPosition() {
354             if (bounds == null) {
355                 bounds = JavaMetamodel.getManager().getElementPosition(initialExpr);
356             }
357             return null;
358         }
359         
360         public String JavaDoc getText() {
361             return getDisplayText();
362         }
363         
364         public void performChange() {
365             BehavioralFeature method = getMethod();
366             if (method == null) {
367                 return;
368             }
369             JavaModelPackage modelPackage = (JavaModelPackage) method.refOutermostPackage();
370             LocalVarDeclarationClass localVarDeclProxy = modelPackage.getLocalVarDeclaration();
371             TypeReference typeRef = typeToTypeReference(modelPackage, type);
372             LocalVariableClass localVarProxy = modelPackage.getLocalVariable();
373             InitialValue initValue = (InitialValue)initialExpr.duplicate();
374             LocalVariable localVar = localVarProxy.createLocalVariable(name, null, isFinal, typeRef, 0, initValue, null);
375             List varList = new ArrayList();
376             varList.add(localVar);
377             LocalVarDeclaration localVarDecl = localVarDeclProxy.createLocalVarDeclaration(isFinal, typeRef, varList);
378             method.getBody().getStatements().add(0, localVarDecl);
379         }
380         
381         public FileObject getParentFile() {
382             Resource res = getMethod().getResource();
383             return JavaMetamodel.getManager().getFileObject(res);
384         }
385         
386         private TypeReference typeToTypeReference(JavaModelPackage modelPackage, Type type) {
387             if (type instanceof Array) {
388                 ArrayReferenceClass arrayProxy = modelPackage.getArrayReference();
389                 int dims = 0;
390                 Type elemType = type;
391                 while (elemType instanceof Array) {
392                     dims++;
393                     elemType = ((Array) elemType).getType();
394                 }
395                 String JavaDoc name = elemType instanceof JavaClass ? ((JavaClass) elemType).getSimpleName() : elemType.getName();
396                 MultipartId id = modelPackage.getMultipartId().createMultipartId(name, null, null);
397                 return arrayProxy.createArrayReference(null, id, dims);
398             } else {
399                 MultipartIdClass idProxy = modelPackage.getMultipartId();
400                 String JavaDoc name = type instanceof JavaClass ? ((JavaClass) type).getSimpleName() : type.getName();
401                 return idProxy.createMultipartId(name, null, null);
402             }
403         }
404         
405     } // IntroduceVariableElement
406

407     // ReplaceExpressionElement .................................................
408
private class ReplaceExpressionElement extends SimpleRefactoringElementImpl {
409         
410         private final String JavaDoc text;
411         private PositionBounds bounds = null;
412         private Resource res = null;
413         private Expression expression;
414         private String JavaDoc localVarName;
415         
416         public ReplaceExpressionElement(Expression expression, String JavaDoc localVarName) {
417             this.expression = expression;
418             this.localVarName = localVarName;
419             text = MessageFormat.format(getString("TXT_ReplaceExpression"), new Object JavaDoc[] {localVarName});
420         }
421          
422         public String JavaDoc getDisplayText() {
423             return text;
424         }
425         
426         public Element getJavaElement() {
427             return JavaModelUtil.getDeclaringFeature(expression);
428         }
429         
430         public PositionBounds getPosition() {
431             if (bounds == null) {
432                 bounds = JavaMetamodel.getManager().getElementPosition(expression);
433             }
434             return bounds;
435         }
436         
437         public String JavaDoc getText() {
438             return getDisplayText();
439         }
440         
441         public void performChange() {
442             JavaModelPackage modelPackage = (JavaModelPackage) expression.refOutermostPackage();
443             VariableAccessClass proxy = modelPackage.getVariableAccess();
444             VariableAccess varAccess = proxy.createVariableAccess(localVarName, null, false);
445             Element comp = (Element) expression.refImmediateComposite();
446             comp.replaceChild(expression, varAccess);
447         }
448
449         public FileObject getParentFile() {
450             return JavaMetamodel.getManager().getFileObject(expression.getResource());
451         }
452
453     } // ReplaceExpressionElement
454

455 }
456
Popular Tags