    /**
     * {@inheritDoc}
     */
    @Override
    public <T> void addToAttachmentList(final AttachmentKey<AttachmentList<T>> key, final T value) {
        if (key != null) {
            if(attachments == null) {
                attachments = createAttachmentMap();
            }
            final Map<AttachmentKey<?>, Object> attachments = this.attachments;
            final AttachmentList<T> list = key.cast(attachments.get(key));
            if (list == null) {
                final AttachmentList<T> newList = new AttachmentList<>(((ListAttachmentKey<T>) key).getValueClass());
                attachments.put(key, newList);
                newList.add(value);
            } else {
                list.add(value);
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public <T> void addToAttachmentList(final AttachmentKey<AttachmentList<T>> key, final T value) {
        if (key != null) {
            if(attachments == null) {
                attachments = createAttachmentMap();
            }
            final Map<AttachmentKey<?>, Object> attachments = this.attachments;
            final AttachmentList<T> list = key.cast(attachments.get(key));
            if (list == null) {
                final AttachmentList<T> newList = new AttachmentList<T>(((ListAttachmentKey<T>) key).getValueClass());
                attachments.put(key, newList);
                newList.add(value);
            } else {
                list.add(value);
            }
        }
    }

Replace Generic With Diamond AttachmentList<T> with AttachmentList<> in method public addToAttachmentList(key AttachmentKey<AttachmentList<T>>, value T) : void from class io.undertow.util.AbstractAttachable


    private static String realCanonicalize(final String path, final int lastDot, final int initialState) {
        int state = initialState;
        int eatCount = 0;
        int tokenEnd = path.length();
        final List<String> parts = new ArrayList<>();
        for (int i = lastDot - 1; i >= 0; --i) {
            final char c = path.charAt(i);
            switch (state) {
                case NORMAL: {
                    if (c == '/') {
                        state = FIRST_SLASH;
                        if (eatCount > 0) {
                            --eatCount;
                            tokenEnd = i;
                        }
                    }
                    break;
                }
                case FIRST_SLASH: {
                    if (c == '.') {
                        state = ONE_DOT;
                    } else if (c == '/') {
                        if (eatCount > 0) {
                            --eatCount;
                            tokenEnd = i;
                        } else {
                            parts.add(path.substring(i + 1, tokenEnd));
                            tokenEnd = i;
                        }
                    } else {
                        state = NORMAL;
                    }
                    break;
                }
                case ONE_DOT: {
                    if (c == '.') {
                        state = TWO_DOT;
                    } else if (c == '/') {
                        if (i + 2 != tokenEnd) {
                            parts.add(path.substring(i + 2, tokenEnd));
                        }
                        tokenEnd = i;
                        state = FIRST_SLASH;
                    } else {
                        state = NORMAL;
                    }
                    break;
                }
                case TWO_DOT: {
                    if (c == '/') {
                        if (i + 3 != tokenEnd) {
                            parts.add(path.substring(i + 3, tokenEnd));
                        }
                        tokenEnd = i;
                        eatCount++;
                        state = FIRST_SLASH;
                    } else {
                        state = NORMAL;
                    }
                }
            }
        }
        final StringBuilder result = new StringBuilder();
        if (tokenEnd != 0) {
            result.append(path.substring(0, tokenEnd));
        }
        for (int i = parts.size() - 1; i >= 0; --i) {
            result.append(parts.get(i));
        }
        if(result.length() == 0) {
            return "/";
        }
        return result.toString();
    }

    private static String realCanonicalize(final String path, final int lastDot, final int initialState) {
        int state = initialState;
        int eatCount = 0;
        int tokenEnd = path.length();
        final List<String> parts = new ArrayList<String>();
        for (int i = lastDot - 1; i >= 0; --i) {
            final char c = path.charAt(i);
            switch (state) {
                case NORMAL: {
                    if (c == '/') {
                        state = FIRST_SLASH;
                        if (eatCount > 0) {
                            --eatCount;
                            tokenEnd = i;
                        }
                    }
                    break;
                }
                case FIRST_SLASH: {
                    if (c == '.') {
                        state = ONE_DOT;
                    } else if (c == '/') {
                        if (eatCount > 0) {
                            --eatCount;
                            tokenEnd = i;
                        } else {
                            parts.add(path.substring(i + 1, tokenEnd));
                            tokenEnd = i;
                        }
                    } else {
                        state = NORMAL;
                    }
                    break;
                }
                case ONE_DOT: {
                    if (c == '.') {
                        state = TWO_DOT;
                    } else if (c == '/') {
                        if (i + 2 != tokenEnd) {
                            parts.add(path.substring(i + 2, tokenEnd));
                        }
                        tokenEnd = i;
                        state = FIRST_SLASH;
                    } else {
                        state = NORMAL;
                    }
                    break;
                }
                case TWO_DOT: {
                    if (c == '/') {
                        if (i + 3 != tokenEnd) {
                            parts.add(path.substring(i + 3, tokenEnd));
                        }
                        tokenEnd = i;
                        eatCount++;
                        state = FIRST_SLASH;
                    } else {
                        state = NORMAL;
                    }
                }
            }
        }
        final StringBuilder result = new StringBuilder();
        if (tokenEnd != 0) {
            result.append(path.substring(0, tokenEnd));
        }
        for (int i = parts.size() - 1; i >= 0; --i) {
            result.append(parts.get(i));
        }
        if(result.length() == 0) {
            return "/";
        }
        return result.toString();
    }

Replace Generic With Diamond ArrayList<String> with ArrayList<> in method private realCanonicalize(path String, lastDot int, initialState int) : String from class io.undertow.util.CanonicalPathUtils


    public CopyOnWriteMap(Map<K, V> existing) {
        this.delegate = new HashMap<>(existing);
    }

    public CopyOnWriteMap(Map<K, V> existing) {
        this.delegate = new HashMap<K, V>(existing);
    }

Replace Generic With Diamond HashMap<K,V> with HashMap<> in method public CopyOnWriteMap(existing Map<K,V>) from class io.undertow.util.CopyOnWriteMap


    @Override
    public synchronized void putAll(Map<? extends K, ? extends V> m) {
        final Map<K, V> delegate = new HashMap<>(this.delegate);
        for(Entry<? extends K, ? extends V> e : m.entrySet()) {
            delegate.put(e.getKey(), e.getValue());
        }
        this.delegate = delegate;
    }

    @Override
    public synchronized void putAll(Map<? extends K, ? extends V> m) {
        final Map<K, V> delegate = new HashMap<K, V>(this.delegate);
        for(Entry<? extends K, ? extends V> e : m.entrySet()) {
            delegate.put(e.getKey(), e.getValue());
        }
        this.delegate = delegate;
    }

Replace Generic With Diamond HashMap<K,V> with HashMap<> in method public putAll(m Map<? extends K,? extends V>) : void from class io.undertow.util.CopyOnWriteMap


    private V putInternal(final K key, final V value) {
        final Map<K, V> delegate = new HashMap<>(this.delegate);
        V existing = delegate.put(key, value);
        this.delegate = delegate;
        return existing;
    }

    private V putInternal(final K key, final V value) {
        final Map<K, V> delegate = new HashMap<K, V>(this.delegate);
        V existing = delegate.put(key, value);
        this.delegate = delegate;
        return existing;
    }

Replace Generic With Diamond HashMap<K,V> with HashMap<> in method private putInternal(key K, value V) : V from class io.undertow.util.CopyOnWriteMap


    public V removeInternal(final Object key) {
        final Map<K, V> delegate = new HashMap<>(this.delegate);
        V existing = delegate.remove(key);
        this.delegate = delegate;
        return existing;
    }

    public V removeInternal(final Object key) {
        final Map<K, V> delegate = new HashMap<K, V>(this.delegate);
        V existing = delegate.remove(key);
        this.delegate = delegate;
        return existing;
    }

Replace Generic With Diamond HashMap<K,V> with HashMap<> in method public removeInternal(key Object) : V from class io.undertow.util.CopyOnWriteMap


    public static List<ETag> parseETagList(final String header) {
        char[] headerChars = header.toCharArray();

        // The LinkedHashMap is used so that the parameter order can also be retained.
        List<ETag> response = new ArrayList<>();

        SearchingFor searchingFor = SearchingFor.START_OF_VALUE;
        String currentToken = null;
        int valueStart = 0;
        boolean weak = false;
        boolean malformed = false;

        for (int i = 0; i < headerChars.length; i++) {
            switch (searchingFor) {
                case START_OF_VALUE:
                    if (headerChars[i] != COMMA && !Character.isWhitespace(headerChars[i])) {
                        if (headerChars[i] == QUOTE) {
                            valueStart = i + 1;
                            searchingFor = SearchingFor.LAST_QUOTE;
                            weak = false;
                            malformed = false;
                        } else if (headerChars[i] == W) {
                            searchingFor = SearchingFor.WEAK_SLASH;
                        }
                    }
                    break;
                case WEAK_SLASH:
                    if (headerChars[i] == QUOTE) {
                        valueStart = i + 1;
                        searchingFor = SearchingFor.LAST_QUOTE;
                        weak = true;
                        malformed = false;
                    } else if (headerChars[i] != SLASH) {
                        malformed = true;
                        searchingFor = SearchingFor.END_OF_VALUE;
                    }
                    break;
                case LAST_QUOTE:
                    if (headerChars[i] == QUOTE) {
                        String value = String.valueOf(headerChars, valueStart, i - valueStart);
                        response.add(new ETag(weak, value.trim()));
                        searchingFor = SearchingFor.START_OF_VALUE;
                    }
                    break;
                case END_OF_VALUE:
                    if (headerChars[i] == COMMA || Character.isWhitespace(headerChars[i])) {
                        if (!malformed) {
                            String value = String.valueOf(headerChars, valueStart, i - valueStart);
                            response.add(new ETag(weak, value.trim()));
                            searchingFor = SearchingFor.START_OF_VALUE;
                        }
                    }
                    break;
            }
        }

        if (searchingFor == SearchingFor.END_OF_VALUE || searchingFor == SearchingFor.LAST_QUOTE) {
            if (!malformed) {
                // Special case where we reached the end of the array containing the header values.
                String value = String.valueOf(headerChars, valueStart, headerChars.length - valueStart);
                response.add(new ETag(weak, value.trim()));
            }
        }

        return response;
    }

    public static List<ETag> parseETagList(final String header) {
        char[] headerChars = header.toCharArray();

        // The LinkedHashMap is used so that the parameter order can also be retained.
        List<ETag> response = new ArrayList<ETag>();

        SearchingFor searchingFor = SearchingFor.START_OF_VALUE;
        String currentToken = null;
        int valueStart = 0;
        boolean weak = false;
        boolean malformed = false;

        for (int i = 0; i < headerChars.length; i++) {
            switch (searchingFor) {
                case START_OF_VALUE:
                    if (headerChars[i] != COMMA && !Character.isWhitespace(headerChars[i])) {
                        if (headerChars[i] == QUOTE) {
                            valueStart = i + 1;
                            searchingFor = SearchingFor.LAST_QUOTE;
                            weak = false;
                            malformed = false;
                        } else if (headerChars[i] == W) {
                            searchingFor = SearchingFor.WEAK_SLASH;
                        }
                    }
                    break;
                case WEAK_SLASH:
                    if (headerChars[i] == QUOTE) {
                        valueStart = i + 1;
                        searchingFor = SearchingFor.LAST_QUOTE;
                        weak = true;
                        malformed = false;
                    } else if (headerChars[i] != SLASH) {
                        malformed = true;
                        searchingFor = SearchingFor.END_OF_VALUE;
                    }
                    break;
                case LAST_QUOTE:
                    if (headerChars[i] == QUOTE) {
                        String value = String.valueOf(headerChars, valueStart, i - valueStart);
                        response.add(new ETag(weak, value.trim()));
                        searchingFor = SearchingFor.START_OF_VALUE;
                    }
                    break;
                case END_OF_VALUE:
                    if (headerChars[i] == COMMA || Character.isWhitespace(headerChars[i])) {
                        if (!malformed) {
                            String value = String.valueOf(headerChars, valueStart, i - valueStart);
                            response.add(new ETag(weak, value.trim()));
                            searchingFor = SearchingFor.START_OF_VALUE;
                        }
                    }
                    break;
            }
        }

        if (searchingFor == SearchingFor.END_OF_VALUE || searchingFor == SearchingFor.LAST_QUOTE) {
            if (!malformed) {
                // Special case where we reached the end of the array containing the header values.
                String value = String.valueOf(headerChars, valueStart, headerChars.length - valueStart);
                response.add(new ETag(weak, value.trim()));
            }
        }

        return response;
    }

Replace Generic With Diamond ArrayList<ETag> with ArrayList<> in method public parseETagList(header String) : List<ETag> from class io.undertow.util.ETagUtils


    /**
     * Links e as first element.
     */
    private Node linkFirst(E e) {
        checkNotNull(e);
        final Node<E> newNode = new Node<>(e);

        restartFromHead:
        for (;;)
            for (Node<E> h = head, p = h, q;;) {
                if ((q = p.prev) != null &&
                    (q = (p = q).prev) != null)
                    // Check for head updates every other hop.
                    // If p == q, we are sure to follow head instead.
                    p = (h != (h = head)) ? h : q;
                else if (p.next == p) // PREV_TERMINATOR
                    continue restartFromHead;
                else {
                    // p is first node
                    newNode.lazySetNext(p); // CAS piggyback
                    if (p.casPrev(null, newNode)) {
                        // Successful CAS is the linearization point
                        // for e to become an element of this deque,
                        // and for newNode to become "live".
                        if (p != h) // hop two nodes at a time
                            casHead(h, newNode);  // Failure is OK.
                        return newNode;
                    }
                    // Lost CAS race to another thread; re-read prev
                }
            }
    }

    /**
     * Links e as first element.
     */
    private Node linkFirst(E e) {
        checkNotNull(e);
        final Node<E> newNode = new Node<E>(e);

        restartFromHead:
        for (;;)
            for (Node<E> h = head, p = h, q;;) {
                if ((q = p.prev) != null &&
                    (q = (p = q).prev) != null)
                    // Check for head updates every other hop.
                    // If p == q, we are sure to follow head instead.
                    p = (h != (h = head)) ? h : q;
                else if (p.next == p) // PREV_TERMINATOR
                    continue restartFromHead;
                else {
                    // p is first node
                    newNode.lazySetNext(p); // CAS piggyback
                    if (p.casPrev(null, newNode)) {
                        // Successful CAS is the linearization point
                        // for e to become an element of this deque,
                        // and for newNode to become "live".
                        if (p != h) // hop two nodes at a time
                            casHead(h, newNode);  // Failure is OK.
                        return newNode;
                    }
                    // Lost CAS race to another thread; re-read prev
                }
            }
    }

Replace Generic With Diamond Node<E> with Node<> in method private linkFirst(e E) : Node from class io.undertow.util.FastConcurrentDirectDeque


    /**
     * Links e as last element.
     */
    private Node linkLast(E e) {
        checkNotNull(e);
        final Node<E> newNode = new Node<>(e);

        restartFromTail:
        for (;;)
            for (Node<E> t = tail, p = t, q;;) {
                if ((q = p.next) != null &&
                    (q = (p = q).next) != null)
                    // Check for tail updates every other hop.
                    // If p == q, we are sure to follow tail instead.
                    p = (t != (t = tail)) ? t : q;
                else if (p.prev == p) // NEXT_TERMINATOR
                    continue restartFromTail;
                else {
                    // p is last node
                    newNode.lazySetPrev(p); // CAS piggyback
                    if (p.casNext(null, newNode)) {
                        // Successful CAS is the linearization point
                        // for e to become an element of this deque,
                        // and for newNode to become "live".
                        if (p != t) // hop two nodes at a time
                            casTail(t, newNode);  // Failure is OK.
                        return newNode;
                    }
                    // Lost CAS race to another thread; re-read next
                }
            }
    }

    /**
     * Links e as last element.
     */
    private Node linkLast(E e) {
        checkNotNull(e);
        final Node<E> newNode = new Node<E>(e);

        restartFromTail:
        for (;;)
            for (Node<E> t = tail, p = t, q;;) {
                if ((q = p.next) != null &&
                    (q = (p = q).next) != null)
                    // Check for tail updates every other hop.
                    // If p == q, we are sure to follow tail instead.
                    p = (t != (t = tail)) ? t : q;
                else if (p.prev == p) // NEXT_TERMINATOR
                    continue restartFromTail;
                else {
                    // p is last node
                    newNode.lazySetPrev(p); // CAS piggyback
                    if (p.casNext(null, newNode)) {
                        // Successful CAS is the linearization point
                        // for e to become an element of this deque,
                        // and for newNode to become "live".
                        if (p != t) // hop two nodes at a time
                            casTail(t, newNode);  // Failure is OK.
                        return newNode;
                    }
                    // Lost CAS race to another thread; re-read next
                }
            }
    }

Replace Generic With Diamond Node<E> with Node<> in method private linkLast(e E) : Node from class io.undertow.util.FastConcurrentDirectDeque


    /**
     * Creates an array list and fills it with elements of this list.
     * Used by toArray.
     *
     * @return the arrayList
     */
    private ArrayList<E> toArrayList() {
        ArrayList<E> list = new ArrayList<>();
        for (Node<E> p = first(); p != null; p = succ(p)) {
            E item = p.item;
            if (item != null)
                list.add(item);
        }
        return list;
    }

    /**
     * Creates an array list and fills it with elements of this list.
     * Used by toArray.
     *
     * @return the arrayList
     */
    private ArrayList<E> toArrayList() {
        ArrayList<E> list = new ArrayList<E>();
        for (Node<E> p = first(); p != null; p = succ(p)) {
            E item = p.item;
            if (item != null)
                list.add(item);
        }
        return list;
    }

Replace Generic With Diamond ArrayList<E> with ArrayList<> in method private toArrayList() : ArrayList<E> from class io.undertow.util.FastConcurrentDirectDeque


    /**
     * Constructs an empty deque.
     */
    public FastConcurrentDirectDeque() {
        head = tail = new Node<>(null);
    }

    /**
     * Constructs an empty deque.
     */
    public FastConcurrentDirectDeque() {
        head = tail = new Node<E>(null);
    }

Replace Generic With Diamond Node<E> with Node<> in method public FastConcurrentDirectDeque() from class io.undertow.util.FastConcurrentDirectDeque


    /**
     * Constructs a deque initially containing the elements of
     * the given collection, added in traversal order of the
     * collection's iterator.
     *
     * @param c the collection of elements to initially contain
     * @throws NullPointerException if the specified collection or any
     *         of its elements are null
     */
    public FastConcurrentDirectDeque(Collection<? extends E> c) {
        // Copy c into a private chain of Nodes
        Node<E> h = null, t = null;
        for (E e : c) {
            checkNotNull(e);
            Node<E> newNode = new Node<>(e);
            if (h == null)
                h = t = newNode;
            else {
                t.lazySetNext(newNode);
                newNode.lazySetPrev(t);
                t = newNode;
            }
        }
        initHeadTail(h, t);
    }

    /**
     * Constructs a deque initially containing the elements of
     * the given collection, added in traversal order of the
     * collection's iterator.
     *
     * @param c the collection of elements to initially contain
     * @throws NullPointerException if the specified collection or any
     *         of its elements are null
     */
    public FastConcurrentDirectDeque(Collection<? extends E> c) {
        // Copy c into a private chain of Nodes
        Node<E> h = null, t = null;
        for (E e : c) {
            checkNotNull(e);
            Node<E> newNode = new Node<E>(e);
            if (h == null)
                h = t = newNode;
            else {
                t.lazySetNext(newNode);
                newNode.lazySetPrev(t);
                t = newNode;
            }
        }
        initHeadTail(h, t);
    }

Replace Generic With Diamond Node<E> with Node<> in method public FastConcurrentDirectDeque(c Collection<? extends E>) from class io.undertow.util.FastConcurrentDirectDeque


    /**
     * Appends all of the elements in the specified collection to the end of
     * this deque, in the order that they are returned by the specified
     * collection's iterator.  Attempts to {@code addAll} of a deque to
     * itself result in {@code IllegalArgumentException}.
     *
     * @param c the elements to be inserted into this deque
     * @return {@code true} if this deque changed as a result of the call
     * @throws NullPointerException if the specified collection or any
     *         of its elements are null
     * @throws IllegalArgumentException if the collection is this deque
     */
    public boolean addAll(Collection<? extends E> c) {
        if (c == this)
            // As historically specified in AbstractQueue#addAll
            throw new IllegalArgumentException();

        // Copy c into a private chain of Nodes
        Node<E> beginningOfTheEnd = null, last = null;
        for (E e : c) {
            checkNotNull(e);
            Node<E> newNode = new Node<>(e);
            if (beginningOfTheEnd == null)
                beginningOfTheEnd = last = newNode;
            else {
                last.lazySetNext(newNode);
                newNode.lazySetPrev(last);
                last = newNode;
            }
        }
        if (beginningOfTheEnd == null)
            return false;

        // Atomically append the chain at the tail of this collection
        restartFromTail:
        for (;;)
            for (Node<E> t = tail, p = t, q;;) {
                if ((q = p.next) != null &&
                    (q = (p = q).next) != null)
                    // Check for tail updates every other hop.
                    // If p == q, we are sure to follow tail instead.
                    p = (t != (t = tail)) ? t : q;
                else if (p.prev == p) // NEXT_TERMINATOR
                    continue restartFromTail;
                else {
                    // p is last node
                    beginningOfTheEnd.lazySetPrev(p); // CAS piggyback
                    if (p.casNext(null, beginningOfTheEnd)) {
                        // Successful CAS is the linearization point
                        // for all elements to be added to this deque.
                        if (!casTail(t, last)) {
                            // Try a little harder to update tail,
                            // since we may be adding many elements.
                            t = tail;
                            if (last.next == null)
                                casTail(t, last);
                        }
                        return true;
                    }
                    // Lost CAS race to another thread; re-read next
                }
            }
    }

    /**
     * Appends all of the elements in the specified collection to the end of
     * this deque, in the order that they are returned by the specified
     * collection's iterator.  Attempts to {@code addAll} of a deque to
     * itself result in {@code IllegalArgumentException}.
     *
     * @param c the elements to be inserted into this deque
     * @return {@code true} if this deque changed as a result of the call
     * @throws NullPointerException if the specified collection or any
     *         of its elements are null
     * @throws IllegalArgumentException if the collection is this deque
     */
    public boolean addAll(Collection<? extends E> c) {
        if (c == this)
            // As historically specified in AbstractQueue#addAll
            throw new IllegalArgumentException();

        // Copy c into a private chain of Nodes
        Node<E> beginningOfTheEnd = null, last = null;
        for (E e : c) {
            checkNotNull(e);
            Node<E> newNode = new Node<E>(e);
            if (beginningOfTheEnd == null)
                beginningOfTheEnd = last = newNode;
            else {
                last.lazySetNext(newNode);
                newNode.lazySetPrev(last);
                last = newNode;
            }
        }
        if (beginningOfTheEnd == null)
            return false;

        // Atomically append the chain at the tail of this collection
        restartFromTail:
        for (;;)
            for (Node<E> t = tail, p = t, q;;) {
                if ((q = p.next) != null &&
                    (q = (p = q).next) != null)
                    // Check for tail updates every other hop.
                    // If p == q, we are sure to follow tail instead.
                    p = (t != (t = tail)) ? t : q;
                else if (p.prev == p) // NEXT_TERMINATOR
                    continue restartFromTail;
                else {
                    // p is last node
                    beginningOfTheEnd.lazySetPrev(p); // CAS piggyback
                    if (p.casNext(null, beginningOfTheEnd)) {
                        // Successful CAS is the linearization point
                        // for all elements to be added to this deque.
                        if (!casTail(t, last)) {
                            // Try a little harder to update tail,
                            // since we may be adding many elements.
                            t = tail;
                            if (last.next == null)
                                casTail(t, last);
                        }
                        return true;
                    }
                    // Lost CAS race to another thread; re-read next
                }
            }
    }

Replace Generic With Diamond Node<E> with Node<> in method public addAll(c Collection<? extends E>) : boolean from class io.undertow.util.FastConcurrentDirectDeque


    /**
     * Reconstitutes this deque from a stream (that is, deserializes it).
     */
    private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
        s.defaultReadObject();

        // Read in elements until trailing null sentinel found
        Node<E> h = null, t = null;
        Object item;
        while ((item = s.readObject()) != null) {
            @SuppressWarnings("unchecked")
            Node<E> newNode = new Node<>((E) item);
            if (h == null)
                h = t = newNode;
            else {
                t.lazySetNext(newNode);
                newNode.lazySetPrev(t);
                t = newNode;
            }
        }
        initHeadTail(h, t);
    }

    /**
     * Reconstitutes this deque from a stream (that is, deserializes it).
     */
    private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
        s.defaultReadObject();

        // Read in elements until trailing null sentinel found
        Node<E> h = null, t = null;
        Object item;
        while ((item = s.readObject()) != null) {
            @SuppressWarnings("unchecked")
            Node<E> newNode = new Node<E>((E) item);
            if (h == null)
                h = t = newNode;
            else {
                t.lazySetNext(newNode);
                newNode.lazySetPrev(t);
                t = newNode;
            }
        }
        initHeadTail(h, t);
    }

Replace Generic With Diamond Node<E> with Node<> in method private readObject(s ObjectInputStream) : void from class io.undertow.util.FastConcurrentDirectDeque


    public Map<E, String> parseHeader(final String header) {
        char[] headerChars = header.toCharArray();

        // The LinkedHashMap is used so that the parameter order can also be retained.
        Map<E, String> response = new LinkedHashMap<>();

        SearchingFor searchingFor = SearchingFor.START_OF_NAME;
        int nameStart = 0;
        E currentToken = null;
        int valueStart = 0;

        for (int i = 0; i < headerChars.length; i++) {
            switch (searchingFor) {
                case START_OF_NAME:
                    // Eliminate any white space before the name of the parameter.
                    if (headerChars[i] != COMMA && !Character.isWhitespace(headerChars[i])) {
                        nameStart = i;
                        searchingFor = SearchingFor.EQUALS_SIGN;
                    }
                    break;
                case EQUALS_SIGN:
                    if (headerChars[i] == EQUALS) {
                        String paramName = String.valueOf(headerChars, nameStart, i - nameStart);
                        currentToken = expectedTokens.get(paramName);
                        if (currentToken == null) {
                            throw MESSAGES.unexpectedTokenInHeader(paramName);
                        }
                        searchingFor = SearchingFor.START_OF_VALUE;
                    }
                    break;
                case START_OF_VALUE:
                    if (!Character.isWhitespace(headerChars[i])) {
                        if (headerChars[i] == QUOTE && currentToken.isAllowQuoted()) {
                            valueStart = i + 1;
                            searchingFor = SearchingFor.LAST_QUOTE;
                        } else {
                            valueStart = i;
                            searchingFor = SearchingFor.END_OF_VALUE;
                        }
                    }
                    break;
                case LAST_QUOTE:
                    if (headerChars[i] == QUOTE) {
                        String value = String.valueOf(headerChars, valueStart, i - valueStart);
                        response.put(currentToken, value);

                        searchingFor = SearchingFor.START_OF_NAME;
                    }
                    break;
                case END_OF_VALUE:
                    if (headerChars[i] == COMMA || Character.isWhitespace(headerChars[i])) {
                        String value = String.valueOf(headerChars, valueStart, i - valueStart);
                        response.put(currentToken, value);

                        searchingFor = SearchingFor.START_OF_NAME;
                    }
                    break;
            }
        }

        if (searchingFor == SearchingFor.END_OF_VALUE) {
            // Special case where we reached the end of the array containing the header values.
            String value = String.valueOf(headerChars, valueStart, headerChars.length - valueStart);
            response.put(currentToken, value);
        } else if (searchingFor != SearchingFor.START_OF_NAME) {
            // Somehow we are still in the middle of searching for a current value.
            throw MESSAGES.invalidHeader();
        }

        return response;
    }

    public Map<E, String> parseHeader(final String header) {
        char[] headerChars = header.toCharArray();

        // The LinkedHashMap is used so that the parameter order can also be retained.
        Map<E, String> response = new LinkedHashMap<E, String>();

        SearchingFor searchingFor = SearchingFor.START_OF_NAME;
        int nameStart = 0;
        E currentToken = null;
        int valueStart = 0;

        for (int i = 0; i < headerChars.length; i++) {
            switch (searchingFor) {
                case START_OF_NAME:
                    // Eliminate any white space before the name of the parameter.
                    if (headerChars[i] != COMMA && !Character.isWhitespace(headerChars[i])) {
                        nameStart = i;
                        searchingFor = SearchingFor.EQUALS_SIGN;
                    }
                    break;
                case EQUALS_SIGN:
                    if (headerChars[i] == EQUALS) {
                        String paramName = String.valueOf(headerChars, nameStart, i - nameStart);
                        currentToken = expectedTokens.get(paramName);
                        if (currentToken == null) {
                            throw MESSAGES.unexpectedTokenInHeader(paramName);
                        }
                        searchingFor = SearchingFor.START_OF_VALUE;
                    }
                    break;
                case START_OF_VALUE:
                    if (!Character.isWhitespace(headerChars[i])) {
                        if (headerChars[i] == QUOTE && currentToken.isAllowQuoted()) {
                            valueStart = i + 1;
                            searchingFor = SearchingFor.LAST_QUOTE;
                        } else {
                            valueStart = i;
                            searchingFor = SearchingFor.END_OF_VALUE;
                        }
                    }
                    break;
                case LAST_QUOTE:
                    if (headerChars[i] == QUOTE) {
                        String value = String.valueOf(headerChars, valueStart, i - valueStart);
                        response.put(currentToken, value);

                        searchingFor = SearchingFor.START_OF_NAME;
                    }
                    break;
                case END_OF_VALUE:
                    if (headerChars[i] == COMMA || Character.isWhitespace(headerChars[i])) {
                        String value = String.valueOf(headerChars, valueStart, i - valueStart);
                        response.put(currentToken, value);

                        searchingFor = SearchingFor.START_OF_NAME;
                    }
                    break;
            }
        }

        if (searchingFor == SearchingFor.END_OF_VALUE) {
            // Special case where we reached the end of the array containing the header values.
            String value = String.valueOf(headerChars, valueStart, headerChars.length - valueStart);
            response.put(currentToken, value);
        } else if (searchingFor != SearchingFor.START_OF_NAME) {
            // Somehow we are still in the middle of searching for a current value.
            throw MESSAGES.invalidHeader();
        }

        return response;
    }

Replace Generic With Diamond LinkedHashMap<E,String> with LinkedHashMap<> in method public parseHeader(header String) : Map<E,String> from class io.undertow.util.HeaderTokenParser


    public static List<Locale> getLocalesFromHeader(final List<String> acceptLanguage) {
        if (acceptLanguage == null || acceptLanguage.isEmpty()) {
            return Collections.singletonList(Locale.getDefault());
        }
        final List<Locale> ret = new ArrayList<>();
        final List<List<QValueParser.QValueResult>> parsedResults = QValueParser.parse(acceptLanguage);
        for (List<QValueParser.QValueResult> qvalueResult : parsedResults) {
            for (QValueParser.QValueResult res : qvalueResult) {
                if (!res.isQValueZero()) {
                    Locale e = LocaleUtils.getLocaleFromString(res.getValue());
                    ret.add(e);
                }
            }
        }
        return ret;
    }

    public static List<Locale> getLocalesFromHeader(final List<String> acceptLanguage) {
        if (acceptLanguage == null || acceptLanguage.isEmpty()) {
            return Collections.singletonList(Locale.getDefault());
        }
        final List<Locale> ret = new ArrayList<Locale>();
        final List<List<QValueParser.QValueResult>> parsedResults = QValueParser.parse(acceptLanguage);
        for (List<QValueParser.QValueResult> qvalueResult : parsedResults) {
            for (QValueParser.QValueResult res : qvalueResult) {
                if (!res.isQValueZero()) {
                    Locale e = LocaleUtils.getLocaleFromString(res.getValue());
                    ret.add(e);
                }
            }
        }
        return ret;
    }

Replace Generic With Diamond ArrayList<Locale> with ArrayList<> in method public getLocalesFromHeader(acceptLanguage List<String>) : List<Locale> from class io.undertow.util.LocaleUtils


    private void buildLengths() {
        final Set<Integer> lengths = new TreeSet<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return -o1.compareTo(o2);
            }
        });
        for (String p : paths.keySet()) {
            lengths.add(p.length());
        }

        int[] lengthArray = new int[lengths.size()];
        int pos = 0;
        for (int i : lengths) {
            lengthArray[pos++] = i;
        }
        this.lengths = lengthArray;
    }

    private void buildLengths() {
        final Set<Integer> lengths = new TreeSet<Integer>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return -o1.compareTo(o2);
            }
        });
        for (String p : paths.keySet()) {
            lengths.add(p.length());
        }

        int[] lengthArray = new int[lengths.size()];
        int pos = 0;
        for (int i : lengths) {
            lengthArray[pos++] = i;
        }
        this.lengths = lengthArray;
    }

