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)
}