All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.owasp.shim.ForJava8 Maven / Gradle / Ivy

Go to download

Backports @since Java 9 collection factories like List.of onto Java8 in a way that uses the real ones where available, falls back to a conforming implementation on Java8 and JIT compiles well.

The newest version!
package org.owasp.shim;

import java.util.*;

class ForJava8 extends Java8Shim {
    @Override public  List listOf() {
        return ImmutableListShim.empty();
    }

    @Override public  List listOf(T a) {
        return new ImmutableListShim<>(Collections.singletonList(a));
    }

    @Override public  List listOf(T a, T b) {
        ArrayList ls = new ArrayList<>(2);
        ls.add(a);
        ls.add(b);
        return new ImmutableListShim<>(ls);
    }

    @Override public  List listOf(T a, T b, T c) {
        ArrayList ls = new ArrayList<>(3);
        ls.add(a);
        ls.add(b);
        ls.add(c);
        return new ImmutableListShim<>(ls);
    }

    @Override public  List listOf(T... els) {
        return new ImmutableListShim<>(Arrays.asList(els));
    }

    @SuppressWarnings("unchecked") // Immutable collections aren't invariant
    @Override public  List listCopyOf(Collection c) {
        if (c instanceof ImmutableListShim) {
            return (ImmutableListShim) c;
        }
        return new ImmutableListShim<>(new ArrayList<>(c));
    }

    @SuppressWarnings("unchecked") // Immutable collections aren't invariant
    @Override public  Map mapCopyOf(Map m) {
        if (m instanceof ImmutableMapShim) {
            return (ImmutableMapShim) m;
        }
        return new ImmutableMapShim<>(new LinkedHashMap<>(m));
    }

    @Override public  Map.Entry mapEntry(K key, V value) {
        return new ImmutableEntryShim<>(key, value);
    }

    @Override public  Map mapOfEntries(Map.Entry... entries) {
        Map m = new LinkedHashMap<>(entries.length);
        for (Map.Entry e : entries) {
            m.put(e.getKey(), e.getValue());
        }
        return new ImmutableMapShim<>(m);
    }

    @Override public  Set setOf() {
        return new ImmutableSetShim<>(Collections.emptySet());
    }

    @Override public  Set setOf(T a) {
        return new ImmutableSetShim<>(Collections.singleton(a));
    }

    @Override public  Set setOf(T a, T b) {
        LinkedHashSet ls = new LinkedHashSet<>(2);
        ls.add(a);
        ls.add(b);
        return new ImmutableSetShim<>(ls);
    }

    @Override public  Set setOf(T a, T b, T c) {
        LinkedHashSet ls = new LinkedHashSet<>(3);
        ls.add(a);
        ls.add(b);
        ls.add(c);
        return new ImmutableSetShim<>(ls);
    }

    @Override public  Set setOf(T... els) {
        return new ImmutableSetShim<>(new LinkedHashSet<>(Arrays.asList(els)));
    }

    @SuppressWarnings("unchecked") // Immutable collections aren't invariant
    @Override public  Set setCopyOf(Collection c) {
        if (c instanceof ImmutableSetShim) {

            return (ImmutableSetShim) c;
        }
        return new ImmutableSetShim<>(new LinkedHashSet<>(c));
    }

    private static final class ImmutableListShim extends AbstractList {
        private final List underlying;

        ImmutableListShim(List underlying) {
            this.underlying = underlying;
        }

        @Override
        public T get(int index) {
            return underlying.get(index);
        }

        @Override
        public int size() {
            return underlying.size();
        }

        private static final ImmutableListShim empty = new ImmutableListShim<>(Collections.emptyList());

        @SuppressWarnings("unchecked") // contains no elements of any specific T
        static  ImmutableListShim empty() {
            return (ImmutableListShim) empty;
        }
    }

    private static final class ImmutableMapShim extends AbstractMap {
        private final Map underlying;

        ImmutableMapShim(Map underlying) {
            this.underlying = underlying;
        }

        @Override
        public V get(Object k) {
            return underlying.get(k);
        }

        @Override
        public boolean containsKey(Object k) {
            return underlying.containsKey(k);
        }

        @Override
        public Set> entrySet() {
            return new ImmutableEntrySetShim<>(underlying.entrySet());
        }
    }

    private static final class ImmutableEntrySetShim extends AbstractSet> {
        private final Set> underlying;
        ImmutableEntrySetShim(Set> underlying) {
            this.underlying = underlying;
        }


        @Override
        public Iterator> iterator() {
            class IteratorImpl implements Iterator> {
                private final Iterator> underlying;
                private ImmutableEntryShim pending;

                IteratorImpl(Iterator> underlying) {
                    this.underlying = underlying;
                }

                @Override
                public boolean hasNext() {
                    if (pending == null && underlying.hasNext()) {
                        Map.Entry e = underlying.next();
                        pending = new ImmutableEntryShim<>(e.getKey(), e.getValue());
                    }
                    return pending != null;
                }

                @Override
                public Map.Entry next() {
                    ImmutableEntryShim next = pending;
                    pending = null;
                    if (next == null) { throw new NoSuchElementException(); }
                    return next;
                }

                @Override
                public void remove() {
                    throw new UnsupportedOperationException();
                }
            }
            return new IteratorImpl(underlying.iterator());
        }

        @Override
        public int size() {
            return underlying.size();
        }
    }

    private static final class ImmutableEntryShim implements Map.Entry {
        private final K key;
        private final V value;
        ImmutableEntryShim(K key, V value) {
            this.key = key;
            this.value = value;
        }

        @Override
        public K getKey() { return key; }

        @Override
        public V getValue() { return value; }

        @Override
        public V setValue(V value) {
            throw new UnsupportedOperationException();
        }
    }

    private static final class ImmutableSetShim extends AbstractSet {
        private final Set underlying;

        ImmutableSetShim(Set underlying) {
            this.underlying = underlying;
        }

        @Override
        public Iterator iterator() {
            class IteratorImpl implements Iterator {
                private final Iterator underlying;
                IteratorImpl(Iterator underlying) {
                    this.underlying = underlying;
                }

                @Override
                public boolean hasNext() {
                    return underlying.hasNext();
                }

                @Override
                public T next() {
                    return underlying.next();
                }

                @Override
                public void remove() {
                    throw new UnsupportedOperationException();
                }
            }
            return new IteratorImpl(underlying.iterator());
        }

        @Override
        public int size() {
            return underlying.size();
        }

        @Override
        public boolean contains(Object o) {
            return underlying.contains(o);
        }
    }
}