Replace Generic With Diamond TreeSet<Integer> with TreeSet<> in method private buildLengths() : void from class io.undertow.util.PathMatcher


    public PathMatchResult<T> match(final String path) {
        final Map<String, String> params = new HashMap<>();
        int length = path.length();
        final int[] lengths = this.lengths;
        for (int i = 0; i < lengths.length; ++i) {
            int pathLength = lengths[i];
            if (pathLength == length) {
                Set<PathTemplateHolder> entry = pathTemplateMap.get(path);
                if (entry != null) {
                    PathMatchResult<T> res = handleStemMatch(entry, path, params);
                    if (res != null) {
                        return res;
                    }
                }
            } else if (pathLength < length) {
                char c = path.charAt(pathLength);
                if (c == '/') {
                    String part = path.substring(0, pathLength);
                    Set<PathTemplateHolder> entry = pathTemplateMap.get(part);
                    if (entry != null) {
                        PathMatchResult<T> res = handleStemMatch(entry, path, params);
                        if (res != null) {
                            return res;
                        }
                    }
                }
            }
        }
        return null;
    }

    public PathMatchResult<T> match(final String path) {
        final Map<String, String> params = new HashMap<String, String>();
        int length = path.length();
        final int[] lengths = this.lengths;
        for (int i = 0; i < lengths.length; ++i) {
            int pathLength = lengths[i];
            if (pathLength == length) {
                Set<PathTemplateHolder> entry = pathTemplateMap.get(path);
                if (entry != null) {
                    PathMatchResult<T> res = handleStemMatch(entry, path, params);
                    if (res != null) {
                        return res;
                    }
                }
            } else if (pathLength < length) {
                char c = path.charAt(pathLength);
                if (c == '/') {
                    String part = path.substring(0, pathLength);
                    Set<PathTemplateHolder> entry = pathTemplateMap.get(part);
                    if (entry != null) {
                        PathMatchResult<T> res = handleStemMatch(entry, path, params);
                        if (res != null) {
                            return res;
                        }
                    }
                }
            }
        }
        return null;
    }

