Procházet zdrojové kódy

fix: CQuery: CQArray#iterator boundaries (skip,offset,limit)
new: CQuery: #imap
new: IteratorUtils: #imap
new: EachFunction

Ranides Atterwim před 10 roky
rodič
revize
e59e8018f7

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 583 - 484
assira/src/main/java/net/ranides/assira/collection/iterators/IteratorUtils.java


+ 3 - 0
assira/src/main/java/net/ranides/assira/collection/query/CQuery.java

@@ -19,6 +19,7 @@ import java.util.function.Predicate;
 import java.util.stream.Collector;
 import java.util.stream.Stream;
 import net.ranides.assira.collection.HashFunction;
+import net.ranides.assira.functional.EachFunction;
 
 /**
  *
@@ -60,6 +61,8 @@ public interface CQuery<T> extends Iterable<T> {
     
     <R> CQuery<R> map(Function<? super T,? extends R> f);
     
+    <R> CQuery<R> imap(EachFunction<? super T,? extends R> f);
+    
     <R> CQuery<R> unfold(Function<? super T, CQuery<R>> f);
     
     <R> CQuery<R> split(Function<? super T, R[]> f);

+ 448 - 442
assira/src/main/java/net/ranides/assira/collection/query/CQueryAbstract.java

@@ -1,442 +1,448 @@
-/*
- * @author Ranides Atterwim <ranides@gmail.com>
- * @copyright Ranides Atterwim
- * @license WTFPL
- * @url http://ranides.net/projects/assira
- */
-package net.ranides.assira.collection.query;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.Set;
-import java.util.Spliterator;
-import java.util.function.BinaryOperator;
-import java.util.function.Consumer;
-import java.util.function.Function;
-import java.util.function.IntFunction;
-import java.util.function.Predicate;
-import java.util.function.Supplier;
-import java.util.stream.Collector;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import java.util.stream.StreamSupport;
-import net.ranides.assira.collection.HashFunction;
-import net.ranides.assira.collection.arrays.ArraySort;
-import net.ranides.assira.collection.arrays.ArrayUtils;
-import net.ranides.assira.collection.iterators.IteratorUtils;
-import net.ranides.assira.collection.sets.CustomSet;
-import net.ranides.assira.collection.sets.HashSet;
-import net.ranides.assira.collection.sets.RBTreeSet;
-import net.ranides.assira.functional.Fold;
-
-/**
- *
- * @author Ranides Atterwim <ranides@gmail.com>
- */
-abstract class CQueryAbstract<T> implements CQuery<T> {
-    
-    @Override
-    public final <A, R> R collect(Collector<? super T, A, R> collector) {
-        return stream().collect(collector);
-    }
-
-    @Override
-    public final Object[] array() {
-        return stream().toArray();
-    }
-
-    @Override
-    public final <A> A[] array(IntFunction<A[]> generator) {
-        return stream().toArray(generator);
-    }
-
-    @Override
-    public final List<T> list() {
-        return stream().collect(Collectors.toList());
-    }
-
-    @Override
-    public final Set<T> set() {
-        return stream().collect(Collectors.toSet());
-    }
-
-    @Override
-    public CQuery<T> limit(Predicate<? super T> p) {
-        return new CQIterable<>(() -> IteratorUtils.limit(iterator(), p));
-    }
-    
-    @Override
-    public CQuery<T> limit(int n) {
-        return new CQBounded<>(this, 0, n);
-    }
-
-    @Override
-    public CQuery<T> skip(int n) {
-        return new CQBounded<>(this, n, Integer.MAX_VALUE);
-    }
-    
-    @Override
-    public CQuery<T> slice(int begin, int end) {
-        return new CQBounded<>(this, begin, end-begin);
-    }
-    
-    @Override
-    public final <K> Map<K, T> group(Function<? super T, ? extends K> key) {
-        return stream().collect(Collectors.toMap(key, v -> v));
-    }
-
-    @Override
-    public final <K, V> Map<K, V> group(Function<? super T, ? extends K> key, Function<? super T, ? extends V> value) {
-        return stream().collect(Collectors.toMap(key, value));
-    }
-
-    @Override
-    public final boolean isEmpty() {
-        return !iterator().hasNext();
-    }
-
-    @Override
-    public final CQuery<T> filter(Predicate<? super T> p) {
-        return new CQIterable<>(() -> IteratorUtils.filter(iterator(), p));
-    }
-
-    @Override
-    public final <R> CQuery<R> map(Function<? super T, ? extends R> f) {
-        return new CQIterable<>(() -> IteratorUtils.map(iterator(), f));
-    }
-
-    @Override
-    public final <R> CQuery<R> unfold(Function<? super T, CQuery<R>> f) {
-        return new CQIterable<>(() -> IteratorUtils.flat(IteratorUtils.map(iterator(), (v) -> f.apply(v).iterator())));
-    }
-
-    @Override
-    public <R> CQuery<R> split(Function<? super T, R[]> f) {
-        return unfold(v -> CQueryBuilder.fromArray(f.apply(v)) );
-    }
-
-    @Override
-    public final T fold(T identity, BinaryOperator<T> accumulator) {
-        Iterator<T> i = iterator();
-        return i.hasNext() ? Fold.apply(i, accumulator::apply) : identity;
-    }
-
-    @Override
-    public final T fold(BinaryOperator<T> accumulator) {
-        return fold(null, accumulator);
-    }
-
-    @Override
-    public final T min(Comparator<? super T> cmp) {
-        return fold((a, b) -> cmp.compare(a, b) < 0 ? a : b);
-    }
-
-    @Override
-    public final T max(Comparator<? super T> cmp) {
-        return fold((a, b) -> cmp.compare(a, b) > 0 ? a : b);
-    }
-
-    @Override
-    public final T first() {
-        return IteratorUtils.first(iterator());
-    }
-
-    @Override
-    public final T last() {
-        return IteratorUtils.last(iterator());
-    }
-
-    @Override
-    public final CQuery<T> distinct() {
-        return new CQCollection<>(() -> new HashSet<>(iterator()));
-    }
-
-    @Override
-    public final CQuery<T> distinct(HashFunction<T> eq) {
-        return new CQCollection<>(() -> new CustomSet<>(iterator(), eq));
-    }
-
-    @Override
-    public final CQuery<T> distinct(Comparator<? super T> cmp) {
-        return new CQCollection<>(() -> new RBTreeSet<>(iterator(), cmp));
-    }
-
-    @Override
-    public final CQuery<T> sort() {
-        return new CQCollection<>(() -> {
-            List<T> list = list();
-            ArraySort.mergeSort(list);
-            return list;
-        });
-    }
-
-    @Override
-    public final CQuery<T> sort(Comparator<? super T> cmp) {
-        return new CQCollection<>(() -> {
-            List<T> list = list();
-            ArraySort.mergeSort(list, cmp);
-            return list;
-        });
-    }
-
-    @Override
-    public final void each(Consumer<? super T> consumer) {
-        stream().forEach(consumer);
-    }
-
-    @Override
-    public void into(Collection<? super T> collection) {
-        stream().forEach(collection::add);
-    }
-
-    @Override
-    public final boolean matchAny(Predicate<? super T> predicate) {
-        return stream().anyMatch(predicate);
-    }
-
-    @Override
-    public final boolean matchAll(Predicate<? super T> predicate) {
-        return stream().allMatch(predicate);
-    }
-
-    @Override
-    public final boolean matchNone(Predicate<? super T> predicate) {
-        return stream().noneMatch(predicate);
-    }
-    
-    protected static class CQCollection<T> extends CQueryAbstract<T> {
-        
-        private final Supplier<Collection<T>> source;
-
-        public CQCollection(Supplier<Collection<T>> source) {
-            this.source = source;
-        }
-        
-        public CQCollection(Collection<T> source) {
-            this(() -> source);
-        }
-
-        @Override
-        public Iterator<T> iterator() {
-            return source.get().iterator();
-        }
-
-        @Override
-        public Spliterator<T> spliterator() {
-            return source.get().spliterator();
-        }
-
-        @Override
-        public Stream<T> stream() {
-            return source.get().stream();
-        }
-
-        @Override
-        public int size() {
-            return source.get().size();
-        }
-       
-    }
-
-    protected static class CQArray<T> extends CQueryAbstract<T> {
-        
-        private final Supplier<T[]> source;
-        private final int offset;
-        private final int limit;
-        
-        public CQArray(Supplier<T[]> source) {
-            this(source, 0, Integer.MAX_VALUE);
-        }
-        
-        public CQArray(Supplier<T[]> source, int offset, int limit) {
-            this.source = source;
-            this.offset = offset;
-            this.limit = limit;
-        }
-        
-        public CQArray(T[] source) {
-            this(source, 0, source.length);
-        }
-        
-        public CQArray(T[] source, int offset, int limit) {
-            this(() -> source, offset,limit);
-        }
-
-        @Override
-        public Iterator<T> iterator() {
-            T[] array = source.get();
-            return ArrayUtils.iterator(array, offset, offset + Math.min(array.length,limit));
-        }
-
-        @Override
-        public Spliterator<T> spliterator() {
-            T[] array = source.get();
-            return Arrays.spliterator(array, offset, offset + Math.min(array.length,limit));
-        }
-
-        @Override
-        public Stream<T> stream() {
-            T[] array = source.get();
-            return Arrays.stream(array, offset, offset + Math.min(array.length,limit));
-        }
-
-        @Override
-        public int size() {
-            return Math.min(limit, source.get().length);
-        }
-        
-        @Override
-        public CQuery<T> limit(int n) {
-            return new CQArray<>(source, offset, Math.min(limit, n));
-        }
-
-        @Override
-        public CQuery<T> skip(int n) {
-            return new CQArray<>(source, offset+n, limit);
-        }
-        
-    }
-        
-    protected static class CQIterable<T> extends CQueryAbstract<T> {
-        
-        private final Supplier<Iterable<T>> source;
-
-        public CQIterable(Supplier<Iterable<T>> source) {
-            this.source = source;
-        }
-        
-        public CQIterable(Iterable<T> source) {
-            this(() -> source);
-        }
-
-        @Override
-        public Iterator<T> iterator() {
-            return source.get().iterator();
-        }
-
-        @Override
-        public Spliterator<T> spliterator() {
-            return source.get().spliterator();
-        }
-
-        @Override
-        public Stream<T> stream() {
-            return StreamSupport.stream(source.get().spliterator(), false);
-        }
-
-        @Override
-        public int size() {
-            return IteratorUtils.size(source.get().iterator());
-        }
-       
-    }
-    
-    protected static class CQQuery<T> extends CQueryAbstract<T> {
-        
-        private final Supplier<CQuery<T>> source;
-
-        public CQQuery(Supplier<CQuery<T>> source) {
-            this.source = source;
-        }
-
-        @Override
-        public Iterator<T> iterator() {
-            return source.get().iterator();
-        }
-
-        @Override
-        public Spliterator<T> spliterator() {
-            return source.get().spliterator();
-        }
-
-        @Override
-        public Stream<T> stream() {
-            return source.get().stream();
-        }
-
-        @Override
-        public int size() {
-            return source.get().size();
-        }
-       
-    }
-    
-    protected static class CQBounded<T> extends CQueryAbstract<T> {
-        
-        private final CQuery<T> stream;
-        private final int begin;
-        private final int size;
-
-        public CQBounded(CQuery<T> stream, int begin, int size) {
-            this.stream = stream;
-            this.begin = begin;
-            this.size = size;
-        }
-        
-        @Override
-        public CQuery<T> limit(int n) {
-            return new CQBounded<>(stream, begin, Math.min(n, size));
-        }
-
-        @Override
-        public CQuery<T> skip(int n) {
-            return new CQBounded<>(stream, begin+n, size);
-        }
-
-        @Override
-        public Iterator<T> iterator() {
-            Iterator<T> i = stream.iterator();
-            IteratorUtils.next(i, begin);
-            return new BIterator<>(i, size);
-        }
-
-        @Override
-        public Spliterator<T> spliterator() {
-            return stream().spliterator();
-        }
-
-        @Override
-        public Stream<T> stream() {
-            return stream.stream().skip(begin).limit(size);
-        }
-
-        @Override
-        public int size() {
-            return Math.min(stream.size(), size);
-        }
-        
-    }
-    
-    private static final class BIterator<T> implements Iterator<T> {
-        
-        private final Iterator<T> src;
-        private final int limit;
-        private int count;
-
-        public BIterator(Iterator<T> src, int limit) {
-            this.src = src;
-            this.limit = limit;
-        }
-
-        @Override
-        public boolean hasNext() {
-            return count<limit && src.hasNext();
-        }
-
-        @Override
-        public T next() {
-            if(count>=limit) {
-                throw new NoSuchElementException();
-            }
-            count++;
-            return src.next();
-        }
-        
-    }
-    
-}
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.collection.query;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.Spliterator;
+import java.util.function.BinaryOperator;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.IntFunction;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+import java.util.stream.Collector;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import net.ranides.assira.collection.HashFunction;
+import net.ranides.assira.collection.arrays.ArraySort;
+import net.ranides.assira.collection.arrays.ArrayUtils;
+import net.ranides.assira.collection.iterators.IteratorUtils;
+import net.ranides.assira.collection.sets.CustomSet;
+import net.ranides.assira.collection.sets.HashSet;
+import net.ranides.assira.collection.sets.RBTreeSet;
+import net.ranides.assira.functional.EachFunction;
+import net.ranides.assira.functional.Fold;
+
+/**
+ *
+ * @author Ranides Atterwim <ranides@gmail.com>
+ */
+abstract class CQueryAbstract<T> implements CQuery<T> {
+    
+    @Override
+    public final <A, R> R collect(Collector<? super T, A, R> collector) {
+        return stream().collect(collector);
+    }
+
+    @Override
+    public final Object[] array() {
+        return stream().toArray();
+    }
+
+    @Override
+    public final <A> A[] array(IntFunction<A[]> generator) {
+        return stream().toArray(generator);
+    }
+
+    @Override
+    public final List<T> list() {
+        return stream().collect(Collectors.toList());
+    }
+
+    @Override
+    public final Set<T> set() {
+        return stream().collect(Collectors.toSet());
+    }
+
+    @Override
+    public CQuery<T> limit(Predicate<? super T> p) {
+        return new CQIterable<>(() -> IteratorUtils.limit(iterator(), p));
+    }
+    
+    @Override
+    public CQuery<T> limit(int n) {
+        return new CQBounded<>(this, 0, n);
+    }
+
+    @Override
+    public CQuery<T> skip(int n) {
+        return new CQBounded<>(this, n, Integer.MAX_VALUE);
+    }
+    
+    @Override
+    public CQuery<T> slice(int begin, int end) {
+        return new CQBounded<>(this, begin, end-begin);
+    }
+    
+    @Override
+    public final <K> Map<K, T> group(Function<? super T, ? extends K> key) {
+        return stream().collect(Collectors.toMap(key, v -> v));
+    }
+
+    @Override
+    public final <K, V> Map<K, V> group(Function<? super T, ? extends K> key, Function<? super T, ? extends V> value) {
+        return stream().collect(Collectors.toMap(key, value));
+    }
+
+    @Override
+    public final boolean isEmpty() {
+        return !iterator().hasNext();
+    }
+
+    @Override
+    public final CQuery<T> filter(Predicate<? super T> p) {
+        return new CQIterable<>(() -> IteratorUtils.filter(iterator(), p));
+    }
+
+    @Override
+    public final <R> CQuery<R> map(Function<? super T, ? extends R> f) {
+        return new CQIterable<>(() -> IteratorUtils.map(iterator(), f));
+    }
+    
+    @Override
+    public final <R> CQuery<R> imap(EachFunction<? super T, ? extends R> f) {
+        return new CQIterable<>(() -> IteratorUtils.imap(iterator(), f));
+    }
+
+    @Override
+    public final <R> CQuery<R> unfold(Function<? super T, CQuery<R>> f) {
+        return new CQIterable<>(() -> IteratorUtils.flat(IteratorUtils.map(iterator(), (v) -> f.apply(v).iterator())));
+    }
+
+    @Override
+    public <R> CQuery<R> split(Function<? super T, R[]> f) {
+        return unfold(v -> CQueryBuilder.fromArray(f.apply(v)) );
+    }
+
+    @Override
+    public final T fold(T identity, BinaryOperator<T> accumulator) {
+        Iterator<T> i = iterator();
+        return i.hasNext() ? Fold.apply(i, accumulator::apply) : identity;
+    }
+
+    @Override
+    public final T fold(BinaryOperator<T> accumulator) {
+        return fold(null, accumulator);
+    }
+
+    @Override
+    public final T min(Comparator<? super T> cmp) {
+        return fold((a, b) -> cmp.compare(a, b) < 0 ? a : b);
+    }
+
+    @Override
+    public final T max(Comparator<? super T> cmp) {
+        return fold((a, b) -> cmp.compare(a, b) > 0 ? a : b);
+    }
+
+    @Override
+    public final T first() {
+        return IteratorUtils.first(iterator());
+    }
+
+    @Override
+    public final T last() {
+        return IteratorUtils.last(iterator());
+    }
+
+    @Override
+    public final CQuery<T> distinct() {
+        return new CQCollection<>(() -> new HashSet<>(iterator()));
+    }
+
+    @Override
+    public final CQuery<T> distinct(HashFunction<T> eq) {
+        return new CQCollection<>(() -> new CustomSet<>(iterator(), eq));
+    }
+
+    @Override
+    public final CQuery<T> distinct(Comparator<? super T> cmp) {
+        return new CQCollection<>(() -> new RBTreeSet<>(iterator(), cmp));
+    }
+
+    @Override
+    public final CQuery<T> sort() {
+        return new CQCollection<>(() -> {
+            List<T> list = list();
+            ArraySort.mergeSort(list);
+            return list;
+        });
+    }
+
+    @Override
+    public final CQuery<T> sort(Comparator<? super T> cmp) {
+        return new CQCollection<>(() -> {
+            List<T> list = list();
+            ArraySort.mergeSort(list, cmp);
+            return list;
+        });
+    }
+
+    @Override
+    public final void each(Consumer<? super T> consumer) {
+        stream().forEach(consumer);
+    }
+
+    @Override
+    public void into(Collection<? super T> collection) {
+        stream().forEach(collection::add);
+    }
+
+    @Override
+    public final boolean matchAny(Predicate<? super T> predicate) {
+        return stream().anyMatch(predicate);
+    }
+
+    @Override
+    public final boolean matchAll(Predicate<? super T> predicate) {
+        return stream().allMatch(predicate);
+    }
+
+    @Override
+    public final boolean matchNone(Predicate<? super T> predicate) {
+        return stream().noneMatch(predicate);
+    }
+    
+    protected static class CQCollection<T> extends CQueryAbstract<T> {
+        
+        private final Supplier<Collection<T>> source;
+
+        public CQCollection(Supplier<Collection<T>> source) {
+            this.source = source;
+        }
+        
+        public CQCollection(Collection<T> source) {
+            this(() -> source);
+        }
+
+        @Override
+        public Iterator<T> iterator() {
+            return source.get().iterator();
+        }
+
+        @Override
+        public Spliterator<T> spliterator() {
+            return source.get().spliterator();
+        }
+
+        @Override
+        public Stream<T> stream() {
+            return source.get().stream();
+        }
+
+        @Override
+        public int size() {
+            return source.get().size();
+        }
+       
+    }
+
+    protected static class CQArray<T> extends CQueryAbstract<T> {
+        
+        private final Supplier<T[]> source;
+        private final int offset;
+        private final int limit;
+        
+        public CQArray(Supplier<T[]> source) {
+            this(source, 0, Integer.MAX_VALUE);
+        }
+        
+        public CQArray(Supplier<T[]> source, int offset, int limit) {
+            this.source = source;
+            this.offset = offset;
+            this.limit = limit;
+        }
+        
+        public CQArray(T[] source) {
+            this(source, 0, source.length);
+        }
+        
+        public CQArray(T[] source, int offset, int limit) {
+            this(() -> source, offset,limit);
+        }
+
+        @Override
+        public Iterator<T> iterator() {
+            T[] array = source.get();
+            return ArrayUtils.iterator(array, offset, Math.min(array.length,offset+limit));
+        }
+
+        @Override
+        public Spliterator<T> spliterator() {
+            T[] array = source.get();
+            return Arrays.spliterator(array, offset, Math.min(array.length,offset+limit));
+        }
+
+        @Override
+        public Stream<T> stream() {
+            T[] array = source.get();
+            return Arrays.stream(array, offset, Math.min(array.length,offset+limit));
+        }
+
+        @Override
+        public int size() {
+            return Math.min(limit, source.get().length);
+        }
+        
+        @Override
+        public CQuery<T> limit(int n) {
+            return new CQArray<>(source, offset, Math.min(limit, n));
+        }
+
+        @Override
+        public CQuery<T> skip(int n) {
+            return new CQArray<>(source, offset+n, limit);
+        }
+        
+    }
+        
+    protected static class CQIterable<T> extends CQueryAbstract<T> {
+        
+        private final Supplier<Iterable<T>> source;
+
+        public CQIterable(Supplier<Iterable<T>> source) {
+            this.source = source;
+        }
+        
+        public CQIterable(Iterable<T> source) {
+            this(() -> source);
+        }
+
+        @Override
+        public Iterator<T> iterator() {
+            return source.get().iterator();
+        }
+
+        @Override
+        public Spliterator<T> spliterator() {
+            return source.get().spliterator();
+        }
+
+        @Override
+        public Stream<T> stream() {
+            return StreamSupport.stream(source.get().spliterator(), false);
+        }
+
+        @Override
+        public int size() {
+            return IteratorUtils.size(source.get().iterator());
+        }
+       
+    }
+    
+    protected static class CQQuery<T> extends CQueryAbstract<T> {
+        
+        private final Supplier<CQuery<T>> source;
+
+        public CQQuery(Supplier<CQuery<T>> source) {
+            this.source = source;
+        }
+
+        @Override
+        public Iterator<T> iterator() {
+            return source.get().iterator();
+        }
+
+        @Override
+        public Spliterator<T> spliterator() {
+            return source.get().spliterator();
+        }
+
+        @Override
+        public Stream<T> stream() {
+            return source.get().stream();
+        }
+
+        @Override
+        public int size() {
+            return source.get().size();
+        }
+       
+    }
+    
+    protected static class CQBounded<T> extends CQueryAbstract<T> {
+        
+        private final CQuery<T> stream;
+        private final int begin;
+        private final int size;
+
+        public CQBounded(CQuery<T> stream, int begin, int size) {
+            this.stream = stream;
+            this.begin = begin;
+            this.size = size;
+        }
+        
+        @Override
+        public CQuery<T> limit(int n) {
+            return new CQBounded<>(stream, begin, Math.min(n, size));
+        }
+
+        @Override
+        public CQuery<T> skip(int n) {
+            return new CQBounded<>(stream, begin+n, size);
+        }
+
+        @Override
+        public Iterator<T> iterator() {
+            Iterator<T> i = stream.iterator();
+            IteratorUtils.next(i, begin);
+            return new BIterator<>(i, size);
+        }
+
+        @Override
+        public Spliterator<T> spliterator() {
+            return stream().spliterator();
+        }
+
+        @Override
+        public Stream<T> stream() {
+            return stream.stream().skip(begin).limit(size);
+        }
+
+        @Override
+        public int size() {
+            return Math.min(stream.size(), size);
+        }
+        
+    }
+    
+    private static final class BIterator<T> implements Iterator<T> {
+        
+        private final Iterator<T> src;
+        private final int limit;
+        private int count;
+
+        public BIterator(Iterator<T> src, int limit) {
+            this.src = src;
+            this.limit = limit;
+        }
+
+        @Override
+        public boolean hasNext() {
+            return count<limit && src.hasNext();
+        }
+
+        @Override
+        public T next() {
+            if(count>=limit) {
+                throw new NoSuchElementException();
+            }
+            count++;
+            return src.next();
+        }
+        
+    }
+    
+}

