11package org .terasology .gestalt .annotation .processing ;
22
3+ import com .google .common .collect .HashMultimap ;
4+ import com .google .common .collect .Multimap ;
35import com .google .common .collect .Queues ;
6+ import org .terasology .context .annotation .BindAnnotationFor ;
47import org .terasology .context .annotation .Index ;
58import org .terasology .context .annotation .IndexInherited ;
69
912import javax .annotation .processing .ProcessingEnvironment ;
1013import javax .annotation .processing .RoundEnvironment ;
1114import javax .lang .model .SourceVersion ;
15+ import javax .lang .model .element .AnnotationValue ;
1216import javax .lang .model .element .Element ;
1317import javax .lang .model .element .ElementKind ;
1418import javax .lang .model .element .PackageElement ;
2024import javax .tools .StandardLocation ;
2125import java .io .IOException ;
2226import java .io .Writer ;
27+ import java .lang .annotation .Annotation ;
2328import java .util .Arrays ;
2429import java .util .Collections ;
30+ import java .util .Map ;
31+ import java .util .Optional ;
2532import java .util .Queue ;
2633import java .util .Set ;
2734
@@ -35,17 +42,34 @@ public class ClassIndexProcessor extends AbstractProcessor {
3542 private SubtypesTypeWriter subtypesTypeWriter ;
3643 private ElementUtility elementUtility ;
3744
45+ private Multimap <TypeMirror , Class <? extends Annotation >> boundAnnotations ;
46+
3847 @ Override
3948 public synchronized void init (ProcessingEnvironment processingEnv ) {
4049 super .init (processingEnv );
4150 filer = processingEnv .getFiler ();
4251 annotationTypeWriter = new AnnotationTypeWriter (filer );
4352 subtypesTypeWriter = new SubtypesTypeWriter (filer );
4453 elementUtility = new ElementUtility (processingEnv .getElementUtils (), processingEnv .getTypeUtils ());
54+ boundAnnotations = HashMultimap .create ();
4555 }
4656
4757 @ Override
4858 public boolean process (Set <? extends TypeElement > annotations , RoundEnvironment roundEnv ) {
59+ for (TypeElement annotation : annotations ) {
60+ if (annotation .asType ().toString ().equals (BindAnnotationFor .class .getName ())) {
61+ for (Element type : roundEnv .getElementsAnnotatedWith (annotation )) {
62+ TypeMirror foreighElement = getBindAnnotationFor (type );
63+ if (elementUtility .hasStereotype (type , Collections .singletonList (IndexInherited .class .getName ()))) {
64+ boundAnnotations .put (foreighElement , IndexInherited .class );
65+ }
66+ if (elementUtility .hasStereotype (type , Collections .singletonList (Index .class .getName ()))) {
67+ boundAnnotations .put (foreighElement , Index .class );
68+ }
69+ }
70+ }
71+ }
72+
4973 for (TypeElement annotation : annotations ) {
5074 // Annotation Index
5175 processAnnotationIndex (roundEnv , annotation );
@@ -75,7 +99,7 @@ private void processSubtypeIndexInReverseWay(Element type) {
7599 TypeMirror candidate = supers .poll ();
76100 if (candidate .getKind () != TypeKind .NONE ) {
77101 if (elementUtility .hasStereotype (elementUtility .getTypes ().asElement (candidate ),
78- Collections .singletonList (IndexInherited .class .getName ()))) {
102+ Collections .singletonList (IndexInherited .class .getName ())) || boundAnnotations . containsEntry ( candidate , IndexInherited . class )) {
79103 TypeElement candidateElement = (TypeElement ) elementUtility .getTypes ().asElement (elementUtility .getTypes ().erasure (candidate ));
80104 TypeElement erasedType = (TypeElement ) elementUtility .getTypes ().asElement (elementUtility .getTypes ().erasure (type .asType ()));
81105 subtypesTypeWriter .writeSubType (elementUtility .getElements ().getBinaryName (candidateElement ).toString (),
@@ -98,7 +122,7 @@ private void processSubtypeIndexByDirectMarked(RoundEnvironment roundEnv, TypeEl
98122 TypeMirror candidate = supers .poll ();
99123 if (candidate .getKind () != TypeKind .NONE ) {
100124 if (elementUtility .hasStereotype (elementUtility .getTypes ().asElement (candidate ),
101- Collections .singletonList (IndexInherited .class .getName ()))) {
125+ Collections .singletonList (IndexInherited .class .getName ())) || boundAnnotations . containsEntry ( candidate , IndexInherited . class ) ) {
102126 TypeElement candidateElement = (TypeElement ) elementUtility .getTypes ().asElement (elementUtility .getTypes ().erasure (candidate ));
103127 TypeElement erasedType = (TypeElement ) elementUtility .getTypes ().asElement (elementUtility .getTypes ().erasure (type .asType ()));
104128 subtypesTypeWriter .writeSubType (elementUtility .getElements ().getBinaryName (candidateElement ).toString (),
@@ -126,6 +150,27 @@ private void processAnnotationIndex(RoundEnvironment roundEnv, TypeElement annot
126150 }
127151 }
128152
153+ private TypeMirror getBindAnnotationFor (Element element ) {
154+ return (TypeMirror ) getAnnotationValue (element , BindAnnotationFor .class , "value" ).orElse (null );
155+ }
156+
157+ private Optional <Object > getAnnotationValue (Element element , Class <?> annotation , String fieldName ) {
158+ return element
159+ .getAnnotationMirrors ()
160+ .stream ()
161+ .filter (am -> am .getAnnotationType ().toString ().equals (annotation .getName ()))
162+ .map (am -> am .getElementValues ()
163+ .entrySet ()
164+ .stream ()
165+ .filter (kv -> kv .getKey ().getSimpleName ().toString ().equals (fieldName ))
166+ .map (Map .Entry ::getValue )
167+ .findFirst ())
168+ .filter (Optional ::isPresent )
169+ .map (Optional ::get )
170+ .map (AnnotationValue ::getValue )
171+ .findFirst ();
172+ }
173+
129174 private void writeIndexes () {
130175 try {
131176 annotationTypeWriter .finish ();
0 commit comments