Replace Generic With Diamond HashMap<String,String> with HashMap<> in method public match(path String) : PathMatchResult<T> from class io.undertow.util.PathTemplateMatcher


    private PathMatchResult<T> handleStemMatch(Set<PathTemplateHolder> entry, final String path, final Map<String, String> params) {
        for (PathTemplateHolder val : entry) {
            if (val.template.matches(path, params)) {
                return new PathMatchResult<>(params, val.template.getTemplateString(), val.value);
            } else {
                params.clear();
            }
        }
        return null;
    }

    private PathMatchResult<T> handleStemMatch(Set<PathTemplateHolder> entry, final String path, final Map<String, String> params) {
        for (PathTemplateHolder val : entry) {
            if (val.template.matches(path, params)) {
                return new PathMatchResult<T>(params, val.template.getTemplateString(), val.value);
            } else {
                params.clear();
            }
        }
        return null;
    }

Replace Generic With Diamond PathMatchResult<T> with PathMatchResult<> in method private handleStemMatch(entry Set<PathTemplateHolder>, path String, params Map<String,String>) : PathMatchResult<T> from class io.undertow.util.PathTemplateMatcher


    private void buildLengths() {
        final Set<Integer> lengths = new TreeSet<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return -o1.compareTo(o2);
            }
        });
        for (String p : pathTemplateMap.keySet()) {
            lengths.add(p.length());
        }

        int[] lengthArray = new int[lengths.size()];
        int pos = 0;
        for (int i : lengths) {
            lengthArray[pos++] = i; //-1 because the base paths end with a /
        }
        this.lengths = lengthArray;
    }

    private void buildLengths() {
        final Set<Integer> lengths = new TreeSet<Integer>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return -o1.compareTo(o2);
            }
        });
        for (String p : pathTemplateMap.keySet()) {
            lengths.add(p.length());
        }

        int[] lengthArray = new int[lengths.size()];
        int pos = 0;
        for (int i : lengths) {
            lengthArray[pos++] = i; //-1 because the base paths end with a /
        }
        this.lengths = lengthArray;
    }

