3
\$\begingroup\$

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?

\$\endgroup\$
1
  • \$\begingroup\$ I feel like a dedicated case class may be better than a Map[String, String] \$\endgroup\$
    – user
    Commented Jun 28, 2021 at 18:24

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.