001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.harmony.lang.reflect.implementation;
019:
020: import java.lang.reflect.TypeVariable;
021: import java.lang.reflect.GenericDeclaration;
022: import java.lang.reflect.Type;
023: import java.lang.reflect.Method;
024: import java.lang.reflect.Constructor;
025:
026: import org.apache.harmony.lang.reflect.support.*;
027: import org.apache.harmony.lang.reflect.parser.*;
028: import org.apache.harmony.lang.reflect.repository.*;
029:
030: /**
031: * @author Serguei S. Zapreyev
032: * @version $Revision: 1.1.2.2 $
033: */
034: public final class TypeVariableImpl<D extends GenericDeclaration>
035: implements TypeVariable<D> {
036: private Type[] bounds;
037: private final D genericDeclaration;
038: private final String name;
039: private final InterimTypeParameter pTypeParameter;
040:
041: /**
042: * @param genericDeclaration declaration where a type variable is declared
043: * @param name type variable name
044: * @param pTypeParameter type variable intermediate representation
045: * @api2vm
046: */
047: public TypeVariableImpl(D genericDeclaration, String name,
048: InterimTypeParameter pTypeParameter) {
049: Class klass = null;
050: if (genericDeclaration instanceof Class) {
051: klass = (Class) genericDeclaration;
052: } else {
053: klass = (genericDeclaration instanceof Method ? ((Method) genericDeclaration)
054: .getDeclaringClass()
055: : ((Constructor) genericDeclaration)
056: .getDeclaringClass());
057: }
058:
059: while (klass != null) {
060: // TODO: it should be revised to provide the correct classloader for resolving.
061: AuxiliaryLoader.resolve(klass);
062: klass = klass.getDeclaringClass();
063: }
064:
065: this .genericDeclaration = genericDeclaration;
066: this .name = AuxiliaryFinder.transform(name);
067: this .bounds = null; // Creating a type variable must not cause the creation of corresponding bounds. So, the creation should be initiated at a moment of first getBounds invocation.
068: this .pTypeParameter = pTypeParameter;
069: }
070:
071: public boolean equals(Object other) {
072: // XXX: The bounds comparing seems to be not actual here because
073: // 1. equality of variables is defined by belonging to the same declaration and a parameter's names coincedence
074: // 2. creating a type variable must not cause the creation of corresponding bounds
075: // Therefore we seem not to have to initiate bounds creation here.
076: // Nevertheless, we can just compare bound reflections within contents of both pTypeParameter fields (type variable intermediate representations)
077:
078: //return other != null && other instanceof TypeVariable && ((TypeVariable)other).name.equals(name) && ((TypeVariable)other).genericDeclaration.equals(genericDeclaration) ? true : false;
079: return other != null
080: && other instanceof TypeVariable
081: && ((TypeVariable) other).getName().equals(name)
082: && (genericDeclaration instanceof Class ? ((Class) genericDeclaration)
083: .equals((Class) ((TypeVariable) other)
084: .getGenericDeclaration())
085: : (genericDeclaration instanceof Method ? ((Method) genericDeclaration)
086: .equals((Method) ((TypeVariable) other)
087: .getGenericDeclaration())
088: : ((Constructor) genericDeclaration)
089: .equals((Constructor) ((TypeVariable) other)
090: .getGenericDeclaration())));
091: }
092:
093: public Type[] getBounds() {
094: // It's time for real bounds creation.
095: if (bounds == null) {
096: Object startPoint = null;
097: if (this .genericDeclaration instanceof Class) {
098: startPoint = (Object) this .genericDeclaration;
099: } else if (this .genericDeclaration instanceof Method) {
100: startPoint = (Object) ((Method) this .genericDeclaration)
101: .getDeclaringClass();
102: } else if (this .genericDeclaration instanceof Constructor) {
103: startPoint = (Object) ((Constructor) this .genericDeclaration)
104: .getDeclaringClass();
105: }
106:
107: int l = pTypeParameter.interfaceBounds.length + 1;
108: bounds = new Type[l];
109: if (pTypeParameter.classBound == null) {
110: bounds[0] = (Type) Object.class;
111: } else {
112: if (pTypeParameter.classBound instanceof InterimParameterizedType) {
113: java.lang.reflect.ParameterizedType pType = ParameterizedTypeRepository
114: .findParameterizedType(
115: (InterimParameterizedType) pTypeParameter.classBound,
116: ((InterimParameterizedType) pTypeParameter.classBound).signature,
117: startPoint);
118: if (pType == null) {
119: try {
120: AuxiliaryFinder
121: .findGenericClassDeclarationForParameterizedType(
122: (InterimParameterizedType) pTypeParameter.classBound,
123: startPoint);
124: } catch (Throwable e) {
125: throw new TypeNotPresentException(
126: ((InterimParameterizedType) pTypeParameter.classBound).rawType.classTypeName
127: .substring(1).replace('/',
128: '.'), e);
129: }
130: // check the correspondence of the formal parameter number and the actual argument number:
131: AuxiliaryChecker
132: .checkArgsNumber(
133: (InterimParameterizedType) pTypeParameter.classBound,
134: startPoint); // the MalformedParameterizedTypeException may raise here
135: try {
136: pType = new ParameterizedTypeImpl(
137: AuxiliaryCreator
138: .createTypeArgs(
139: (InterimParameterizedType) pTypeParameter.classBound,
140: startPoint),
141: AuxiliaryCreator
142: .createRawType(
143: (InterimParameterizedType) pTypeParameter.classBound,
144: startPoint),
145: AuxiliaryCreator
146: .createOwnerType(
147: (InterimParameterizedType) pTypeParameter.classBound,
148: startPoint));
149: } catch (ClassNotFoundException e) {
150: throw new TypeNotPresentException(e
151: .getMessage(), e);
152: }
153: ParameterizedTypeRepository
154: .registerParameterizedType(
155: pType,
156: (InterimParameterizedType) pTypeParameter.classBound,
157: ((InterimParameterizedType) pTypeParameter.classBound).signature,
158: startPoint);
159: }
160: bounds[0] = (Type) pType;
161: } else if (pTypeParameter.classBound instanceof InterimClassType) {
162: try {
163: bounds[0] = (Type) AuxiliaryLoader
164: .findClass(
165: ((InterimClassType) pTypeParameter.classBound).classTypeName
166: .substring(1).replace(
167: '/', '.'),
168: startPoint);
169: } catch (ClassNotFoundException e) {
170: throw new TypeNotPresentException(
171: ((InterimClassType) pTypeParameter.classBound).classTypeName
172: .substring(1).replace('/', '.'),
173: e);
174: } catch (ExceptionInInitializerError e) {
175: } catch (LinkageError e) {
176: }
177: }
178: }
179: for (int i = 1; i < l; i++) {
180: if (pTypeParameter.interfaceBounds[i - 1] instanceof InterimParameterizedType) {
181: java.lang.reflect.ParameterizedType pType = ParameterizedTypeRepository
182: .findParameterizedType(
183: (InterimParameterizedType) pTypeParameter.interfaceBounds[i - 1],
184: ((InterimParameterizedType) pTypeParameter.interfaceBounds[i - 1]).signature,
185: startPoint);
186: if (pType == null) {
187: try {
188: AuxiliaryFinder
189: .findGenericClassDeclarationForParameterizedType(
190: (InterimParameterizedType) pTypeParameter.interfaceBounds[i - 1],
191: startPoint);
192: } catch (Throwable e) {
193: throw new TypeNotPresentException(
194: ((InterimParameterizedType) pTypeParameter.interfaceBounds[i - 1]).rawType.classTypeName
195: .substring(1).replace('/',
196: '.'), e);
197: }
198: // check the correspondence of the formal parameter number and the actual argument number:
199: AuxiliaryChecker
200: .checkArgsNumber(
201: (InterimParameterizedType) pTypeParameter.interfaceBounds[i - 1],
202: startPoint); // the MalformedParameterizedTypeException may raise here
203: try {
204: pType = new ParameterizedTypeImpl(
205: AuxiliaryCreator
206: .createTypeArgs(
207: (InterimParameterizedType) pTypeParameter.interfaceBounds[i - 1],
208: startPoint),
209: AuxiliaryCreator
210: .createRawType(
211: (InterimParameterizedType) pTypeParameter.interfaceBounds[i - 1],
212: startPoint),
213: AuxiliaryCreator
214: .createOwnerType(
215: (InterimParameterizedType) pTypeParameter.interfaceBounds[i - 1],
216: startPoint));
217: } catch (ClassNotFoundException e) {
218: throw new TypeNotPresentException(e
219: .getMessage(), e);
220: }
221: ParameterizedTypeRepository
222: .registerParameterizedType(
223: pType,
224: (InterimParameterizedType) pTypeParameter.interfaceBounds[i - 1],
225: ((InterimParameterizedType) pTypeParameter.interfaceBounds[i - 1]).signature,
226: startPoint);
227: }
228: bounds[i] = (Type) pType;
229: } else if (pTypeParameter.interfaceBounds[i - 1] instanceof InterimClassType) {
230: try {
231: bounds[i] = (Type) AuxiliaryLoader
232: .findClass(
233: ((InterimClassType) pTypeParameter.interfaceBounds[i - 1]).classTypeName
234: .substring(1).replace(
235: '/', '.'),
236: startPoint);
237: } catch (ClassNotFoundException e) {
238: throw new TypeNotPresentException(
239: ((InterimClassType) pTypeParameter.interfaceBounds[i - 1]).classTypeName
240: .substring(1).replace('/', '.'),
241: e);
242: } catch (ExceptionInInitializerError e) {
243: } catch (LinkageError e) {
244: }
245: }
246: }
247: }
248: return (Type[]) bounds.clone();
249: }
250:
251: public D getGenericDeclaration() {
252: return genericDeclaration;
253: }
254:
255: public String getName() {
256: return name;
257: }
258:
259: public int hashCode() {
260: //return super.hashCode();
261: return getName().hashCode()
262: ^ (genericDeclaration instanceof Class ? ((Class) genericDeclaration)
263: .getName().hashCode()
264: : (genericDeclaration instanceof Method ? ((Method) genericDeclaration)
265: .hashCode()
266: : ((Constructor) genericDeclaration)
267: .hashCode()));
268: }
269:
270: public String toString() {
271: return name;
272: }
273: }
|