Replace Generic With Diamond TreeSet<Integer> with TreeSet<> in method private buildLengths() : void from class io.undertow.util.PathTemplateMatcher


    private synchronized PathTemplateMatcher<T> remove(PathTemplate template) {
        Set<PathTemplateHolder> values = pathTemplateMap.get(trimBase(template));
        Set<PathTemplateHolder> newValues;
        if (values == null) {
            return this;
        } else {
            newValues = new TreeSet<>(values);
        }
        Iterator<PathTemplateHolder> it = newValues.iterator();
        while (it.hasNext()) {
            PathTemplateHolder next = it.next();
            if (next.template.getTemplateString().equals(template.getTemplateString())) {
                it.remove();
                break;
            }
        }
        if (newValues.size() == 0) {
            pathTemplateMap.remove(trimBase(template));
        } else {
            pathTemplateMap.put(trimBase(template), newValues);
        }
        buildLengths();
        return this;
    }

    private synchronized PathTemplateMatcher<T> remove(PathTemplate template) {
        Set<PathTemplateHolder> values = pathTemplateMap.get(trimBase(template));
        Set<PathTemplateHolder> newValues;
        if (values == null) {
            return this;
        } else {
            newValues = new TreeSet<PathTemplateHolder>(values);
        }
        Iterator<PathTemplateHolder> it = newValues.iterator();
        while (it.hasNext()) {
            PathTemplateHolder next = it.next();
            if (next.template.getTemplateString().equals(template.getTemplateString())) {
                it.remove();
                break;
            }
        }
        if (newValues.size() == 0) {
            pathTemplateMap.remove(trimBase(template));
        } else {
            pathTemplateMap.put(trimBase(template), newValues);
        }
        buildLengths();
        return this;
    }

Replace Generic With Diamond TreeSet<PathTemplateHolder> with TreeSet<> in method private remove(template PathTemplate) : PathTemplateMatcher<T> from class io.undertow.util.PathTemplateMatcher


                @Override
                public void run() {
                    LinkedList<Runnable> queue = THREAD_QUEUE.get();
                    if (queue == null) {
                        THREAD_QUEUE.set(queue = new LinkedList<>());
                    }
                    try {
                        command.run();
                    } catch (Throwable t) {
                        UndertowLogger.REQUEST_LOGGER.debugf(t, "Task %s failed", command);
                    }
                    Runnable runnable = queue.poll();
                    while (runnable != null) {
                        try {
                            runnable.run();
                        } catch (Throwable t) {
                            UndertowLogger.REQUEST_LOGGER.debugf(t, "Task %s failed", command);
                        }
                        runnable = queue.poll();
                    }

                }

                @Override
                public void run() {
                    LinkedList<Runnable> queue = THREAD_QUEUE.get();
                    if (queue == null) {
                        THREAD_QUEUE.set(queue = new LinkedList<Runnable>());
                    }
                    try {
                        command.run();
                    } catch (Throwable t) {
                        UndertowLogger.REQUEST_LOGGER.debugf(t, "Task %s failed", command);
                    }
                    Runnable runnable = queue.poll();
                    while (runnable != null) {
                        try {
                            runnable.run();
                        } catch (Throwable t) {
                            UndertowLogger.REQUEST_LOGGER.debugf(t, "Task %s failed", command);
                        }
                        runnable = queue.poll();
                    }

                }

