List<Schema.Field> fields = new ArrayList<Schema.Field>();
String[] paramNames = paranamer.lookupParameterNames(method);
Type[] paramTypes = method.getGenericParameterTypes();
Annotation[][] annotations = method.getParameterAnnotations();
for (int i = 0; i < paramTypes.length; i++) {
Schema paramSchema = getSchema(paramTypes[i], names);
for (int j = 0; j < annotations[i].length; j++) {
Annotation annotation = annotations[i][j];
if (annotation instanceof AvroSchema) // explicit schema
paramSchema = Schema.parse(((AvroSchema)annotation).value());
else if (annotation instanceof Union) // union
paramSchema = getAnnotatedUnion(((Union)annotation), names);
else if (annotation instanceof Nullable) // nullable
paramSchema = makeNullable(paramSchema);
}
String paramName = paramNames.length == paramTypes.length
? paramNames[i]
: paramSchema.getName()+i;
fields.add(new Schema.Field(paramName, paramSchema,
null /* doc */, null));
}
Schema request = Schema.createRecord(fields);
Union union = method.getAnnotation(Union.class);
Schema response = union == null
? getSchema(method.getGenericReturnType(), names)
: getAnnotatedUnion(union, names);
if (method.isAnnotationPresent(Nullable.class)) // nullable
response = makeNullable(response);
AvroSchema explicit = method.getAnnotation(AvroSchema.class);
if (explicit != null) // explicit schema
response = Schema.parse(explicit.value());
List<Schema> errs = new ArrayList<Schema>();
errs.add(Protocol.SYSTEM_ERROR); // every method can throw
for (Type err : method.getGenericExceptionTypes())
if (err != AvroRemoteException.class)
errs.add(getSchema(err, names));
Schema errors = Schema.createUnion(errs);
return protocol.createMessage(method.getName(), null /* doc */, request, response, errors);
}