+ 17 - 0
assira/src/main/java/net/ranides/assira/functional/EachFunction.java

@@ -0,0 +1,17 @@
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.functional;
+
+/**
+ *
+ * @author Ranides Atterwim <ranides@gmail.com>
+ */
+public interface EachFunction<U,R> {
+    
+    R apply(int index, U value);
+    
+}

+ 136 - 137
assira/src/main/java/net/ranides/assira/reflection/impl/CDParameters.java

@@ -1,137 +1,136 @@
-/*
- * @author Ranides Atterwim <ranides@gmail.com>
- * @copyright Ranides Atterwim
- * @license WTFPL
- * @url http://ranides.net/projects/assira
- */
-
-package net.ranides.assira.reflection.impl;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-import java.lang.reflect.Parameter;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Arrays;
-
-import net.ranides.asm.ClassReader;
-import net.ranides.asm.ClassVisitor;
-import net.ranides.asm.Label;
-import net.ranides.asm.MethodVisitor;
-import net.ranides.asm.Opcodes;
-import net.ranides.asm.Type;
-import net.ranides.assira.collection.maps.Cache;
-import net.ranides.assira.reflection.util.MemberTraits;
-import net.ranides.assira.trace.ExceptionUtils;
-
-public class CDParameters {
-    
-    private static final Cache<Class<?>, CDParameters> CACHE = new Cache<>();
-    
-    final Map<Constructor<?>,String[]> cParams = new HashMap<>();
-    
-    final Map<Method,String[]> mParams = new HashMap<>();
-    
-    CDParameters(Class<?> clazz) {
-        try {
-            ClassReader reader = reader(clazz);
-            if(null != reader) {
-                PNVisitor visitor = new PNVisitor(clazz);
-                reader.accept(visitor, 0);
-            }
-        } catch (IOException cause) {
-            throw ExceptionUtils.rethrow(cause);
-        }
-    }
-    
-    public static String[] getParams(Method method) {
-        Class<?> type = method.getDeclaringClass();
-        return CACHE.get(type, () -> new CDParameters(type)).mParams.get(method);
-    }
-    
-    public static String[] getParams(Constructor<?> constructor) {
-        Class<?> type = constructor.getDeclaringClass();
-        return CACHE.get(type, () -> new CDParameters(type)).cParams.get(constructor);
-    }
-    
-    static ClassReader reader(Class<?> clazz) throws IOException {
-        ClassLoader cc = clazz.getClassLoader();
-        if(null == cc) {
-            return null;
-        }
-        try (InputStream in = cc.getResourceAsStream(clazz.getName().replace('.', '/') + ".class")) {
-            return new ClassReader(in);
-        }
-    }
-
-    private class PNVisitor extends ClassVisitor {
-        
-        private final Map<String,Method> mMethods = new HashMap<>();
-        private final Map<String,Constructor<?>> mConstructors = new HashMap<>();
-
-        public PNVisitor(Class<?> type) {
-            super(Opcodes.ASM5);
-
-            List<Method> methods = new ArrayList<Method>(Arrays.asList(type.getMethods()));
-            methods.addAll(Arrays.asList(type.getDeclaredMethods()));
-            for (Method method : methods) {
-                mMethods.put(method.getName() + Type.getMethodDescriptor(method), method);
-            }
-            
-            List<Constructor<?>> constructors = new ArrayList<>();
-            constructors.addAll(Arrays.asList(type.getDeclaredConstructors()));
-            for (Constructor<?> constructor : constructors) {
-                Type[] types = new Type[constructor.getParameterTypes().length];
-                for (int j = 0; j < types.length; j++) {
-                    types[j] = Type.getType(constructor.getParameterTypes()[j]);
-                }
-                mConstructors.put(Type.getMethodDescriptor(Type.VOID_TYPE, types), constructor);
-            }
-        }
-
-        public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
-            Constructor<?> constructor = mConstructors.get(desc);
-            if (constructor != null) {
-                String[] names = new String[constructor.getParameterCount()];
-                cParams.put(constructor, names);
-                return new LMVisitor(names, 0);
-            }
-            
-            Method method = mMethods.get(name + desc);
-            if (method != null) {
-                String[] names = new String[method.getParameterCount()];
-                mParams.put(method, names);
-                return new LMVisitor(names, MemberTraits.isStatic(method) ? 0 : 1);
-            }
-            return null;
-       }
-        
-    }
-    
-    @SuppressWarnings("PMD.ArrayIsStoredDirectly")
-    private static class LMVisitor extends MethodVisitor {
-        
-        private final String[] out;
-        private final int offset;
-        
-        public LMVisitor(String[] out, int offset) {
-            super(Opcodes.ASM5);
-            this.out = out;
-            this.offset = offset;
-        }
-        
-        @Override
-        public void visitLocalVariable(String name, String description, String signature, Label start, Label end, int index) {
-            int i = index - offset;
-            if(i>=0 && i < out.length) {
-                out[i] = name;
-            }
-        }
-        
-    };
-}
-
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+
+package net.ranides.assira.reflection.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Arrays;
+
+import net.ranides.asm.ClassReader;
+import net.ranides.asm.ClassVisitor;
+import net.ranides.asm.Label;
+import net.ranides.asm.MethodVisitor;
+import net.ranides.asm.Opcodes;
+import net.ranides.asm.Type;
+import net.ranides.assira.collection.maps.Cache;
+import net.ranides.assira.reflection.util.MemberTraits;
+import net.ranides.assira.trace.ExceptionUtils;
+
+public class CDParameters {
+    
+    private static final Cache<Class<?>, CDParameters> CACHE = new Cache<>();
+    
+    final Map<Constructor<?>,String[]> cParams = new HashMap<>();
+    
+    final Map<Method,String[]> mParams = new HashMap<>();
+    
+    CDParameters(Class<?> clazz) {
+        try {
+            ClassReader reader = reader(clazz);
+            if(null != reader) {
+                PNVisitor visitor = new PNVisitor(clazz);
+                reader.accept(visitor, 0);
+            }
+        } catch (IOException cause) {
+            throw ExceptionUtils.rethrow(cause);
+        }
+    }
+    
+    public static String[] getParams(Method method) {
+        Class<?> type = method.getDeclaringClass();
+        return CACHE.get(type, () -> new CDParameters(type)).mParams.get(method);
+    }
+    
+    public static String[] getParams(Constructor<?> constructor) {
+        Class<?> type = constructor.getDeclaringClass();
+        return CACHE.get(type, () -> new CDParameters(type)).cParams.get(constructor);
+    }
+    
+    static ClassReader reader(Class<?> clazz) throws IOException {
+        ClassLoader cc = clazz.getClassLoader();
+        if(null == cc) {
+            return null;
+        }
+        try (InputStream in = cc.getResourceAsStream(clazz.getName().replace('.', '/') + ".class")) {
+            return new ClassReader(in);
+        }
+    }
+
+    private class PNVisitor extends ClassVisitor {
+        
+        private final Map<String,Method> mMethods = new HashMap<>();
+        private final Map<String,Constructor<?>> mConstructors = new HashMap<>();
+
+        public PNVisitor(Class<?> type) {
+            super(Opcodes.ASM5);
+
+            List<Method> methods = new ArrayList<Method>(Arrays.asList(type.getMethods()));
+            methods.addAll(Arrays.asList(type.getDeclaredMethods()));
+            for (Method method : methods) {
+                mMethods.put(method.getName() + Type.getMethodDescriptor(method), method);
+            }
+            
+            List<Constructor<?>> constructors = new ArrayList<>();
+            constructors.addAll(Arrays.asList(type.getDeclaredConstructors()));
+            for (Constructor<?> constructor : constructors) {
+                Type[] types = new Type[constructor.getParameterTypes().length];
+                for (int j = 0; j < types.length; j++) {
+                    types[j] = Type.getType(constructor.getParameterTypes()[j]);
+                }
+                mConstructors.put(Type.getMethodDescriptor(Type.VOID_TYPE, types), constructor);
+            }
+        }
+
+        public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
+            Constructor<?> constructor = mConstructors.get(desc);
+            if (constructor != null) {
+                String[] names = new String[constructor.getParameterCount()];
+                cParams.put(constructor, names);
+                return new LMVisitor(names, 0);
+            }
+            
+            Method method = mMethods.get(name + desc);
+            if (method != null) {
+                String[] names = new String[method.getParameterCount()];
+                mParams.put(method, names);
+                return new LMVisitor(names, MemberTraits.isStatic(method) ? 0 : 1);
+            }
+            return null;
+       }
+        
+    }
+    
+    @SuppressWarnings("PMD.ArrayIsStoredDirectly")
+    private static class LMVisitor extends MethodVisitor {
+        
+        private final String[] out;
+        private final int offset;
+        
+        public LMVisitor(String[] out, int offset) {
+            super(Opcodes.ASM5);
+            this.out = out;
+            this.offset = offset;
+        }
+        
+        @Override
+        public void visitLocalVariable(String name, String description, String signature, Label start, Label end, int index) {
+            int i = index - offset;
+            if(i>=0 && i < out.length) {
+                out[i] = name;
+            }
+        }
+        
+    };
+}
+

