Browse Source

new: ArrayUtils #append #prepend
new: NativeArrayUtils #append #prepend
change: PathUtils - file extension is defined in different way
new: IExecutable#callThis

Ranides Atterwim 6 năm trước cách đây
mục cha
commit
62dffcd61f

+ 229 - 221
assira/src/main/java/net/ranides/assira/collection/arrays/ArrayUtils.java

@@ -1,221 +1,229 @@
-/*
- * @author Ranides Atterwim <ranides@gmail.com>
- * @copyright Ranides Atterwim
- * @license WTFPL
- * @url http://ranides.net/projects/assira
- */
-package net.ranides.assira.collection.arrays;
-
-import java.lang.reflect.Array;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.ListIterator;
-import java.util.Random;
-import java.util.function.BiPredicate;
-import net.ranides.assira.collection.iterators.IntIterator;
-
-@SuppressWarnings({
-    "PMD.AvoidReassigningParameters"
-})
-public final class ArrayUtils {
-
-    private ArrayUtils() {
-        // utility class
-    }
-    
-    /**
-     * Unwraps an iterator into an array starting at a given offset for a given
-     * number of elements.
-     *
-     * <P>This method iterates over the given type-specific iterator and stores
-     * the elements returned, up to a maximum of
-     * <code>length</code>, in the given array starting at
-     * <code>offset</code>. The number of actually unwrapped elements is
-     * returned (it may be less than
-     * <code>max</code> if the iterator emits less than
-     * <code>max</code> elements).
-     *
-     * @param iterator a type-specific iterator.
-     * @param target an array to contain the output of the iterator.
-     * @param begin the first element of the array to be returned.
-     * @param end the maximum number of elements to collect.
-     * @return the number of elements unwrapped.
-     */
-    public static <A,T> int collect(Iterator<T> iterator, A target, int begin, int end) {
-        if($isint(target)) {
-            return $collect(IntIterator.$wrap(iterator), (int[])target, begin, end);
-        } else {
-            return NativeArrayUtils.collect(iterator, NativeArray.wrap(target), begin, end);
-        }
-    }
-
-    private static <A> boolean $isint(A array) {
-        return null!=array && int[].class.equals(array.getClass());
-    }
-    
-    /**
-     * Unwraps an iterator into an array.
-     *
-     * <P>This method iterates over the given type-specific iterator and stores
-     * the elements returned in the given array. The iteration will stop when
-     * the iterator has no more elements or when the end of the array has been
-     * reached.
-     *
-     * @param iterator a type-specific iterator.
-     * @param target an array to contain the output of the iterator.
-     * @return the number of elements unwrapped.
-     */
-    public static <A,T> int collect(Iterator<T> iterator, A target) {
-        if($isint(target)) {
-            int[] array = (int[])target;
-            return $collect(IntIterator.$wrap(iterator), array, 0, array.length);
-        } else {
-            return NativeArrayUtils.collect(iterator, NativeArray.wrap(target));
-        }
-    }
-    
-    static int $collect(IntIterator iterator, int target[], int begin, int end) {
-        NativeArrayAllocator.ensureFromTo(target.length, begin, end);
-        int j = end;
-        while (j-- != 0 && iterator.hasNext()) {
-            target[begin++] = iterator.nextInt();
-        }
-        return end - j - 1;
-    }
-        
-    /**
-     * Fills the given array with the given value.
-     *
-     * <P>This method uses a backward loop. It is significantly faster than the
-     * corresponding method in {@link java.util.Arrays}.
-     *
-     * @param array an array.
-     * @param value the new value for all elements of the array.
-     */
-    public static <A,T> void fill(A array, T value) {
-        NativeArrayUtils.fill(NativeArray.wrap(array), value);
-    }
-
-    /**
-     * Fills a portion of the given array with the given value.
-     *
-     * <P>If possible (i.e.,
-     * <code>from</code> is 0) this method uses a backward loop. In this case,
-     * it is significantly faster than the corresponding method in
-     * {@link java.util.Arrays}.
-     *
-     * @param array an array.
-     * @param begin the starting index of the portion to fill (inclusive).
-     * @param end the end index of the portion to fill (exclusive).
-     * @param value the new value for all elements of the specified portion of
-     * the array.
-     */
-    public static <A,T> void fill(A array, int begin, int end, T value) {
-        NativeArrayUtils.fill(NativeArray.wrap(array), begin, end, value);
-    }
-    
-    public static <A> A reverse(A array, int begin, int end){
-        NativeArrayUtils.reverse(NativeArray.wrap(array), begin, end);
-        return array;
-    }
-
-    /**
-     * Reverses the order of the elements in the specified array.
-     *
-     * @param array the array to be reversed.
-     * @return <code>a</code>.
-     */
-    public static <A> A reverse(A array) {
-        NativeArrayUtils.reverse(NativeArray.wrap(array));
-        return array;
-    }
-    
-    /**
-     * Returns true if the two arrays are elementwise equal.
-     *
-     * <P>This method uses a backward loop. It is significantly faster than the
-     * corresponding method in {@link java.util.Arrays}.
-     *
-     * @param array1 an array.
-     * @param array2 another array.
-     * @return true if the two arrays are of the same length, and their elements
-     * are equal.
-     */
-    public static <A> boolean equals(A array1, A array2) {
-        return NativeArrayUtils.equals(NativeArray.wrap(array1), NativeArray.wrap(array2));
-    }
-    
-    public static <A,T> A head(A array, int index) {
-        return NativeArrayUtils.head(NativeArray.wrap(array), index).$array();
-    }
-
-    public static <A,T> A head(A array, T value, Comparator<? super T> cmp) {
-        return NativeArrayUtils.head(NativeArray.wrap(array), value, cmp).$array();
-    }
-    
-    public static <A,T> A tail(A array, int index) {
-        return NativeArrayUtils.tail(NativeArray.wrap(array), index).$array();
-    }
-    
-    public static <A,T> A tail(A array, T value, Comparator<? super T> cmp) {
-        return NativeArrayUtils.tail(NativeArray.wrap(array), value, cmp).$array();
-    }
-   
-    public static <A,T> A slice(A values, T begin, T end, Comparator<? super T> cmp) {
-        return NativeArrayUtils.slice(NativeArray.wrap(values), begin, end, cmp).$array();
-    }
-    
-    public static <A> A slice(A array, int begin, int end) {
-        return NativeArrayUtils.slice(NativeArray.wrap(array), begin, end).$array();
-    }
-    
-    public static <A> A rotate(A array, int offset) {
-        return NativeArrayUtils.rotate(NativeArray.wrap(array), offset).$array();
-    }
-    
-    public static <A> A shuffle(Random random, A array) {
-        return NativeArrayUtils.shuffle(random, NativeArray.wrap(array)).$array();
-    }
-    
-    public static <A> int size(A array) {
-        return null == array ? 0 : Array.getLength(array);
-    }
-    
-    @SuppressWarnings("SuspiciousSystemArraycopy")
-    public static <A> A copy(A src, int srcpos, A dst, int dstpos, int size) {
-        System.arraycopy(src, srcpos, dst, dstpos, size);
-        return dst;
-    }
-    
-    public static <A> A copy(A array) {
-        if(null == array) {
-            return null;
-        }
-        int n = Array.getLength(array);
-        return copy(array, 0, ArrayAllocator.forPrototype(array, n), 0, n);
-    }
-    
-    public static <A> A concat(A a, A b) {
-        return NativeArrayUtils.concat(NativeArray.wrap(a), NativeArray.wrap(b)).$array();
-    }
-
-    public static <A,T> ListIterator<T> iterator(A array) {
-        return NativeArrayUtils.iterator(NativeArray.wrap(array));
-    }
-
-    public static <A,T> ListIterator<T> iterator(A array, int begin, int end) {
-        return NativeArrayUtils.iterator(NativeArray.wrap(array), begin, end);
-    }
-    
-    public static <A,T> boolean equals(A a, A b, BiPredicate<T,T> predicate) {
-        return NativeArrayUtils.equals(NativeArray.wrap(a), NativeArray.wrap(b), predicate);
-    }
-    
-    public static <A,T> int compare(A a, A b) {
-        return NativeArrayUtils.compare(NativeArray.wrap(a), NativeArray.wrap(b));
-    }
-    
-    public static <A,T> int compare(A a, A b, Comparator<T> cmp) {
-        return NativeArrayUtils.compare(NativeArray.wrap(a), NativeArray.wrap(b), cmp);
-    }
-}
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.collection.arrays;
+
+import java.lang.reflect.Array;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.ListIterator;
+import java.util.Random;
+import java.util.function.BiPredicate;
+import net.ranides.assira.collection.iterators.IntIterator;
+
+@SuppressWarnings({
+    "PMD.AvoidReassigningParameters"
+})
+public final class ArrayUtils {
+
+    private ArrayUtils() {
+        // utility class
+    }
+    
+    /**
+     * Unwraps an iterator into an array starting at a given offset for a given
+     * number of elements.
+     *
+     * <P>This method iterates over the given type-specific iterator and stores
+     * the elements returned, up to a maximum of
+     * <code>length</code>, in the given array starting at
+     * <code>offset</code>. The number of actually unwrapped elements is
+     * returned (it may be less than
+     * <code>max</code> if the iterator emits less than
+     * <code>max</code> elements).
+     *
+     * @param iterator a type-specific iterator.
+     * @param target an array to contain the output of the iterator.
+     * @param begin the first element of the array to be returned.
+     * @param end the maximum number of elements to collect.
+     * @return the number of elements unwrapped.
+     */
+    public static <A,T> int collect(Iterator<T> iterator, A target, int begin, int end) {
+        if($isint(target)) {
+            return $collect(IntIterator.$wrap(iterator), (int[])target, begin, end);
+        } else {
+            return NativeArrayUtils.collect(iterator, NativeArray.wrap(target), begin, end);
+        }
+    }
+
+    private static <A> boolean $isint(A array) {
+        return null!=array && int[].class.equals(array.getClass());
+    }
+    
+    /**
+     * Unwraps an iterator into an array.
+     *
+     * <P>This method iterates over the given type-specific iterator and stores
+     * the elements returned in the given array. The iteration will stop when
+     * the iterator has no more elements or when the end of the array has been
+     * reached.
+     *
+     * @param iterator a type-specific iterator.
+     * @param target an array to contain the output of the iterator.
+     * @return the number of elements unwrapped.
+     */
+    public static <A,T> int collect(Iterator<T> iterator, A target) {
+        if($isint(target)) {
+            int[] array = (int[])target;
+            return $collect(IntIterator.$wrap(iterator), array, 0, array.length);
+        } else {
+            return NativeArrayUtils.collect(iterator, NativeArray.wrap(target));
+        }
+    }
+    
+    static int $collect(IntIterator iterator, int target[], int begin, int end) {
+        NativeArrayAllocator.ensureFromTo(target.length, begin, end);
+        int j = end;
+        while (j-- != 0 && iterator.hasNext()) {
+            target[begin++] = iterator.nextInt();
+        }
+        return end - j - 1;
+    }
+        
+    /**
+     * Fills the given array with the given value.
+     *
+     * <P>This method uses a backward loop. It is significantly faster than the
+     * corresponding method in {@link java.util.Arrays}.
+     *
+     * @param array an array.
+     * @param value the new value for all elements of the array.
+     */
+    public static <A,T> void fill(A array, T value) {
+        NativeArrayUtils.fill(NativeArray.wrap(array), value);
+    }
+
+    /**
+     * Fills a portion of the given array with the given value.
+     *
+     * <P>If possible (i.e.,
+     * <code>from</code> is 0) this method uses a backward loop. In this case,
+     * it is significantly faster than the corresponding method in
+     * {@link java.util.Arrays}.
+     *
+     * @param array an array.
+     * @param begin the starting index of the portion to fill (inclusive).
+     * @param end the end index of the portion to fill (exclusive).
+     * @param value the new value for all elements of the specified portion of
+     * the array.
+     */
+    public static <A,T> void fill(A array, int begin, int end, T value) {
+        NativeArrayUtils.fill(NativeArray.wrap(array), begin, end, value);
+    }
+    
+    public static <A> A reverse(A array, int begin, int end){
+        NativeArrayUtils.reverse(NativeArray.wrap(array), begin, end);
+        return array;
+    }
+
+    /**
+     * Reverses the order of the elements in the specified array.
+     *
+     * @param array the array to be reversed.
+     * @return <code>a</code>.
+     */
+    public static <A> A reverse(A array) {
+        NativeArrayUtils.reverse(NativeArray.wrap(array));
+        return array;
+    }
+    
+    /**
+     * Returns true if the two arrays are elementwise equal.
+     *
+     * <P>This method uses a backward loop. It is significantly faster than the
+     * corresponding method in {@link java.util.Arrays}.
+     *
+     * @param array1 an array.
+     * @param array2 another array.
+     * @return true if the two arrays are of the same length, and their elements
+     * are equal.
+     */
+    public static <A> boolean equals(A array1, A array2) {
+        return NativeArrayUtils.equals(NativeArray.wrap(array1), NativeArray.wrap(array2));
+    }
+    
+    public static <A,T> A head(A array, int index) {
+        return NativeArrayUtils.head(NativeArray.wrap(array), index).$array();
+    }
+
+    public static <A,T> A head(A array, T value, Comparator<? super T> cmp) {
+        return NativeArrayUtils.head(NativeArray.wrap(array), value, cmp).$array();
+    }
+    
+    public static <A,T> A tail(A array, int index) {
+        return NativeArrayUtils.tail(NativeArray.wrap(array), index).$array();
+    }
+    
+    public static <A,T> A tail(A array, T value, Comparator<? super T> cmp) {
+        return NativeArrayUtils.tail(NativeArray.wrap(array), value, cmp).$array();
+    }
+   
+    public static <A,T> A slice(A values, T begin, T end, Comparator<? super T> cmp) {
+        return NativeArrayUtils.slice(NativeArray.wrap(values), begin, end, cmp).$array();
+    }
+    
+    public static <A> A slice(A array, int begin, int end) {
+        return NativeArrayUtils.slice(NativeArray.wrap(array), begin, end).$array();
+    }
+    
+    public static <A> A rotate(A array, int offset) {
+        return NativeArrayUtils.rotate(NativeArray.wrap(array), offset).$array();
+    }
+    
+    public static <A> A shuffle(Random random, A array) {
+        return NativeArrayUtils.shuffle(random, NativeArray.wrap(array)).$array();
+    }
+    
+    public static <A> int size(A array) {
+        return null == array ? 0 : Array.getLength(array);
+    }
+    
+    @SuppressWarnings("SuspiciousSystemArraycopy")
+    public static <A> A copy(A src, int srcpos, A dst, int dstpos, int size) {
+        System.arraycopy(src, srcpos, dst, dstpos, size);
+        return dst;
+    }
+    
+    public static <A> A copy(A array) {
+        if(null == array) {
+            return null;
+        }
+        int n = Array.getLength(array);
+        return copy(array, 0, ArrayAllocator.forPrototype(array, n), 0, n);
+    }
+    
+    public static <A> A concat(A a, A b) {
+        return NativeArrayUtils.concat(NativeArray.wrap(a), NativeArray.wrap(b)).$array();
+    }
+    
+    public static <A> A append(A a, Object value) {
+        return NativeArrayUtils.append(NativeArray.wrap(a), value).$array();
+    }
+
+    public static <A> A prepend(A a, Object value) {
+        return NativeArrayUtils.prepend(NativeArray.wrap(a), value).$array();
+    }
+
+    public static <A,T> ListIterator<T> iterator(A array) {
+        return NativeArrayUtils.iterator(NativeArray.wrap(array));
+    }
+
+    public static <A,T> ListIterator<T> iterator(A array, int begin, int end) {
+        return NativeArrayUtils.iterator(NativeArray.wrap(array), begin, end);
+    }
+    
+    public static <A,T> boolean equals(A a, A b, BiPredicate<T,T> predicate) {
+        return NativeArrayUtils.equals(NativeArray.wrap(a), NativeArray.wrap(b), predicate);
+    }
+    
+    public static <A,T> int compare(A a, A b) {
+        return NativeArrayUtils.compare(NativeArray.wrap(a), NativeArray.wrap(b));
+    }
+    
+    public static <A,T> int compare(A a, A b, Comparator<T> cmp) {
+        return NativeArrayUtils.compare(NativeArray.wrap(a), NativeArray.wrap(b), cmp);
+    }
+}

