mirror of
https://github.com/JHUAPL/Jackfruit.git
synced 2026-01-09 20:37:58 -05:00
Merge branch '7-include-annotated-methods-from-superclass' into 'main'
Resolve "Include annotated methods from superclass" Closes #7 See merge request nairah1/jackfruit!7
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
# jackfruit
|
||||
# Jackfruit
|
||||
|
||||
## Quick start
|
||||
|
||||
Jackfruit processes annotations on Java interfaces to generate code that can read and write Apache Configuration files. The `demo` module includes sample code. In the top level directory, run `mvn clean package`, which will build the annotation library, run the annotation processor on the file `demo/src/main/java/jackfruit/demo/DemoInterface.java`, and generate the class `demo/target/generated-sources/annotations/jackfruit/demo/DemoInterfaceFactory.java`. The file `demo/src/main/java/jackfruit/demo/JackfruitDemo.java` shows some simple examples of use.
|
||||
Jackfruit processes annotations on Java interfaces and abstract classes to generate code that can read and write Apache Configuration files. The `demo` module includes sample code. In the top level directory, run `mvn clean package`, which will build the annotation library, run the annotation processor on the file `demo/src/main/java/jackfruit/demo/DemoInterface.java`, and generate the class `demo/target/generated-sources/annotations/jackfruit/demo/DemoInterfaceFactory.java`. The file `demo/src/main/java/jackfruit/demo/JackfruitDemo.java` shows some simple examples of use.
|
||||
|
||||
## Introduction
|
||||
|
||||
@@ -132,6 +132,10 @@ The annotation processor generates a class called DemoInterfaceFactory. An exam
|
||||
System.out.println("random.toUpperCase() = " + random.toUpperCase());
|
||||
```
|
||||
|
||||
## Inheritance
|
||||
|
||||
Methods can be inherited by abstract classes. The `@Jackfruit` annotation must be present on the parent class as well as the inherited class. The annotation processor will build factory classes for both parent and child classes.
|
||||
|
||||
## Supported Annotations
|
||||
|
||||
The `@Jackfruit` annotation goes on the abstract type. The remaining annotations are for use on methods.
|
||||
|
||||
@@ -8,11 +8,12 @@ import jackfruit.annotations.Key;
|
||||
import jackfruit.annotations.ParserClass;
|
||||
|
||||
@Jackfruit(prefix = "prefix")
|
||||
public abstract class DemoClass {
|
||||
public abstract class DemoClass extends DemoSuperClass {
|
||||
|
||||
@Key("key")
|
||||
@Comment("One line comment")
|
||||
@Comment("This method overrides one defined in DemoSuperClass")
|
||||
@DefaultValue("1")
|
||||
@Override
|
||||
public abstract int intMethod();
|
||||
|
||||
@Comment("This is a very long comment line that really should be wrapped into more than one line but that's really up to you.")
|
||||
|
||||
20
demo/src/main/java/jackfruit/demo/DemoSuperClass.java
Normal file
20
demo/src/main/java/jackfruit/demo/DemoSuperClass.java
Normal file
@@ -0,0 +1,20 @@
|
||||
package jackfruit.demo;
|
||||
|
||||
import jackfruit.annotations.Comment;
|
||||
import jackfruit.annotations.DefaultValue;
|
||||
import jackfruit.annotations.Jackfruit;
|
||||
|
||||
// prefix can be superseded by inherited classes
|
||||
@Jackfruit
|
||||
public abstract class DemoSuperClass extends DemoSuperSuperClass {
|
||||
|
||||
@Comment("from DemoSuperClass")
|
||||
@DefaultValue("-1")
|
||||
@Override
|
||||
public abstract int inherited();
|
||||
|
||||
@Comment("from DemoSuperClass")
|
||||
@DefaultValue("2")
|
||||
@Override
|
||||
public abstract int intMethod();
|
||||
}
|
||||
21
demo/src/main/java/jackfruit/demo/DemoSuperSuperClass.java
Normal file
21
demo/src/main/java/jackfruit/demo/DemoSuperSuperClass.java
Normal file
@@ -0,0 +1,21 @@
|
||||
package jackfruit.demo;
|
||||
|
||||
import jackfruit.annotations.Comment;
|
||||
import jackfruit.annotations.DefaultValue;
|
||||
import jackfruit.annotations.Jackfruit;
|
||||
|
||||
@Jackfruit
|
||||
public abstract class DemoSuperSuperClass {
|
||||
|
||||
@Comment("from DemoSuperSuperClass")
|
||||
@DefaultValue("-3")
|
||||
public abstract int inherited2();
|
||||
|
||||
@Comment("from DemoSuperSuperClass")
|
||||
@DefaultValue("-2")
|
||||
public abstract int inherited();
|
||||
|
||||
@Comment("from DemoSuperSuperClass")
|
||||
@DefaultValue("3")
|
||||
public abstract int intMethod();
|
||||
}
|
||||
@@ -13,18 +13,18 @@ public class JackfruitDemo {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
/*-
|
||||
// this factory is built by the annotation processor after reading
|
||||
// DemoClass
|
||||
DemoClassFactory factory = new DemoClassFactory();
|
||||
|
||||
|
||||
// get an example config object
|
||||
DemoClass template = factory.getTemplate();
|
||||
*/
|
||||
|
||||
/*-
|
||||
// or if you prefer, use an interface
|
||||
DemoInterfaceFactory factory = new DemoInterfaceFactory();
|
||||
DemoInterface template = factory.getTemplate();
|
||||
*/
|
||||
|
||||
// generate an Apache PropertiesConfiguration object. This can be written out to
|
||||
// a file
|
||||
|
||||
@@ -5,6 +5,7 @@ import java.io.PrintWriter;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -106,17 +107,41 @@ public class ConfigProcessor extends AbstractProcessor {
|
||||
classBuilder.addField(loggerField);
|
||||
*/
|
||||
|
||||
// this contains a hierarchy of parent classes
|
||||
List<DeclaredType> superClasses = new ArrayList<>();
|
||||
{
|
||||
TypeElement thisElement = annotatedType;
|
||||
TypeMirror superClass = thisElement.getSuperclass();
|
||||
while (superClass.getKind() == TypeKind.DECLARED) {
|
||||
DeclaredType superType = (DeclaredType) superClass;
|
||||
// have to use asElement() here
|
||||
if (superType.asElement().getAnnotation(Jackfruit.class) == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
superClasses.add(superType);
|
||||
thisElement = (TypeElement) superType.asElement();
|
||||
superClass = thisElement.getSuperclass();
|
||||
}
|
||||
}
|
||||
|
||||
Collections.reverse(superClasses);
|
||||
superClasses.add((DeclaredType) annotatedType.asType());
|
||||
|
||||
// create a list of methods annotated with DefaultValue - ignore everything else
|
||||
List<ExecutableElement> enclosedMethods = new ArrayList<>();
|
||||
for (Element e : annotatedType.getEnclosedElements()) {
|
||||
if (e.getKind() == ElementKind.METHOD && e.getAnnotation(DefaultValue.class) != null
|
||||
&& e instanceof ExecutableElement)
|
||||
enclosedMethods.add((ExecutableElement) e);
|
||||
Map<String, ExecutableElement> enclosedMethods = new LinkedHashMap<>();
|
||||
for (DeclaredType superClass : superClasses) {
|
||||
for (Element e : superClass.asElement().getEnclosedElements()) {
|
||||
if (e.getKind() == ElementKind.METHOD && e.getAnnotation(DefaultValue.class) != null
|
||||
&& e instanceof ExecutableElement) {
|
||||
enclosedMethods.put(e.getSimpleName().toString(), (ExecutableElement) e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// holds the annotation information on each method
|
||||
Map<ExecutableElement, AnnotationBundle> annotationsMap = new LinkedHashMap<>();
|
||||
for (ExecutableElement e : enclosedMethods) {
|
||||
for (ExecutableElement e : enclosedMethods.values()) {
|
||||
|
||||
ImmutableAnnotationBundle.Builder builder = ImmutableAnnotationBundle.builder();
|
||||
builder.key(e.getSimpleName().toString());
|
||||
|
||||
Reference in New Issue
Block a user