improve annotation processor

This commit is contained in:
Sebastian Sdorra
2014-03-28 20:38:36 +01:00
parent 812021f212
commit 93dc44b729
4 changed files with 144 additions and 19 deletions

View File

@@ -47,7 +47,7 @@ import java.lang.annotation.Target;
*/
@Documented
@Target({ ElementType.TYPE })
@PluginAnnotation("extension-points")
@PluginAnnotation("extension-point")
@Retention(RetentionPolicy.RUNTIME)
public @interface ExtensionPoint
{

View File

@@ -51,6 +51,6 @@ import java.lang.annotation.Target;
*/
@Documented
@Target({ ElementType.TYPE })
@PluginAnnotation("extensions")
@PluginAnnotation("extension")
@Retention(RetentionPolicy.RUNTIME)
public @interface Extension {}

View File

@@ -36,6 +36,11 @@ package sonia.scm.annotation;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
//~--- JDK imports ------------------------------------------------------------
import java.util.Map;
import java.util.Map.Entry;
/**
*
* @author Sebastian Sdorra
@@ -55,7 +60,8 @@ public class ClassSetElement implements DescriptorElement
* @param elementName
* @param classes
*/
public ClassSetElement(String elementName, Iterable<String> classes)
public ClassSetElement(String elementName,
Iterable<ClassWithAttributes> classes)
{
this.elementName = elementName;
this.classes = classes;
@@ -73,23 +79,67 @@ public class ClassSetElement implements DescriptorElement
@Override
public void append(Document doc, Element root)
{
Element element = doc.createElement(elementName);
for (String c : classes)
for (ClassWithAttributes c : classes)
{
Element element = doc.createElement(elementName);
Element classEl = doc.createElement(EL_CLASS);
classEl.setTextContent(c);
element.appendChild(classEl);
classEl.setTextContent(c.className);
for (Entry<String, String> e : c.attributes.entrySet())
{
Element attr = doc.createElement(e.getKey());
attr.setTextContent(e.getValue());
element.appendChild(attr);
}
element.appendChild(classEl);
root.appendChild(element);
}
}
//~--- inner classes --------------------------------------------------------
/**
* Class description
*
*
* @version Enter version here..., 14/03/18
* @author Enter your name here...
*/
public static class ClassWithAttributes
{
/**
* Constructs ...
*
*
* @param className
* @param attributes
*/
public ClassWithAttributes(String className, Map<String, String> attributes)
{
this.className = className;
this.attributes = attributes;
}
//~--- fields -------------------------------------------------------------
/** Field description */
private final Map<String, String> attributes;
/** Field description */
private final String className;
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private final Iterable<String> classes;
private final Iterable<ClassWithAttributes> classes;
/** Field description */
private final String elementName;

View File

@@ -37,12 +37,14 @@ import com.github.legman.Subscribe;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.kohsuke.MetaInfServices;
import org.w3c.dom.Document;
import sonia.scm.annotation.ClassSetElement.ClassWithAttributes;
import sonia.scm.plugin.PluginAnnotation;
//~--- JDK imports ------------------------------------------------------------
@@ -58,6 +60,8 @@ import java.io.Writer;
import java.lang.annotation.Annotation;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
@@ -68,6 +72,8 @@ import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
@@ -115,8 +121,8 @@ public final class ScmAnnotationProcessor extends AbstractProcessor
/** Field description */
private static final Set<ClassAnnotation> CLASS_ANNOTATIONS =
ImmutableSet.of(new ClassAnnotation("jaxrs-resources", Path.class),
new ClassAnnotation("jaxrs-providers", Provider.class));
ImmutableSet.of(new ClassAnnotation("jaxrs-resource", Path.class),
new ClassAnnotation("jaxrs-provider", Provider.class));
//~--- methods --------------------------------------------------------------
@@ -144,8 +150,7 @@ public final class ScmAnnotationProcessor extends AbstractProcessor
if (pa != null)
{
scanForClassAnnotations(descriptorElements, pa.value(),
roundEnv.getElementsAnnotatedWith(e));
scanForClassAnnotations(descriptorElements, roundEnv, e, pa.value());
}
if (SUBSCRIBE_ANNOTATIONS.contains(e.getQualifiedName().toString()))
@@ -156,8 +161,14 @@ public final class ScmAnnotationProcessor extends AbstractProcessor
for (ClassAnnotation ca : CLASS_ANNOTATIONS)
{
scanForClassAnnotations(descriptorElements, ca.elementName,
roundEnv.getElementsAnnotatedWith(ca.annotationClass));
TypeElement annotation = findAnnotation(annotations,
ca.annotationClass);
if (annotation != null)
{
scanForClassAnnotations(descriptorElements, roundEnv, annotation,
ca.elementName);
}
}
for (TypeElement annotation : subscriberAnnotations)
@@ -193,6 +204,33 @@ public final class ScmAnnotationProcessor extends AbstractProcessor
}
}
/**
* Method description
*
*
* @param annotations
* @param annotationClass
*
* @return
*/
private TypeElement findAnnotation(Set<? extends TypeElement> annotations,
Class<? extends Annotation> annotationClass)
{
TypeElement annotation = null;
for (TypeElement te : annotations)
{
if (te.getQualifiedName().toString().equals(annotationClass.getName()))
{
annotation = te;
break;
}
}
return annotation;
}
/**
* Method description
*
@@ -283,24 +321,27 @@ public final class ScmAnnotationProcessor extends AbstractProcessor
*
*
* @param descriptorElements
* @param roundEnv
* @param annotation
* @param elementName
* @param elements
*
* @return
*/
private void scanForClassAnnotations(
Set<DescriptorElement> descriptorElements, String elementName,
Set<? extends Element> elements)
Set<DescriptorElement> descriptorElements, RoundEnvironment roundEnv,
TypeElement annotation, String elementName)
{
Set<String> classes = Sets.newHashSet();
Set<ClassWithAttributes> classes = Sets.newHashSet();
for (Element e : elements)
for (Element e : roundEnv.getElementsAnnotatedWith(annotation))
{
if (e.getKind().isClass() || e.getKind().isInterface())
{
TypeElement type = (TypeElement) e;
classes.add(type.getQualifiedName().toString());
classes.add(new ClassWithAttributes(type.getQualifiedName().toString(),
getAttributesFromAnnotation(e, annotation)));
}
}
@@ -405,6 +446,40 @@ public final class ScmAnnotationProcessor extends AbstractProcessor
}
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @param el
* @param annotation
*
* @return
*/
private Map<String, String> getAttributesFromAnnotation(Element el,
TypeElement annotation)
{
Map<String, String> attributes = Maps.newHashMap();
for (AnnotationMirror am : el.getAnnotationMirrors())
{
String qn = am.getAnnotationType().asElement().toString();
if (qn.equals(annotation.toString()))
{
for (Entry<? extends ExecutableElement,
? extends AnnotationValue> entry : am.getElementValues().entrySet())
{
attributes.put(entry.getKey().getSimpleName().toString(),
entry.getValue().getValue().toString());
}
}
}
return attributes;
}
//~--- inner classes --------------------------------------------------------
/**