+ 47 - 47
assira/src/main/java/net/ranides/assira/reflection/impl/FArgument.java

@@ -1,47 +1,47 @@
-/*
- * @author Ranides Atterwim <ranides@gmail.com>
- * @copyright Ranides Atterwim
- * @license WTFPL
- * @url http://ranides.net/projects/assira
- */
-
-package net.ranides.assira.reflection.impl;
-
-import java.lang.reflect.Parameter;
-import java.util.Map;
-import net.ranides.assira.reflection.IArgument;
-import net.ranides.assira.reflection.IClass;
-import net.ranides.assira.reflection.IContext;
-import net.ranides.assira.reflection.IMethod;
-
-/**
- *
- * @author Ranides Atterwim <ranides@gmail.com>
- */
-public final class FArgument {
-    
-    private FArgument() {
-        /* utility class */
-    }
-
-    public static CArgument newArgument(String name, IClass type) {
-        return new CArgument(name, type);
-    }
-    
-    public static CArgument newArgument(Class<?> type) {
-        return newArgument(null, IClass.typeinfo(type));
-    }
-
-    public static CArgument newArgument(IClass type) {
-        return newArgument(null, type);
-    }
-
-    public static CArgument newArgument(Map.Entry<String, IClass> entry) {
-        return newArgument(entry.getKey(), entry.getValue());
-    }
-    
-    public static IArgument newArgument(IContext context, IMethod parent, Parameter param) {
-        return new RArgument(context, parent, param);
-    }
-    
-}
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+
+package net.ranides.assira.reflection.impl;
+
+import java.lang.reflect.Parameter;
+import java.util.Map;
+import net.ranides.assira.reflection.IArgument;
+import net.ranides.assira.reflection.IClass;
+import net.ranides.assira.reflection.IContext;
+import net.ranides.assira.reflection.IMethod;
+
+/**
+ *
+ * @author Ranides Atterwim <ranides@gmail.com>
+ */
+public final class FArgument {
+    
+    private FArgument() {
+        /* utility class */
+    }
+
+    public static CArgument newArgument(String name, IClass type) {
+        return new CArgument(name, type);
+    }
+    
+    public static CArgument newArgument(Class<?> type) {
+        return newArgument(null, IClass.typeinfo(type));
+    }
+
+    public static CArgument newArgument(IClass type) {
+        return newArgument(null, type);
+    }
+
+    public static CArgument newArgument(Map.Entry<String, IClass> entry) {
+        return newArgument(entry.getKey(), entry.getValue());
+    }
+    
+    public static IArgument newArgument(IContext context, IMethod parent, Parameter param, int index) {
+        return new RArgument(context, parent, param, index);
+    }
+    
+}

