KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > refactoring > structure > TypeVariableUtil


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.structure;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Arrays JavaDoc;
15 import java.util.HashSet JavaDoc;
16 import java.util.List JavaDoc;
17 import java.util.Set JavaDoc;
18
19 import org.eclipse.core.runtime.Assert;
20
21 import org.eclipse.jdt.core.IField;
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.ITypeParameter;
26 import org.eclipse.jdt.core.JavaModelException;
27 import org.eclipse.jdt.core.Signature;
28
29
30 import org.eclipse.jdt.internal.ui.JavaPlugin;
31
32 /**
33  * Utilities to create mappings between type variables of different types in a type hierarchy.
34  */

35 public final class TypeVariableUtil {
36
37     /**
38      * Returns the composition of two type variable mappings. The type variables signatures can have an arbitrary format.
39      *
40      * @param first
41      * the first type variable mapping
42      * @param second
43      * the second type variable mapping
44      * @return the possibly empty composed type variable mapping
45      */

46     public static TypeVariableMaplet[] composeMappings(final TypeVariableMaplet[] first, final TypeVariableMaplet[] second) {
47         Assert.isNotNull(first);
48         Assert.isNotNull(second);
49
50         if (first.length == 0)
51             return first;
52         else if (second.length == 0)
53             return second;
54         else {
55             TypeVariableMaplet source= null;
56             TypeVariableMaplet target= null;
57             final Set JavaDoc set= new HashSet JavaDoc(first.length * second.length);
58             for (int index= 0; index < first.length; index++) {
59                 for (int offset= 0; offset < second.length; offset++) {
60                     source= first[index];
61                     target= second[offset];
62                     if (source.getTargetIndex() == target.getSourceIndex() && source.getTargetName().equals(target.getSourceName()))
63                         set.add(new TypeVariableMaplet(source.getSourceName(), index, target.getTargetName(), offset));
64                 }
65             }
66             final TypeVariableMaplet[] mapping= new TypeVariableMaplet[set.size()];
67             set.toArray(mapping);
68             return mapping;
69         }
70     }
71
72     /**
73      * Extracts the type variables from a signature
74      *
75      * @param signature
76      * the signature to extract the type variables from
77      * @param variables
78      * the set of variables to fill in
79      */

80     private static void extractTypeVariables(final String JavaDoc signature, final Set JavaDoc variables) {
81         Assert.isNotNull(signature);
82         Assert.isNotNull(variables);
83
84         final String JavaDoc[] arguments= Signature.getTypeArguments(signature);
85         if (arguments.length == 0) {
86             variables.add(Signature.toString(signature));
87         } else {
88             for (int index= 0; index < arguments.length; index++)
89                 variables.add(Signature.toString(arguments[index]));
90         }
91     }
92
93     /**
94      * Returns the type variables referenced in the signature of the specified member.
95      *
96      * @param declaring
97      * The declaring type of the specified member
98      * @param member
99      * the member to get its type variables. Can be a type, field or a method.
100      * @return a possibly empty array of type variable candidates
101      * @throws JavaModelException
102      * if the signature of the specified member could not be resolved
103      */

104     private static String JavaDoc[] getReferencedVariables(final IType declaring, final IMember member) throws JavaModelException {
105
106         Assert.isNotNull(declaring);
107         Assert.isNotNull(member);
108
109         final String JavaDoc[] variables= parametersToVariables(declaring.getTypeParameters());
110         String JavaDoc[] result= new String JavaDoc[0];
111         if (member instanceof IField) {
112             final String JavaDoc signature= ((IField) member).getTypeSignature();
113             final String JavaDoc[] signatures= getVariableSignatures(signature);
114             if (signatures.length == 0) {
115                 final String JavaDoc variable= Signature.toString(signature);
116                 for (int index= 0; index < variables.length; index++) {
117                     if (variable.equals(variables[index])) {
118                         result= new String JavaDoc[] { variable};
119                         break;
120                     }
121                 }
122             } else {
123                 result= new String JavaDoc[signatures.length];
124                 for (int index= 0; index < result.length; index++)
125                     result[index]= Signature.toString(signatures[index]);
126             }
127         } else if (member instanceof IMethod) {
128             final IMethod method= (IMethod) member;
129             final HashSet JavaDoc set= new HashSet JavaDoc();
130             final String JavaDoc[] types= method.getParameterTypes();
131             for (int index= 0; index < types.length; index++)
132                 extractTypeVariables(types[index], set);
133             extractTypeVariables(method.getReturnType(), set);
134             final String JavaDoc[] arguments= parametersToVariables(((IMethod) member).getTypeParameters());
135             for (int index= 0; index < arguments.length; index++)
136                 set.add(arguments[index]);
137             result= new String JavaDoc[set.size()];
138             set.toArray(result);
139         } else if (member instanceof IType)
140             result= parametersToVariables(((IType) member).getTypeParameters());
141         else {
142             JavaPlugin.logErrorMessage("Unexpected sub-type of IMember: " + member.getClass().getName()); //$NON-NLS-1$
143
Assert.isTrue(false);
144         }
145
146         final List JavaDoc list= new ArrayList JavaDoc(variables.length);
147         String JavaDoc variable= null;
148         for (int index= 0; index < variables.length; index++) {
149             variable= variables[index];
150             for (int offset= 0; offset < result.length; offset++)
151                 if (variable.equals(result[offset]))
152                     list.add(result[offset]);
153         }
154         result= new String JavaDoc[list.size()];
155         list.toArray(result);
156         return result;
157     }
158
159     /**
160      * Returns all type variable names of the indicated member not mapped by the specified type variable mapping.
161      *
162      * @param mapping
163      * the type variable mapping. The entries of this mapping must be simple type variable names.
164      * @param declaring
165      * the declaring type of the indicated member
166      * @param member
167      * the member to determine its unmapped type variable names
168      * @return a possibly empty array of unmapped type variable names
169      * @throws JavaModelException
170      * if the type parameters of the member could not be determined
171      */

172     public static String JavaDoc[] getUnmappedVariables(final TypeVariableMaplet[] mapping, final IType declaring, final IMember member) throws JavaModelException {
173
174         Assert.isNotNull(mapping);
175         Assert.isNotNull(declaring);
176         Assert.isNotNull(member);
177
178         List JavaDoc list= null;
179         final String JavaDoc[] types= getReferencedVariables(declaring, member);
180         if (mapping.length == 0) {
181             list= new ArrayList JavaDoc(types.length);
182             list.addAll(Arrays.asList(types));
183         } else {
184             final Set JavaDoc mapped= new HashSet JavaDoc(types.length);
185             String JavaDoc type= null;
186             for (int index= 0; index < types.length; index++) {
187                 for (int offset= 0; offset < mapping.length; offset++) {
188                     type= types[index];
189                     if (mapping[offset].getSourceName().equals(type))
190                         mapped.add(type);
191                 }
192             }
193             list= new ArrayList JavaDoc(types.length - mapped.size());
194             for (int index= 0; index < types.length; index++) {
195                 type= types[index];
196                 if (!mapped.contains(type))
197                     list.add(type);
198             }
199         }
200         final String JavaDoc[] result= new String JavaDoc[list.size()];
201         list.toArray(result);
202         return result;
203     }
204
205     /**
206      * Returns the type variable signatures of the specified parameterized type signature, or an empty array if none.
207      *
208      * @param signature
209      * the signature to get its type variable signatures from. The signature must be a parameterized type signature.
210      * @return a possibly empty array of type variable signatures
211      * @see Signature#getTypeArguments(String)
212      */

213     private static String JavaDoc[] getVariableSignatures(final String JavaDoc signature) {
214         Assert.isNotNull(signature);
215
216         String JavaDoc[] result= null;
217         try {
218             result= Signature.getTypeArguments(signature);
219         } catch (IllegalArgumentException JavaDoc exception) {
220             result= new String JavaDoc[0];
221         }
222         return result;
223     }
224
225     /**
226      * Returns the reversed type variable mapping of the specified mapping.
227      *
228      * @param mapping
229      * the mapping to inverse
230      * @return the possibly empty inverse mapping
231      */

232     public static TypeVariableMaplet[] inverseMapping(final TypeVariableMaplet[] mapping) {
233         Assert.isNotNull(mapping);
234
235         final TypeVariableMaplet[] result= new TypeVariableMaplet[mapping.length];
236         TypeVariableMaplet maplet= null;
237         for (int index= 0; index < mapping.length; index++) {
238             maplet= mapping[index];
239             result[index]= new TypeVariableMaplet(maplet.getTargetName(), maplet.getTargetIndex(), maplet.getSourceName(), maplet.getSourceIndex());
240         }
241         return result;
242     }
243
244     /**
245      * Creates a type variable mapping from a domain to a range.
246      *
247      * @param domain
248      * the domain of the mapping
249      * @param range
250      * the range of the mapping
251      * @param indexes
252      * <code>true</code> if the indexes should be compared, <code>false</code> if the names should be compared
253      * @return a possibly empty type variable mapping
254      */

255     private static TypeVariableMaplet[] parametersToSignatures(final ITypeParameter[] domain, final String JavaDoc[] range, final boolean indexes) {
256         Assert.isNotNull(domain);
257         Assert.isNotNull(range);
258
259         final Set JavaDoc set= new HashSet JavaDoc();
260         ITypeParameter source= null;
261         String JavaDoc target= null;
262         String JavaDoc element= null;
263         String JavaDoc signature= null;
264         for (int index= 0; index < domain.length; index++) {
265             source= domain[index];
266             for (int offset= 0; offset < range.length; offset++) {
267                 target= range[offset];
268                 element= source.getElementName();
269                 signature= Signature.toString(target);
270                 if (indexes) {
271                     if (offset == index)
272                         set.add(new TypeVariableMaplet(element, index, signature, offset));
273                 } else {
274                     if (element.equals(signature))
275                         set.add(new TypeVariableMaplet(element, index, signature, offset));
276                 }
277             }
278         }
279         final TypeVariableMaplet[] result= new TypeVariableMaplet[set.size()];
280         set.toArray(result);
281         return result;
282     }
283
284     /**
285      * Converts the specified type parameters to type variable names.
286      *
287      * @param parameters
288      * the type parameters to convert.
289      * @return the converted type variable names
290      * @see ITypeParameter#getElementName()
291      */

292     private static String JavaDoc[] parametersToVariables(final ITypeParameter[] parameters) {
293         Assert.isNotNull(parameters);
294
295         String JavaDoc[] result= new String JavaDoc[parameters.length];
296         for (int index= 0; index < parameters.length; index++)
297             result[index]= parameters[index].getElementName();
298
299         return result;
300     }
301
302     /**
303      * Creates a type variable mapping from a domain to a range.
304      *
305      * @param domain
306      * the domain of the mapping
307      * @param range
308      * the range of the mapping
309      * @return a possibly empty type variable mapping
310      */

311     private static TypeVariableMaplet[] signaturesToParameters(final String JavaDoc[] domain, final ITypeParameter[] range) {
312         Assert.isNotNull(domain);
313         Assert.isNotNull(range);
314         Assert.isTrue(domain.length == 0 || domain.length == range.length);
315
316         final List JavaDoc list= new ArrayList JavaDoc();
317         String JavaDoc source= null;
318         String JavaDoc target= null;
319         for (int index= 0; index < domain.length; index++) {
320             source= Signature.toString(domain[index]);
321             target= range[index].getElementName();
322             list.add(new TypeVariableMaplet(source, index, target, index));
323         }
324         final TypeVariableMaplet[] result= new TypeVariableMaplet[list.size()];
325         list.toArray(result);
326         return result;
327     }
328
329     /**
330      * Returns a type variable mapping from a subclass to a superclass.
331      *
332      * @param type
333      * the type representing the subclass class
334      * @return a type variable mapping. The mapping entries consist of simple type variable names.
335      * @throws JavaModelException
336      * if the signature of one of the types involved could not be retrieved
337      */

338     public static TypeVariableMaplet[] subTypeToInheritedType(final IType type) throws JavaModelException {
339         Assert.isNotNull(type);
340
341         final ITypeParameter[] domain= type.getTypeParameters();
342         if (domain.length > 0) {
343             final String JavaDoc signature= type.getSuperclassTypeSignature();
344             if (signature != null) {
345                 final String JavaDoc[] range= getVariableSignatures(signature);
346                 if (range.length > 0)
347                     return parametersToSignatures(domain, range, false);
348             }
349         }
350         return new TypeVariableMaplet[0];
351     }
352
353     /**
354      * Returns a type variable mapping from a subclass to a superclass.
355      *
356      * @param subtype
357      * the type representing the subclass
358      * @param supertype
359      * the type representing the superclass
360      * @return a type variable mapping. The mapping entries consist of simple type variable names.
361      * @throws JavaModelException
362      * if the signature of one of the types involved could not be retrieved
363      */

364     public static TypeVariableMaplet[] subTypeToSuperType(final IType subtype, final IType supertype) throws JavaModelException {
365         Assert.isNotNull(subtype);
366         Assert.isNotNull(supertype);
367
368         final TypeVariableMaplet[] mapping= subTypeToInheritedType(subtype);
369         if (mapping.length > 0) {
370             final ITypeParameter[] range= supertype.getTypeParameters();
371             if (range.length > 0) {
372                 final String JavaDoc signature= subtype.getSuperclassTypeSignature();
373                 if (signature != null) {
374                     final String JavaDoc[] domain= getVariableSignatures(signature);
375                     if (domain.length > 0)
376                         return composeMappings(mapping, signaturesToParameters(domain, range));
377                 }
378             }
379         }
380         return mapping;
381     }
382
383     /**
384      * Returns a type variable mapping from a superclass to a subclass.
385      *
386      * @param supertype
387      * the type representing the superclass
388      * @param subtype
389      * the type representing the subclass
390      * @return a type variable mapping. The mapping entries consist of simple type variable names.
391      * @throws JavaModelException
392      * if the signature of one of the types involved could not be retrieved
393      */

394     public static TypeVariableMaplet[] superTypeToInheritedType(final IType supertype, final IType subtype) throws JavaModelException {
395         Assert.isNotNull(subtype);
396         Assert.isNotNull(supertype);
397
398         final ITypeParameter[] domain= supertype.getTypeParameters();
399         if (domain.length > 0) {
400             final String JavaDoc signature= subtype.getSuperclassTypeSignature();
401             if (signature != null) {
402                 final String JavaDoc[] range= getVariableSignatures(signature);
403                 if (range.length > 0)
404                     return parametersToSignatures(domain, range, true);
405             }
406         }
407         return new TypeVariableMaplet[0];
408     }
409
410     /**
411      * Returns a type variable mapping from a superclass to a subclass.
412      *
413      * @param supertype
414      * the type representing the superclass
415      * @param subtype
416      * the type representing the subclass
417      * @return a type variable mapping. The mapping entries consist of simple type variable names.
418      * @throws JavaModelException
419      * if the signature of one of the types involved could not be retrieved
420      */

421     public static TypeVariableMaplet[] superTypeToSubType(final IType supertype, final IType subtype) throws JavaModelException {
422         Assert.isNotNull(supertype);
423         Assert.isNotNull(subtype);
424
425         return inverseMapping(subTypeToSuperType(subtype, supertype));
426     }
427
428     private TypeVariableUtil() {
429         // Not to be instantiated
430
}
431 }
432
Popular Tags