parent
11f18a9abf
commit
1d447b2045
@ -0,0 +1 @@ |
||||
de.kreth.property2java.processor.Property2JavaGenerator |
||||
@ -0,0 +1,40 @@ |
||||
package de.kreth.property2java.processor; |
||||
|
||||
import static java.lang.annotation.ElementType.TYPE; |
||||
|
||||
import java.lang.annotation.Retention; |
||||
import java.lang.annotation.RetentionPolicy; |
||||
import java.lang.annotation.Target; |
||||
|
||||
@Target(TYPE) |
||||
@Retention(RetentionPolicy.SOURCE) |
||||
/** |
||||
* Für die konfigurierten Resourcen wird jeweils eine Java Klasse erzeugt. Es |
||||
* muss nur die Abhängigkeit eingebunden werden und die Annotation in einer |
||||
* Klasse verwendet werden, in deren Package die neuen Klassen generiert werden. |
||||
* |
||||
* Für die Ausgabe der Prozessornachrichten muss folgendes im maven compiler |
||||
* konfiguriert werden: |
||||
* |
||||
* <pre> |
||||
<build> |
||||
<plugins> |
||||
<plugin> |
||||
<groupId>org.apache.maven.plugins</groupId> |
||||
<artifactId>maven-compiler-plugin</artifactId> |
||||
<version>3.8.0</version> |
||||
<configuration> |
||||
<release>${java.version}</release> |
||||
<b><showWarnings>true</showWarnings></b> |
||||
</configuration> |
||||
</plugin> |
||||
</plugins> |
||||
</build> |
||||
* </pre> |
||||
* |
||||
* @author Markus |
||||
* |
||||
*/ |
||||
public @interface GenerateProperty2Java { |
||||
String[] resources(); |
||||
} |
||||
@ -0,0 +1,105 @@ |
||||
package de.kreth.property2java.processor; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.Reader; |
||||
import java.io.Writer; |
||||
import java.nio.file.Path; |
||||
import java.util.ArrayList; |
||||
import java.util.Arrays; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
import javax.annotation.processing.Filer; |
||||
import javax.lang.model.element.Element; |
||||
import javax.lang.model.element.PackageElement; |
||||
import javax.lang.model.element.TypeElement; |
||||
import javax.tools.FileObject; |
||||
import javax.tools.StandardLocation; |
||||
|
||||
import de.kreth.property2java.Configuration; |
||||
import de.kreth.property2java.Generator; |
||||
import de.kreth.property2java.GeneratorException; |
||||
|
||||
public class ProcessorConfiguration implements Configuration { |
||||
|
||||
private final Filer filer; |
||||
private final Element element; |
||||
private final Map<String, Reader> input; |
||||
|
||||
ProcessorConfiguration(Builder builder) throws IOException { |
||||
this.filer = builder.filer; |
||||
this.element = builder.element; |
||||
this.input = new HashMap<>(); |
||||
for (String resource : builder.resourcenames) { |
||||
|
||||
FileObject ressource = filer.getResource(StandardLocation.CLASS_PATH, "", |
||||
resource); |
||||
String className = mapFilenameToClassName(resource); |
||||
input.put(className, ressource.openReader(false)); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public String getPackage() { |
||||
|
||||
String packageName = ""; |
||||
if (element instanceof TypeElement) { |
||||
TypeElement typeElement = (TypeElement) element; |
||||
PackageElement packageElement = (PackageElement) typeElement.getEnclosingElement(); |
||||
packageName = packageElement.getQualifiedName().toString(); |
||||
} |
||||
return packageName; |
||||
} |
||||
|
||||
@Override |
||||
public Map<String, Reader> getInput() { |
||||
return input; |
||||
} |
||||
|
||||
@Override |
||||
public Path getRootPath() { |
||||
throw new UnsupportedOperationException( |
||||
"For Annotation Processor this is not supported as outWriter is overwritten."); |
||||
} |
||||
|
||||
@Override |
||||
public Writer outWriter(String fileName) throws IOException { |
||||
String packageName = getPackage(); |
||||
if (packageName != null && !packageName.isBlank()) { |
||||
fileName = packageName + "." + fileName; |
||||
} |
||||
return filer.createSourceFile(fileName, element).openWriter(); |
||||
} |
||||
|
||||
static Builder builder(Filer filer, Element element) { |
||||
return new Builder(filer, element); |
||||
} |
||||
|
||||
static class Builder { |
||||
private final Filer filer; |
||||
private final Element element; |
||||
private final List<String> resourcenames; |
||||
|
||||
private Builder(Filer filer, Element element) { |
||||
this.filer = filer; |
||||
this.element = element; |
||||
this.resourcenames = new ArrayList<>(); |
||||
} |
||||
|
||||
public Builder addAll(String[] resourceNames) { |
||||
this.resourcenames.addAll(Arrays.asList(resourceNames)); |
||||
return this; |
||||
} |
||||
|
||||
public Builder addAll(List<String> resourceNames) { |
||||
this.resourcenames.addAll(resourceNames); |
||||
return this; |
||||
} |
||||
|
||||
public void startGeneration() throws IOException, GeneratorException { |
||||
Generator g = new Generator(new ProcessorConfiguration(this)); |
||||
g.start(); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,61 @@ |
||||
package de.kreth.property2java.processor; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.PrintWriter; |
||||
import java.io.StringWriter; |
||||
import java.util.Arrays; |
||||
import java.util.Set; |
||||
|
||||
import javax.annotation.processing.AbstractProcessor; |
||||
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.tools.Diagnostic.Kind; |
||||
|
||||
import de.kreth.property2java.GeneratorException; |
||||
|
||||
@SupportedAnnotationTypes({ "de.kreth.property2java.processor.GenerateProperty2Java" }) |
||||
@SupportedSourceVersion(SourceVersion.RELEASE_8) |
||||
public class Property2JavaGenerator extends AbstractProcessor { |
||||
|
||||
@Override |
||||
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { |
||||
|
||||
if (!roundEnv.processingOver()) { |
||||
processingEnv.getMessager().printMessage(Kind.NOTE, |
||||
"Processing annotation " + GenerateProperty2Java.class); |
||||
|
||||
Set<? extends Element> elementsAnnotatedWith = roundEnv |
||||
.getElementsAnnotatedWith(GenerateProperty2Java.class); |
||||
|
||||
processElements(elementsAnnotatedWith); |
||||
} else { |
||||
processingEnv.getMessager().printMessage(Kind.NOTE, |
||||
"finished working on annotation " + GenerateProperty2Java.class); |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
private void processElements(Set<? extends Element> elementsAnnotatedWith) { |
||||
for (Element element : elementsAnnotatedWith) { |
||||
String[] resources = element.getAnnotation(GenerateProperty2Java.class).resources(); |
||||
processingEnv.getMessager().printMessage(Kind.NOTE, |
||||
"Generating Java for " + Arrays.asList(resources)); |
||||
try { |
||||
ProcessorConfiguration |
||||
.builder(processingEnv.getFiler(), element) |
||||
.addAll(resources) |
||||
.startGeneration(); |
||||
} catch (IOException | GeneratorException e) { |
||||
StringWriter out = new StringWriter(); |
||||
e.printStackTrace(new PrintWriter(out)); |
||||
out.flush(); |
||||
processingEnv.getMessager().printMessage(Kind.ERROR, "Exception " + e + "\n" + out.toString(), |
||||
element); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1 @@ |
||||
de.kreth.property2java.processor.Property2JavaGenerator |
||||
@ -0,0 +1,46 @@ |
||||
package de.kreth.property2java.processor; |
||||
|
||||
import static org.mockito.Mockito.when; |
||||
|
||||
import java.util.HashSet; |
||||
import java.util.Set; |
||||
|
||||
import javax.annotation.processing.Messager; |
||||
import javax.annotation.processing.ProcessingEnvironment; |
||||
import javax.annotation.processing.RoundEnvironment; |
||||
import javax.lang.model.element.TypeElement; |
||||
|
||||
import org.junit.jupiter.api.BeforeEach; |
||||
import org.junit.jupiter.api.Test; |
||||
import org.mockito.ArgumentMatchers; |
||||
import org.mockito.Mock; |
||||
import org.mockito.MockitoAnnotations; |
||||
|
||||
public class Property2JavaGeneratorTest { |
||||
|
||||
private Property2JavaGenerator processor; |
||||
@Mock |
||||
private ProcessingEnvironment processingEnv; |
||||
@Mock |
||||
private RoundEnvironment roundEnv; |
||||
private Set<TypeElement> annotations; |
||||
@Mock |
||||
private Messager messanger; |
||||
|
||||
@BeforeEach |
||||
void initProcesor() { |
||||
MockitoAnnotations.initMocks(this); |
||||
annotations = new HashSet<>(); |
||||
|
||||
processor = new Property2JavaGenerator(); |
||||
processor.init(processingEnv); |
||||
when(processingEnv.getMessager()).thenReturn(messanger); |
||||
} |
||||
|
||||
@Test |
||||
void testGeneratorInitializedCorrectly() { |
||||
when(roundEnv.getElementsAnnotatedWith(ArgumentMatchers.any(Class.class))) |
||||
.thenReturn(annotations); |
||||
processor.process(annotations, roundEnv); |
||||
} |
||||
} |
||||
Loading…
Reference in new issue