Replace Generic With Diamond LinkedList<Runnable> with LinkedList<> in method public run() : void from class io.undertow.util.PipeliningExecutor.execute.execute.new Runnable


    @Override
    public void execute(final Runnable command) {
        List<Runnable> queue = THREAD_QUEUE.get();
        if (queue != null) {
            queue.add(command);
        } else {
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    LinkedList<Runnable> queue = THREAD_QUEUE.get();
                    if (queue == null) {
                        THREAD_QUEUE.set(queue = new LinkedList<>());
                    }
                    try {
                        command.run();
                    } catch (Throwable t) {
                        UndertowLogger.REQUEST_LOGGER.debugf(t, "Task %s failed", command);
                    }
                    Runnable runnable = queue.poll();
                    while (runnable != null) {
                        try {
                            runnable.run();
                        } catch (Throwable t) {
                            UndertowLogger.REQUEST_LOGGER.debugf(t, "Task %s failed", command);
                        }
                        runnable = queue.poll();
                    }

                }
            });
        }
    }

    @Override
    public void execute(final Runnable command) {
        List<Runnable> queue = THREAD_QUEUE.get();
        if (queue != null) {
            queue.add(command);
        } else {
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    LinkedList<Runnable> queue = THREAD_QUEUE.get();
                    if (queue == null) {
                        THREAD_QUEUE.set(queue = new LinkedList<Runnable>());
                    }
                    try {
                        command.run();
                    } catch (Throwable t) {
                        UndertowLogger.REQUEST_LOGGER.debugf(t, "Task %s failed", command);
                    }
                    Runnable runnable = queue.poll();
                    while (runnable != null) {
                        try {
                            runnable.run();
                        } catch (Throwable t) {
                            UndertowLogger.REQUEST_LOGGER.debugf(t, "Task %s failed", command);
                        }
                        runnable = queue.poll();
                    }

                }
            });
        }
    }

Replace Generic With Diamond LinkedList<Runnable> with LinkedList<> in method public execute(command Runnable) : void from class io.undertow.util.PipeliningExecutor


    /**
     * Constructs an empty deque.
     */
    public PortableConcurrentDirectDeque() {
        head = tail = new Node<>(null);
    }

    /**
     * Constructs an empty deque.
     */
    public PortableConcurrentDirectDeque() {
        head = tail = new Node<E>(null);
    }

Replace Generic With Diamond Node<E> with Node<> in method public PortableConcurrentDirectDeque() from class io.undertow.util.PortableConcurrentDirectDeque


    /**
     * Constructs a deque initially containing the elements of
     * the given collection, added in traversal order of the
     * collection's iterator.
     *
     * @param c the collection of elements to initially contain
     * @throws NullPointerException if the specified collection or any
     *         of its elements are null
     */
    public PortableConcurrentDirectDeque(Collection<? extends E> c) {
        // Copy c into a private chain of Nodes
        Node<E> h = null, t = null;
        for (E e : c) {
            checkNotNull(e);
            Node<E> newNode = new Node<>(e);
            if (h == null)
                h = t = newNode;
            else {
                t.lazySetNext(newNode);
                newNode.lazySetPrev(t);
                t = newNode;
            }
        }
        initHeadTail(h, t);
    }

    /**
     * Constructs a deque initially containing the elements of
     * the given collection, added in traversal order of the
     * collection's iterator.
     *
     * @param c the collection of elements to initially contain
     * @throws NullPointerException if the specified collection or any
     *         of its elements are null
     */
    public PortableConcurrentDirectDeque(Collection<? extends E> c) {
        // Copy c into a private chain of Nodes
        Node<E> h = null, t = null;
        for (E e : c) {
            checkNotNull(e);
            Node<E> newNode = new Node<E>(e);
            if (h == null)
                h = t = newNode;
            else {
                t.lazySetNext(newNode);
                newNode.lazySetPrev(t);
                t = newNode;
            }
        }
        initHeadTail(h, t);
    }

Replace Generic With Diamond Node<E> with Node<> in method public PortableConcurrentDirectDeque(c Collection<? extends E>) from class io.undertow.util.PortableConcurrentDirectDeque


    /**
     * Parses a query string into a map
     * @param newQueryString The query string
     * @return The map of key value parameters
     */
    public static Map<String, Deque<String>> parseQueryString(final String newQueryString) {
        Map<String, Deque<String>> newQueryParameters = new LinkedHashMap<>();
        int startPos = 0;
        int equalPos = -1;
        for(int i = 0; i < newQueryString.length(); ++i) {
            char c = newQueryString.charAt(i);
            if(c == '=' && equalPos == -1) {
                equalPos = i;
            } else if(c == '&') {
                handleQueryParameter(newQueryString, newQueryParameters, startPos, equalPos, i);
                startPos = i + 1;
                equalPos = -1;
            }
        }
        if(startPos != newQueryString.length()) {
            handleQueryParameter(newQueryString, newQueryParameters, startPos, equalPos, newQueryString.length());
        }
        return newQueryParameters;
    }

    /**
     * Parses a query string into a map
     * @param newQueryString The query string
     * @return The map of key value parameters
     */
    public static Map<String, Deque<String>> parseQueryString(final String newQueryString) {
        Map<String, Deque<String>> newQueryParameters = new LinkedHashMap<String, Deque<String>>();
        int startPos = 0;
        int equalPos = -1;
        for(int i = 0; i < newQueryString.length(); ++i) {
            char c = newQueryString.charAt(i);
            if(c == '=' && equalPos == -1) {
                equalPos = i;
            } else if(c == '&') {
                handleQueryParameter(newQueryString, newQueryParameters, startPos, equalPos, i);
                startPos = i + 1;
                equalPos = -1;
            }
        }
        if(startPos != newQueryString.length()) {
            handleQueryParameter(newQueryString, newQueryParameters, startPos, equalPos, newQueryString.length());
        }
        return newQueryParameters;
    }

Replace Generic With Diamond LinkedHashMap<String,Deque<String>> with LinkedHashMap<> in method public parseQueryString(newQueryString String) : Map<String,Deque<String>> from class io.undertow.util.QueryParameterUtils


    private static void handleQueryParameter(String newQueryString, Map<String, Deque<String>> newQueryParameters, int startPos, int equalPos, int i) {
        String key;
        String value = "";
        if(equalPos == -1) {
            key = newQueryString.substring(startPos, i);
        } else {
            key = newQueryString.substring(startPos, equalPos);
            value = newQueryString.substring(equalPos + 1, i);
        }

        Deque<String> queue = newQueryParameters.get(key);
        if (queue == null) {
            newQueryParameters.put(key, queue = new ArrayDeque<>(1));
        }
        if(value != null) {
            queue.add(value);
        }
    }

    private static void handleQueryParameter(String newQueryString, Map<String, Deque<String>> newQueryParameters, int startPos, int equalPos, int i) {
        String key;
        String value = "";
        if(equalPos == -1) {
            key = newQueryString.substring(startPos, i);
        } else {
            key = newQueryString.substring(startPos, equalPos);
            value = newQueryString.substring(equalPos + 1, i);
        }

        Deque<String> queue = newQueryParameters.get(key);
        if (queue == null) {
            newQueryParameters.put(key, queue = new ArrayDeque<String>(1));
        }
        if(value != null) {
            queue.add(value);
        }
    }

Replace Generic With Diamond ArrayDeque<String> with ArrayDeque<> in method private handleQueryParameter(newQueryString String, newQueryParameters Map<String,Deque<String>>, startPos int, equalPos int, i int) : void from class io.undertow.util.QueryParameterUtils


    public static Map<String, Deque<String>> mergeQueryParametersWithNewQueryString(final Map<String, Deque<String>> queryParameters, final String newQueryString) {

        Map<String, Deque<String>> newQueryParameters = parseQueryString(newQueryString);
        //according to the spec the new query parameters have to 'take precedence'
        for (Map.Entry<String, Deque<String>> entry : queryParameters.entrySet()) {
            if (!newQueryParameters.containsKey(entry.getKey())) {
                newQueryParameters.put(entry.getKey(), new ArrayDeque<>(entry.getValue()));
            } else {
                newQueryParameters.get(entry.getKey()).addAll(entry.getValue());
            }
        }
        return newQueryParameters;
    }

    public static Map<String, Deque<String>> mergeQueryParametersWithNewQueryString(final Map<String, Deque<String>> queryParameters, final String newQueryString) {

        Map<String, Deque<String>> newQueryParameters = parseQueryString(newQueryString);
        //according to the spec the new query parameters have to 'take precedence'
        for (Map.Entry<String, Deque<String>> entry : queryParameters.entrySet()) {
            if (!newQueryParameters.containsKey(entry.getKey())) {
                newQueryParameters.put(entry.getKey(), new ArrayDeque<String>(entry.getValue()));
            } else {
                newQueryParameters.get(entry.getKey()).addAll(entry.getValue());
            }
        }
        return newQueryParameters;
    }

Replace Generic With Diamond ArrayDeque<String> with ArrayDeque<> in method public mergeQueryParametersWithNewQueryString(queryParameters Map<String,Deque<String>>, newQueryString String) : Map<String,Deque<String>> from class io.undertow.util.QueryParameterUtils


        public Object[] toArray() {
            ArrayList<Object> list = new ArrayList<>(size());
            list.addAll(this);
            return list.toArray();
        }

        public Object[] toArray() {
            ArrayList<Object> list = new ArrayList<Object>(size());
            list.addAll(this);
            return list.toArray();
        }

Replace Generic With Diamond ArrayList<Object> with ArrayList<> in method public toArray() : Object[] from class io.undertow.util.SecureHashMap.KeySet


        public <T> T[] toArray(final T[] a) {
            ArrayList<T> list = new ArrayList<>();
            list.addAll((Collection<T>) this);
            return list.toArray(a);
        }

        public <T> T[] toArray(final T[] a) {
            ArrayList<T> list = new ArrayList<T>();
            list.addAll((Collection<T>) this);
            return list.toArray(a);
        }

Replace Generic With Diamond ArrayList<T> with ArrayList<> in method public toArray(a T[]) : T[] from class io.undertow.util.SecureHashMap.KeySet


        public <T> T[] toArray(final T[] a) {
            ArrayList<T> list = new ArrayList<>();
            list.addAll((Set<T>) this);
            return list.toArray(a);
        }

        public <T> T[] toArray(final T[] a) {
            ArrayList<T> list = new ArrayList<T>();
            list.addAll((Set<T>) this);
            return list.toArray(a);
        }