+ 104 - 106
assira/src/main/java/net/ranides/assira/reflection/impl/RArgument.java

@@ -1,106 +1,104 @@
-/*
- * @author Ranides Atterwim <ranides@gmail.com>
- * @copyright Ranides Atterwim
- * @license WTFPL
- * @url http://ranides.net/projects/assira
- */
-package net.ranides.assira.reflection.impl;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Parameter;
-import java.util.Set;
-import net.ranides.assira.reflection.*;
-import net.ranides.assira.collection.query.CQueryBuilder;
-
-/**
- *
- * @author Ranides Atterwim <ranides@gmail.com>
- */
-public class RArgument implements IArgument {
-
-    private final IContext context;
-    
-    private final IMethod parent;
-    
-    private final Parameter param;
-    
-//    private final int index;
-
-    RArgument(IContext context, IMethod parent, Parameter param) {
-        this.parent = parent;
-        this.param = param;
-        this.context = context;
-    }
-
-    @Override
-    public IContext context() {
-        return context;
-    }
-
-    @Override
-    public IArguments collect() {
-        return FElements.newArguments(AHints.EMPTY, 1, CQueryBuilder.of(this));
-    }
-
-    @Override
-    public Parameter reflective() {
-        return param;
-    }
-
-    @Override
-    public IClass type() {
-        final IContext c = context();
-        return FClass.newClass(c, param.getParameterizedType(), param.getAnnotatedType());
-    }
-
-    @Override
-    public String name() {
-        if(!param.isNamePresent()) {
-            // @todo (assira #1) reflective: extract name from debug-info
-            //
-            // DEBUG info za pomocą ASM
-            // http://stackoverflow.com/questions/2729580/how-to-get-the-parameter-names-of-an-objects-constructors-reflection
-            //
-            // Własny kod możemy też traktować za pomocą APT
-            // https://community.oracle.com/blogs/emcmanus/2006/06/13/using-annotation-processors-save-method-parameter-names
-            throw new UnsupportedOperationException("You have to compile class with -parameters switch");
-        }
-        return param.getName();
-    }
-
-    @Override
-    public IMethod parent() {
-        return parent;
-    }
-
-    @Override
-    public Set<IAttribute> attributes() {
-        return IAttribute.resolve(param);
-    }
-
-    @Override
-    public IAnnotations annotations() {
-        return FElements.newAnnotations(AHints.EMPTY, CQueryBuilder.fromArray(param.getAnnotations()));
-    }
-    
-    @Override
-    public <A extends Annotation> A annotation(Class<A> type) {
-        return annotations().first(type);
-    }
-
-    @Override
-    public final boolean equals(Object object) {
-        return (object instanceof IArgument) && ((IArgument)object).type().equals(type());
-    }
-    
-    @Override
-    public final int hashCode() {
-        return this.type().hashCode();
-    }
-
-    @Override
-    public String toString() {
-        return type() + " " + param.getName();
-    }
-    
-}
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.reflection.impl;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Parameter;
+import java.util.Set;
+import net.ranides.assira.reflection.*;
+import net.ranides.assira.collection.query.CQueryBuilder;
+
+/**
+ *
+ * @author Ranides Atterwim <ranides@gmail.com>
+ */
+public class RArgument implements IArgument {
+
+    private final IContext context;
+    
+    private final IMethod parent;
+    
+    private final Parameter param;
+    
+    private final int index;
+
+    RArgument(IContext context, IMethod parent, Parameter param, int index) {
+        this.parent = parent;
+        this.param = param;
+        this.context = context;
+        this.index = index;
+    }
+
+    @Override
+    public IContext context() {
+        return context;
+    }
+
+    @Override
+    public IArguments collect() {
+        return FElements.newArguments(AHints.EMPTY, 1, CQueryBuilder.of(this));
+    }
+
+    @Override
+    public Parameter reflective() {
+        return param;
+    }
+
+    @Override
+    public IClass type() {
+        final IContext c = context();
+        return FClass.newClass(c, param.getParameterizedType(), param.getAnnotatedType());
+    }
+
+    @Override
+    public String name() {
+        if(!param.isNamePresent()) {
+            String[] names = CDParameters.getParams(parent.reflective());
+            if(null == names) {
+                throw new UnsupportedOperationException("You have to compile class with -parameters or -g switch");
+            }
+            return names[index];
+        }
+        return param.getName();
+    }
+
+    @Override
+    public IMethod parent() {
+        return parent;
+    }
+
+    @Override
+    public Set<IAttribute> attributes() {
+        return IAttribute.resolve(param);
+    }
+
+    @Override
+    public IAnnotations annotations() {
+        return FElements.newAnnotations(AHints.EMPTY, CQueryBuilder.fromArray(param.getAnnotations()));
+    }
+    
+    @Override
+    public <A extends Annotation> A annotation(Class<A> type) {
+        return annotations().first(type);
+    }
+
+    @Override
+    public final boolean equals(Object object) {
+        return (object instanceof IArgument) && ((IArgument)object).type().equals(type());
+    }
+    
+    @Override
+    public final int hashCode() {
+        return this.type().hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return type() + " " + param.getName();
+    }
+    
+}