+ 254 - 238
assira/src/main/java/net/ranides/assira/collection/arrays/NativeArrayUtils.java

@@ -1,238 +1,254 @@
-/*
- * @author Ranides Atterwim <ranides@gmail.com>
- * @copyright Ranides Atterwim
- * @license WTFPL
- * @url http://ranides.net/projects/assira
- */
-package net.ranides.assira.collection.arrays;
-
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.ListIterator;
-import java.util.Random;
-import java.util.function.BiPredicate;
-import net.ranides.assira.collection.IntComparator;
-import net.ranides.assira.collection.Swapper;
-import net.ranides.assira.collection.arrays.NativeArray.NativeComparator;
-import net.ranides.assira.collection.iterators.RandomAccessIterator;
-import net.ranides.assira.generic.CompareUtils;
-
-@SuppressWarnings({
-    "PMD.AvoidReassigningParameters"
-})
-public final class NativeArrayUtils {
-
-    private NativeArrayUtils() {
-        // utility class
-    }
-    
-    public static <T> int collect(Iterator<? extends T> iterator, NativeArray target, int begin, int end) {
-        NativeArrayAllocator.ensureFromTo(target, begin, end);
-        int j = end;
-        while (j-- != 0 && iterator.hasNext()) {
-            target.set(begin++, iterator.next());
-        }
-        return end - j - 1;
-    }
-
-    public static <T> int collect(Iterator<? extends T> iterator, NativeArray target) {
-        return collect(iterator, target, 0, target.size());
-    }
-
-    /**
-     * Fills the given array with the given value.
-     *
-     * <P>This method uses a backward loop. It is significantly faster than the
-     * corresponding method in {@link java.util.Arrays}.
-     *
-     * @param array an array.
-     * @param value the new value for all elements of the array.
-     */
-    public static <T> void fill(NativeArray array, T value) {
-        array.set(0, array.size(), value);
-    }
-
-    public static <T> void fill(NativeArray array, int begin, int end, T value) {
-        NativeArrayAllocator.ensureFromTo(array, begin, end);
-        array.set(begin, end, value);
-    }
-    
-    public static <S extends Swapper> S reverse(S swapper, int begin, int end){
-        while(begin < --end){
-            swapper.swap(begin++, end);
-        }
-        return swapper;
-    }
-
-    public static <S extends Swapper> S reverse(S swapper, int size) {
-        return reverse(swapper, 0, size);
-    }
-    
-    public static NativeArray reverse(NativeArray array) {
-        reverse(array, array.size());
-        return array;
-    }
-    
-    public static boolean equals(NativeArray array1, NativeArray array2) {
-        return array1.equals(array2);
-    }
-    
-    public static <T> NativeArray head(NativeArray values, int index) {
-        return slice(values, 0, index);
-    }
-
-    public static <T> NativeArray head(NativeArray values, T value, Comparator<? super T> cmp) {
-        return slice(values, 0, ifind(values, value, 0, cmp));
-    }
-    
-    public static <T> NativeArray tail(NativeArray values, int index) {
-        return slice(values, index, values.size());
-    }
-    
-    public static <T> NativeArray tail(NativeArray values, T value, Comparator<? super T> cmp) {
-        return slice(values, ifind(values, value, 0, cmp), values.size());
-    }
-    
-    public static <T> NativeArray slice(NativeArray values, T begin, T end, Comparator<? super T> cmp) {
-        int bi = ifind(values, begin, 0, cmp);
-        int ei = ifind(values, end, bi, cmp);
-        return slice(values, bi, ei);
-    }
-
-    public static NativeArray slice(NativeArray values, int begin, int end) {
-        int size = end - begin;
-        NativeArray result = values.allocate(size);
-        NativeArrayUtils.copy(values, begin, result, 0, size);
-        return result;
-    }
-    
-    public static NativeArray rotate(NativeArray array, int offset) {
-        int n = array.size();
-        offset = offset % n;
-        if( offset > 0) {
-            int a = n - offset; 
-            reverse(array, 0, a);
-            reverse(array, a, n);
-            reverse(array, 0, n);
-        } 
-        else if( offset < 0) {
-            rotate(array, offset+n);
-        }
-        return array;
-    }
-    
-    private static <T> int ifind(NativeArray values, T value, int begin, Comparator<? super T> cmp) {
-        NativeComparator icmp = values.rcmp(value, cmp);
-        int i = begin, n = values.size();
-        while(i<n && icmp.compare(i) < 0) {
-            i++;
-        }
-        return i;
-    }
-    
-    public static NativeArray shuffle(Random random, NativeArray array) {
-        shuffle(random, array.size(), array);
-        return array;
-    }
-    
-    public static void shuffle(Random random, int size, Swapper swapper) {
-        for(int i=size; i>1; i--) {
-            swapper.swap(i-1, random.nextInt(i));
-        }
-    }
-
-    public static int size(NativeArray array) {
-        return array.size();
-    }
-    
-    @SuppressWarnings("SuspiciousSystemArraycopy")
-    public static <T> NativeArray copy(NativeArray src, int srcpos, NativeArray dst, int dstpos, int size) {
-        System.arraycopy(src.array(), srcpos, dst.array(), dstpos, size);
-        return dst;
-    }
-    
-    public static NativeArray copy(NativeArray array) {
-        int n = array.size();
-        return copy(array, 0, NativeArrayAllocator.forPrototype(array, n), 0, n);
-    }
-    
-    public static NativeArray concat(NativeArray a, NativeArray b) {
-        int as = a.size();
-        int bs = b.size();
-        NativeArray result = a.allocate(as+bs);
-        copy(a, 0, result, 0, as);
-        copy(b, 0, result, as, bs);
-        return result;
-    }
-    
-    public static <T> ListIterator<T> iterator(NativeArray array) {
-        return iterator(array, 0, array.size());
-    }
-
-    @SuppressWarnings("unchecked")
-    public static <T> ListIterator<T> iterator(NativeArray array, int begin, int end) {
-        return new RandomAccessIterator<T>() {
-            @Override
-            protected int size() {
-                return end-begin;
-            }
-
-            @Override
-            protected T get(int index) {
-                return (T)array.get(begin+index);
-            }
-
-            @Override
-            protected void set(int index, T value) {
-                array.set(begin+index, value);
-            }
-            
-        };
-    }
-    
-    public static <T> boolean equals(NativeArray a, NativeArray b, Comparator<T> cmp) {
-        if(a.size() != b.size()) {
-            return false;
-        }
-        IntComparator icmp = a.comparator(b, cmp);
-        for(int i=0, n=a.size(); i<n; i++) {
-            if( 0 != icmp.compare(i,i)) {
-                return false;
-            }
-        }
-        return true;
-    }
-    
-    public static <T> boolean equals(NativeArray a, NativeArray b, BiPredicate<T,T> predicate) {
-        if(a.size() != b.size()) {
-            return false;
-        }
-        Comparator<T> vcmp = (av,bv) -> predicate.test(av, bv) ? 0 : -1;
-        IntComparator icmp = a.comparator(b, vcmp);
-        for(int i=0, n=a.size(); i<n; i++) {
-            if( 0 != icmp.compare(i,i)) {
-                return false;
-            }
-        }
-        return true;
-    }
-    
-    public static <T> int compare(NativeArray a, NativeArray b) {
-        return icompare(a.size(), b.size(), a.comparator(b));
-    }
-    
-    public static <T> int compare(NativeArray a, NativeArray b, Comparator<T> cmp) {
-        return icompare(a.size(), b.size(), a.comparator(b, cmp));
-    }
-    
-    private static <T> int icompare(int a, int b, IntComparator cmp) {
-        for(int i=0, n=Math.min(a,b); i<n; i++) {
-            int ic = cmp.compare(i,i);
-            if(ic != 0) {
-                return ic;
-            }
-        }
-        return CompareUtils.cmp(a,b);
-    }
-    
-}
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.collection.arrays;
+
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.ListIterator;
+import java.util.Random;
+import java.util.function.BiPredicate;
+import net.ranides.assira.collection.IntComparator;
+import net.ranides.assira.collection.Swapper;
+import net.ranides.assira.collection.arrays.NativeArray.NativeComparator;
+import net.ranides.assira.collection.iterators.RandomAccessIterator;
+import net.ranides.assira.generic.CompareUtils;
+
+@SuppressWarnings({
+    "PMD.AvoidReassigningParameters"
+})
+public final class NativeArrayUtils {
+
+    private NativeArrayUtils() {
+        // utility class
+    }
+    
+    public static <T> int collect(Iterator<? extends T> iterator, NativeArray target, int begin, int end) {
+        NativeArrayAllocator.ensureFromTo(target, begin, end);
+        int j = end;
+        while (j-- != 0 && iterator.hasNext()) {
+            target.set(begin++, iterator.next());
+        }
+        return end - j - 1;
+    }
+
+    public static <T> int collect(Iterator<? extends T> iterator, NativeArray target) {
+        return collect(iterator, target, 0, target.size());
+    }
+
+    /**
+     * Fills the given array with the given value.
+     *
+     * <P>This method uses a backward loop. It is significantly faster than the
+     * corresponding method in {@link java.util.Arrays}.
+     *
+     * @param array an array.
+     * @param value the new value for all elements of the array.
+     */
+    public static <T> void fill(NativeArray array, T value) {
+        array.set(0, array.size(), value);
+    }
+
+    public static <T> void fill(NativeArray array, int begin, int end, T value) {
+        NativeArrayAllocator.ensureFromTo(array, begin, end);
+        array.set(begin, end, value);
+    }
+    
+    public static <S extends Swapper> S reverse(S swapper, int begin, int end){
+        while(begin < --end){
+            swapper.swap(begin++, end);
+        }
+        return swapper;
+    }
+
+    public static <S extends Swapper> S reverse(S swapper, int size) {
+        return reverse(swapper, 0, size);
+    }
+    
+    public static NativeArray reverse(NativeArray array) {
+        reverse(array, array.size());
+        return array;
+    }
+    
+    public static boolean equals(NativeArray array1, NativeArray array2) {
+        return array1.equals(array2);
+    }
+    
+    public static <T> NativeArray head(NativeArray values, int index) {
+        return slice(values, 0, index);
+    }
+
+    public static <T> NativeArray head(NativeArray values, T value, Comparator<? super T> cmp) {
+        return slice(values, 0, ifind(values, value, 0, cmp));
+    }
+    
+    public static <T> NativeArray tail(NativeArray values, int index) {
+        return slice(values, index, values.size());
+    }
+    
+    public static <T> NativeArray tail(NativeArray values, T value, Comparator<? super T> cmp) {
+        return slice(values, ifind(values, value, 0, cmp), values.size());
+    }
+    
+    public static <T> NativeArray slice(NativeArray values, T begin, T end, Comparator<? super T> cmp) {
+        int bi = ifind(values, begin, 0, cmp);
+        int ei = ifind(values, end, bi, cmp);
+        return slice(values, bi, ei);
+    }
+
+    public static NativeArray slice(NativeArray values, int begin, int end) {
+        int size = end - begin;
+        NativeArray result = values.allocate(size);
+        NativeArrayUtils.copy(values, begin, result, 0, size);
+        return result;
+    }
+    
+    public static NativeArray rotate(NativeArray array, int offset) {
+        int n = array.size();
+        offset = offset % n;
+        if( offset > 0) {
+            int a = n - offset; 
+            reverse(array, 0, a);
+            reverse(array, a, n);
+            reverse(array, 0, n);
+        } 
+        else if( offset < 0) {
+            rotate(array, offset+n);
+        }
+        return array;
+    }
+    
+    private static <T> int ifind(NativeArray values, T value, int begin, Comparator<? super T> cmp) {
+        NativeComparator icmp = values.rcmp(value, cmp);
+        int i = begin, n = values.size();
+        while(i<n && icmp.compare(i) < 0) {
+            i++;
+        }
+        return i;
+    }
+    
+    public static NativeArray shuffle(Random random, NativeArray array) {
+        shuffle(random, array.size(), array);
+        return array;
+    }
+    
+    public static void shuffle(Random random, int size, Swapper swapper) {
+        for(int i=size; i>1; i--) {
+            swapper.swap(i-1, random.nextInt(i));
+        }
+    }
+
+    public static int size(NativeArray array) {
+        return array.size();
+    }
+    
+    @SuppressWarnings("SuspiciousSystemArraycopy")
+    public static <T> NativeArray copy(NativeArray src, int srcpos, NativeArray dst, int dstpos, int size) {
+        System.arraycopy(src.array(), srcpos, dst.array(), dstpos, size);
+        return dst;
+    }
+    
+    public static NativeArray copy(NativeArray array) {
+        int n = array.size();
+        return copy(array, 0, NativeArrayAllocator.forPrototype(array, n), 0, n);
+    }
+    
+    public static NativeArray concat(NativeArray a, NativeArray b) {
+        int as = a.size();
+        int bs = b.size();
+        NativeArray result = a.allocate(as+bs);
+        copy(a, 0, result, 0, as);
+        copy(b, 0, result, as, bs);
+        return result;
+    }
+    
+    public static NativeArray append(NativeArray a, Object value) {
+        int as = a.size();
+        NativeArray result = a.allocate(as + 1);
+        copy(a, 0, result, 0, as);
+        result.set(as, value);
+        return result;
+    }
+    
+    public static NativeArray prepend(NativeArray a, Object value) {
+        int as = a.size();
+        NativeArray result = a.allocate(as + 1);
+        copy(a, 0, result, 1, as);
+        result.set(0, value);
+        return result;
+    }
+    
+    public static <T> ListIterator<T> iterator(NativeArray array) {
+        return iterator(array, 0, array.size());
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> ListIterator<T> iterator(NativeArray array, int begin, int end) {
+        return new RandomAccessIterator<T>() {
+            @Override
+            protected int size() {
+                return end-begin;
+            }
+
+            @Override
+            protected T get(int index) {
+                return (T)array.get(begin+index);
+            }
+
+            @Override
+            protected void set(int index, T value) {
+                array.set(begin+index, value);
+            }
+            
+        };
+    }
+    
+    public static <T> boolean equals(NativeArray a, NativeArray b, Comparator<T> cmp) {
+        if(a.size() != b.size()) {
+            return false;
+        }
+        IntComparator icmp = a.comparator(b, cmp);
+        for(int i=0, n=a.size(); i<n; i++) {
+            if( 0 != icmp.compare(i,i)) {
+                return false;
+            }
+        }
+        return true;
+    }
+    
+    public static <T> boolean equals(NativeArray a, NativeArray b, BiPredicate<T,T> predicate) {
+        if(a.size() != b.size()) {
+            return false;
+        }
+        Comparator<T> vcmp = (av,bv) -> predicate.test(av, bv) ? 0 : -1;
+        IntComparator icmp = a.comparator(b, vcmp);
+        for(int i=0, n=a.size(); i<n; i++) {
+            if( 0 != icmp.compare(i,i)) {
+                return false;
+            }
+        }
+        return true;
+    }
+    
+    public static <T> int compare(NativeArray a, NativeArray b) {
+        return icompare(a.size(), b.size(), a.comparator(b));
+    }
+    
+    public static <T> int compare(NativeArray a, NativeArray b, Comparator<T> cmp) {
+        return icompare(a.size(), b.size(), a.comparator(b, cmp));
+    }
+    
+    private static <T> int icompare(int a, int b, IntComparator cmp) {
+        for(int i=0, n=Math.min(a,b); i<n; i++) {
+            int ic = cmp.compare(i,i);
+            if(ic != 0) {
+                return ic;
+            }
+        }
+        return CompareUtils.cmp(a,b);
+    }
+    
+}

+ 64 - 64
assira/src/main/java/net/ranides/assira/io/PathUtils.java

@@ -1,64 +1,64 @@
-/*
- * @author Ranides Atterwim <ranides@gmail.com>
- * @copyright Ranides Atterwim
- * @license WTFPL
- * @url http://ranides.net/projects/assira
- */
-package net.ranides.assira.io;
-
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-/**
- *
- * @author Ranides Atterwim <ranides@gmail.com>
- */
-public final class PathUtils {
-    
-    private PathUtils() {
-        /* utility class */
-    }
-    
-    public static Path fromURL(URL url) {
-        try {
-            return Paths.get(url.toURI());
-        } catch (URISyntaxException cause) {
-            throw new IllegalArgumentException(cause);
-        }
-    }
-    
-    public static String getExtension(String path) {
-        return getExtension(Paths.get(path));
-    }
-    
-    public static String getExtension(Path path) {
-        String name = path.getFileName().toString();
-        int index = name.lastIndexOf(".");
-        return (-1==index) ? "" : name.substring(index);
-    }
-    
-    public static Path changeExtension(Path path, String extension) {
-        return changeExtension(path.toString(), extension);
-    }
-    
-    public static Path changeExtension(String path, String extension) {
-        int index = path.lastIndexOf(".");
-        if(-1==index) {
-            return Paths.get(path + extension);
-        } else {
-            return Paths.get(path.substring(0,index) + extension);
-        }
-    }
-    
-    public static String getSimpleName(String path) {
-        return getSimpleName(Paths.get(path));
-    }
-    
-    public static String getSimpleName(Path path) {
-        String name = path.getFileName().toString();
-        int index = name.lastIndexOf(".");
-        return index<0 ? name : name.substring(0, index);
-    }
-}
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.io;
+
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+/**
+ *
+ * @author Ranides Atterwim <ranides@gmail.com>
+ */
+public final class PathUtils {
+    
+    private PathUtils() {
+        /* utility class */
+    }
+    
+    public static Path fromURL(URL url) {
+        try {
+            return Paths.get(url.toURI());
+        } catch (URISyntaxException cause) {
+            throw new IllegalArgumentException(cause);
+        }
+    }
+    
+    public static String getExtension(String path) {
+        return getExtension(Paths.get(path));
+    }
+    
+    public static String getExtension(Path path) {
+        String name = path.getFileName().toString();
+        int index = name.indexOf(".");
+        return (-1==index) ? "" : name.substring(index);
+    }
+    
+    public static Path changeExtension(Path path, String extension) {
+        return changeExtension(path.toString(), extension);
+    }
+    
+    public static Path changeExtension(String path, String extension) {
+        int index = path.indexOf(".");
+        if(-1==index) {
+            return Paths.get(path + extension);
+        } else {
+            return Paths.get(path.substring(0,index) + extension);
+        }
+    }
+    
+    public static String getSimpleName(String path) {
+        return getSimpleName(Paths.get(path));
+    }
+    
+    public static String getSimpleName(Path path) {
+        String name = path.getFileName().toString();
+        int index = name.indexOf(".");
+        return index<0 ? name : name.substring(0, index);
+    }
+}

+ 84 - 77
assira/src/main/java/net/ranides/assira/reflection/IExecutable.java

@@ -1,77 +1,84 @@
-/*
- * @author Ranides Atterwim <ranides@gmail.com>
- * @copyright Ranides Atterwim
- * @license WTFPL
- * @url http://ranides.net/projects/assira
- */
-package net.ranides.assira.reflection;
-
-import net.ranides.assira.functional.VarFunction;
-
-import java.lang.invoke.MethodHandle;
-import java.util.List;
-
-/**
- * @author Ranides Atterwim <ranides@gmail.com>
- */
-public interface IExecutable extends IElement {
-
-    @Override
-    IExecutables collect();
-    
-    List<IClass<?>> params();
-    
-    IClass<?> returns();
-    
-    IArguments arguments();
-    
-    @Override
-    IClass<?> parent();
-    
-    boolean matches(IClasses arguments);
-    
-    boolean matches(IClass<?>... arguments);
-    
-    boolean matches(Class<?>... arguments);
-    
-    boolean matches();
-    
-    boolean accepts(Object... arguments);
-
-    Object apply();
-    
-    Object apply(Object that);
-    
-    Object apply(Object that, Object... arguments);
-
-    Object call(Object... arguments);
-    
-    @SuppressWarnings("unchecked")
-    default <T> T $apply() {
-        return (T)apply();
-    }
-    
-    @SuppressWarnings("unchecked")
-    default <T> T $apply(Object that) {
-        return (T)apply(that);
-    }
-    
-    @SuppressWarnings("unchecked")
-    default <T> T $apply(Object that, Object... arguments) {
-        return (T)apply(that, arguments);
-    }
-
-    @SuppressWarnings("unchecked")
-    default <T> T $call(Object... arguments) {
-        return (T)call(arguments);
-    }
-    
-    VarFunction<Object> bind(Object that);
-
-    MethodHandle handle();
-    
-    <F> F handle(Class<F> functor);
-    
-    <F> F handle(IClass<F> functor);
-    
-}
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.reflection;
+
+import net.ranides.assira.functional.VarFunction;
+
+import java.lang.invoke.MethodHandle;
+import java.util.List;
+
+/**
+ * @author Ranides Atterwim <ranides@gmail.com>
+ */
+public interface IExecutable extends IElement {
+
+    @Override
+    IExecutables collect();
+    
+    List<IClass<?>> params();
+    
+    IClass<?> returns();
+    
+    IArguments arguments();
+    
+    @Override
+    IClass<?> parent();
+    
+    boolean matches(IClasses arguments);
+    
+    boolean matches(IClass<?>... arguments);
+    
+    boolean matches(Class<?>... arguments);
+    
+    boolean matches();
+    
+    boolean accepts(Object... arguments);
+
+    Object apply();
+    
+    Object apply(Object that);
+    
+    Object apply(Object that, Object... arguments);
+
+    Object call(Object... arguments);
+    
+    Object callThis(Object that, Object... arguments);
+    
+    @SuppressWarnings("unchecked")
+    default <T> T $apply() {
+        return (T)apply();
+    }
+    
+    @SuppressWarnings("unchecked")
+    default <T> T $apply(Object that) {
+        return (T)IExecutable.this.apply(that);
+    }
+    
+    @SuppressWarnings("unchecked")
+    default <T> T $apply(Object that, Object... arguments) {
+        return (T)IExecutable.this.apply(that, arguments);
+    }
+
+    @SuppressWarnings("unchecked")
+    default <T> T $call(Object... arguments) {
+        return (T)call(arguments);
+    }
+    
+    @SuppressWarnings("unchecked")
+    default <T> T $callThis(Object that, Object... arguments) {
+        return (T)callThis(that, arguments);
+    }
+    
+    VarFunction<Object> bind(Object that);
+
+    MethodHandle handle();
+    
+    <F> F handle(Class<F> functor);
+    
+    <F> F handle(IClass<F> functor);
+    
+}

+ 156 - 150
assira/src/main/java/net/ranides/assira/reflection/impl/AExecutable.java

@@ -1,150 +1,156 @@
-/*
- * @author Ranides Atterwim <ranides@gmail.com>
- * @copyright Ranides Atterwim
- * @license WTFPL
- * @url http://ranides.net/projects/assira
- */
-
-package net.ranides.assira.reflection.impl;
-
-import net.ranides.assira.functional.VarFunction;
-import net.ranides.assira.reflection.IClass;
-import net.ranides.assira.reflection.IClasses;
-import net.ranides.assira.reflection.IContext;
-import net.ranides.assira.reflection.IExecutable;
-import net.ranides.assira.text.StrBuilder;
-import net.ranides.assira.trace.ExceptionUtils;
-
-import java.lang.annotation.Annotation;
-import java.lang.invoke.CallSite;
-import java.lang.invoke.LambdaConversionException;
-import java.lang.invoke.LambdaMetafactory;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
-import java.util.Optional;
-
-import static net.ranides.assira.reflection.IAttribute.BRIDGE;
-import static net.ranides.assira.reflection.IAttribute.DECLARED;
-import static net.ranides.assira.reflection.IAttribute.SYNTHETIC;
-
-/**
- *
- * @author Ranides Atterwim <ranides@gmail.com>
- */
-public abstract class AExecutable implements IExecutable {
-
-    private final IContext context;
-
-    protected AExecutable(IContext context) {
-        this.context = context;
-    }
-
-    @Override
-    public final IContext context() {
-        return context;
-    }
-    	
-    @Override
-    public final <A extends Annotation> Optional<A> annotation(Class<A> type) {
-        return annotations().first(type);
-    }
-
-    @Override
-    public final boolean matches(IClasses arguments) {
-        return this.arguments().types().isSuper(arguments);
-    }
-    
-    @Override
-    public final boolean matches(IClass<?>... arguments) {
-        return matches(IClasses.typeinfo(arguments));
-    }
-    
-    @Override
-    public final boolean matches(Class<?>... arguments) {
-        return matches(IClasses.typeinfo(arguments));
-    }
-    
-    @Override
-    public final boolean matches() {
-        return matches(IClasses.EMPTY);
-    }
-    
-    @Override
-    public final boolean accepts(Object... arguments) {
-        return this.arguments().types().isInstance(arguments);
-    }
-
-	@Override
-	public VarFunction<Object> bind(Object that) {
-        MethodHandle mh = handle().bindTo(that);
-        return (args) -> {
-            try {
-                return mh.invokeWithArguments(args);
-            } catch (Throwable cause) { //NOPMD rethrow idiom
-                throw ExceptionUtils.rethrow(cause);
-            }
-        };
-	}
-
-    @Override
-    public <F> F handle(Class<F> functor) {
-        return handle(IClass.typeinfo(functor));
-    }
-
-    @Override
-    public <F> F handle(IClass<F> functor) {
-        try {
-            Class<?> rfunctor = functor.raw();
-            
-            IExecutable method = IClass.typeinfo(rfunctor).methods().require(DECLARED).discard(SYNTHETIC).discard(BRIDGE).first().get();
-
-            // invoke vs invokeExact:
-            // http://stackoverflow.com/questions/28196829/java-8-generic-lambdametafactory
-            return (F)site(method, functor.raw()).getTarget().invoke();
-            
-        } catch(Throwable cause) {
-            throw ExceptionUtils.rethrow(cause);
-        }
-    }
-    
-    private CallSite site(IExecutable method, Class<?> functor) throws LambdaConversionException {
-        MethodHandle handle = handle();
-        
-        MethodType signature = MethodType.methodType(
-            method.returns().raw(), 
-            method.arguments().types().raw().array(Class[]::new)
-        );
-        
-        return LambdaMetafactory.metafactory(
-            MethodHandles.lookup(), 
-            method.name(), 
-            MethodType.methodType(functor), 
-            signature, 
-            handle, 
-            handle.type()
-        );
-    }
-  
-    @Override
-    public final int hashCode() {
-        return name().hashCode();
-    }
-
-    @Override
-    public final boolean equals(Object object) {
-        if(object == this) {
-            return true;
-        }
-        if(!(object instanceof IExecutable)) {
-            return false;
-        }
-        IExecutable that = (IExecutable)object;
-        return this.name().equals(that.name())
-            && this.arguments().equals(that.arguments())
-            && this.returns().equals(that.returns());
-    }
-
-    protected abstract String[] $debugParams();
-
-}
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+
+package net.ranides.assira.reflection.impl;
+
+import net.ranides.assira.functional.VarFunction;
+import net.ranides.assira.reflection.IClass;
+import net.ranides.assira.reflection.IClasses;
+import net.ranides.assira.reflection.IContext;
+import net.ranides.assira.reflection.IExecutable;
+import net.ranides.assira.text.StrBuilder;
+import net.ranides.assira.trace.ExceptionUtils;
+
+import java.lang.annotation.Annotation;
+import java.lang.invoke.CallSite;
+import java.lang.invoke.LambdaConversionException;
+import java.lang.invoke.LambdaMetafactory;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.Optional;
+import net.ranides.assira.collection.arrays.ArrayUtils;
+
+import static net.ranides.assira.reflection.IAttribute.BRIDGE;
+import static net.ranides.assira.reflection.IAttribute.DECLARED;
+import static net.ranides.assira.reflection.IAttribute.SYNTHETIC;
+
+/**
+ *
+ * @author Ranides Atterwim <ranides@gmail.com>
+ */
+public abstract class AExecutable implements IExecutable {
+
+    private final IContext context;
+
+    protected AExecutable(IContext context) {
+        this.context = context;
+    }
+
+    @Override
+    public final IContext context() {
+        return context;
+    }
+    	
+    @Override
+    public final <A extends Annotation> Optional<A> annotation(Class<A> type) {
+        return annotations().first(type);
+    }
+
+    @Override
+    public final boolean matches(IClasses arguments) {
+        return this.arguments().types().isSuper(arguments);
+    }
+    
+    @Override
+    public final boolean matches(IClass<?>... arguments) {
+        return matches(IClasses.typeinfo(arguments));
+    }
+    
+    @Override
+    public final boolean matches(Class<?>... arguments) {
+        return matches(IClasses.typeinfo(arguments));
+    }
+    
+    @Override
+    public final boolean matches() {
+        return matches(IClasses.EMPTY);
+    }
+    
+    @Override
+    public final boolean accepts(Object... arguments) {
+        return this.arguments().types().isInstance(arguments);
+    }
+
+	@Override
+	public VarFunction<Object> bind(Object that) {
+        MethodHandle mh = handle().bindTo(that);
+        return (args) -> {
+            try {
+                return mh.invokeWithArguments(args);
+            } catch (Throwable cause) { //NOPMD rethrow idiom
+                throw ExceptionUtils.rethrow(cause);
+            }
+        };
+	}
+    
+    @Override
+    public Object callThis(Object that, Object... arguments) {
+        return call(ArrayUtils.prepend(arguments, that));
+    }
+
+    @Override
+    public <F> F handle(Class<F> functor) {
+        return handle(IClass.typeinfo(functor));
+    }
+
+    @Override
+    public <F> F handle(IClass<F> functor) {
+        try {
+            Class<?> rfunctor = functor.raw();
+            
+            IExecutable method = IClass.typeinfo(rfunctor).methods().require(DECLARED).discard(SYNTHETIC).discard(BRIDGE).first().get();
+
+            // invoke vs invokeExact:
+            // http://stackoverflow.com/questions/28196829/java-8-generic-lambdametafactory
+            return (F)site(method, functor.raw()).getTarget().invoke();
+            
+        } catch(Throwable cause) {
+            throw ExceptionUtils.rethrow(cause);
+        }
+    }
+    
+    private CallSite site(IExecutable method, Class<?> functor) throws LambdaConversionException {
+        MethodHandle handle = handle();
+        
+        MethodType signature = MethodType.methodType(
+            method.returns().raw(), 
+            method.arguments().types().raw().array(Class[]::new)
+        );
+        
+        return LambdaMetafactory.metafactory(
+            MethodHandles.lookup(), 
+            method.name(), 
+            MethodType.methodType(functor), 
+            signature, 
+            handle, 
+            handle.type()
+        );
+    }
+  
+    @Override
+    public final int hashCode() {
+        return name().hashCode();
+    }
+
+    @Override
+    public final boolean equals(Object object) {
+        if(object == this) {
+            return true;
+        }
+        if(!(object instanceof IExecutable)) {
+            return false;
+        }
+        IExecutable that = (IExecutable)object;
+        return this.name().equals(that.name())
+            && this.arguments().equals(that.arguments())
+            && this.returns().equals(that.returns());
+    }
+
+    protected abstract String[] $debugParams();
+
+}

+ 128 - 126
assira/src/test/java/net/ranides/assira/io/PathUtilsTest.java

@@ -1,126 +1,128 @@
-/*
- * @author Ranides Atterwim <ranides@gmail.com>
- * @copyright Ranides Atterwim
- * @license WTFPL
- * @url http://ranides.net/projects/assira
- */
-package net.ranides.assira.io;
-
-import static net.ranides.assira.junit.NewAssert.*;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.nio.file.FileSystemNotFoundException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-import org.junit.Assume;
-import org.junit.Test;
-
-import net.ranides.assira.system.HostSystem;
-
-/**
- *
- * @author Ranides Atterwim <ranides@gmail.com>
- * @todo (assira #7) PathUtils: inconsistent name separators linux/windows
- * implement tests for linux
- */
-public class PathUtilsTest {
-    
-    @Test
-    public void testGetExtension() {
-        assertEquals(".txt", PathUtils.getExtension("file.txt"));
-        assertEquals(".txt", PathUtils.getExtension("\\base\\file.txt"));
-        assertEquals(".txt", PathUtils.getExtension("/base/file.txt"));
-        assertEquals(".txt", PathUtils.getExtension("/base/file.log.txt"));
-    }
-
-    @Test
-    public void testGetSimpleName() {
-        assertEquals("file", PathUtils.getSimpleName("c:/ms/file"));
-        assertEquals("file", PathUtils.getSimpleName("c:/ms/file.txt"));
-        assertEquals("file", PathUtils.getSimpleName("c:\\ms\\file.txt"));
-        assertEquals("file", PathUtils.getSimpleName("file.txt"));
-        assertEquals("file", PathUtils.getSimpleName("/ms/file.txt"));
-
-        assertEquals("file.info", PathUtils.getSimpleName("c:/ms/file.info."));
-        assertEquals("file.info", PathUtils.getSimpleName("c:/ms/file.info.txt"));
-        assertEquals("file.info", PathUtils.getSimpleName("c:\\ms\\file.info.txt"));
-        assertEquals("file.info", PathUtils.getSimpleName("file.info.txt"));
-        assertEquals("file.info", PathUtils.getSimpleName("/ms/file.info.txt"));
-    }
-
-    @Test
-    public void testChangeExtension_W32() {
-        Assume.assumeTrue(HostSystem.WINDOWS.detected());
-
-        assertEquals(Paths.get("file.txt"), PathUtils.changeExtension("file.txt", ".txt"));
-        assertEquals(Paths.get("file.dat"), PathUtils.changeExtension("file.txt", ".dat"));
-        assertEquals(Paths.get("file.txt.dat"), PathUtils.changeExtension("file.txt.info", ".dat"));
-        assertEquals(Paths.get("file.dat"), PathUtils.changeExtension("file", ".dat"));
-        
-        assertEquals(Paths.get("base","name","file.txt"), PathUtils.changeExtension("base/name/file.txt", ".txt"));
-        assertEquals(Paths.get("base","name","file.dat"), PathUtils.changeExtension("base\\name\\file.txt", ".dat"));
-        assertEquals(Paths.get("c:","base","name","file.dat"), PathUtils.changeExtension("c:\\base\\name\\file.txt", ".dat"));
-        assertEquals(Paths.get("/base","name","file.dat"), PathUtils.changeExtension("/base/name\\file.txt", ".dat"));
-    }
-
-    @Test
-    public void testChangeExtension_NIX() {
-        Assume.assumeFalse(HostSystem.WINDOWS.detected());
-        fail("implement");
-    }
-    
-    @Test
-    public void testChangeExtensionP_W32() {
-        Assume.assumeTrue(HostSystem.WINDOWS.detected());
-
-        assertEquals(Paths.get("file.txt"), pce("file.txt", ".txt"));
-        assertEquals(Paths.get("file.dat"), pce("file.txt", ".dat"));
-        assertEquals(Paths.get("file.txt.dat"), pce("file.txt.info", ".dat"));
-        assertEquals(Paths.get("file.dat"), pce("file", ".dat"));
-        
-        assertEquals(Paths.get("base","name","file.txt"), pce("base/name/file.txt", ".txt"));
-        assertEquals(Paths.get("base","name","file.dat"), pce("base\\name\\file.txt", ".dat"));
-        assertEquals(Paths.get("c:","base","name","file.dat"), pce("c:\\base\\name\\file.txt", ".dat"));
-        assertEquals(Paths.get("/base","name","file.dat"), pce("/base/name\\file.txt", ".dat"));
-    }
-
-    @Test
-    public void testChangeExtensionP_NIX() {
-        Assume.assumeFalse(HostSystem.WINDOWS.detected());
-        fail("implement");
-    }
-
-    @Test
-    public void testFromURL_W32() throws MalformedURLException {
-        Assume.assumeTrue(HostSystem.WINDOWS.detected());
-
-        assertThrows(FileSystemNotFoundException.class, ()->{
-            PathUtils.fromURL(new URL("http://ranides.net/index.htm"));
-        });
-        assertThrows(FileSystemNotFoundException.class, ()->{
-            PathUtils.fromURL(new URL("ftp://ranides.net/index.htm"));
-        });
-
-        assertEquals(Paths.get("/ranides.net/index.htm"), PathUtils.fromURL(new URL("file:///ranides.net/index.htm")));
-        assertEquals(Paths.get("c:/ms/index.htm"), PathUtils.fromURL(new URL("file:///c:/ms/index.htm")));
-        
-                
-        assertThrows(IllegalArgumentException.class, ()->{
-            PathUtils.fromURL(new URL("file://c:/ms/index.htm?query"));
-        });
-    }
-
-    @Test
-    public void testFromURL_NIX() {
-        Assume.assumeFalse(HostSystem.WINDOWS.detected());
-        fail("implement");
-    }
-
-    private static Path pce(String path, String ext) {
-        return PathUtils.changeExtension(Paths.get(path), ext);
-    }
-
-
-}
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.io;
+
+import static net.ranides.assira.junit.NewAssert.*;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.nio.file.FileSystemNotFoundException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.junit.Assume;
+import org.junit.Test;
+
+import net.ranides.assira.system.HostSystem;
+
+/**
+ *
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @todo (assira #7) PathUtils: inconsistent name separators linux/windows
+ * implement tests for linux
+ */
+public class PathUtilsTest {
+    
+    @Test
+    public void testGetExtension() {
+        assertEquals(".txt", PathUtils.getExtension("file.txt"));
+        assertEquals(".txt", PathUtils.getExtension("\\base\\file.txt"));
+        assertEquals(".txt", PathUtils.getExtension("/base/file.txt"));
+        assertEquals(".log.txt", PathUtils.getExtension("/base/file.log.txt"));
+    }
+
+    @Test
+    public void testGetSimpleName() {
+        assertEquals("file", PathUtils.getSimpleName("c:/ms/file"));
+        assertEquals("file", PathUtils.getSimpleName("c:/ms/file.txt"));
+        assertEquals("file", PathUtils.getSimpleName("c:\\ms\\file.txt"));
+        assertEquals("file", PathUtils.getSimpleName("file.txt"));
+        assertEquals("file", PathUtils.getSimpleName("/ms/file.txt"));
+
+        assertEquals("file", PathUtils.getSimpleName("c:/ms/file.info."));
+        assertEquals("file", PathUtils.getSimpleName("c:/ms/file.info.txt"));
+        assertEquals("file", PathUtils.getSimpleName("c:\\ms\\file.info.txt"));
+        assertEquals("file", PathUtils.getSimpleName("file.info.txt"));
+        assertEquals("file", PathUtils.getSimpleName("/ms/file.info.txt"));
+    }
+
+    @Test
+    public void testChangeExtensionString_W32() {
+        Assume.assumeTrue(HostSystem.WINDOWS.detected());
+
+        assertEquals(Paths.get("file.txt"), PathUtils.changeExtension("file.txt", ".txt"));
+        assertEquals(Paths.get("file.dat"), PathUtils.changeExtension("file.txt", ".dat"));
+        assertEquals(Paths.get("file.txt.dat"), PathUtils.changeExtension("file.txt.info", ".txt.dat"));
+        assertEquals(Paths.get("file.dat"), PathUtils.changeExtension("file.txt.info", ".dat"));
+        assertEquals(Paths.get("file.dat"), PathUtils.changeExtension("file", ".dat"));
+        
+        assertEquals(Paths.get("base","name","file.txt"), PathUtils.changeExtension("base/name/file.txt", ".txt"));
+        assertEquals(Paths.get("base","name","file.dat"), PathUtils.changeExtension("base\\name\\file.txt", ".dat"));
+        assertEquals(Paths.get("c:","base","name","file.dat"), PathUtils.changeExtension("c:\\base\\name\\file.txt", ".dat"));
+        assertEquals(Paths.get("/base","name","file.dat"), PathUtils.changeExtension("/base/name\\file.txt", ".dat"));
+    }
+
+    @Test
+    public void testChangeExtension_NIX() {
+        Assume.assumeFalse(HostSystem.WINDOWS.detected());
+        fail("implement");
+    }
+    
+    @Test
+    public void testChangeExtensionPath_W32() {
+        Assume.assumeTrue(HostSystem.WINDOWS.detected());
+
+        assertEquals(Paths.get("file.txt"), pce("file.txt", ".txt"));
+        assertEquals(Paths.get("file.dat"), pce("file.txt", ".dat"));
+        assertEquals(Paths.get("file.txt.dat"), pce("file.txt.info", ".txt.dat"));
+        assertEquals(Paths.get("file.dat"), pce("file.txt.info", ".dat"));
+        assertEquals(Paths.get("file.dat"), pce("file", ".dat"));
+        
+        assertEquals(Paths.get("base","name","file.txt"), pce("base/name/file.txt", ".txt"));
+        assertEquals(Paths.get("base","name","file.dat"), pce("base\\name\\file.txt", ".dat"));
+        assertEquals(Paths.get("c:","base","name","file.dat"), pce("c:\\base\\name\\file.txt", ".dat"));
+        assertEquals(Paths.get("/base","name","file.dat"), pce("/base/name\\file.txt", ".dat"));
+    }
+
+    @Test
+    public void testChangeExtensionP_NIX() {
+        Assume.assumeFalse(HostSystem.WINDOWS.detected());
+        fail("implement");
+    }
+
+    @Test
+    public void testFromURL_W32() throws MalformedURLException {
+        Assume.assumeTrue(HostSystem.WINDOWS.detected());
+
+        assertThrows(FileSystemNotFoundException.class, ()->{
+            PathUtils.fromURL(new URL("http://ranides.net/index.htm"));
+        });
+        assertThrows(FileSystemNotFoundException.class, ()->{
+            PathUtils.fromURL(new URL("ftp://ranides.net/index.htm"));
+        });
+
+        assertEquals(Paths.get("/ranides.net/index.htm"), PathUtils.fromURL(new URL("file:///ranides.net/index.htm")));
+        assertEquals(Paths.get("c:/ms/index.htm"), PathUtils.fromURL(new URL("file:///c:/ms/index.htm")));
+        
+                
+        assertThrows(IllegalArgumentException.class, ()->{
+            PathUtils.fromURL(new URL("file://c:/ms/index.htm?query"));
+        });
+    }
+
+    @Test
+    public void testFromURL_NIX() {
+        Assume.assumeFalse(HostSystem.WINDOWS.detected());
+        fail("implement");
+    }
+
+    private static Path pce(String path, String ext) {
+        return PathUtils.changeExtension(Paths.get(path), ext);
+    }
+
+
+}