1 /*
2 * Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26 package sun.reflect.generics.reflectiveObjects;
27
28 import sun.reflect.generics.tree.FieldTypeSignature;
29
30 import java.lang.reflect.MalformedParameterizedTypeException;
31 import java.lang.reflect.Method;
32 import java.lang.reflect.ParameterizedType;
33 import java.lang.reflect.Type;
34 import java.lang.reflect.TypeVariable;
35 import java.util.Arrays;
36
37
38 /** Implementing class for ParameterizedType interface. */
39
40 public class ParameterizedTypeImpl implements ParameterizedType {
41 private Type[] actualTypeArguments;
42 private Class<?> rawType;
43 private Type ownerType;
44
45 private ParameterizedTypeImpl(Class<?> rawType,
46 Type[] actualTypeArguments,
47 Type ownerType) {
48 this.actualTypeArguments = actualTypeArguments;
49 this.rawType = rawType;
50 if (ownerType != null) {
51 this.ownerType = ownerType;
52 } else { this.ownerType = rawType.getDeclaringClass();}
53 validateConstructorArguments();
54 }
55
56 private void validateConstructorArguments() {
57 TypeVariable/*<?>*/[] formals = rawType.getTypeParameters();
58 // check correct arity of actual type args
59 if (formals.length != actualTypeArguments.length){
60 throw new MalformedParameterizedTypeException();
61 }
62 for (int i = 0; i < actualTypeArguments.length; i++) {
63 // check actuals against formals' bounds
64 }
65
66 }
67
68 /**
69 * Static factory. Given a (generic) class, actual type arguments
70 * and an owner type, creates a parameterized type.
71 * This class can be instantiated with a a raw type that does not
72 * represent a generic type, provided the list of actual type
73 * arguments is empty.
74 * If the ownerType argument is null, the declaring class of the
75 * raw type is used as the owner type.
76 * <p> This method throws a MalformedParameterizedTypeException
77 * under the following circumstances:
78 * If the number of actual type arguments (i.e., the size of the
79 * array <tt>typeArgs</tt>) does not correspond to the number of
80 * formal type arguments.
81 * If any of the actual type arguments is not an instance of the
82 * bounds on the corresponding formal.
83 * @param rawType the Class representing the generic type declaration being
84 * instantiated
85 * @param actualTypeArguments - a (possibly empty) array of types
86 * representing the actual type arguments to the parameterized type
87 * @param ownerType - the enclosing type, if known.
88 * @return An instance of <tt>ParameterizedType</tt>
89 * @throws MalformedParameterizedTypeException - if the instantiation
90 * is invalid
91 */
92 public static ParameterizedTypeImpl make(Class<?> rawType,
93 Type[] actualTypeArguments,
94 Type ownerType) {
95 return new ParameterizedTypeImpl(rawType, actualTypeArguments,
96 ownerType);
97 }
98
99
100 /**
101 * Returns an array of <tt>Type</tt> objects representing the actual type
102 * arguments to this type.
103 *
104 * <p>Note that in some cases, the returned array be empty. This can occur
105 * if this type represents a non-parameterized type nested within
106 * a parameterized type.
107 *
108 * @return an array of <tt>Type</tt> objects representing the actual type
109 * arguments to this type
110 * @throws <tt>TypeNotPresentException</tt> if any of the
111 * actual type arguments refers to a non-existent type declaration
112 * @throws <tt>MalformedParameterizedTypeException</tt> if any of the
113 * actual type parameters refer to a parameterized type that cannot
114 * be instantiated for any reason
115 * @since 1.5
116 */
117 public Type[] getActualTypeArguments() {
118 return actualTypeArguments.clone();
119 }
120
121 /**
122 * Returns the <tt>Type</tt> object representing the class or interface
123 * that declared this type.
124 *
125 * @return the <tt>Type</tt> object representing the class or interface
126 * that declared this type
127 */
128 public Class<?> getRawType() {
129 return rawType;
130 }
131
132
133 /**
134 * Returns a <tt>Type</tt> object representing the type that this type
135 * is a member of. For example, if this type is <tt>O<T>.I<S></tt>,
136 * return a representation of <tt>O<T></tt>.
137 *
138 * <p>If this type is a top-level type, <tt>null</tt> is returned.
139 *
140 * @return a <tt>Type</tt> object representing the type that
141 * this type is a member of. If this type is a top-level type,
142 * <tt>null</tt> is returned
143 * @throws <tt>TypeNotPresentException</tt> if the owner type
144 * refers to a non-existent type declaration
145 * @throws <tt>MalformedParameterizedTypeException</tt> if the owner type
146 * refers to a parameterized type that cannot be instantiated
147 * for any reason
148 *
149 */
150 public Type getOwnerType() {
151 return ownerType;
152 }
153
154 /*
155 * From the JavaDoc for java.lang.reflect.ParameterizedType
156 * "Instances of classes that implement this interface must
157 * implement an equals() method that equates any two instances
158 * that share the same generic type declaration and have equal
159 * type parameters."
160 */
161 @Override
162 public boolean equals(Object o) {
163 if (o instanceof ParameterizedType) {
164 // Check that information is equivalent
165 ParameterizedType that = (ParameterizedType) o;
166
167 if (this == that)
168 return true;
169
170 Type thatOwner = that.getOwnerType();
171 Type thatRawType = that.getRawType();
172
173 if (false) { // Debugging
174 boolean ownerEquality = (ownerType == null ?
175 thatOwner == null :
176 ownerType.equals(thatOwner));
177 boolean rawEquality = (rawType == null ?
178 thatRawType == null :
179 rawType.equals(thatRawType));
180
181 boolean typeArgEquality = Arrays.equals(actualTypeArguments, // avoid clone
182 that.getActualTypeArguments());
183 for (Type t : actualTypeArguments) {
184 System.out.printf("\t\t%s%s%n", t, t.getClass());
185 }
186
187 System.out.printf("\towner %s\traw %s\ttypeArg %s%n",
188 ownerEquality, rawEquality, typeArgEquality);
189 return ownerEquality && rawEquality && typeArgEquality;
190 }
191
192
193 return
194 (ownerType == null ?
195 thatOwner == null :
196 ownerType.equals(thatOwner)) &&
197 (rawType == null ?
198 thatRawType == null :
199 rawType.equals(thatRawType)) &&
200 Arrays.equals(actualTypeArguments, // avoid clone
201 that.getActualTypeArguments());
202 } else
203 return false;
204 }
205
206 @Override
207 public int hashCode() {
208 return
209 Arrays.hashCode(actualTypeArguments) ^
210 (ownerType == null ? 0 : ownerType.hashCode() ) ^
211 (rawType == null ? 0 : rawType.hashCode() );
212 }
213
214 public String toString() {
215 StringBuilder sb = new StringBuilder();
216
217 if (ownerType != null) {
218 if (ownerType instanceof Class)
219 sb.append(((Class)ownerType).getName());
220 else
221 sb.append(ownerType.toString());
222
223 sb.append(".");
224
225 if (ownerType instanceof ParameterizedTypeImpl) {
226 // Find simple name of nested type by removing the
227 // shared prefix with owner.
228 sb.append(rawType.getName().replace( ((ParameterizedTypeImpl)ownerType).rawType.getName() + "$",
229 ""));
230 } else
231 sb.append(rawType.getName());
232 } else
233 sb.append(rawType.getName());
234
235 if (actualTypeArguments != null &&
236 actualTypeArguments.length > 0) {
237 sb.append("<");
238 boolean first = true;
239 for(Type t: actualTypeArguments) {
240 if (!first)
241 sb.append(", ");
242 if (t instanceof Class)
243 sb.append(((Class)t).getName());
244 else
245 sb.append(t.toString());
246 first = false;
247 }
248 sb.append(">");
249 }
250
251 return sb.toString();
252 }
253 }