Adding ParameterizedTypeImpl.java for parameterized types.
[jpf-core.git] / src / classes / sun / reflect / generics / reflectiveObjects / ParameterizedTypeImpl.java
1 package sun.reflect.generics.reflectiveObjects;
2
3 import sun.reflect.generics.tree.FieldTypeSignature;
4
5 import java.lang.reflect.MalformedParameterizedTypeException;
6 import java.lang.reflect.Method;
7 import java.lang.reflect.ParameterizedType;
8 import java.lang.reflect.Type;
9 import java.lang.reflect.TypeVariable;
10 import java.util.Arrays;
11 import java.util.Objects;
12
13 /**
14  * MJI model class for sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
15  *
16  * This is a JPF specific version of a system class because we can't use the real,
17  * platform VM specific version (it's native all over the place, its field
18  * structure isn't documented, most of its methods are private, hence we can't
19  * even instantiate it properly).
20  *
21  * Note that this class never gets seen by the real VM - it's for JPF's eyes only.
22  *
23  */
24
25 /** Implementing class for ParameterizedType interface. */
26 public class ParameterizedTypeImpl implements ParameterizedType {
27     private final Type[] actualTypeArguments;
28     private final Class<?>  rawType;
29     private final Type   ownerType;
30
31     private ParameterizedTypeImpl(Class<?> rawType,
32                                   Type[] actualTypeArguments,
33                                   Type ownerType) {
34         this.actualTypeArguments = actualTypeArguments;
35         this.rawType             = rawType;
36         this.ownerType = (ownerType != null) ? ownerType : rawType.getDeclaringClass();
37         validateConstructorArguments();
38     }
39
40     private void validateConstructorArguments() {
41         TypeVariable<?>[] formals = rawType.getTypeParameters();
42         // check correct arity of actual type args
43         if (formals.length != actualTypeArguments.length){
44             throw new MalformedParameterizedTypeException();
45         }
46         for (int i = 0; i < actualTypeArguments.length; i++) {
47             // check actuals against formals' bounds
48         }
49     }
50
51     /**
52      * Static factory. Given a (generic) class, actual type arguments
53      * and an owner type, creates a parameterized type.
54      */
55     public static ParameterizedTypeImpl make(Class<?> rawType,
56                                              Type[] actualTypeArguments,
57                                              Type ownerType) {
58         return new ParameterizedTypeImpl(rawType, actualTypeArguments,
59                                          ownerType);
60     }
61
62     public Type[] getActualTypeArguments() {
63         return actualTypeArguments.clone();
64     }
65
66     /**
67      * Returns the <tt>Type</tt> object representing the class or interface
68      * that declared this type.
69      *
70      * @return the <tt>Type</tt> object representing the class or interface
71      *     that declared this type
72      */
73     public Class<?> getRawType() {
74         return rawType;
75     }
76
77
78     public Type getOwnerType() {
79         return ownerType;
80     }
81
82     @Override
83     public boolean equals(Object o) {
84         if (o instanceof ParameterizedType) {
85             // Check that information is equivalent
86             ParameterizedType that = (ParameterizedType) o;
87
88             if (this == that)
89                 return true;
90
91             Type thatOwner   = that.getOwnerType();
92             Type thatRawType = that.getRawType();
93
94             if (false) { // Debugging
95                 boolean ownerEquality = (ownerType == null ?
96                                          thatOwner == null :
97                                          ownerType.equals(thatOwner));
98                 boolean rawEquality = (rawType == null ?
99                                        thatRawType == null :
100                                        rawType.equals(thatRawType));
101
102                 boolean typeArgEquality = Arrays.equals(actualTypeArguments, // avoid clone
103                                                         that.getActualTypeArguments());
104                 for (Type t : actualTypeArguments) {
105                     System.out.printf("\t\t%s%s%n", t, t.getClass());
106                 }
107
108                 System.out.printf("\towner %s\traw %s\ttypeArg %s%n",
109                                   ownerEquality, rawEquality, typeArgEquality);
110                 return ownerEquality && rawEquality && typeArgEquality;
111             }
112
113             return
114                 Objects.equals(ownerType, thatOwner) &&
115                 Objects.equals(rawType, thatRawType) &&
116                 Arrays.equals(actualTypeArguments, // avoid clone
117                               that.getActualTypeArguments());
118         } else
119             return false;
120     }
121
122     @Override
123     public int hashCode() {
124         return
125             Arrays.hashCode(actualTypeArguments) ^
126             Objects.hashCode(ownerType) ^
127             Objects.hashCode(rawType);
128     }
129
130     public String toString() {
131         StringBuilder sb = new StringBuilder();
132
133         if (ownerType != null) {
134             if (ownerType instanceof Class)
135                 sb.append(((Class)ownerType).getName());
136             else
137                 sb.append(ownerType.toString());
138
139             sb.append(".");
140
141             if (ownerType instanceof ParameterizedTypeImpl) {
142                 // Find simple name of nested type by removing the
143                 // shared prefix with owner.
144                 sb.append(rawType.getName().replace( ((ParameterizedTypeImpl)ownerType).rawType.getName() + "$",
145                                          ""));
146             } else
147                 sb.append(rawType.getName());
148         } else
149             sb.append(rawType.getName());
150
151         if (actualTypeArguments != null &&
152             actualTypeArguments.length > 0) {
153             sb.append("<");
154             boolean first = true;
155             for(Type t: actualTypeArguments) {
156                 if (!first)
157                     sb.append(", ");
158                 sb.append(t.getTypeName());
159                 first = false;
160             }
161             sb.append(">");
162         }
163
164         return sb.toString();
165     }
166 }
167