KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > refactoring > rename > RefactoringHandleTransplanter


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.corext.refactoring.rename;
12
13 import java.util.Collections JavaDoc;
14 import java.util.LinkedList JavaDoc;
15 import java.util.Map JavaDoc;
16
17 import org.eclipse.core.runtime.Assert;
18
19 import org.eclipse.jdt.core.IField;
20 import org.eclipse.jdt.core.IInitializer;
21 import org.eclipse.jdt.core.IJavaElement;
22 import org.eclipse.jdt.core.IMember;
23 import org.eclipse.jdt.core.IMethod;
24 import org.eclipse.jdt.core.IType;
25 import org.eclipse.jdt.core.Signature;
26
27
28 /**
29  * Helper class to transplant a IJavaElement handle from a certain state of the
30  * Java Model into another.
31  *
32  * The changes to the workspace include one type rename, a number of field
33  * renames, and a number of method renames including signature changes.
34  *
35  * The returned handle exists in the target model state.
36  *
37  * @since 3.2
38  *
39  */

40 public class RefactoringHandleTransplanter {
41
42     private final IType fOldType;
43     private final IType fNewType;
44     private final Map JavaDoc/*<IJavaElement, String>*/ fRefactoredSimilarElements;
45
46     /**
47      * @param oldType old type
48      * @param newType renamed type
49      * @param refactoredSimilarElements map from similar element (IJavaElement) to new name (String), or <code>null</code>
50      */

51     public RefactoringHandleTransplanter(IType oldType, IType newType, Map JavaDoc/*<IJavaElement, String>*/ refactoredSimilarElements) {
52         fOldType= oldType;
53         fNewType= newType;
54         if (refactoredSimilarElements == null)
55             fRefactoredSimilarElements= Collections.EMPTY_MAP;
56         else
57             fRefactoredSimilarElements= refactoredSimilarElements;
58     }
59
60     /**
61      * Converts the handle. Handle need not exist, but must be a source
62      * reference.
63      *
64      * @param handle
65      * @return the new handle
66      */

67     public IMember transplantHandle(IMember handle) {
68
69         /*
70          * Create a list of handles from top-level type to the handle
71          */

72         final LinkedList JavaDoc oldElements= new LinkedList JavaDoc();
73         addElements(handle, oldElements);
74
75         /*
76          * Step through the elements and re-locate them in the new parents.
77          */

78         final IMember[] newElements= convertElements((IMember[]) oldElements.toArray(new IMember[0]));
79
80         return newElements[newElements.length - 1];
81     }
82
83     private void addElements(IMember element, LinkedList JavaDoc chain) {
84         chain.addFirst(element);
85         IJavaElement parent= element.getParent();
86         if (parent instanceof IMember)
87             addElements((IMember) parent, chain);
88     }
89     
90     private IMember[] convertElements(IMember[] oldElements) {
91
92         final IMember[] newElements= new IMember[oldElements.length];
93         final IMember first= oldElements[0];
94
95         Assert.isTrue(first instanceof IType);
96
97         if (first.equals(fOldType))
98             // We renamed a top level type.
99
newElements[0]= fNewType;
100         else
101             newElements[0]= first;
102
103         /*
104          * Note that we only need to translate the information necessary to
105          * create new handles. For example, the return type of a method is not
106          * relevant; neither is information about generic specifics in types.
107          */

108
109         for (int i= 1; i < oldElements.length; i++) {
110             final IJavaElement newParent= newElements[i - 1];
111             final IJavaElement currentElement= oldElements[i];
112             switch (newParent.getElementType()) {
113                 case IJavaElement.TYPE: {
114                     switch (currentElement.getElementType()) {
115                         case IJavaElement.TYPE: {
116                             final String JavaDoc newName= resolveTypeName((IType) currentElement);
117                             newElements[i]= ((IType) newParent).getType(newName);
118                             break;
119                         }
120                         case IJavaElement.METHOD: {
121                             final String JavaDoc newName= resolveElementName(currentElement);
122                             final String JavaDoc[] newParameterTypes= resolveParameterTypes((IMethod) currentElement);
123                             newElements[i]= ((IType) newParent).getMethod(newName, newParameterTypes);
124                             break;
125                         }
126                         case IJavaElement.INITIALIZER: {
127                             final IInitializer initializer= (IInitializer) currentElement;
128                             newElements[i]= ((IType) newParent).getInitializer(initializer.getOccurrenceCount());
129                             break;
130                         }
131                         case IJavaElement.FIELD: {
132                             final String JavaDoc newName= resolveElementName(currentElement);
133                             newElements[i]= ((IType) newParent).getField(newName);
134                             break;
135                         }
136                     }
137                     break;
138                 }
139                 case IJavaElement.METHOD: {
140                     switch (currentElement.getElementType()) {
141                         case IJavaElement.TYPE: {
142                             newElements[i]= resolveTypeInMember((IMethod) newParent, (IType) currentElement);
143                             break;
144                         }
145                     }
146                     break;
147                 }
148                 case IJavaElement.INITIALIZER: {
149                     switch (currentElement.getElementType()) {
150                         case IJavaElement.TYPE: {
151                             newElements[i]= resolveTypeInMember((IInitializer) newParent, (IType) currentElement);
152                             break;
153                         }
154                     }
155                     break;
156                 }
157                 case IJavaElement.FIELD: {
158                     switch (currentElement.getElementType()) {
159                         case IJavaElement.TYPE: {
160                             // anonymous type in field declaration
161
newElements[i]= resolveTypeInMember((IField) newParent, (IType) currentElement);
162                             break;
163                         }
164                     }
165                     break;
166                 }
167             }
168         }
169         return newElements;
170     }
171
172     private String JavaDoc[] resolveParameterTypes(IMethod method) {
173         final String JavaDoc[] oldParameterTypes= method.getParameterTypes();
174         final String JavaDoc[] newparams= new String JavaDoc[oldParameterTypes.length];
175
176         final String JavaDoc[] possibleOldSigs= new String JavaDoc[4];
177         possibleOldSigs[0]= Signature.createTypeSignature(fOldType.getElementName(), false);
178         possibleOldSigs[1]= Signature.createTypeSignature(fOldType.getElementName(), true);
179         possibleOldSigs[2]= Signature.createTypeSignature(fOldType.getFullyQualifiedName(), false);
180         possibleOldSigs[3]= Signature.createTypeSignature(fOldType.getFullyQualifiedName(), true);
181
182         final String JavaDoc[] possibleNewSigs= new String JavaDoc[4];
183         possibleNewSigs[0]= Signature.createTypeSignature(fNewType.getElementName(), false);
184         possibleNewSigs[1]= Signature.createTypeSignature(fNewType.getElementName(), true);
185         possibleNewSigs[2]= Signature.createTypeSignature(fNewType.getFullyQualifiedName(), false);
186         possibleNewSigs[3]= Signature.createTypeSignature(fNewType.getFullyQualifiedName(), true);
187
188         // Textually replace all occurrences
189
// This handles stuff like Map<SomeClass, some.package.SomeClass>
190
for (int i= 0; i < oldParameterTypes.length; i++) {
191             newparams[i]= oldParameterTypes[i];
192             for (int j= 0; j < possibleOldSigs.length; j++) {
193                 newparams[i]= replaceAll(newparams[i], possibleOldSigs[j], possibleNewSigs[j]);
194             }
195         }
196         return newparams;
197     }
198
199     private String JavaDoc resolveElementName(IJavaElement element) {
200         final String JavaDoc newName= (String JavaDoc) fRefactoredSimilarElements.get(element);
201         if (newName != null)
202             return newName;
203         else
204             return element.getElementName();
205     }
206
207     private IMember resolveTypeInMember(final IMember newParent, IType oldChild) {
208         // Local type or anonymous type. Only local types can be renamed.
209
String JavaDoc newName= ""; //$NON-NLS-1$
210
if (oldChild.getElementName().length() != 0)
211             newName= resolveTypeName(oldChild);
212         return newParent.getType(newName, oldChild.getOccurrenceCount());
213     }
214
215     private String JavaDoc resolveTypeName(IType type) {
216         return type.equals(fOldType) ? fNewType.getElementName() : type.getElementName();
217     }
218
219     private static String JavaDoc replaceAll(final String JavaDoc source, final String JavaDoc replaceFrom, final String JavaDoc replaceTo) {
220         final StringBuffer JavaDoc buf= new StringBuffer JavaDoc(source.length());
221         int currentIndex= 0;
222         int matchIndex;
223         while ((matchIndex= source.indexOf(replaceFrom, currentIndex)) != -1) {
224             buf.append(source.substring(currentIndex, matchIndex));
225             buf.append(replaceTo);
226             currentIndex= matchIndex + replaceFrom.length();
227         }
228         buf.append(source.substring(currentIndex));
229         return buf.toString();
230     }
231 }
232
Popular Tags