From fba4dd2d9a9a347a83b557432fdc4da32ab3ccaa Mon Sep 17 00:00:00 2001 From: snowleo Date: Sun, 28 Aug 2011 05:12:13 +0200 Subject: Testing yaml annotations --- YamlAnnotations/src/me/snowleo/yaml/YamlClass.java | 11 + .../src/me/snowleo/yaml/YamlComment.java | 12 ++ .../src/me/snowleo/yaml/YamlPropertyProcessor.java | 238 +++++++++++++++++++++ 3 files changed, 261 insertions(+) create mode 100644 YamlAnnotations/src/me/snowleo/yaml/YamlClass.java create mode 100644 YamlAnnotations/src/me/snowleo/yaml/YamlComment.java create mode 100644 YamlAnnotations/src/me/snowleo/yaml/YamlPropertyProcessor.java (limited to 'YamlAnnotations/src/me/snowleo') diff --git a/YamlAnnotations/src/me/snowleo/yaml/YamlClass.java b/YamlAnnotations/src/me/snowleo/yaml/YamlClass.java new file mode 100644 index 000000000..e98a0fc38 --- /dev/null +++ b/YamlAnnotations/src/me/snowleo/yaml/YamlClass.java @@ -0,0 +1,11 @@ +package me.snowleo.yaml; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + + +@Target(ElementType.TYPE) +public @interface YamlClass +{ +} + diff --git a/YamlAnnotations/src/me/snowleo/yaml/YamlComment.java b/YamlAnnotations/src/me/snowleo/yaml/YamlComment.java new file mode 100644 index 000000000..5e8ba04e4 --- /dev/null +++ b/YamlAnnotations/src/me/snowleo/yaml/YamlComment.java @@ -0,0 +1,12 @@ +package me.snowleo.yaml; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + + +@Target(ElementType.FIELD) +public @interface YamlComment +{ + String[] comment() default ""; +} + diff --git a/YamlAnnotations/src/me/snowleo/yaml/YamlPropertyProcessor.java b/YamlAnnotations/src/me/snowleo/yaml/YamlPropertyProcessor.java new file mode 100644 index 000000000..c56b51b61 --- /dev/null +++ b/YamlAnnotations/src/me/snowleo/yaml/YamlPropertyProcessor.java @@ -0,0 +1,238 @@ +package me.snowleo.yaml; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.Writer; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.Filer; +import javax.annotation.processing.Messager; +import javax.annotation.processing.ProcessingEnvironment; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.annotation.processing.SupportedSourceVersion; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.ElementFilter; +import javax.lang.model.util.Elements; +import javax.tools.Diagnostic; +import javax.tools.JavaFileObject; + + +@SupportedAnnotationTypes("me.snowleo.yaml.YamlClass") +@SupportedSourceVersion(SourceVersion.RELEASE_6) +public class YamlPropertyProcessor extends AbstractProcessor +{ + private transient Filer filer; + private transient Messager messager; + private Elements eltUtils; + + public YamlPropertyProcessor() + { + super(); + } + + @Override + public void init(final ProcessingEnvironment processingEnv) + { + super.init(processingEnv); + filer = processingEnv.getFiler(); + messager = processingEnv.getMessager(); + eltUtils = processingEnv.getElementUtils(); + } + + @Override + public boolean process(final Set set, final RoundEnvironment roundEnv) + { + for (Element elem : roundEnv.getElementsAnnotatedWith(YamlClass.class)) + { + if (elem.getKind() != ElementKind.CLASS) + { + messager.printMessage(Diagnostic.Kind.ERROR, "YamlClass has to be a class", elem); + continue; + } + final TypeElement clazz = (TypeElement)elem; + String superClassName = clazz.getSuperclass().toString(); + if (!superClassName.startsWith(clazz.getEnclosingElement().toString())) + { + superClassName = clazz.getEnclosingElement().toString() + "." + superClassName; + } + if (!superClassName.equalsIgnoreCase(clazz.getQualifiedName().toString() + "Yaml")) + { + messager.printMessage(Diagnostic.Kind.ERROR, "YamlClass must be extended by " + clazz.getQualifiedName().toString() + "Yaml", elem); + continue; + } + final List fields = new ArrayList(); + for (VariableElement field : ElementFilter.fieldsIn(clazz.getEnclosedElements())) + { + if (!(field.getModifiers().contains(Modifier.STATIC)) + && field.getModifiers().contains(Modifier.PROTECTED)) + { + fields.add(field); + } + else if (field.getAnnotation(YamlComment.class) != null) + { + messager.printMessage(Diagnostic.Kind.ERROR, "YamlComment fields have to be nonstatic and protected.", field); + continue; + } + } + if (fields.isEmpty()) + { + messager.printMessage(Diagnostic.Kind.ERROR, "YamlClass needs at least one protected field.", clazz); + continue; + } + createImplclass(clazz, fields); + createSuperclass(clazz, fields); + } + return true; + } + + private void createSuperclass(final TypeElement clazz, final List fields) + { + try + { + final JavaFileObject file = filer.createSourceFile(clazz.getQualifiedName() + "Yaml"); + messager.printMessage(Diagnostic.Kind.NOTE, "Creating " + file.toUri()); + + final Writer writer = file.openWriter(); + //Add the content to the newly generated file. + + final PrintWriter pwriter = new PrintWriter(writer); + try + { + pwriter.print("package "); + pwriter.print(clazz.getEnclosingElement()); + pwriter.println(';'); + pwriter.println(); + pwriter.print("public class "); + pwriter.print(clazz.getSimpleName()); + pwriter.print("Yaml extends BaseYaml<"); + pwriter.print(clazz.getSimpleName()); + pwriter.println("> {"); + + pwriter.println(" @Override"); + pwriter.print(" protected Class<"); + pwriter.print(clazz.getSimpleName()); + pwriter.print("YamlImpl> getClazz() { return "); + pwriter.print(clazz.getSimpleName()); + pwriter.println("YamlImpl.class; };"); + + for (VariableElement var : fields) + { + final TypeMirror type = var.asType(); + final String name = capitalize(var.getSimpleName().toString()); + pwriter.print(" public "); + pwriter.print(type.toString()); + if (type.toString().equalsIgnoreCase("boolean")) + { + pwriter.print(" is"); + } + else + { + pwriter.print(" get"); + } + pwriter.print(name); + pwriter.println("() { throw new AssertionError(\"Cannot be called.\"); }"); + pwriter.print(" public void set"); + pwriter.print(name); + pwriter.print("(final "); + pwriter.print(type.toString()); + pwriter.print(' '); + pwriter.print(name); + pwriter.println(") { throw new AssertionError(\"Cannot be called.\"); }"); + } + pwriter.println("}"); + pwriter.flush(); + } + finally + { + pwriter.close(); + } + } + catch (IOException ex) + { + messager.printMessage(Diagnostic.Kind.ERROR, ex.toString()); + } + } + + private void createImplclass(final TypeElement clazz, final List fields) + { + try + { + final JavaFileObject file = filer.createSourceFile(clazz.getQualifiedName() + "YamlImpl"); + messager.printMessage(Diagnostic.Kind.NOTE, "Creating " + file.toUri()); + + final Writer writer = file.openWriter(); + //Add the content to the newly generated file. + + final PrintWriter pwriter = new PrintWriter(writer); + try + { + pwriter.print("package "); + pwriter.print(clazz.getEnclosingElement()); + pwriter.println(';'); + pwriter.println(); + pwriter.print("public class "); + pwriter.print(clazz.getSimpleName()); + pwriter.print("YamlImpl extends "); + pwriter.print(clazz.getSimpleName()); + pwriter.println(" {"); + + for (VariableElement var : fields) + { + final TypeMirror type = var.asType(); + final String name = capitalize(var.getSimpleName().toString()); + pwriter.print(" public "); + pwriter.print(type.toString()); + if (type.toString().equalsIgnoreCase("boolean")) + { + pwriter.print(" is"); + } + else + { + pwriter.print(" get"); + } + pwriter.print(name); + pwriter.print("() { return this."); + pwriter.print(var.getSimpleName().toString()); + pwriter.println("; }"); + pwriter.print(" public void set"); + pwriter.print(name); + pwriter.print("(final "); + pwriter.print(type.toString()); + pwriter.print(' '); + pwriter.print(name); + pwriter.print(") { this."); + pwriter.print(var.getSimpleName().toString()); + pwriter.print(" = "); + pwriter.print(name); + pwriter.println("; }"); + } + pwriter.println("}"); + pwriter.flush(); + } + finally + { + pwriter.close(); + } + } + catch (IOException ex) + { + messager.printMessage(Diagnostic.Kind.ERROR, ex.toString()); + } + } + + private static String capitalize(String name) + { + char[] c = name.toCharArray(); + c[0] = Character.toUpperCase(c[0]); + return new String(c); + } +} -- cgit v1.2.3