Kaynağa Gözat

new: IAnnotations support searching for repeatable types

Ranides Atterwim 4 yıl önce
ebeveyn
işleme
1e5800a784

+ 29 - 5
assira.core/src/main/java/net/ranides/assira/reflection/impl/AAnnotations.java

@@ -12,6 +12,8 @@ import net.ranides.assira.reflection.*;
 
 import java.io.Serializable;
 import java.lang.annotation.Annotation;
+import java.lang.annotation.Repeatable;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Optional;
 import java.util.function.Predicate;
@@ -37,17 +39,17 @@ public class AAnnotations extends AElements<Annotation> implements IAnnotations,
 
     @Override
     public <A extends Annotation> Optional<A> first(Class<A> type) {
-        return stream().filter(type).first();
+        return stream(type).first();
     }
 
     @Override
     public <A extends Annotation> CQuery<A> stream(Class<A> type) {
-        return stream().filter(type);
+        return stream0(type);
     }
 
     @Override
     public <A extends Annotation> List<A> list(Class<A> type) {
-        return stream().filter(type).list();
+        return stream(type).list();
     }
 
     @Override
@@ -58,7 +60,8 @@ public class AAnnotations extends AElements<Annotation> implements IAnnotations,
 
     @Override
     public IAnnotations require(Class<? extends Annotation> type) {
-        return require(a -> type.isInstance(a));
+        rebind(stream0(type));
+        return this;
     }
 
     @Override
@@ -68,7 +71,28 @@ public class AAnnotations extends AElements<Annotation> implements IAnnotations,
 
     @Override
     public IAnnotations discard(Class<? extends Annotation> type) {
-        return require(a -> !type.isInstance(a));
+        Repeatable repeat = type.getAnnotation(Repeatable.class);
+        if(repeat == null) {
+            return require(a -> !type.isInstance(a));
+        } else {
+            Class<? extends Annotation> container = repeat.value();
+            return require(a -> !type.isInstance(a) && !container.isInstance(a));
+        }
+    }
+
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    protected <T> CQuery<T> stream0(Class<?> type) {
+        Repeatable repeat = type.getAnnotation(Repeatable.class);
+        if(repeat == null) {
+            return (CQuery)stream().filter(a -> type.isInstance(a));
+        }
+
+        Class<? extends Annotation> container = repeat.value();
+        IMethod method = IClass.typeinfo(container).method("value").get();
+
+        return (CQuery)stream()
+            .filter(a -> type.isInstance(a) || container.isInstance(a))
+            .flatIf(a -> container.isInstance(a), a -> Arrays.asList(method.$call(a)));
     }
 
     @Override

+ 5 - 1
assira.core/src/main/java/net/ranides/assira/reflection/impl/AElements.java

@@ -23,7 +23,7 @@ import net.ranides.assira.reflection.*;
 public abstract class AElements<T> implements IElements<T> {
     
     private final IHints hints;
-    
+
     private CQuery<T> cquery;
 
     protected AElements(IHints hints, CQuery<T> cquery) {
@@ -34,6 +34,10 @@ public abstract class AElements<T> implements IElements<T> {
     protected void filter(Predicate<? super T> predicate) {
         this.cquery = cquery.filter(predicate);
     }
+
+    protected void rebind(CQuery<T> cquery) {
+        this.cquery = cquery;
+    }
     
     @Override
     public CQuery<T> stream() {