diff --git a/pom.xml b/pom.xml index a391f9a..39cade8 100644 --- a/pom.xml +++ b/pom.xml @@ -7,10 +7,57 @@ org.sadtech.example create-annotation 0.0.1-SNAPSHOT + jar 11 11 + + + com.google.auto.service + auto-service + 1.0 + provided + + + com.google.guava + guava + 30.1.1-jre + + + + + + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + ${java.home}/bin/javadoc + + + + attach-javadocs + + jar + + + + + + + \ No newline at end of file diff --git a/src/main/java/org/sadtech/example/annotation/ClassCreator.java b/src/main/java/org/sadtech/example/annotation/ClassCreator.java new file mode 100644 index 0000000..ba01377 --- /dev/null +++ b/src/main/java/org/sadtech/example/annotation/ClassCreator.java @@ -0,0 +1,52 @@ +package org.sadtech.example.annotation; + +import org.sadtech.example.annotation.domain.ClassDto; +import org.sadtech.example.annotation.domain.FieldDto; + +import javax.annotation.processing.ProcessingEnvironment; +import javax.tools.JavaFileObject; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Set; + +/** + * // TODO: 20.06.2021 Добавить описание. + * + * @author upagge 20.06.2021 + */ +public class ClassCreator { + + private ClassCreator() { + + } + + public static void record(ClassDto classDto, ProcessingEnvironment environment) { + JavaFileObject builderFile = null; + try { + builderFile = environment.getFiler().createSourceFile(classDto.getClassName()); + } catch (IOException e) { + e.printStackTrace(); + } + + try (PrintWriter out = new PrintWriter(builderFile.openWriter())) { + out.println("package " + classDto.getClassPackage() + ";"); + out.println(); + out.print("public class " + classDto.getClassName() + " {"); + out.println(); + out.println(); + generateNames(classDto.getFields(), out); + out.println(); + out.println("}"); + out.println(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private static void generateNames(Set fields, PrintWriter out) { + for (FieldDto field : fields) { + out.println(" public static final String " + field.getFieldStringName() + " = \"" + field.getFieldName() + "\";"); + } + } + +} diff --git a/src/main/java/org/sadtech/example/annotation/FieldNames.java b/src/main/java/org/sadtech/example/annotation/FieldNames.java new file mode 100644 index 0000000..8a2710c --- /dev/null +++ b/src/main/java/org/sadtech/example/annotation/FieldNames.java @@ -0,0 +1,14 @@ +package org.sadtech.example.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.CLASS) +public @interface FieldNames { + + String postfix() default "Fields"; + +} diff --git a/src/main/java/org/sadtech/example/annotation/domain/ClassDto.java b/src/main/java/org/sadtech/example/annotation/domain/ClassDto.java new file mode 100644 index 0000000..a85d401 --- /dev/null +++ b/src/main/java/org/sadtech/example/annotation/domain/ClassDto.java @@ -0,0 +1,35 @@ +package org.sadtech.example.annotation.domain; + +import java.util.Set; + +public class ClassDto { + + private String className; + private Set fields; + private String classPackage; + + public String getClassName() { + return className; + } + + public void setClassName(String className) { + this.className = className; + } + + public Set getFields() { + return fields; + } + + public void setFields(Set fields) { + this.fields = fields; + } + + public String getClassPackage() { + return classPackage; + } + + public void setClassPackage(String classPackage) { + this.classPackage = classPackage; + } + +} diff --git a/src/main/java/org/sadtech/example/annotation/domain/FieldDto.java b/src/main/java/org/sadtech/example/annotation/domain/FieldDto.java new file mode 100644 index 0000000..6d8bfc8 --- /dev/null +++ b/src/main/java/org/sadtech/example/annotation/domain/FieldDto.java @@ -0,0 +1,30 @@ +package org.sadtech.example.annotation.domain; + +/** + * // TODO: 07.06.2021 Добавить описание. + * + * @author upagge 07.06.2021 + */ +public class FieldDto { + + private final String fieldStringName; + private final String fieldName; + + private FieldDto(String fieldStringName, String fieldName) { + this.fieldStringName = fieldStringName; + this.fieldName = fieldName; + } + + public static FieldDto of(String fieldStringName, String fieldName) { + return new FieldDto(fieldStringName, fieldName); + } + + public String getFieldStringName() { + return fieldStringName; + } + + public String getFieldName() { + return fieldName; + } + +} diff --git a/src/main/java/org/sadtech/example/annotation/processor/FieldNameProcessor.java b/src/main/java/org/sadtech/example/annotation/processor/FieldNameProcessor.java new file mode 100644 index 0000000..29a1665 --- /dev/null +++ b/src/main/java/org/sadtech/example/annotation/processor/FieldNameProcessor.java @@ -0,0 +1,67 @@ +package org.sadtech.example.annotation.processor; + +import com.google.auto.service.AutoService; +import com.google.common.base.CaseFormat; +import org.sadtech.example.annotation.ClassCreator; +import org.sadtech.example.annotation.FieldNames; +import org.sadtech.example.annotation.domain.ClassDto; +import org.sadtech.example.annotation.domain.FieldDto; + +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.Processor; +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.TypeElement; +import javax.lang.model.type.TypeMirror; +import java.util.Arrays; +import java.util.Set; +import java.util.stream.Collectors; + +@SupportedAnnotationTypes("org.sadtech.example.annotation.FieldNames") +@SupportedSourceVersion(SourceVersion.RELEASE_11) +@AutoService(Processor.class) +public class FieldNameProcessor extends AbstractProcessor { + + @Override + public boolean process(Set set, RoundEnvironment roundEnvironment) { + for (TypeElement annotation : set) { + Set annotatedElements = roundEnvironment.getElementsAnnotatedWith(annotation); + for (Element annotatedElement : annotatedElements) { + final TypeMirror mirror = annotatedElement.asType(); + final String annotatedElementName = annotatedElement.getSimpleName().toString(); + final FieldNames settings = annotatedElement.getAnnotation(FieldNames.class); + final String newClassName = annotatedElementName + settings.postfix(); + + final Set fields = annotatedElement.getEnclosedElements().stream() + .filter(this::isField) + .map( + element -> { + final String fieldName = element.getSimpleName().toString(); + final String fieldStringName = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, fieldName); + return FieldDto.of(fieldStringName, fieldName); + } + ).collect(Collectors.toSet()); + + final ClassDto newClass = new ClassDto(); + newClass.setClassName(newClassName); + newClass.setFields(fields); + newClass.setClassPackage(getPackage(mirror)); + ClassCreator.record(newClass, processingEnv); + } + } + return true; + } + + public boolean isField(Element element) { + return element != null && element.getKind().isField(); + } + + public static String getPackage(TypeMirror typeMirror) { + final String[] split = typeMirror.toString().split("\\."); + return String.join(".", Arrays.copyOf(split, split.length - 1)); + } + +}