KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > umd > cs > findbugs > ba > generic > GenericUtilities


1 /*
2  * FindBugs - Find Bugs in Java programs
3  * Copyright (C) 2006, University of Maryland
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  */

19
20 package edu.umd.cs.findbugs.ba.generic;
21
22 import java.util.ArrayList JavaDoc;
23 import java.util.Iterator JavaDoc;
24 import java.util.List JavaDoc;
25
26 import org.apache.bcel.generic.ArrayType;
27 import org.apache.bcel.generic.ObjectType;
28 import org.apache.bcel.generic.Type;
29
30 /**
31  * Utilities for adding support for generics. Most of these
32  * methods can be applied to generic and non generic type
33  * information.
34  *
35  * @author Nat Ayewah
36  */

37 public class GenericUtilities {
38
39     public static abstract class TypeCategory {
40         /** anything that is not a reference */
41         public static final TypeCategory NON_REFERENCE_TYPE = new TypeCategory(){
42             public String JavaDoc asString(GenericObjectType obj) {
43                 // obj.getTypeCategory() does not return NON_REFERENCE_TYPE
44
return GenericUtilities.getString(obj);
45             }
46         };
47     
48         /** A simple (non-generic ObjectType) */
49         public static final TypeCategory PLAIN_OBJECT_TYPE = new TypeCategory()
50          {
51             public String JavaDoc asString(GenericObjectType obj) {
52                 // obj.getTypeCategory() does not return PLAIN_OBJECT_TYPE
53
return GenericUtilities.getString(obj);
54             }
55         };
56     
57         /** A array */
58         public static final TypeCategory ARRAY_TYPE = new TypeCategory()
59          {
60             public String JavaDoc asString(GenericObjectType obj) {
61                 // obj.getTypeCategory() does not return ARRAY_TYPE
62
return GenericUtilities.getString(obj);
63             }
64         };
65     
66         /** A parameterized class e.g. <code>List&lt;String&gt;</code> */
67         public static final TypeCategory PARAMETERS = new TypeCategory()
68          {
69             public String JavaDoc asString(GenericObjectType obj) {
70                 String JavaDoc result = obj.toString();
71                 result += "<";
72                 for (Type t : obj.parameters) {
73                     result += GenericUtilities.getString(t) + ",";
74                 }
75                 return result.substring(0,result.length()-1) + ">";
76             }
77         };
78     
79         /** A simple type variable e.g. <code>E</code>.
80          * Underlying ObjectType is <code>java.lang.Object</code> */

81         public static final TypeCategory TYPE_VARIABLE = new TypeCategory()
82          {
83             public String JavaDoc asString(GenericObjectType obj) {
84                 return obj.variable;
85             }
86         };
87     
88         /** A simple wildcard i.e. <code>?</code>.
89          * Underlying ObjectType is <code>java.lang.Object</code> */

90         public static final TypeCategory WILDCARD = new TypeCategory()
91          {
92             public String JavaDoc asString(GenericObjectType obj) {
93                 return "?";
94             }
95         };
96     
97         /** A wildcard that extends another ObjectType e.g. <code>? extends Comparable</code>.
98          * Underlying ObjectType is <code>java.lang.Object</code>.
99          * The extended type can be an ObjectType or a GenericObjectType */

100         public static final TypeCategory WILDCARD_EXTENDS = new TypeCategory()
101          {
102             public String JavaDoc asString(GenericObjectType obj) {
103                 return "? extends " + GenericUtilities.getString(obj.extension);
104             }
105         };
106     
107         /** A wildcard that is extended by another ObjectType e.g. <code>? super Comparable</code>.
108          * Underlying ObjectType is <code>java.lang.Object</code>.
109          * The super type can be an ObjectType or a GenericObjectType */

110         public static final TypeCategory WILDCARD_SUPER = new TypeCategory()
111          {
112             public String JavaDoc asString(GenericObjectType obj) {
113                 return "? super " + GenericUtilities.getString(obj.extension);
114             }
115         };
116         
117         public abstract String JavaDoc asString(GenericObjectType obj);
118         
119         public static String JavaDoc asString(ArrayType atype) {
120             Type obj = atype.getBasicType();
121             String JavaDoc result = GenericUtilities.getString(obj);
122             for (int i=0; i<atype.getDimensions(); i++)
123                 result += "[]";
124             return result;
125         }
126     }
127     
128     /**
129      * Get the TypeCategory that represents this Object
130      * @see GenericUtilities.TypeCategory
131      */

132     public static final TypeCategory getTypeCategory(Type type) {
133         if (type instanceof GenericObjectType)
134             return ((GenericObjectType) type).getTypeCategory();
135         
136         if (type instanceof ObjectType)
137             return TypeCategory.PLAIN_OBJECT_TYPE;
138         
139         if (type instanceof ArrayType)
140             return TypeCategory.ARRAY_TYPE;
141         
142         return TypeCategory.NON_REFERENCE_TYPE;
143     }
144     
145     public static final boolean isPlainObject(Type type) {
146         return getTypeCategory(type) == TypeCategory.PLAIN_OBJECT_TYPE;
147     }
148
149     /**
150      * Get String representation of a Type including Generic information
151      */

152     public static final String JavaDoc getString(Type type) {
153         if (type instanceof GenericObjectType)
154             return ((GenericObjectType) type).toString(true);
155         else if (type instanceof ArrayType)
156             return TypeCategory.asString((ArrayType) type);
157         else
158             return type.toString();
159     }
160
161     /**
162      * This method is analogous to <code>Type.getType(String)</code>,
163      * except that it also accepts signatures with generic information.
164      * e.g. <code>Ljava/util/ArrayList&lt;TT;&gt;;</code> <p>
165      *
166      * The signature should only contain one type. Use GenericSignatureParser
167      * to break up a signature with many types or call createTypes(String) to
168      * return a list of types
169      */

170     public static final Type getType(String JavaDoc signature) {
171         // ensure signature only has one type
172
if (new GenericSignatureParser("(" + signature + ")V").getNumParameters() != 1)
173             throw new IllegalArgumentException JavaDoc("the following signature does not " +
174                     "contain exactly one type: " + signature);
175         
176         int index = 0;
177     
178         if (signature.startsWith("L")) {
179             index = signature.indexOf('<');
180             if (index < 0)
181                 return Type.getType(signature);
182             
183             List JavaDoc<Type> parameters = GenericUtilities.getTypes(
184                     signature.substring(index+1, signature.lastIndexOf('>')));
185             return new GenericObjectType(signature.substring(1,index), parameters);
186             
187         } else if (signature.startsWith("T")) {
188             // ignore the prefix "T" and the suffix ";"
189
return new GenericObjectType(signature.substring(1,signature.length()-1));
190             
191         } else if (signature.startsWith("[")) {
192             index = signature.lastIndexOf('[') + 1;
193             return new ArrayType( getType(signature.substring(index)), index);
194             
195         } else if (signature.startsWith("*")) {
196             return new GenericObjectType("*");
197             
198         } else if (signature.startsWith("+") || signature.startsWith("-")) {
199             return new GenericObjectType(
200                     signature.substring(0,1),
201                     getType(signature.substring(1)) );
202             
203         } else
204             // assert signature contains no generic information
205
return Type.getType(signature);
206     }
207
208     /**
209      * Parse a bytecode signature that has 1 or more (possibly generic) types
210      * and return a list of the Types.
211      * @param signature bytecode signature e.g.
212      * e.g. <code>Ljava/util/ArrayList&lt;Ljava/lang/String;&gt;;Ljava/util/ArrayList&lt;TT;&gt;;Ljava/util/ArrayList&lt;*&gt;;</code>
213      */

214     public static final List JavaDoc<Type> getTypes(String JavaDoc signature) {
215         GenericSignatureParser parser = new GenericSignatureParser("(" + signature + ")V");
216         List JavaDoc<Type> types = new ArrayList JavaDoc<Type>();
217         
218         Iterator JavaDoc<String JavaDoc> iter = parser.parameterSignatureIterator();
219         while (iter.hasNext()) {
220             String JavaDoc parameterString = iter.next();
221             types.add(getType(parameterString));
222         }
223         return types;
224     }
225
226 }
227
Popular Tags