48c30d2f8cd8b65ff8060b9d0d32c5592d682548
[jpf-core.git] / src / classes / sun / reflect / generics / reflectiveObjects / ParameterizedTypeImpl.java
1 /*
2  * Copyright (C) 2014, United States Government, as represented by the
3  * Administrator of the National Aeronautics and Space Administration.
4  * All rights reserved.
5  *
6  * The Java Pathfinder core (jpf-core) platform is licensed under the
7  * Apache License, Version 2.0 (the "License"); you may not use this file except
8  * in compliance with the License. You may obtain a copy of the License at
9  *
10  *        http://www.apache.org/licenses/LICENSE-2.0.
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 package sun.reflect.generics.reflectiveObjects;
19
20 import sun.reflect.generics.tree.FieldTypeSignature;
21
22 import java.lang.reflect.MalformedParameterizedTypeException;
23 import java.lang.reflect.Method;
24 import java.lang.reflect.ParameterizedType;
25 import java.lang.reflect.Type;
26 import java.lang.reflect.TypeVariable;
27 import java.util.Arrays;
28 import java.util.Objects;
29
30 // TODO: Fix for Groovy's model-checking
31 /**
32  * MJI model class for sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
33  *
34  * This is a JPF specific version of a system class because we can't use the real,
35  * platform VM specific version (it's native all over the place, its field
36  * structure isn't documented, most of its methods are private, hence we can't
37  * even instantiate it properly).
38  *
39  * Note that this class never gets seen by the real VM - it's for JPF's eyes only.
40  *
41  */
42
43 /** Implementing class for ParameterizedType interface. */
44 public class ParameterizedTypeImpl implements ParameterizedType {
45     private final Type[] actualTypeArguments;
46     private final Class<?>  rawType;
47     private final Type   ownerType;
48
49     private ParameterizedTypeImpl(Class<?> rawType,
50                                   Type[] actualTypeArguments,
51                                   Type ownerType) {
52         this.actualTypeArguments = actualTypeArguments;
53         this.rawType             = rawType;
54         this.ownerType = (ownerType != null) ? ownerType : rawType.getDeclaringClass();
55         validateConstructorArguments();
56     }
57
58     private void validateConstructorArguments() {
59         TypeVariable<?>[] formals = rawType.getTypeParameters();
60         // check correct arity of actual type args
61         if (formals.length != actualTypeArguments.length){
62             throw new MalformedParameterizedTypeException();
63         }
64         for (int i = 0; i < actualTypeArguments.length; i++) {
65             // check actuals against formals' bounds
66         }
67     }
68
69     /**
70      * Static factory. Given a (generic) class, actual type arguments
71      * and an owner type, creates a parameterized type.
72      */
73     public static ParameterizedTypeImpl make(Class<?> rawType,
74                                              Type[] actualTypeArguments,
75                                              Type ownerType) {
76         return new ParameterizedTypeImpl(rawType, actualTypeArguments,
77                                          ownerType);
78     }
79
80     public Type[] getActualTypeArguments() {
81         return actualTypeArguments.clone();
82     }
83
84     /**
85      * Returns the <tt>Type</tt> object representing the class or interface
86      * that declared this type.
87      *
88      * @return the <tt>Type</tt> object representing the class or interface
89      *     that declared this type
90      */
91     public Class<?> getRawType() {
92         return rawType;
93     }
94
95
96     public Type getOwnerType() {
97         return ownerType;
98     }
99
100     @Override
101     public boolean equals(Object o) {
102         if (o instanceof ParameterizedType) {
103             // Check that information is equivalent
104             ParameterizedType that = (ParameterizedType) o;
105
106             if (this == that)
107                 return true;
108
109             Type thatOwner   = that.getOwnerType();
110             Type thatRawType = that.getRawType();
111
112             if (false) { // Debugging
113                 boolean ownerEquality = (ownerType == null ?
114                                          thatOwner == null :
115                                          ownerType.equals(thatOwner));
116                 boolean rawEquality = (rawType == null ?
117                                        thatRawType == null :
118                                        rawType.equals(thatRawType));
119
120                 boolean typeArgEquality = Arrays.equals(actualTypeArguments, // avoid clone
121                                                         that.getActualTypeArguments());
122                 for (Type t : actualTypeArguments) {
123                     System.out.printf("\t\t%s%s%n", t, t.getClass());
124                 }
125
126                 System.out.printf("\towner %s\traw %s\ttypeArg %s%n",
127                                   ownerEquality, rawEquality, typeArgEquality);
128                 return ownerEquality && rawEquality && typeArgEquality;
129             }
130
131             return
132                 Objects.equals(ownerType, thatOwner) &&
133                 Objects.equals(rawType, thatRawType) &&
134                 Arrays.equals(actualTypeArguments, // avoid clone
135                               that.getActualTypeArguments());
136         } else
137             return false;
138     }
139
140     @Override
141     public int hashCode() {
142         return
143             Arrays.hashCode(actualTypeArguments) ^
144             Objects.hashCode(ownerType) ^
145             Objects.hashCode(rawType);
146     }
147
148     public String toString() {
149         StringBuilder sb = new StringBuilder();
150
151         if (ownerType != null) {
152             if (ownerType instanceof Class)
153                 sb.append(((Class)ownerType).getName());
154             else
155                 sb.append(ownerType.toString());
156
157             sb.append(".");
158
159             if (ownerType instanceof ParameterizedTypeImpl) {
160                 // Find simple name of nested type by removing the
161                 // shared prefix with owner.
162                 sb.append(rawType.getName().replace( ((ParameterizedTypeImpl)ownerType).rawType.getName() + "$",
163                                          ""));
164             } else
165                 sb.append(rawType.getName());
166         } else
167             sb.append(rawType.getName());
168
169         if (actualTypeArguments != null &&
170             actualTypeArguments.length > 0) {
171             sb.append("<");
172             boolean first = true;
173             for(Type t: actualTypeArguments) {
174                 if (!first)
175                     sb.append(", ");
176                 sb.append(t.getTypeName());
177                 first = false;
178             }
179             sb.append(">");
180         }
181
182         return sb.toString();
183     }
184 }
185