1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package libcore.reflect;
18 
19 import java.lang.reflect.ParameterizedType;
20 import java.lang.reflect.Type;
21 import java.util.Arrays;
22 import java.util.Objects;
23 
24 public final class ParameterizedTypeImpl implements ParameterizedType {
25     private final ListOfTypes args;
26     private final ParameterizedTypeImpl ownerType0; // Potentially unresolved.
27     private Type ownerTypeRes; // Potentially unresolved.
28     private Class rawType; // Potentially unresolved.
29     private final String rawTypeName;
30     private final ClassLoader loader;
31 
ParameterizedTypeImpl(ParameterizedTypeImpl ownerType, String rawTypeName, ListOfTypes args, ClassLoader loader)32     public ParameterizedTypeImpl(ParameterizedTypeImpl ownerType, String rawTypeName,
33             ListOfTypes args, ClassLoader loader) {
34         if (args == null) {
35             throw new NullPointerException();
36         }
37         this.ownerType0 = ownerType;
38         this.rawTypeName = rawTypeName;
39         this.args = args;
40         this.loader = loader;
41     }
42 
43 
getActualTypeArguments()44     public Type[] getActualTypeArguments() {
45         return args.getResolvedTypes().clone();
46     }
47 
getOwnerType()48     public Type getOwnerType() {
49         if (ownerTypeRes == null) {
50             if (ownerType0 != null) {
51                 ownerTypeRes = ownerType0.getResolvedType();
52             } else {
53                 ownerTypeRes = getRawType().getDeclaringClass();
54             }
55         }
56         return ownerTypeRes;
57     }
58 
getRawType()59     public Class getRawType() {
60         if (rawType == null) {
61             // Here the actual loading of the class has to be performed and the
62             // Exceptions have to be re-thrown TypeNotPresent...
63             // How to deal with member (nested) classes?
64             try {
65                 rawType = Class.forName(rawTypeName, false, loader);
66             } catch (ClassNotFoundException e) {
67                 throw new TypeNotPresentException(rawTypeName, e);
68             }
69         }
70         return rawType;
71     }
72 
73 
getResolvedType()74     Type getResolvedType() {
75         if (args.getResolvedTypes().length == 0) {
76             return getRawType();
77         } else {
78             return this;
79         }
80     }
81 
82     @Override
equals(Object o)83     public boolean equals(Object o) {
84         if (!(o instanceof ParameterizedType)) {
85             return false;
86         }
87         ParameterizedType that = (ParameterizedType) o;
88         return Objects.equals(getRawType(), that.getRawType()) &&
89                 Objects.equals(getOwnerType(), that.getOwnerType()) &&
90                 Arrays.equals(args.getResolvedTypes(), that.getActualTypeArguments());
91     }
92 
93     @Override
hashCode()94     public int hashCode() {
95         return 31 * (31 * Objects.hashCode(getRawType()) + Objects.hashCode(getOwnerType())) +
96             Arrays.hashCode(args.getResolvedTypes());
97     }
98 
99     @Override
toString()100     public String toString() {
101         StringBuilder sb = new StringBuilder();
102         sb.append(rawTypeName);
103         if (args.length() > 0) {
104             sb.append("<").append(args).append(">");
105         }
106         return sb.toString();
107     }
108 }
109