I'm somewhat new to Scala and am not sure if I'm doing things in a very Scala-esque way.
In particular, I'm not sure if I'm using Option correctly, since by calling .isDefined, I'm basically just doing ye olde Java null check. Also, the getMethodAndAnnotationFromInfaces method could probably be done better.
Please point out ways in which I could better leverage language features in the below code:
for (val method <- clazz.getMethods) {
val methodAndAnnotation = method.getAnnotation(annotationType) match {
case annotation: MessageHandler => Some((method, annotation))
case _ => getMethodAndAnnotationFromInterfaces(clazz.getInterfaces, method, annotationType)
}
if (methodAndAnnotation.isDefined){
// do something
}
}
getMethodAndAnnotationFromInterfaces function:
def getMethodAndAnnotationFromInterfaces(interfaces: Array[java.lang.Class[_]], method: Method, annotationType: Class[_ <: java.lang.annotation.Annotation])
: Option[(Method, java.lang.annotation.Annotation)] = {
@tailrec
def getMethodAndAnnotationFromInterfacesInner(interfaces: Array[java.lang.Class[_]], acc: Option[(Method, java.lang.annotation.Annotation)])
: Option[(Method, java.lang.annotation.Annotation)] = {
interfaces.length match {
case 0 => acc
case _ =>
try {
interfaces.head.getMethod(method.getName, method.getParameterTypes: _*) match {
case newMethod: Method =>
val newAnnotation = newMethod.getAnnotation(annotationType)
if (newAnnotation != null && acc.isDefined) {
throw new RuntimeException("The annotation is applied to the method in more than one interface of the class.")
}
getMethodAndAnnotationFromInterfacesInner(interfaces.tail, Some((newMethod, newAnnotation)))
case _ => getMethodAndAnnotationFromInterfacesInner(interfaces.tail, acc)
}
} catch {
case e: NoSuchMethodException => getMethodAndAnnotationFromInterfacesInner(interfaces.tail, acc)
}
}
}
getMethodAndAnnotationFromInterfacesInner(interfaces, None)
}