1 package org.ximtec.igesture.tool.util;
2
3 import java.lang.reflect.GenericArrayType;
4 import java.lang.reflect.Method;
5 import java.lang.reflect.Modifier;
6 import java.lang.reflect.ParameterizedType;
7 import java.lang.reflect.Type;
8 import java.lang.reflect.TypeVariable;
9 import java.util.Collections;
10 import java.util.LinkedList;
11 import java.util.List;
12
13 import org.ximtec.igesture.tool.view.testbench.TestbenchView;
14
15
16 public class InterfaceGenerator {
17
18 private static final String ARRAY = "[]";
19 private static final String COMMA = ",";
20 private static final String QMARK = "?";
21 private static final String AND = "&";
22 private static final String A_OPEN = "<";
23 private static final String A_CLOSE = ">";
24 private static final String B_OPEN = "(";
25 private static final String B_CLOSE = ")";
26 private static final String CB_CLOSE = "}";
27 private static final String CB_OPEN = "{";
28 private static final String AB_CLOSE = "]";
29 private static final String AB_OPEN = "[";
30 private static final String INTERFACE_PREFIX = "I";
31 private static final String PACKAGE = "package";
32 private static final String PUBLIC = "public";
33 private static final String INTERFACE = "interface";
34 private static final String EXTENDS = "extends";
35 private static final String THROWS = "throws";
36 private static final String BLANK = " ";
37 private static final String SEMICOLON = ";";
38 private static final String NL = "\n";
39
40 private static final List<String> declaredGenericTypes = new LinkedList<String>();
41 private static int declaredGenericTypesInsertPosition;
42
43 public static void main(String[] args) {
44 System.out.println(generateInterface(TestbenchView.class));
45 }
46
47 public static StringBuilder generateInterface(Class<?> type) {
48 StringBuilder sb = new StringBuilder();
49
50 sb.append("// automatically generated code");
51 sb.append(NL);
52 sb.append(PACKAGE + BLANK + type.getPackage().getName() + SEMICOLON);
53 sb.append(NL);
54 sb.append(NL);
55 sb.append(PUBLIC + BLANK + INTERFACE + BLANK + INTERFACE_PREFIX
56 + type.getSimpleName() + BLANK);
57 declaredGenericTypesInsertPosition = sb.length();
58 sb.append(CB_OPEN);
59 sb.append(NL);
60 sb.append(NL);
61 for (Method method : type.getMethods()) {
62
63 if (method.isSynthetic() || method.isBridge()
64 || (Modifier.isStatic(method.getModifiers())) || (Modifier.isFinal(method.getModifiers()))) {
65 continue;
66 }
67
68 generateMethodDefinition(sb, method);
69
70 sb.append(NL);
71 sb.append(NL);
72 }
73 sb.append(CB_CLOSE);
74
75 if (!declaredGenericTypes.isEmpty()) {
76 Collections.reverse(declaredGenericTypes);
77 sb.insert(declaredGenericTypesInsertPosition, A_CLOSE + BLANK);
78 boolean last = true;
79 for (String typeName : declaredGenericTypes) {
80 if (last) {
81 last = false;
82 } else {
83 sb
84 .insert(declaredGenericTypesInsertPosition, COMMA
85 + BLANK);
86 }
87 sb.insert(declaredGenericTypesInsertPosition, typeName);
88 }
89 sb.insert(declaredGenericTypesInsertPosition, A_OPEN);
90 }
91 return sb;
92 }
93
94 private static void generateMethodDefinition(StringBuilder sb, Method method) {
95 sb.append(BLANK + BLANK + PUBLIC + BLANK);
96
97 TypeVariable<Method>[] typeParameters = method.getTypeParameters();
98 if (typeParameters.length > 0) {
99 sb.append(A_OPEN);
100 boolean firstParam = true;
101 for (TypeVariable<Method> typeVar : typeParameters) {
102 if (firstParam) {
103 firstParam = false;
104 } else {
105 sb.append(COMMA).append(BLANK);
106 }
107 sb.append(typeVar.getName());
108 if (typeVar.getBounds() != null) {
109 boolean first = true;
110 for (Type bound : typeVar.getBounds()) {
111 if (bound != Object.class
112 || typeVar.getBounds().length > 1) {
113 if (first) {
114 first = false;
115 sb.append(BLANK).append(EXTENDS);
116 } else {
117 sb.append(BLANK).append(AND);
118 }
119 sb.append(BLANK);
120 writeType(sb, bound);
121 }
122 }
123 }
124 }
125 sb.append(A_CLOSE).append(BLANK);
126 }
127
128 writeType(sb, method.getGenericReturnType());
129
130 sb.append(BLANK + method.getName() + B_OPEN);
131
132 int i = 1;
133 for (Type parameterType : method.getGenericParameterTypes()) {
134 if (i > 1) {
135 sb.append(COMMA).append(BLANK);
136 }
137 writeType(sb, parameterType);
138 sb.append(BLANK).append("arg").append(i);
139 i++;
140 }
141 sb.append(B_CLOSE);
142
143 boolean first = true;
144 for (Type exceptionType : method.getGenericExceptionTypes()) {
145 if (first) {
146 sb.append(BLANK).append(THROWS).append(BLANK);
147 first = false;
148 } else {
149 sb.append(COMMA).append(BLANK);
150 }
151 writeType(sb, exceptionType);
152 }
153
154 sb.append(SEMICOLON);
155 }
156
157 private static void writeType(StringBuilder sb, Type type) {
158
159 if (type instanceof Class<?>) {
160 Class<?> typeClass = (Class<?>) type;
161
162 if (typeClass.isArray()) {
163 Class<?> componentType = typeClass.getComponentType();
164 sb.append(componentType.getName().replace('$','.')).append(ARRAY);
165 } else {
166 sb.append(typeClass.getName().replace('$','.'));
167 }
168 } else if (type instanceof TypeVariable<?>) {
169 TypeVariable<?> typeVar = (TypeVariable<?>) type;
170
171 Object genericDeclaration = typeVar.getGenericDeclaration();
172 if (genericDeclaration instanceof Method) {
173 } else {
174 if (!declaredGenericTypes.contains(typeVar.getName())) {
175 declaredGenericTypes.add(typeVar.getName());
176 }
177 }
178 sb.append(typeVar.getName());
179 } else if (type instanceof GenericArrayType) {
180 GenericArrayType arrayType = (GenericArrayType) type;
181
182 Type genericComponentType = arrayType.getGenericComponentType();
183 writeType(sb, genericComponentType);
184 sb.append(ARRAY);
185 } else if (type instanceof ParameterizedType) {
186 ParameterizedType paramType = (ParameterizedType) type;
187
188 sb.append(paramType);
189 }
190 }
191 }