blob: 32ae94fed7e2ebefa0f6fcff023608101a863ccc [file] [log] [blame]
Stuart McCullochbb014372012-06-07 21:57:32 +00001package aQute.bnd.compatibility;
2
3import java.lang.reflect.*;
4
5public class RuntimeSignatureBuilder {
6 final Scope root;
7
8 public RuntimeSignatureBuilder(Scope root) {
9 this.root = root;
10 }
11
12 static public String identity(Class<?> c) {
13 return Scope.classIdentity(c.getName());
14 }
15
16 static public String identity(Method m) {
17 return Scope.methodIdentity(m.getName(), getDescriptor(m.getReturnType(), m
18 .getParameterTypes()));
19 }
20
21 static public String identity(Constructor<?> m) {
22 return Scope.constructorIdentity(getDescriptor(void.class, m.getParameterTypes()));
23 }
24
25 static public String identity(Field m) {
26 return Scope.fieldIdentity(m.getName(), getDescriptor(m.getType(), null));
27 }
28
29 static public String getDescriptor(Class<?> base, Class<?>[] parameters) {
30 StringBuilder sb = new StringBuilder();
31 if (parameters != null) {
32 sb.append("(");
33 for (Class<?> parameter : parameters) {
34 sb.append(getDescriptor(parameter));
35 }
36 sb.append(")");
37 }
38 sb.append(getDescriptor(base));
39 return sb.toString();
40 }
41
42 public Scope add(Class<?> c) {
43 Scope local = add(root, getEnclosingScope(c), c.getModifiers(), c.getTypeParameters(),
44 Kind.CLASS, identity(c), c.getGenericSuperclass(), c.getGenericInterfaces(), null);
45
46 for (Field f : c.getDeclaredFields()) {
47 add(local, // declaring scope
48 local, // enclosing
49 f.getModifiers(), // access modifiers
50 null, // fields have no type vars
51 Kind.FIELD, // field
52 identity(f), // the name of the field
53 f.getGenericType(), // the type of the field
54 null, // fields have no parameters
55 null // fields have no exceptions
56 );
57 }
58
59 for (Constructor<?> constr : c.getConstructors()) {
60 add(local, // class scope
61 local, // enclosing
62 constr.getModifiers(), // access modifiers
63 constr.getTypeParameters(), // Type vars
64 Kind.CONSTRUCTOR, // constructor
65 identity(constr), // <init>(type*)
66 void.class, // Always void
67 constr.getGenericParameterTypes(), // parameters types
68 constr.getGenericExceptionTypes() // exception types
69 );
70 }
71
72 for (Method m : c.getDeclaredMethods()) {
73 if (m.getDeclaringClass() != Object.class) {
74 add(local, // class scope
75 local, // enclosing
76 m.getModifiers(), // access modifiers
77 m.getTypeParameters(), Kind.METHOD, // method
78 identity(m), // <name>(type*)return
79 m.getGenericReturnType(), // return type
80 m.getGenericParameterTypes(), // parameter types
81 m.getGenericExceptionTypes() // exception types
82 );
83 }
84 }
85
86 return local;
87 }
88
89 private Scope getEnclosingScope(Class<?> c) {
90 Method m = c.getEnclosingMethod();
91 if (m != null) {
92 Scope s = getGlobalScope(m.getDeclaringClass());
93 return s.getScope(identity(m));
94 }
95// TODO
96// Constructor cnstr = c.getEnclosingConstructor();
97// if (m != null) {
98// Scope s = getGlobalScope(cnstr.getDeclaringClass());
99// return s.getScope(identity(cnstr));
100//
101// }
102 Class<?> enclosingClass = c.getEnclosingClass();
103 if (enclosingClass != null) {
104 return getGlobalScope(enclosingClass);
105 }
106
107 return null;
108 }
109
110 private Scope getGlobalScope(Class<?> c) {
111 if (c == null)
112 return null;
113 String id = identity(c);
114 return root.getScope(id);
115 }
116
117 private Scope add(Scope declaring, Scope enclosing, int modifiers,
118 TypeVariable<?>[] typeVariables, Kind kind, String id, Type mainType,
119 Type[] parameterTypes, Type exceptionTypes[]) {
120
121 Scope scope = declaring.getScope(id);
122 assert scope.access == Access.UNKNOWN;
123 scope.setAccess(Access.modifier(modifiers));
124 scope.setKind(kind);
125 scope.setGenericParameter(convert(typeVariables));
126 scope.setBase(convert(scope,mainType));
127 scope.setParameterTypes(convert(parameterTypes));
128 scope.setExceptionTypes(convert(exceptionTypes));
129 scope.setDeclaring(declaring);
130 scope.setEnclosing(enclosing);
131 return scope;
132 }
133
134 private GenericType convert(Scope source, Type t) {
135 if (t instanceof ParameterizedType) {
136 // C<P..>
137 ParameterizedType pt = (ParameterizedType) t;
138 /*Scope reference =*/ root.getScope(identity((Class<?>)pt.getRawType()));
139 Type args[] = pt.getActualTypeArguments();
140 GenericType[] arguments = new GenericType[args.length];
141 int n = 0;
142 for (Type arg : args)
143 arguments[n++] = convert(source,arg);
144// return new GenericType(reference,null,arguments);
145
146 } else if (t instanceof TypeVariable) {
147// TypeVariable tv = (TypeVariable) t;
148// return new GenericType(source,tv.getName(), null);
149 } else if (t instanceof WildcardType) {
150// WildcardType wc = (WildcardType) t;
151// wc.
152 } else if (t instanceof GenericArrayType) {
153
154 }
155 if (t instanceof Class<?>) {
156// raw = ((Class<?>) t).getName() + ";";
157 } else
158 throw new IllegalArgumentException(t.toString());
159
160 return null;
161 }
162
163 private GenericParameter[] convert(TypeVariable<?> vars[]) {
164 if (vars == null)
165 return null;
166
167 GenericParameter out[] = new GenericParameter[vars.length];
168 for (int i = 0; i < vars.length; i++) {
169 GenericType gss[] = convert(vars[i].getBounds());
170 out[i] = new GenericParameter(vars[i].getName(), gss);
171 }
172 return out;
173 }
174
175 private GenericType[] convert(Type[] parameterTypes) {
176 if (parameterTypes == null || parameterTypes.length == 0)
177 return GenericType.EMPTY;
178
179 GenericType tss[] = new GenericType[parameterTypes.length];
180 for (int i = 0; i < parameterTypes.length; i++) {
181 //tss[i] = new GenericType(parameterTypes[i]);
182 }
183 return tss;
184 }
185
186 private static String getDescriptor(Class<?> c) {
187 StringBuilder sb = new StringBuilder();
188 if (c.isPrimitive()) {
189 if (c == boolean.class)
190 sb.append("Z");
191 else if (c == byte.class)
192 sb.append("Z");
193 else if (c == char.class)
194 sb.append("C");
195 else if (c == short.class)
196 sb.append("S");
197 else if (c == int.class)
198 sb.append("I");
199 else if (c == long.class)
200 sb.append("J");
201 else if (c == float.class)
202 sb.append("F");
203 else if (c == double.class)
204 sb.append("D");
205 else if (c == void.class)
206 sb.append("V");
207 else
208 throw new IllegalArgumentException("unknown primitive type: " + c);
209 } else if (c.isArray()) {
210 sb.append("[");
211 sb.append(getDescriptor(c));
212 } else {
213 sb.append("L");
214 sb.append(c.getName().replace('.', '/'));
215 sb.append(";");
216 }
217 return sb.toString();
218 }
219
220}