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.