Replace Generic With Diamond ArrayList<T> with ArrayList<> in method public toArray(a T[]) : T[] from class io.undertow.util.SecureHashMap.EntrySet


        private Table(int capacity, float loadFactor) {
            array = new AtomicReferenceArray<>(capacity);
            threshold = capacity == MAXIMUM_CAPACITY ? Integer.MAX_VALUE : (int)(capacity * loadFactor);
        }

        private Table(int capacity, float loadFactor) {
            array = new AtomicReferenceArray<Item<K, V>[]>(capacity);
            threshold = capacity == MAXIMUM_CAPACITY ? Integer.MAX_VALUE : (int)(capacity * loadFactor);
        }

Replace Generic With Diamond AtomicReferenceArray<Item<K,V>[]> with AtomicReferenceArray<> in method private Table(capacity int, loadFactor float) from class io.undertow.util.SecureHashMap.Table


    /**
     * Construct a new instance.
     *
     * @param initialCapacity the initial capacity
     * @param loadFactor the load factor
     */
    public SecureHashMap(int initialCapacity, float loadFactor) {
        if (initialCapacity < 0) {
            throw new IllegalArgumentException("Initial capacity must be > 0");
        }
        if (initialCapacity > MAXIMUM_CAPACITY) {
            initialCapacity = MAXIMUM_CAPACITY;
        }
        if (loadFactor <= 0.0 || Float.isNaN(loadFactor) || loadFactor >= 1.0) {
            throw new IllegalArgumentException("Load factor must be between 0.0f and 1.0f");
        }

        int capacity = 1;

        while (capacity < initialCapacity) {
            capacity <<= 1;
        }

        this.loadFactor = loadFactor;
        this.initialCapacity = capacity;

        final Table<K, V> table = new Table<>(capacity, loadFactor);
        tableUpdater.set(this, table);
    }

    /**
     * Construct a new instance.
     *
     * @param initialCapacity the initial capacity
     * @param loadFactor the load factor
     */
    public SecureHashMap(int initialCapacity, float loadFactor) {
        if (initialCapacity < 0) {
            throw new IllegalArgumentException("Initial capacity must be > 0");
        }
        if (initialCapacity > MAXIMUM_CAPACITY) {
            initialCapacity = MAXIMUM_CAPACITY;
        }
        if (loadFactor <= 0.0 || Float.isNaN(loadFactor) || loadFactor >= 1.0) {
            throw new IllegalArgumentException("Load factor must be between 0.0f and 1.0f");
        }

        int capacity = 1;

        while (capacity < initialCapacity) {
            capacity <<= 1;
        }

        this.loadFactor = loadFactor;
        this.initialCapacity = capacity;

        final Table<K, V> table = new Table<K, V>(capacity, loadFactor);
        tableUpdater.set(this, table);
    }

Replace Generic With Diamond Table<K,V> with Table<> in method public SecureHashMap(initialCapacity int, loadFactor float) from class io.undertow.util.SecureHashMap


    private V doPut(K key, V value, boolean ifAbsent, Table<K, V> table) {
        final int hashCode = hashOf(key);
        final AtomicReferenceArray<Item<K, V>[]> array = table.array;
        final int idx = hashCode & array.length() - 1;

        OUTER: for (;;) {

            // Fetch the table row.
            Item<K, V>[] oldRow = array.get(idx);
            if (oldRow == RESIZED) {
                // row was transported to the new table so recalculate everything
                final V result = doPut(key, value, ifAbsent, table.resizeView);
                // keep a consistent size view though!
                if (result == NONEXISTENT) sizeUpdater.getAndIncrement(table);
                return result;
            }
            if (oldRow != null) {
                // Find the matching Item in the row.
                Item<K, V> oldItem = null;
                for (Item<K, V> tryItem : oldRow) {
                    if (equals(key, tryItem.key)) {
                        oldItem = tryItem;
                        break;
                    }
                }
                if (oldItem != null) {
                    // entry exists; try to return the old value and try to replace the value if allowed.
                    V oldItemValue;
                    do {
                        oldItemValue = oldItem.value;
                        if (oldItemValue == NONEXISTENT) {
                            // Key was removed; on the next iteration or two the doornail should be gone.
                            continue OUTER;
                        }
                    } while (! ifAbsent && ! valueUpdater.compareAndSet(oldItem, oldItemValue, value));
                    return oldItemValue;
                }
                // Row exists but item doesn't.
            }

            // Row doesn't exist, or row exists but item doesn't; try and add a new item to the row.
            final Item<K, V> newItem = new Item<>(key, hashCode, value);
            final Item<K, V>[] newRow = addItem(oldRow, newItem);
            if (! array.compareAndSet(idx, oldRow, newRow)) {
                // Nope, row changed; retry.
                continue;
            }

            // Up the table size.
            final int threshold = table.threshold;
            int newSize = sizeUpdater.incrementAndGet(table);
            // >= 0 is really a sign-bit check
            while (newSize >= 0 && (newSize & 0x7fffffff) > threshold) {
                if (sizeUpdater.compareAndSet(table, newSize, newSize | 0x80000000)) {
                    resize(table);
                    return nonexistent();
                }
                newSize = sizeUpdater.get(table);
            }
            // Success.
            return nonexistent();
        }
    }

    private V doPut(K key, V value, boolean ifAbsent, Table<K, V> table) {
        final int hashCode = hashOf(key);
        final AtomicReferenceArray<Item<K, V>[]> array = table.array;
        final int idx = hashCode & array.length() - 1;

        OUTER: for (;;) {

            // Fetch the table row.
            Item<K, V>[] oldRow = array.get(idx);
            if (oldRow == RESIZED) {
                // row was transported to the new table so recalculate everything
                final V result = doPut(key, value, ifAbsent, table.resizeView);
                // keep a consistent size view though!
                if (result == NONEXISTENT) sizeUpdater.getAndIncrement(table);
                return result;
            }
            if (oldRow != null) {
                // Find the matching Item in the row.
                Item<K, V> oldItem = null;
                for (Item<K, V> tryItem : oldRow) {
                    if (equals(key, tryItem.key)) {
                        oldItem = tryItem;
                        break;
                    }
                }
                if (oldItem != null) {
                    // entry exists; try to return the old value and try to replace the value if allowed.
                    V oldItemValue;
                    do {
                        oldItemValue = oldItem.value;
                        if (oldItemValue == NONEXISTENT) {
                            // Key was removed; on the next iteration or two the doornail should be gone.
                            continue OUTER;
                        }
                    } while (! ifAbsent && ! valueUpdater.compareAndSet(oldItem, oldItemValue, value));
                    return oldItemValue;
                }
                // Row exists but item doesn't.
            }

            // Row doesn't exist, or row exists but item doesn't; try and add a new item to the row.
            final Item<K, V> newItem = new Item<K, V>(key, hashCode, value);
            final Item<K, V>[] newRow = addItem(oldRow, newItem);
            if (! array.compareAndSet(idx, oldRow, newRow)) {
                // Nope, row changed; retry.
                continue;
            }

            // Up the table size.
            final int threshold = table.threshold;
            int newSize = sizeUpdater.incrementAndGet(table);
            // >= 0 is really a sign-bit check
            while (newSize >= 0 && (newSize & 0x7fffffff) > threshold) {
                if (sizeUpdater.compareAndSet(table, newSize, newSize | 0x80000000)) {
                    resize(table);
                    return nonexistent();
                }
                newSize = sizeUpdater.get(table);
            }
            // Success.
            return nonexistent();
        }
    }

Replace Generic With Diamond Item<K,V> with Item<> in method private doPut(key K, value V, ifAbsent boolean, table Table<K,V>) : V from class io.undertow.util.SecureHashMap


    private void resize(Table<K, V> origTable) {
        final AtomicReferenceArray<Item<K, V>[]> origArray = origTable.array;
        final int origCapacity = origArray.length();
        final Table<K, V> newTable = new Table<>(origCapacity << 1, loadFactor);
        // Prevent resize until we're done...
        newTable.size = 0x80000000;
        origTable.resizeView = newTable;
        final AtomicReferenceArray<Item<K, V>[]> newArray = newTable.array;

        for (int i = 0; i < origCapacity; i ++) {
            // for each row, try to resize into two new rows
            Item<K, V>[] origRow, newRow0, newRow1;
            do {
                origRow = origArray.get(i);
                if (origRow != null) {
                    int count0 = 0, count1 = 0;
                    for (Item<K, V> item : origRow) {
                        if ((item.hashCode & origCapacity) == 0) {
                            count0++;
                        } else {
                            count1++;
                        }
                    }
                    if (count0 != 0) {
                        newRow0 = createRow(count0);
                        int j = 0;
                        for (Item<K, V> item : origRow) {
                            if ((item.hashCode & origCapacity) == 0) {
                                newRow0[j++] = item;
                            }
                        }
                        newArray.lazySet(i, newRow0);
                    }
                    if (count1 != 0) {
                        newRow1 = createRow(count1);
                        int j = 0;
                        for (Item<K, V> item : origRow) {
                            if ((item.hashCode & origCapacity) != 0) {
                                newRow1[j++] = item;
                            }
                        }
                        newArray.lazySet(i + origCapacity, newRow1);
                    }
                }
            } while (! origArray.compareAndSet(i, origRow, SecureHashMap.<K, V>resized()));
            if (origRow != null) sizeUpdater.getAndAdd(newTable, origRow.length);
        }

        int size;
        do {
            size = newTable.size;
            if ((size & 0x7fffffff) >= newTable.threshold) {
                // shorter path for reads and writes
                table = newTable;
                // then time for another resize, right away
                resize(newTable);
                return;
            }
        } while (!sizeUpdater.compareAndSet(newTable, size, size & 0x7fffffff));

        // All done, plug in the new table
        table = newTable;
    }

    private void resize(Table<K, V> origTable) {
        final AtomicReferenceArray<Item<K, V>[]> origArray = origTable.array;
        final int origCapacity = origArray.length();
        final Table<K, V> newTable = new Table<K, V>(origCapacity << 1, loadFactor);
        // Prevent resize until we're done...
        newTable.size = 0x80000000;
        origTable.resizeView = newTable;
        final AtomicReferenceArray<Item<K, V>[]> newArray = newTable.array;

        for (int i = 0; i < origCapacity; i ++) {
            // for each row, try to resize into two new rows
            Item<K, V>[] origRow, newRow0, newRow1;
            do {
                origRow = origArray.get(i);
                if (origRow != null) {
                    int count0 = 0, count1 = 0;
                    for (Item<K, V> item : origRow) {
                        if ((item.hashCode & origCapacity) == 0) {
                            count0++;
                        } else {
                            count1++;
                        }
                    }
                    if (count0 != 0) {
                        newRow0 = createRow(count0);
                        int j = 0;
                        for (Item<K, V> item : origRow) {
                            if ((item.hashCode & origCapacity) == 0) {
                                newRow0[j++] = item;
                            }
                        }
                        newArray.lazySet(i, newRow0);
                    }
                    if (count1 != 0) {
                        newRow1 = createRow(count1);
                        int j = 0;
                        for (Item<K, V> item : origRow) {
                            if ((item.hashCode & origCapacity) != 0) {
                                newRow1[j++] = item;
                            }
                        }
                        newArray.lazySet(i + origCapacity, newRow1);
                    }
                }
            } while (! origArray.compareAndSet(i, origRow, SecureHashMap.<K, V>resized()));
            if (origRow != null) sizeUpdater.getAndAdd(newTable, origRow.length);
        }

        int size;
        do {
            size = newTable.size;
            if ((size & 0x7fffffff) >= newTable.threshold) {
                // shorter path for reads and writes
                table = newTable;
                // then time for another resize, right away
                resize(newTable);
                return;
            }
        } while (!sizeUpdater.compareAndSet(newTable, size, size & 0x7fffffff));

        // All done, plug in the new table
        table = newTable;
    }

