View Javadoc

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 }