package pocketknife.internal.codegen;
import com.google.common.base.CaseFormat;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import java.lang.annotation.Annotation;
import java.util.Map;
public abstract class BaseProcessor {
protected Elements elements;
protected Types types;
protected TypeUtil typeUtil;
public BaseProcessor(Elements elements, Types types) {
this.elements = elements;
this.types = types;
this.typeUtil = TypeUtil.getInstance(elements, types);
}
protected boolean isDefaultAnnotationElement(Element element, String annotation, String annotationElement) {
for (AnnotationMirror mirror : element.getAnnotationMirrors()) {
if (annotation.equals(mirror.getAnnotationType().toString())) {
for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : mirror.getElementValues().entrySet()) {
if (annotationElement.equals(entry.getKey().getSimpleName().toString())) {
return false;
}
}
}
}
return true;
}
protected String generateKey(String prefix, String name) {
return prefix + CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, name);
}
protected TypeMirror getAnnotationElementClass(Element element, Class<? extends Annotation> annotation) {
return getAnnotationElementClass(element, annotation, "value");
}
protected TypeMirror getAnnotationElementClass(Element element, Class<? extends Annotation> annotation, String annotationElement) {
for (AnnotationMirror mirror : element.getAnnotationMirrors()) {
if (annotation.getName().equals(mirror.getAnnotationType().toString())) {
for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : mirror.getElementValues().entrySet()) {
if (annotationElement.equals(entry.getKey().getSimpleName().toString())) {
return (TypeMirror) entry.getValue().getValue();
}
}
break;
}
}
return null;
}
protected void validateSerializer(Element element, Class<? extends Annotation> annotation, TypeMirror serializer, Class abstractSerializer) {
if (serializer == null) {
return;
}
Element absSerializerElement = elements.getTypeElement(abstractSerializer.getName());
if (absSerializerElement == null) {
throw new IllegalStateException(String.format("Unable to find %s type", abstractSerializer.getName()));
}
TypeMirror absSerializerMirror = absSerializerElement.asType();
if (!types.isAssignable(serializer, types.erasure(absSerializerMirror))) {
throw new IllegalStateException(String.format("@%s value must extend %s", annotation.getName(), abstractSerializer.getName()));
}
TypeMirror elementType = element.asType();
for (TypeMirror superType : types.directSupertypes(serializer)) {
if (types.isAssignable(superType, types.erasure(absSerializerMirror)) && superType instanceof DeclaredType) {
if (types.isSameType(((DeclaredType) superType).getTypeArguments().get(0), elementType)) {
return;
} else {
throw new IllegalStateException(String.format("Serializer T must be of type %s", elementType.toString()));
}
}
}
throw new IllegalStateException(String.format("%s must extend %s", serializer.toString(), absSerializerMirror.toString()));
}
}