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