br.com.objectos.code.AnnotationExecutor Maven / Gradle / Ivy
/*
* Copyright 2016 Objectos, Fábrica de Software LTDA.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package br.com.objectos.code;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Stream;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
/**
* @author [email protected] (Marcio Endo)
*/
class AnnotationExecutor {
private final ProcessingEnvironmentWrapper processingEnv;
private final List artifactGeneratorList;
private final ProcessorListener listener;
private final Set elementRetrySet = new LinkedHashSet<>();
public AnnotationExecutor(ProcessingEnvironmentWrapper processingEnv,
List artifactGeneratorList,
ProcessorListener listener) {
this.processingEnv = processingEnv;
this.artifactGeneratorList = artifactGeneratorList;
this.listener = listener;
}
public void onInit() {
listener.onInit(processingEnv);
}
public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {
try {
listener.onStart(annotations, roundEnv);
List elementRetryList = new ArrayList<>(elementRetrySet);
Stream extends Element> retryStream = elementRetryList
.stream()
.map(el -> el.retry(processingEnv));
Stream extends Element> roundStream = roundStream(annotations, roundEnv);
Stream.concat(retryStream, roundStream)
.flatMap(this::generateIfPossible)
.peek(listener::peek)
.forEach(this::execute);
return listener.onSuccess(annotations, roundEnv);
} catch (Throwable e) {
String msg = Throwables.getStackTraceAsString(e);
processingEnv.compilationError("Processor threw an exception: " + msg);
return listener.onError(annotations, roundEnv, e);
} finally {
listener.onFinish(annotations, roundEnv);
}
}
void execute(Artifact artifact) {
artifact.execute(processingEnv.unwrap());
}
private Stream generateIfPossible(Element element) {
Stream.Builder stream = Stream.builder();
ElementRetry elementRetry = ElementRetry.of(element);
for (ArtifactGenerator generator : artifactGeneratorList) {
if (generator.test(element)) {
try {
Artifact artifact = generator.generateArtifact(processingEnv, element);
if (artifact == null) {
processingEnv.compilationError("ArtifactGenerator returned null.");
} else {
stream.accept(artifact);
}
elementRetry.removeFrom(elementRetrySet);
} catch (CodeGenerationIncompleteException e) {
elementRetry.addTo(elementRetrySet);
} catch (Exception e) {
String msg = Throwables.getStackTraceAsString(e);
processingEnv.compilationError("Processor threw an exception: " + msg);
}
}
}
return stream.build();
}
private Stream extends Element> roundStream(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {
return annotations.stream()
.map(annotationType -> roundEnv.getElementsAnnotatedWith(annotationType))
.flatMap(Set::stream);
}
}