I have code written in Scala that reads annotations decorating other Scala classes. These annotations are written in Java. The sticking point is that annotations don't allow advanced data structures, and one of these annotations is a wrapper that contains an array of other annotations. This is where Scala starts throwing a fit. The following is my solution:
import java.util
import scala.collection.JavaConversions._
import scala.collection.mutable
import scala.io.Source
val line = "package.structure.leading.to.annotated.Class"
val anns = AnnotationUtils.getAllAnnotationsInheritted(Class.forName(line).newInstance.getClass)
var attributesMap = mutable.Map[String, Map[String, String]]()
for (ann <- anns) {
if (ann.annotationType == classOf[Attributes]) {
for (attr <- List(ann.asInstanceOf[Attributes].value)) {
val i = new util.ArrayList[Attribute](asJavaCollection(attr))
for (a <- i) {
attributesMap += a.attributeName -> Map(
"type" -> a.attributeType,
"description" -> a.attributeDescription,
"optional" -> a.attributeDescription(),
"pattern" -> a.valueMatchPattern,
"default" -> a.defaultValue,
"options" -> asJavaCollection(a.attributeOptions).mkString(", "),
"excludes" -> asJavaCollection(a.excludesAttributes).mkString(", "),
"requires" -> asJavaCollection(a.requiresAttributes).mkString(", "),
"someOf" -> asJavaCollection(a.someOfTheseAttributes).mkString(", "))
println(asJavaCollection(a.attributeOptions).mkString(", "))
}
}
}
}
Most of the actual processing has been removed to highlight the part I'm finding really ugly.
The Attributes
class is the wrapper annotation, and is declared like this:
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Attributes {
Attribute[] value();
}
Attribute
is the class with the actual information and is defined like this:
@Repeatable(Attributes.class)
@Retention(RetentionPolicy.RUNTIME)
public @interface Attribute {
String attributeName();
String attributeType();
String attributeDescription();
String valueMatchPattern() default ".*";
String optional() default "false";
String defaultValue() default "N/A";
String [] attributeOptions() default {};
String [] excludesAttributes() default {};
String [] requiresAttributes() default {};
String [] someOfTheseAttributes() default {};
}
I find the constant switching back and forth between Scala and Java datatypes to be terrible code and difficult to read. Is there a better way to do this?
Map[String, String]
\$\endgroup\$