package org.richfaces.cdk.apt;
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
import java.util.Set;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import org.richfaces.cdk.CdkProcessingException;
import org.richfaces.cdk.Logger;
import org.richfaces.cdk.apt.processors.CdkAnnotationProcessor;
import org.richfaces.cdk.model.ComponentLibrary;
import com.google.inject.Inject;
public class JavaSourceProcessor {
@Inject
private Logger log;
@Inject
private Set<CdkAnnotationProcessor> processors;
@Inject
private ComponentLibrary library;
@Inject
private JavaSourceTracker sourceCache;
private ProcessingEnvironment processingEnv;
public void process(ProcessingEnvironment processingEnv, RoundEnvironment roundEnv) {
this.processingEnv = processingEnv;
// Process annotations.
for (CdkAnnotationProcessor processor : processors) {
processAnnotation(processor, roundEnv);
}
}
protected void processAnnotation(CdkAnnotationProcessor processor, RoundEnvironment environment) {
Class<? extends Annotation> processedAnnotation = processor.getProcessedAnnotation();
log.debug("Process all elements annotated with " + processedAnnotation.getName());
Target target = processedAnnotation.getAnnotation(Target.class);
Set<? extends Element> rootElements = environment.getRootElements();
for (Element element : rootElements) {
if (!sourceCache.isChanged(element)) {
continue;
}
if (isAppropriateTarget(element, target)) {
processElement(processor, processedAnnotation, element);
} else {
for (Element enclosedElement : element.getEnclosedElements()) {
if (!sourceCache.isChanged(enclosedElement)) {
continue;
}
if (isAppropriateTarget(enclosedElement, target)) {
processElement(processor, processedAnnotation, enclosedElement);
}
}
}
}
}
private void processElement(CdkAnnotationProcessor processor, Class<? extends Annotation> processedAnnotation,
Element element) {
if (null != element.getAnnotation(processedAnnotation)) {
try {
log.debug("Process " + element.getSimpleName() + " annotated with " + processedAnnotation.getName());
processor.process(element, library);
} catch (CdkProcessingException e) {
sendError(element, e);
}
}
}
private boolean isAppropriateTarget(Element element, Target target) {
boolean match = false;
ElementKind kind = element.getKind();
if (null != target) {
for (ElementType targetType : target.value()) {
switch (targetType) {
case TYPE:
match |= ElementKind.CLASS.equals(kind) || ElementKind.INTERFACE.equals(kind)
|| ElementKind.ENUM.equals(kind);
break;
case PACKAGE:
match |= ElementKind.PACKAGE.equals(kind);
break;
case METHOD:
match |= ElementKind.METHOD.equals(kind);
break;
case FIELD:
match |= ElementKind.FIELD.equals(kind);
break;
default:
break;
}
}
} else {
// Annotation without @Target match any element.
match = ElementKind.CLASS.equals(kind) || ElementKind.INTERFACE.equals(kind) || ElementKind.ENUM.equals(kind)
|| ElementKind.PACKAGE.equals(kind) || ElementKind.METHOD.equals(kind) || ElementKind.FIELD.equals(kind);
}
return match;
}
private void sendError(Element componentElement, Exception e) {
// rise error and continue.
processingEnv.getMessager().printMessage(javax.tools.Diagnostic.Kind.ERROR, e.getMessage(), componentElement);
}
}