+ 133 - 129
assira/src/main/java/net/ranides/assira/reflection/impl/RConstructor.java

@@ -1,129 +1,133 @@
-/*
- * @author Ranides Atterwim <ranides@gmail.com>
- * @copyright Ranides Atterwim
- * @license WTFPL
- * @url http://ranides.net/projects/assira
- */
-
-package net.ranides.assira.reflection.impl;
-
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Set;
-import java.util.function.Supplier;
-import net.ranides.assira.collection.lists.ListUtils;
-import net.ranides.assira.generic.LazyReference;
-import net.ranides.assira.trace.ExceptionUtils;
-import net.ranides.assira.reflection.util.MethodUtils;
-import net.ranides.assira.reflection.util.ReflectUtils;
-import net.ranides.assira.reflection.*;
-import net.ranides.assira.collection.query.CQueryBuilder;
-
-/**
- *
- * @author Ranides Atterwim <ranides@gmail.com>
- */
-public final class RConstructor extends AMethod {
-
-    private final Constructor<?> method;
-    private final Supplier<MethodHandle> handle;
-
-	RConstructor(IContext context, Constructor<?> method) {
-        super(context);
-		ReflectUtils.access(method);
-		this.method = method;
-        this.handle = LazyReference.concurrent(() -> {
-            try {
-                return MethodHandles.lookup().unreflectConstructor(method);
-            } catch (IllegalAccessException cause) {
-                throw ExceptionUtils.rethrow(cause);
-            }
-        });
-	}
-    
-	@Override
-	public List<IClass> params() {
-        IContext c = context();
-        return ListUtils.map(Arrays.asList(method.getTypeParameters()), c::typeinfo);
-	}
-
-	@Override
-	public IClass returns() {
-        return parent();
-	}
-
-	@Override
-	public IArguments arguments() {
-        IContext c = context();
-        return FElements.newArguments(AHints.EMPTY, method.getParameterCount(), CQueryBuilder.fromArray(method.getParameters()).map(a -> FArgument.newArgument(c, this, a)));
-	}
-
-	@Override
-	public IClass parent() {
-        return context().typeinfo(method.getDeclaringClass());
-	}
-
-	@Override
-	public Object apply() {
-		return MethodUtils.invoke(method);
-	}
-
-	@Override
-	public Object apply(Object that) {
-        if(that != null) {
-            throw new IllegalArgumentException("constructors doesn't support 'this'");
-        }
-		return MethodUtils.invoke(method);
-	}
-
-	@Override
-	public Object apply(Object that, Object... arguments) {
-        if(that != null) {
-            throw new IllegalArgumentException("constructors doesn't support 'this'");
-        }
-		return MethodUtils.invoke(method, arguments);
-	}
-
-    @Override
-    public Object call(Object... arguments) {
-        try {
-            return handle.get().invokeWithArguments(arguments);
-        } catch (Throwable cause) { // NOPMD rethrow idiom
-            throw ExceptionUtils.rethrow(cause);
-        }
-    }
-    
-	@Override
-	public Method reflective() {
-        throw new UnsupportedOperationException();
-	}
-
-	@Override
-	public MethodHandle handle() {
-        try {
-            return MethodHandles.lookup().unreflectConstructor(method);
-        } catch (IllegalAccessException cause) {
-            throw ExceptionUtils.rethrow(cause);
-        }
-	}
-
-	@Override
-	public String name() {
-        return method.getName();
-	}
-
-	@Override
-	public Set<IAttribute> attributes() {
-        return IAttribute.resolve(method);
-	}
-
-	@Override
-	public IAnnotations annotations() {
-        return FElements.newAnnotations(AHints.EMPTY, CQueryBuilder.fromArray(method.getAnnotations()));
-	}
-
-}
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+
+package net.ranides.assira.reflection.impl;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Supplier;
+import net.ranides.assira.collection.lists.ListUtils;
+import net.ranides.assira.generic.LazyReference;
+import net.ranides.assira.trace.ExceptionUtils;
+import net.ranides.assira.reflection.util.MethodUtils;
+import net.ranides.assira.reflection.util.ReflectUtils;
+import net.ranides.assira.reflection.*;
+import net.ranides.assira.collection.query.CQueryBuilder;
+
+/**
+ *
+ * @author Ranides Atterwim <ranides@gmail.com>
+ */
+public final class RConstructor extends AMethod {
+
+    private final Constructor<?> method;
+    private final Supplier<MethodHandle> handle;
+
+	RConstructor(IContext context, Constructor<?> method) {
+        super(context);
+		ReflectUtils.access(method);
+		this.method = method;
+        this.handle = LazyReference.concurrent(() -> {
+            try {
+                return MethodHandles.lookup().unreflectConstructor(method);
+            } catch (IllegalAccessException cause) {
+                throw ExceptionUtils.rethrow(cause);
+            }
+        });
+	}
+    
+	@Override
+	public List<IClass> params() {
+        IContext c = context();
+        return ListUtils.map(Arrays.asList(method.getTypeParameters()), c::typeinfo);
+	}
+
+	@Override
+	public IClass returns() {
+        return parent();
+	}
+
+	@Override
+	public IArguments arguments() {
+        IContext c = context();
+        return FElements.newArguments(
+            AHints.EMPTY, 
+            method.getParameterCount(), 
+            CQueryBuilder.fromArray(method.getParameters()).imap((i,v)-> FArgument.newArgument(c, this, v, i))
+        );
+	}
+
+	@Override
+	public IClass parent() {
+        return context().typeinfo(method.getDeclaringClass());
+	}
+
+	@Override
+	public Object apply() {
+		return MethodUtils.invoke(method);
+	}
+
+	@Override
+	public Object apply(Object that) {
+        if(that != null) {
+            throw new IllegalArgumentException("constructors doesn't support 'this'");
+        }
+		return MethodUtils.invoke(method);
+	}
+
+	@Override
+	public Object apply(Object that, Object... arguments) {
+        if(that != null) {
+            throw new IllegalArgumentException("constructors doesn't support 'this'");
+        }
+		return MethodUtils.invoke(method, arguments);
+	}
+
+    @Override
+    public Object call(Object... arguments) {
+        try {
+            return handle.get().invokeWithArguments(arguments);
+        } catch (Throwable cause) { // NOPMD rethrow idiom
+            throw ExceptionUtils.rethrow(cause);
+        }
+    }
+    
+	@Override
+	public Method reflective() {
+        throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public MethodHandle handle() {
+        try {
+            return MethodHandles.lookup().unreflectConstructor(method);
+        } catch (IllegalAccessException cause) {
+            throw ExceptionUtils.rethrow(cause);
+        }
+	}
+
+	@Override
+	public String name() {
+        return method.getName();
+	}
+
+	@Override
+	public Set<IAttribute> attributes() {
+        return IAttribute.resolve(method);
+	}
+
+	@Override
+	public IAnnotations annotations() {
+        return FElements.newAnnotations(AHints.EMPTY, CQueryBuilder.fromArray(method.getAnnotations()));
+	}
+
+}

+ 130 - 126
assira/src/main/java/net/ranides/assira/reflection/impl/RMethod.java

@@ -1,126 +1,130 @@
-/*
- * @author Ranides Atterwim <ranides@gmail.com>
- * @copyright Ranides Atterwim
- * @license WTFPL
- * @url http://ranides.net/projects/assira
- */
-
-package net.ranides.assira.reflection.impl;
-
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.reflect.Method;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Set;
-import java.util.function.Supplier;
-import net.ranides.assira.collection.lists.ListUtils;
-import net.ranides.assira.generic.LazyReference;
-import net.ranides.assira.reflection.*;
-import net.ranides.assira.reflection.util.MethodUtils;
-import net.ranides.assira.reflection.util.ReflectUtils;
-import net.ranides.assira.trace.ExceptionUtils;
-import net.ranides.assira.collection.query.CQueryBuilder;
-
-/**
- *
- * @author Ranides Atterwim <ranides@gmail.com>
- */
-public class RMethod extends AMethod implements IMethod {
-
-	private final boolean declared;
-	private final Method method;
-	private final Supplier<MethodHandle> handle;
-
-    RMethod(boolean declared, IContext context, Method method, Object that) {
-        super(context);
-        ReflectUtils.access(method);
-		this.method = method;
-        this.handle = LazyReference.concurrent(() -> {
-            try {
-                MethodHandle m = MethodHandles.lookup().unreflect(method);
-                return null!=that ? m.bindTo(that) : m;
-            } catch (IllegalAccessException cause) {
-                throw ExceptionUtils.rethrow(cause);
-            }
-        });
-        this.declared = declared;
-	}
-    
-	@Override
-	public List<IClass> params() {
-        IContext c = context();
-        return ListUtils.map(Arrays.asList(method.getTypeParameters()), c::typeinfo);
-	}
-
-	@Override
-	public IClass returns() {
-        IContext c = context();
-        return FClass.newClass(c, method.getGenericReturnType(), method.getAnnotatedReturnType());
-	}
-
-	@Override
-	public IArguments arguments() {
-        IContext c = context();
-        return FElements.newArguments(AHints.EMPTY, method.getParameterCount(), CQueryBuilder.fromArray(method.getParameters()).map(a -> FArgument.newArgument(c, this, a)));
-	}
-    
-	@Override
-	public IClass parent() {
-		return context().typeinfo(method.getDeclaringClass());
-	}
-
-	@Override
-	public Object apply() {
-		return MethodUtils.invoke(method, null);
-	}
-
-	@Override
-	public Object apply(Object that) {
-		return MethodUtils.invoke(method, that);
-	}
-
-	@Override
-	public Object apply(Object that, Object... arguments) {
-		return MethodUtils.invoke(method, that, arguments);
-	}
-
-    @Override
-    public Object call(Object... arguments) {
-        try {
-            return handle().invokeWithArguments(arguments);
-        } catch (Throwable cause) { // NOPMD rethrow
-            throw ExceptionUtils.rethrow(cause);
-        }
-    }
-
-	@Override
-	public Method reflective() {
-        return method;
-	}
-
-	@Override
-	public MethodHandle handle() {
-        return handle.get();
-	}
-
-	@Override
-	public String name() {
-        return method.getName();
-	}
-
-	@Override
-	public Set<IAttribute> attributes() {
-        Set<IAttribute> attr = IAttribute.resolve(method);
-        if(declared) {
-            attr.add(IAttribute.DECLARED);
-        }
-        return attr;
-	}
-
-	@Override
-	public IAnnotations annotations() {
-		return FElements.newAnnotations(AHints.EMPTY, CQueryBuilder.fromArray(method.getAnnotations()));
-	}
-
-}
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+
+package net.ranides.assira.reflection.impl;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Supplier;
+import net.ranides.assira.collection.lists.ListUtils;
+import net.ranides.assira.generic.LazyReference;
+import net.ranides.assira.reflection.*;
+import net.ranides.assira.reflection.util.MethodUtils;
+import net.ranides.assira.reflection.util.ReflectUtils;
+import net.ranides.assira.trace.ExceptionUtils;
+import net.ranides.assira.collection.query.CQueryBuilder;
+
+/**
+ *
+ * @author Ranides Atterwim <ranides@gmail.com>
+ */
+public class RMethod extends AMethod implements IMethod {
+
+	private final boolean declared;
+	private final Method method;
+	private final Supplier<MethodHandle> handle;
+
+    RMethod(boolean declared, IContext context, Method method, Object that) {
+        super(context);
+        ReflectUtils.access(method);
+		this.method = method;
+        this.handle = LazyReference.concurrent(() -> {
+            try {
+                MethodHandle m = MethodHandles.lookup().unreflect(method);
+                return null!=that ? m.bindTo(that) : m;
+            } catch (IllegalAccessException cause) {
+                throw ExceptionUtils.rethrow(cause);
+            }
+        });
+        this.declared = declared;
+	}
+    
+	@Override
+	public List<IClass> params() {
+        IContext c = context();
+        return ListUtils.map(Arrays.asList(method.getTypeParameters()), c::typeinfo);
+	}
+
+	@Override
+	public IClass returns() {
+        IContext c = context();
+        return FClass.newClass(c, method.getGenericReturnType(), method.getAnnotatedReturnType());
+	}
+
+	@Override
+	public IArguments arguments() {
+        IContext c = context();
+        return FElements.newArguments(
+            AHints.EMPTY, 
+            method.getParameterCount(), 
+            CQueryBuilder.fromArray(method.getParameters()).imap((i,v)-> FArgument.newArgument(c, this, v, i))
+        );
+	}
+    
+	@Override
+	public IClass parent() {
+		return context().typeinfo(method.getDeclaringClass());
+	}
+
+	@Override
+	public Object apply() {
+		return MethodUtils.invoke(method, null);
+	}
+
+	@Override
+	public Object apply(Object that) {
+		return MethodUtils.invoke(method, that);
+	}
+
+	@Override
+	public Object apply(Object that, Object... arguments) {
+		return MethodUtils.invoke(method, that, arguments);
+	}
+
+    @Override
+    public Object call(Object... arguments) {
+        try {
+            return handle().invokeWithArguments(arguments);
+        } catch (Throwable cause) { // NOPMD rethrow
+            throw ExceptionUtils.rethrow(cause);
+        }
+    }
+
+	@Override
+	public Method reflective() {
+        return method;
+	}
+
+	@Override
+	public MethodHandle handle() {
+        return handle.get();
+	}
+
+	@Override
+	public String name() {
+        return method.getName();
+	}
+
+	@Override
+	public Set<IAttribute> attributes() {
+        Set<IAttribute> attr = IAttribute.resolve(method);
+        if(declared) {
+            attr.add(IAttribute.DECLARED);
+        }
+        return attr;
+	}
+
+	@Override
+	public IAnnotations annotations() {
+		return FElements.newAnnotations(AHints.EMPTY, CQueryBuilder.fromArray(method.getAnnotations()));
+	}
+
+}

+ 155 - 155
assira/src/test/java/net/ranides/assira/xml/XMLQueryTest.java

@@ -1,155 +1,155 @@
-/*
- * @author Ranides Atterwim <ranides@gmail.com>
- * @copyright Ranides Atterwim
- * @license WTFPL
- * @url http://ranides.net/projects/assira
- */
-package net.ranides.assira.xml;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.List;
-import javax.xml.transform.TransformerConfigurationException;
-import net.ranides.assira.TestFiles;
-import net.ranides.assira.collection.maps.MultiMap;
-import static net.ranides.assira.junit.NewAssert.*;
-import static net.ranides.assira.xml.XMLElement.$;
-import org.junit.Test;
-
-/**
- *
- * @author Ranides Atterwim <ranides@gmail.com>
- */
-@SuppressWarnings("PMD.AvoidDuplicateLiterals")
-public class XMLQueryTest {
-    
-    @Test
-    public void testRoot() throws IOException {
-        XMLElement doc = $(TestFiles.XML_INPUT);
-        
-        List<String> root = Arrays.asList("info", "info", "params", "#comment", "ccms");
-        List<String> body = Arrays.asList("#text", "users", "#text", "data", "#text", "configuration", "#text");
-        List<String> items = Arrays.asList("users", "data", "configuration");
-        
-        assertEquals(root.subList(0, 5), doc.children().names());
-        assertEquals(root.subList(0, 3), doc.children(XMLType.PROCESSING).names());
-        assertEquals(root.subList(4, 5), doc.children(XMLType.ELEMENT).names());
-        assertEquals(" @author Ranides Atterwim <ranides@gmail.com> ", doc.children(XMLType.COMMENT).text());
-        
-        assertEquals(body, doc.root().children().names());
-        assertEquals(items, doc.root().children(XMLType.ELEMENT).names());
-        assertEquals(items, doc.normalize().root().children().names());
-        
-        assertEquals("ccms", doc.root().name());
-    }
-    
-    @Test
-    public void testFindStar() throws IOException {
-        XMLElement doc = $(TestFiles.XML_INPUT);
-        
-        assertEquals(41, doc.find("*").size());
-        assertEquals(40, doc.root().find("*").size());
-        
-        assertEquals(27, doc.find("users *").size());
-        assertEquals(27, doc.find("users").find("*").size());
-        assertEquals(Arrays.asList("login", "password", "name", "mail", "mail"), doc.find("? //user[1]").find("*").names());
-    }
-    
-    @Test
-    public void testXPath() throws IOException {
-        XMLElement doc = $(TestFiles.XML_INPUT);
-        
-        List<String> exp1 = Arrays.asList("101", "102", "103", "104", "105");
-        List<String> exp2 = Arrays.asList();
-
-        assertEquals(exp1, doc.find("? //users/user/@id").texts());
-        assertEquals(exp2, doc.find("? /users/user/@id").texts());
-        assertEquals(exp2, doc.find("? users/user/@id").texts());
-        assertEquals(exp1, doc.find("? ccms/users/user/@id").texts());
-        assertEquals(exp1, doc.find("? /ccms/users/user/@id").texts());
-    }
-    
-    @Test
-    public void testCSS() throws IOException {
-        XMLElement doc = $(TestFiles.XML_INPUT);
-        
-        XMLElements css = doc.find("users user[active='true']").attrs("id");
-
-        assertEquals(Arrays.asList("101", "102", "105"), css.texts());
-        
-        List<Integer> numbers = Arrays.asList(101, 105);
-        
-        assertEquals(numbers, css.stream(this::$int).filter(v -> 1 == v%2).list());
-    }
-
-    private int $int(XMLElement n) throws NumberFormatException {
-        return Integer.parseInt(n.content());
-    }
-    
-    @Test
-    public void testChildren() throws IOException {
-        XMLElement doc = $(TestFiles.XML_INPUT);
-        
-        assertFalse(doc.children("xxx").matches());
-        assertFalse(doc.children("users").matches());
-        assertFalse(doc.children(" users").matches());
-        assertFalse(doc.children("users user").matches());
-        
-        assertFalse(doc.root().children("xxx").matches());
-        assertTrue(doc.root().children("users").matches());
-        assertTrue(doc.root().children(" users").matches());
-        assertFalse(doc.root().children("users user").matches());
-        
-        assertEquals(0, doc.root().children("xxx").size());
-        assertEquals(1, doc.root().children("users").size());
-        assertEquals(1, doc.root().children(" users").size());
-        assertEquals(0, doc.root().children("users user").size());
-        
-        assertEquals(0, doc.find("xxx").size());
-        assertEquals(1, doc.find("users").size());
-        assertEquals(1, doc.find(" users").size());
-        assertEquals(5, doc.find("users user").size());
-    }
-        
-    
-    @Test
-    public void testAttrMap() throws IOException {
-        XMLElement doc = $(TestFiles.XML_INPUT);
-        
-        assertTrue(doc.children("xxx").attrs().map().isEmpty());
-        assertTrue(doc.find("users item").attrs().map().isEmpty());
-        assertTrue(doc.find("users user login").attrs().map().isEmpty());
-
-        MultiMap<String, String> attr = doc.find("users user").attrs().map();
-        
-        List<String> exp1 = Arrays.asList("101", "102", "103", "104", "105");
-        List<String> exp2 = Arrays.asList("5461", "8721", "7542", "1952", "3773");
-        List<String> exp3 = Arrays.asList("false","true");
-        
-        assertEquivalent(exp1, attr.getAll("id"));
-        assertEquivalent(exp2, attr.getAll("uid"));
-        assertEquivalent(exp3, attr.getAll("active"));
-    }
-    
-    @Test
-    public void testAttributes() throws IOException, TransformerConfigurationException {
-        XMLElement doc = $(TestFiles.XML_INPUT);
-        
-        XMLElement attr1 = doc.find("users user").attrs("id").first();
-        XMLElement attr2 = doc.find("users user").attrs().first("id");
-        
-        assertSame(attr1.node(), attr2.node());
-        
-        assertEquals("id", attr1.name());
-        assertEquals("101", attr1.content());
-        assertEquals("101", attr1.text());
-        assertEquals("101", attr1.get());
-        assertEquals("user", attr1.parent().name());
-        assertEquals(Arrays.asList(), attr1.attrs().names());
-        assertEquivalent(Arrays.asList("login", "password", "name", "mail", "mail"), attr1.parent().children(XMLType.ELEMENT).names());
-        assertEquivalent(Arrays.asList("id", "uid", "active", "public"), attr1.parent().attrs().names());
-        assertEquals(Arrays.asList("user", "users", "ccms", "#document"), attr1.parents().names());
-    }
-    
-}
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.xml;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import javax.xml.transform.TransformerConfigurationException;
+import net.ranides.assira.TestFiles;
+import net.ranides.assira.collection.maps.MultiMap;
+import static net.ranides.assira.junit.NewAssert.*;
+import static net.ranides.assira.xml.XMLElement.$;
+import org.junit.Test;
+
+/**
+ *
+ * @author Ranides Atterwim <ranides@gmail.com>
+ */
+@SuppressWarnings("PMD.AvoidDuplicateLiterals")
+public class XMLQueryTest {
+    
+    @Test
+    public void testRoot() throws IOException {
+        XMLElement doc = $(TestFiles.XML_INPUT);
+        
+        List<String> root = Arrays.asList("info", "info", "params", "#comment", "ccms");
+        List<String> body = Arrays.asList("#text", "users", "#text", "data", "#text", "configuration", "#text");
+        List<String> items = Arrays.asList("users", "data", "configuration");
+        
+        assertEquals(root.subList(0, 5), doc.children().names());
+        assertEquals(root.subList(0, 3), doc.children(XMLType.PROCESSING).names());
+        assertEquals(root.subList(4, 5), doc.children(XMLType.ELEMENT).names());
+        assertEquals(" @author Ranides Atterwim <ranides@gmail.com> ", doc.children(XMLType.COMMENT).text());
+        
+        assertEquals(body, doc.root().children().names());
+        assertEquals(items, doc.root().children(XMLType.ELEMENT).names());
+        assertEquals(items, doc.normalize().root().children().names());
+        
+        assertEquals("ccms", doc.root().name());
+    }
+    
+    @Test
+    public void testFindStar() throws IOException {
+        XMLElement doc = $(TestFiles.XML_INPUT);
+        
+        assertEquals(41, doc.find("*").size());
+        assertEquals(40, doc.root().find("*").size());
+        
+        assertEquals(27, doc.find("users *").size());
+        assertEquals(27, doc.find("users").find("*").size());
+        assertEquals(Arrays.asList("login", "password", "name", "mail", "mail"), doc.find("? //user[1]").find("*").names());
+    }
+    
+    @Test
+    public void testXPath() throws IOException {
+        XMLElement doc = $(TestFiles.XML_INPUT);
+        
+        List<String> exp1 = Arrays.asList("101", "102", "103", "104", "105");
+        List<String> exp2 = Arrays.asList();
+
+        assertEquals(exp1, doc.find("? //users/user/@id").texts());
+        assertEquals(exp2, doc.find("? /users/user/@id").texts());
+        assertEquals(exp2, doc.find("? users/user/@id").texts());
+        assertEquals(exp1, doc.find("? ccms/users/user/@id").texts());
+        assertEquals(exp1, doc.find("? /ccms/users/user/@id").texts());
+    }
+    
+    @Test
+    public void testCSS() throws IOException {
+        XMLElement doc = $(TestFiles.XML_INPUT);
+        
+        XMLElements css = doc.find("users user[active='true']").attrs("id");
+
+        assertEquals(Arrays.asList("101", "102", "105"), css.texts());
+        
+        List<Integer> numbers = Arrays.asList(101, 105);
+        
+        assertEquals(numbers, css.stream(this::$int).filter(v -> 1 == v%2).list());
+    }
+
+    private int $int(XMLElement n) throws NumberFormatException {
+        return Integer.parseInt(n.content());
+    }
+    
+    @Test
+    public void testChildren() throws IOException {
+        XMLElement doc = $(TestFiles.XML_INPUT);
+        
+        assertFalse(doc.children("xxx").matches());
+        assertFalse(doc.children("users").matches());
+        assertFalse(doc.children(" users").matches());
+        assertFalse(doc.children("users user").matches());
+        
+        assertFalse(doc.root().children("xxx").matches());
+        assertTrue(doc.root().children("users").matches());
+        assertTrue(doc.root().children(" users").matches());
+        assertFalse(doc.root().children("users user").matches());
+        
+        assertEquals(0, doc.root().children("xxx").size());
+        assertEquals(1, doc.root().children("users").size());
+        assertEquals(1, doc.root().children(" users").size());
+        assertEquals(0, doc.root().children("users user").size());
+        
+        assertEquals(0, doc.find("xxx").size());
+        assertEquals(1, doc.find("users").size());
+        assertEquals(1, doc.find(" users").size());
+        assertEquals(5, doc.find("users user").size());
+    }
+        
+    
+    @Test
+    public void testAttrMap() throws IOException {
+        XMLElement doc = $(TestFiles.XML_INPUT);
+        
+        assertTrue(doc.children("xxx").attrs().map().isEmpty());
+        assertTrue(doc.find("users item").attrs().map().isEmpty());
+        assertTrue(doc.find("users user login").attrs().map().isEmpty());
+
+        MultiMap<String, String> attr = doc.find("users user").attrs().map();
+        
+        List<String> exp1 = Arrays.asList("101", "102", "103", "104", "105");
+        List<String> exp2 = Arrays.asList("5461", "8721", "7542", "1952", "3773");
+        List<String> exp3 = Arrays.asList("false","true");
+        
+        assertEquivalent(exp1, attr.getAll("id"));
+        assertEquivalent(exp2, attr.getAll("uid"));
+        assertEquivalent(exp3, attr.getAll("active"));
+    }
+    
+    @Test
+    public void testAttributes() throws IOException, TransformerConfigurationException {
+        XMLElement doc = $(TestFiles.XML_INPUT);
+        
+        XMLElement attr1 = doc.find("users user").attrs("id").first();
+        XMLElement attr2 = doc.find("users user").attrs().first("id");
+        
+        assertSame(attr1.node(), attr2.node());
+        
+        assertEquals("id", attr1.name());
+        assertEquals("101", attr1.content());
+        assertEquals("101", attr1.text());
+        assertEquals("101", attr1.get());
+        assertEquals("user", attr1.parent().name());
+        assertEquals(Arrays.asList(), attr1.attrs().names());
+        assertEquivalent(Arrays.asList("login", "password", "name", "mail", "mail"), attr1.parent().children(XMLType.ELEMENT).names());
+        assertEquivalent(Arrays.asList("id", "uid", "active", "public"), attr1.parent().attrs().names());
+        assertEquals(Arrays.asList("user", "users", "ccms", "#document"), attr1.parents().names());
+    }
+    
+}