Here is an implementation of multiline string literals in Java, using Javadoc comments, an annotation and an annotation processor.
This method works by annotating a String field with a @Multiline annotation, placing the fields initialisation value in a Javadoc comment, then using an annotation processor to set the fields value to the contents of the Javadoc comment at compile time.
First off, the @Multiline annotation.
Multiline.java
package org.adrianwalker.multilinestring;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.SOURCE)
public @interface Multiline {
}
Next, the annotation processor to insert the value of the Javadoc comment into the String field.
MultilineProcessor.java
package org.adrianwalker.multilinestring;
import com.sun.tools.javac.model.JavacElements;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.TreeMaker;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
@SupportedAnnotationTypes({"org.adrianwalker.multilinestring.Multiline"})
public final class MultilineProcessor extends AbstractProcessor {
private JavacElements elementUtils;
private TreeMaker maker;
@Override
public void init(final ProcessingEnvironment procEnv) {
super.init(procEnv);
JavacProcessingEnvironment javacProcessingEnv = (JavacProcessingEnvironment) procEnv;
this.elementUtils = javacProcessingEnv.getElementUtils();
this.maker = TreeMaker.instance(javacProcessingEnv.getContext());
}
@Override
public boolean process(final Set<? extends TypeElement> annotations, final RoundEnvironment roundEnv) {
Set<? extends Element> fields = roundEnv.getElementsAnnotatedWith(Multiline.class);
for (Element field : fields) {
String docComment = elementUtils.getDocComment(field);
if (null != docComment) {
JCTree.JCVariableDecl fieldNode = (JCTree.JCVariableDecl) elementUtils.getTree(field);
fieldNode.init = maker.Literal(docComment);
}
}
return true;
}
}
And finally, a class which demonstrates the usage of the annotation.
MultilineStringUsage.java
package org.adrianwalker.multilinestring;
public final class MultilineStringUsage {
/**
<html>
<head/>
<body>
<p>
Hello<br/>
Multiline<br/>
World<br/>
</p>
</body>
</html>
*/
@Multiline
private static String html;
public static void main(final String[] args) {
System.out.println(html);
}
}
Maven
Remember to include an <annotationProcessor> element when compiling classes which use @Multiline in the compiler plugin configuration when using Maven.
pom.xml
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<annotationProcessors>
<annotationProcessor>
org.adrianwalker.multilinestring.MultilineProcessor
</annotationProcessor>
</annotationProcessors>
</configuration>
</plugin>
...
Eclipse
To use in a non Maven Java project with Eclipse, try this: https://github.com/benelog/multiline/wiki/Non-Maven-Java-project-with-Eclipse
Source Code
- Github - multiline-string
Usage
Build and install the Multiline String project which contains the @Multiline annotation and annotation processor, using 'mvn clean install'.
Build and install the Multiline String Usage project which contains an example of how to use the @Multiline annotation, using 'mvn clean install'.
Run the MultilineStringUsage class to output the multiline string.