Replace Generic With Diamond Table<K,V> with Table<> in method private resize(origTable Table<K,V>) : void from class io.undertow.util.SecureHashMap


    public void clear() {
        table = new Table<>(initialCapacity, loadFactor);
    }

    public void clear() {
        table = new Table<K, V>(initialCapacity, loadFactor);
    }

Replace Generic With Diamond Table<K,V> with Table<> in method public clear() : void from class io.undertow.util.SecureHashMap


    public WebSocketExtension(String name, List<Parameter> parameters) {
        this.name = name;
        this.parameters = Collections.unmodifiableList(new ArrayList<>(parameters));
    }

    public WebSocketExtension(String name, List<Parameter> parameters) {
        this.name = name;
        this.parameters = Collections.unmodifiableList(new ArrayList<Parameter>(parameters));
    }

Replace Generic With Diamond ArrayList<Parameter> with ArrayList<> in method public WebSocketExtension(name String, parameters List<Parameter>) from class io.undertow.websockets.WebSocketExtension


    /**
     * Create a new {@link WebSocketProtocolHandshakeHandler}
     *
     * @param callback The {@link WebSocketConnectionCallback} which will be executed once the handshake was
     *                 established
     */
    public WebSocketProtocolHandshakeHandler(final WebSocketConnectionCallback callback, final HttpHandler next) {
        this.callback = callback;
        Set<Handshake> handshakes = new HashSet<>();
        handshakes.add(new Hybi13Handshake());
        handshakes.add(new Hybi08Handshake());
        handshakes.add(new Hybi07Handshake());
        this.handshakes = handshakes;
        this.next = next;
        this.upgradeListener = null;
    }

    /**
     * Create a new {@link WebSocketProtocolHandshakeHandler}
     *
     * @param callback The {@link WebSocketConnectionCallback} which will be executed once the handshake was
     *                 established
     */
    public WebSocketProtocolHandshakeHandler(final WebSocketConnectionCallback callback, final HttpHandler next) {
        this.callback = callback;
        Set<Handshake> handshakes = new HashSet<Handshake>();
        handshakes.add(new Hybi13Handshake());
        handshakes.add(new Hybi08Handshake());
        handshakes.add(new Hybi07Handshake());
        this.handshakes = handshakes;
        this.next = next;
        this.upgradeListener = null;
    }

Replace Generic With Diamond HashSet<Handshake> with HashSet<> in method public WebSocketProtocolHandshakeHandler(callback WebSocketConnectionCallback, next HttpHandler) from class io.undertow.websockets.WebSocketProtocolHandshakeHandler


    /**
     * Create a new {@link WebSocketProtocolHandshakeHandler}
     *
     * @param handshakes The supported handshake methods
     * @param callback   The {@link WebSocketConnectionCallback} which will be executed once the handshake was
     *                   established
     */
    public WebSocketProtocolHandshakeHandler(Collection<Handshake> handshakes, final WebSocketConnectionCallback callback, final HttpHandler next) {
        this.callback = callback;
        this.handshakes = new HashSet<>(handshakes);
        this.next = next;
        this.upgradeListener = null;
    }

    /**
     * Create a new {@link WebSocketProtocolHandshakeHandler}
     *
     * @param handshakes The supported handshake methods
     * @param callback   The {@link WebSocketConnectionCallback} which will be executed once the handshake was
     *                   established
     */
    public WebSocketProtocolHandshakeHandler(Collection<Handshake> handshakes, final WebSocketConnectionCallback callback, final HttpHandler next) {
        this.callback = callback;
        this.handshakes = new HashSet<Handshake>(handshakes);
        this.next = next;
        this.upgradeListener = null;
    }

Replace Generic With Diamond HashSet<Handshake> with HashSet<> in method public WebSocketProtocolHandshakeHandler(handshakes Collection<Handshake>, callback WebSocketConnectionCallback, next HttpHandler) from class io.undertow.websockets.WebSocketProtocolHandshakeHandler


    /**
     * Create a new {@link WebSocketProtocolHandshakeHandler}
     *
     * @param callback The {@link WebSocketConnectionCallback} which will be executed once the handshake was
     *                 established
     */
    public WebSocketProtocolHandshakeHandler(final HttpUpgradeListener callback, final HttpHandler next) {
        this.callback = null;
        Set<Handshake> handshakes = new HashSet<>();
        handshakes.add(new Hybi13Handshake());
        handshakes.add(new Hybi08Handshake());
        handshakes.add(new Hybi07Handshake());
        this.handshakes = handshakes;
        this.next = next;
        this.upgradeListener = callback;
    }

    /**
     * Create a new {@link WebSocketProtocolHandshakeHandler}
     *
     * @param callback The {@link WebSocketConnectionCallback} which will be executed once the handshake was
     *                 established
     */
    public WebSocketProtocolHandshakeHandler(final HttpUpgradeListener callback, final HttpHandler next) {
        this.callback = null;
        Set<Handshake> handshakes = new HashSet<Handshake>();
        handshakes.add(new Hybi13Handshake());
        handshakes.add(new Hybi08Handshake());
        handshakes.add(new Hybi07Handshake());
        this.handshakes = handshakes;
        this.next = next;
        this.upgradeListener = callback;
    }

Replace Generic With Diamond HashSet<Handshake> with HashSet<> in method public WebSocketProtocolHandshakeHandler(callback HttpUpgradeListener, next HttpHandler) from class io.undertow.websockets.WebSocketProtocolHandshakeHandler


    /**
     * Create a new {@link WebSocketProtocolHandshakeHandler}
     *
     * @param handshakes The supported handshake methods
     * @param callback   The {@link WebSocketConnectionCallback} which will be executed once the handshake was
     *                   established
     */
    public WebSocketProtocolHandshakeHandler(Collection<Handshake> handshakes, final HttpUpgradeListener callback, final HttpHandler next) {
        this.callback = null;
        this.handshakes = new HashSet<>(handshakes);
        this.next = next;
        this.upgradeListener = callback;
    }

    /**
     * Create a new {@link WebSocketProtocolHandshakeHandler}
     *
     * @param handshakes The supported handshake methods
     * @param callback   The {@link WebSocketConnectionCallback} which will be executed once the handshake was
     *                   established
     */
    public WebSocketProtocolHandshakeHandler(Collection<Handshake> handshakes, final HttpUpgradeListener callback, final HttpHandler next) {
        this.callback = null;
        this.handshakes = new HashSet<Handshake>(handshakes);
        this.next = next;
        this.upgradeListener = callback;
    }

Replace Generic With Diamond HashSet<Handshake> with HashSet<> in method public WebSocketProtocolHandshakeHandler(handshakes Collection<Handshake>, callback HttpUpgradeListener, next HttpHandler) from class io.undertow.websockets.WebSocketProtocolHandshakeHandler


    public Map<String, String> createHeaders() {
        Map<String, String> headers = new HashMap<>();
        headers.put(Headers.UPGRADE_STRING, "websocket");
        headers.put(Headers.CONNECTION_STRING, "upgrade");
        String key = createSecKey();
        headers.put(Headers.SEC_WEB_SOCKET_KEY_STRING, key);
        headers.put(Headers.SEC_WEB_SOCKET_VERSION_STRING, getVersion().toHttpHeaderValue());
        if (negotiation != null) {
            List<String> subProtocols = negotiation.getSupportedSubProtocols();
            if (subProtocols != null && !subProtocols.isEmpty()) {
                StringBuilder sb = new StringBuilder();
                Iterator<String> it = subProtocols.iterator();
                while (it.hasNext()) {
                    sb.append(it.next());
                    if (it.hasNext()) {
                        sb.append(", ");
                    }
                }
                headers.put(Headers.SEC_WEB_SOCKET_PROTOCOL_STRING, sb.toString());
            }
            List<WebSocketExtension> extensions = negotiation.getSupportedExtensions();
            if (extensions != null && !extensions.isEmpty()) {
                StringBuilder sb = new StringBuilder();
                Iterator<WebSocketExtension> it = extensions.iterator();
                while (it.hasNext()) {
                    WebSocketExtension next = it.next();
                    sb.append(next);
                    for (WebSocketExtension.Parameter param : next.getParameters()) {
                        sb.append("; ");
                        sb.append(param.getName());
                        sb.append("=");
                        sb.append(param.getValue());
                    }
                    if (it.hasNext()) {
                        sb.append(", ");
                    }
                }
                headers.put(Headers.SEC_WEB_SOCKET_EXTENSIONS_STRING, sb.toString());
            }
        }
        return headers;

    }

    public Map<String, String> createHeaders() {
        Map<String, String> headers = new HashMap<String, String>();
        headers.put(Headers.UPGRADE_STRING, "websocket");
        headers.put(Headers.CONNECTION_STRING, "upgrade");
        String key = createSecKey();
        headers.put(Headers.SEC_WEB_SOCKET_KEY_STRING, key);
        headers.put(Headers.SEC_WEB_SOCKET_VERSION_STRING, getVersion().toHttpHeaderValue());
        if (negotiation != null) {
            List<String> subProtocols = negotiation.getSupportedSubProtocols();
            if (subProtocols != null && !subProtocols.isEmpty()) {
                StringBuilder sb = new StringBuilder();
                Iterator<String> it = subProtocols.iterator();
                while (it.hasNext()) {
                    sb.append(it.next());
                    if (it.hasNext()) {
                        sb.append(", ");
                    }
                }
                headers.put(Headers.SEC_WEB_SOCKET_PROTOCOL_STRING, sb.toString());
            }
            List<WebSocketExtension> extensions = negotiation.getSupportedExtensions();
            if (extensions != null && !extensions.isEmpty()) {
                StringBuilder sb = new StringBuilder();
                Iterator<WebSocketExtension> it = extensions.iterator();
                while (it.hasNext()) {
                    WebSocketExtension next = it.next();
                    sb.append(next);
                    for (WebSocketExtension.Parameter param : next.getParameters()) {
                        sb.append("; ");
                        sb.append(param.getName());
                        sb.append("=");
                        sb.append(param.getValue());
                    }
                    if (it.hasNext()) {
                        sb.append(", ");
                    }
                }
                headers.put(Headers.SEC_WEB_SOCKET_EXTENSIONS_STRING, sb.toString());
            }
        }
        return headers;

    }

