1
2
3 package org.virtualmock.call;
4
5 /***
6 * The signature for a method call, representing the class, method name, and
7 * classes of the arguments. It is NOT a unique identifier for a call, since
8 * multiple calls can be recorded for the same signature.
9 *
10 * @author Chad Woolley
11 * @version $Revision: 1.14 $
12 */
13 public class Signature {
14 private static final int LENGTH_OF_WORD_CLASS_PLUS_ONE_SPACE = 6;
15 private Class classType = null;
16 private Class returnType = null;
17 private String methodName = null;
18 private Class[] argTypes = null;
19
20 /***
21 * Creates a new Signature object with a return value and arguments.
22 *
23 * @param returnType The type of the return value for this signature
24 * @param classType The type of the class which owns this signature
25 * @param methodName The name of the method for this signature
26 * @param argTypes Class array representing the argument types, or null if
27 * there are no arguments.
28 */
29 public Signature(Class returnType, Class classType, String methodName,
30 Class[] argTypes) {
31 create(returnType, classType, methodName, argTypes);
32 }
33
34 /***
35 * Creates a new Signature object with a return value but no arguments.
36 *
37 * @param returnType The type of the return value for this signature
38 * @param classType The type of the class which owns this signature
39 * @param methodName The name of the method for this signature
40 */
41 public Signature(Class returnType, Class classType, String methodName) {
42 create(returnType, classType, methodName, null);
43 }
44
45 /***
46 * Creates a new Signature object with no return value but with arguments.
47 *
48 * @param classType The type of the class which owns this signature
49 * @param methodName The name of the method for this signature
50 * @param argTypes Class array representing the argument types, or null if
51 * there are no arguments.
52 */
53 public Signature(Class classType, String methodName, Class[] argTypes) {
54 create(null, classType, methodName, argTypes);
55 }
56
57 /***
58 * Creates a new Signature object with no return value or arguments.
59 *
60 * @param classType The type of the class which owns this signature
61 * @param methodName The name of the method for this signature
62 */
63 public Signature(Class classType, String methodName) {
64 create(null, classType, methodName, null);
65 }
66
67 /***
68 * Accessor.
69 *
70 * @return An array of Class objects representing the argument types for
71 * this signature, or an empty array if there are no arguments for
72 * this signature.
73 */
74 public Class[] getArgTypes() {
75 return argTypes;
76 }
77
78 /***
79 * <p>
80 * This method is similar to Java's Class.isAssignableFrom() method, but it
81 * checks the class type, method name and each individual argument type
82 * for this Signature.
83 * </p>
84 *
85 * <p>
86 * To paraphrase the javadoc for Class.isAssignableFrom(): "Determines if
87 * all argument types contained in this Signature object are either the
88 * same as, or are superclasses or superinterfaces of, the argument types
89 * of the Signature represented by the specified call parameter. It
90 * returns true if so; otherwise it returns false. If the argument types
91 * of this Signature object represent primitive types, the method returns
92 * true if the specified argument types of the Signature parameter are
93 * exactly this Calls argument objects; otherwise it returns false."
94 * </p>
95 *
96 * @param signature the Signature which will be checked against this
97 * Signature
98 *
99 * @return true if the passed Signature's method name and argument types
100 * are assignable to this Signature
101 */
102 public boolean isAssignableFrom(Signature signature) {
103
104 if (!classType.equals(signature.getClassType())) {
105 return false;
106 }
107
108
109 if (!methodName.equals(signature.getMethodName())) {
110 return false;
111 }
112
113
114 if (argTypes.length != signature.getArgTypes().length) {
115 return false;
116 }
117
118
119 for (int i = 0; i < argTypes.length; i++) {
120
121
122 if (!argTypes[i].isAssignableFrom(signature.getArgTypes()[i])) {
123 return false;
124 }
125 }
126
127 return true;
128 }
129
130 /***
131 * Returns the name of the class type of this Signature.
132 *
133 * @return the name of the class type of this Signature
134 */
135 public String getClassName() {
136 return classType.getName();
137 }
138
139 /***
140 * Accessor.
141 *
142 * @return the class type of this signature
143 */
144 public Class getClassType() {
145 return classType;
146 }
147
148 /***
149 * Accessor.
150 *
151 * @return the method name of this signature
152 */
153 public String getMethodName() {
154 return methodName;
155 }
156
157 /***
158 * Accessor.
159 *
160 * @return the return type of this signature
161 */
162 public Class getReturnType() {
163 return returnType;
164 }
165
166 /***
167 * Returns true is return type is primitive.
168 *
169 * @return true is return type is primitive
170 */
171 public boolean isReturnTypePrimitive() {
172 if (returnType == null) {
173 return false;
174 }
175
176 return returnType.isPrimitive();
177 }
178
179 /***
180 * Compares this Signature to another object. Note that this ignores the
181 * type of the return value, like Java does.
182 *
183 * @param object The object with which we are comparing
184 *
185 * @return true if the passed object is a Signature that matches this one
186 */
187 public boolean equals(Object object) {
188 if (!(object instanceof Signature)) {
189 return false;
190 }
191
192 Signature compareSignature = (Signature) object;
193
194
195 if (!classType.equals(compareSignature.getClassType())) {
196 return false;
197 }
198
199
200 if (!methodName.equals(compareSignature.getMethodName())) {
201 return false;
202 }
203
204
205 if (argTypes.length != compareSignature.getArgTypes().length) {
206 return false;
207 }
208
209
210 for (int i = 0; i < argTypes.length; i++) {
211 if (!argTypes[i].equals(compareSignature.getArgTypes()[i])) {
212 return false;
213 }
214 }
215
216 return true;
217 }
218
219 /***
220 * Return hashCode for this Signature.
221 *
222 * @return the hashCode for this Signature
223 */
224 public int hashCode() {
225 return this.toStringWithoutReturnType().hashCode();
226 }
227
228 /***
229 * Represents this signature as a String.
230 *
231 * @return This Signature, represented as a String
232 *
233 * @todo investigate all possible values for return type string other than
234 * not null, null, or void
235 */
236 public String toString() {
237 StringBuffer stringBuffer = new StringBuffer();
238 String returnTypeClass = null;
239 String returnTypeString = null;
240
241 if (getReturnType() != null) {
242 returnTypeString = getReturnType().toString();
243 }
244
245 if ((returnTypeString == null) || "void".equals(returnTypeString)) {
246 returnTypeClass = "void";
247 } else if (!returnTypeString.startsWith("class")) {
248
249 returnTypeClass = returnTypeString;
250 } else {
251
252 returnTypeClass =
253 returnTypeString.substring(LENGTH_OF_WORD_CLASS_PLUS_ONE_SPACE);
254 }
255
256 stringBuffer.append(returnTypeClass);
257 stringBuffer.append(" ");
258 stringBuffer.append(toStringWithoutReturnType());
259
260 return stringBuffer.toString();
261 }
262
263 /***
264 * Internal method which contains the logic to create a signature.
265 *
266 * @param newReturnType the returnType which will be used to create this
267 * Signature
268 * @param newClassType the classType which will be used to create this
269 * Signature
270 * @param newMethodName the methodName which will be used to create this
271 * Signature
272 * @param newArgTypes the argTypes which will be used to create this
273 * Signature
274 */
275 protected void create(Class newReturnType, Class newClassType,
276 String newMethodName, Class[] newArgTypes) {
277 returnType = newReturnType;
278 classType = newClassType;
279 methodName = newMethodName;
280
281 if (newArgTypes == null) {
282 argTypes = new Class[0];
283 } else {
284 argTypes = newArgTypes;
285 }
286 }
287
288 /***
289 * Returns the representation of the Signature as a string, with the return
290 * type omitted.
291 *
292 * @return the representation of the Signature as a string, with the return
293 * type omitted.
294 */
295 protected String toStringWithoutReturnType() {
296 StringBuffer stringBuffer = new StringBuffer();
297 stringBuffer.append(getClassName());
298 stringBuffer.append(".");
299 stringBuffer.append(methodName);
300 stringBuffer.append("(");
301
302 for (int i = 0; i < argTypes.length; i++) {
303 stringBuffer.append(argTypes[i].getName());
304
305 if (i < (argTypes.length - 1)) {
306 stringBuffer.append(", ");
307 }
308 }
309
310 stringBuffer.append(")");
311
312 return stringBuffer.toString();
313 }
314 }