Replace Generic With Diamond HashMap<String,String> with HashMap<> in method public createHeaders() : Map<String,String> from class io.undertow.websockets.client.WebSocket13ClientHandshake


    public static IoFuture<WebSocketChannel> connect(XnioWorker worker, XnioSsl ssl, final Pool<ByteBuffer> bufferPool, final OptionMap optionMap, final URI uri, WebSocketVersion version, WebSocketClientNegotiation clientNegotiation) {

        final FutureResult<WebSocketChannel> ioFuture = new FutureResult<>();
        final URI newUri;
        try {
            newUri = new URI(uri.getScheme().equals("wss") ? "https" : "http", uri.getUserInfo(), uri.getHost(), uri.getPort() == -1 ? (uri.getScheme().equals("wss") ? 443 : 80) : uri.getPort(), uri.getPath().isEmpty() ? "/" : uri.getPath(), uri.getQuery(), uri.getFragment());
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }
        final WebSocketClientHandshake handshake = WebSocketClientHandshake.create(version, newUri, clientNegotiation);
        final Map<String, String> headers = handshake.createHeaders();
        if (clientNegotiation != null) {
            clientNegotiation.beforeRequest(headers);
        }
        IoFuture<? extends StreamConnection> result;
        if (ssl != null) {
            result = HttpUpgrade.performUpgrade(worker, ssl, null, newUri, headers, new ChannelListener<StreamConnection>() {
                @Override
                public void handleEvent(StreamConnection channel) {
                    WebSocketChannel result = handshake.createChannel(channel, newUri.toString(), bufferPool);
                    ioFuture.setResult(result);
                }
            }, null, optionMap, handshake.handshakeChecker(newUri, headers));
        } else {
            result = HttpUpgrade.performUpgrade(worker, null, newUri, headers, new ChannelListener<StreamConnection>() {
                @Override
                public void handleEvent(StreamConnection channel) {
                    WebSocketChannel result = handshake.createChannel(channel, newUri.toString(), bufferPool);
                    ioFuture.setResult(result);
                }
            }, null, optionMap, handshake.handshakeChecker(newUri, headers));
        }
        result.addNotifier(new IoFuture.Notifier<StreamConnection, Object>() {
            @Override
            public void notify(IoFuture<? extends StreamConnection> res, Object attachment) {
                if (res.getStatus() == IoFuture.Status.FAILED) {
                    ioFuture.setException(res.getException());
                }
            }
        }, null);
        return ioFuture.getIoFuture();
    }

    public static IoFuture<WebSocketChannel> connect(XnioWorker worker, XnioSsl ssl, final Pool<ByteBuffer> bufferPool, final OptionMap optionMap, final URI uri, WebSocketVersion version, WebSocketClientNegotiation clientNegotiation) {

        final FutureResult<WebSocketChannel> ioFuture = new FutureResult<WebSocketChannel>();
        final URI newUri;
        try {
            newUri = new URI(uri.getScheme().equals("wss") ? "https" : "http", uri.getUserInfo(), uri.getHost(), uri.getPort() == -1 ? (uri.getScheme().equals("wss") ? 443 : 80) : uri.getPort(), uri.getPath().isEmpty() ? "/" : uri.getPath(), uri.getQuery(), uri.getFragment());
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }
        final WebSocketClientHandshake handshake = WebSocketClientHandshake.create(version, newUri, clientNegotiation);
        final Map<String, String> headers = handshake.createHeaders();
        if (clientNegotiation != null) {
            clientNegotiation.beforeRequest(headers);
        }
        IoFuture<? extends StreamConnection> result;
        if (ssl != null) {
            result = HttpUpgrade.performUpgrade(worker, ssl, null, newUri, headers, new ChannelListener<StreamConnection>() {
                @Override
                public void handleEvent(StreamConnection channel) {
                    WebSocketChannel result = handshake.createChannel(channel, newUri.toString(), bufferPool);
                    ioFuture.setResult(result);
                }
            }, null, optionMap, handshake.handshakeChecker(newUri, headers));
        } else {
            result = HttpUpgrade.performUpgrade(worker, null, newUri, headers, new ChannelListener<StreamConnection>() {
                @Override
                public void handleEvent(StreamConnection channel) {
                    WebSocketChannel result = handshake.createChannel(channel, newUri.toString(), bufferPool);
                    ioFuture.setResult(result);
                }
            }, null, optionMap, handshake.handshakeChecker(newUri, headers));
        }
        result.addNotifier(new IoFuture.Notifier<StreamConnection, Object>() {
            @Override
            public void notify(IoFuture<? extends StreamConnection> res, Object attachment) {
                if (res.getStatus() == IoFuture.Status.FAILED) {
                    ioFuture.setException(res.getException());
                }
            }
        }, null);
        return ioFuture.getIoFuture();
    }

Replace Generic With Diamond FutureResult<WebSocketChannel> with FutureResult<> in method public connect(worker XnioWorker, ssl XnioSsl, bufferPool Pool<ByteBuffer>, optionMap OptionMap, uri URI, version WebSocketVersion, clientNegotiation WebSocketClientNegotiation) : IoFuture<WebSocketChannel> from class io.undertow.websockets.client.WebSocketClient


    @Override
    public IoFuture<Void> sendData(final ByteBuffer data) {
        if (sender == null) {
            this.sender = exchange.getResponseSender();
        }
        final FutureResult<Void> future = new FutureResult<>();
        sender.send(data, new IoCallback() {
            @Override
            public void onComplete(final HttpServerExchange exchange, final Sender sender) {
                future.setResult(null);
            }

            @Override
            public void onException(final HttpServerExchange exchange, final Sender sender, final IOException exception) {
                UndertowLogger.REQUEST_IO_LOGGER.ioException(exception);
                future.setException(exception);

            }
        });
        return future.getIoFuture();
    }

    @Override
    public IoFuture<Void> sendData(final ByteBuffer data) {
        if (sender == null) {
            this.sender = exchange.getResponseSender();
        }
        final FutureResult<Void> future = new FutureResult<Void>();
        sender.send(data, new IoCallback() {
            @Override
            public void onComplete(final HttpServerExchange exchange, final Sender sender) {
                future.setResult(null);
            }

            @Override
            public void onException(final HttpServerExchange exchange, final Sender sender, final IOException exception) {
                UndertowLogger.REQUEST_IO_LOGGER.ioException(exception);
                future.setException(exception);

            }
        });
        return future.getIoFuture();
    }

Replace Generic With Diamond FutureResult<Void> with FutureResult<> in method public sendData(data ByteBuffer) : IoFuture<Void> from class io.undertow.websockets.spi.AsyncWebSocketHttpServerExchange


    @Test
    public void testSimpleBasic() throws Exception {
        //
        DefaultServer.setRootHandler(SIMPLE_MESSAGE_HANDLER);
        final UndertowClient client = createClient();

        final List<ClientResponse> responses = new CopyOnWriteArrayList<>();
        final CountDownLatch latch = new CountDownLatch(10);
        final ClientConnection connection = client.connect(ADDRESS, worker, new ByteBufferSlicePool(1024, 1024), OptionMap.EMPTY).get();
        try {
            connection.getIoThread().execute(new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < 10; i++) {
                        final ClientRequest request = new ClientRequest().setMethod(Methods.GET).setPath("/");
                        connection.sendRequest(request, createClientCallback(responses, latch));
                    }
                }

            });

            latch.await(10, TimeUnit.MINUTES);

            Assert.assertEquals(10, responses.size());
            for (final ClientResponse response : responses) {
                Assert.assertEquals(message, response.getAttachment(RESPONSE_BODY));
            }
        } finally {
            IoUtils.safeClose(connection);
        }
    }

    @Test
    public void testSimpleBasic() throws Exception {
        //
        DefaultServer.setRootHandler(SIMPLE_MESSAGE_HANDLER);
        final UndertowClient client = createClient();

        final List<ClientResponse> responses = new CopyOnWriteArrayList<ClientResponse>();
        final CountDownLatch latch = new CountDownLatch(10);
        final ClientConnection connection = client.connect(ADDRESS, worker, new ByteBufferSlicePool(1024, 1024), OptionMap.EMPTY).get();
        try {
            connection.getIoThread().execute(new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < 10; i++) {
                        final ClientRequest request = new ClientRequest().setMethod(Methods.GET).setPath("/");
                        connection.sendRequest(request, createClientCallback(responses, latch));
                    }
                }

            });

            latch.await(10, TimeUnit.MINUTES);

            Assert.assertEquals(10, responses.size());
            for (final ClientResponse response : responses) {
                Assert.assertEquals(message, response.getAttachment(RESPONSE_BODY));
            }
        } finally {
            IoUtils.safeClose(connection);
        }
    }

Replace Generic With Diamond CopyOnWriteArrayList<ClientResponse> with CopyOnWriteArrayList<> in method public testSimpleBasic() : void from class io.undertow.client.http.HttpClientTestCase