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

org.glassfish.jersey.internal.util.collection.GuardianStringKeyMultivaluedMap Maven / Gradle / Ivy

Go to download

A bundle project producing JAX-RS RI bundles. The primary artifact is an "all-in-one" OSGi-fied JAX-RS RI bundle (jaxrs-ri.jar). Attached to that are two compressed JAX-RS RI archives. The first archive (jaxrs-ri.zip) consists of binary RI bits and contains the API jar (under "api" directory), RI libraries (under "lib" directory) as well as all external RI dependencies (under "ext" directory). The secondary archive (jaxrs-ri-src.zip) contains buildable JAX-RS RI source bundle and contains the API jar (under "api" directory), RI sources (under "src" directory) as well as all external RI dependencies (under "ext" directory). The second archive also contains "build.xml" ANT script that builds the RI sources. To build the JAX-RS RI simply unzip the archive, cd to the created jaxrs-ri directory and invoke "ant" from the command line.

There is a newer version: 3.1.9
Show newest version
/*
 * Copyright (c) 2022, 2023 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package org.glassfish.jersey.internal.util.collection;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;

/**
 * The {@link MultivaluedMap} wrapper that is able to set guards observing changes of values represented by a key.
 * @param  The value type of the wrapped {@code MultivaluedMap}.
 *
 * @since 2.38
 */
public class GuardianStringKeyMultivaluedMap implements MultivaluedMap {

    private final MultivaluedMap inner;
    private final Map guards = new HashMap<>();

    private static boolean isMutable(Object mutable) {
        return !String.class.isInstance(mutable) && !MediaType.class.isInstance(mutable);
    }

    public GuardianStringKeyMultivaluedMap(MultivaluedMap inner) {
        this.inner = inner;
    }

    @Override
    public void putSingle(String key, V value) {
        observe(key);
        inner.putSingle(key, value);
    }

    @Override
    public void add(String key, V value) {
        observe(key);
        inner.add(key, value);
    }

    @Override
    public V getFirst(String key) {
        V first = inner.getFirst(key);
        if (isMutable(key)) {
            observe(key);
        }
        return first;
    }

    @Override
    public void addAll(String key, V... newValues) {
        observe(key);
        inner.addAll(key, newValues);
    }

    @Override
    public void addAll(String key, List valueList) {
        observe(key);
        inner.addAll(key, valueList);
    }

    @Override
    public void addFirst(String key, V value) {
        observe(key);
        inner.addFirst(key, value);
    }

    @Override
    public boolean equalsIgnoreValueOrder(MultivaluedMap otherMap) {
        return inner.equalsIgnoreValueOrder(otherMap);
    }

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

    @Override
    public boolean isEmpty() {
        return inner.isEmpty();
    }

    @Override
    public boolean containsKey(Object key) {
        return inner.containsKey(key);
    }

    @Override
    public boolean containsValue(Object value) {
        return inner.containsValue(value);
    }

    @Override
    public List get(Object key) {
        final List innerList = inner.get(key);
        if (innerList != null) {
            for (Map.Entry guard : guards.entrySet()) {
                if (guard.getKey().equals(key)) {
                    return new GuardianList(innerList, guard);
                }
            }
        }
        return innerList;
    }

    @Override
    public List put(String key, List value) {
        observe(key);
        return inner.put(key, value);
    }

    @Override
    public List remove(Object key) {
        if (key != null) {
            observe(key.toString());
        }
        return inner.remove(key);
    }

    @Override
    public void putAll(Map> m) {
        for (String key : m.keySet()) {
            observe(key);
        }
        inner.putAll(m);
    }

    @Override
    public void clear() {
        observeAll();
        inner.clear();
    }

    @Override
    public Set keySet() {
        return inner.keySet();
    }

    @Override
    public Collection> values() {
        observeAll();
        return inner.values();
    }

    @Override
    public Set>> entrySet() {
        observeAll();
        return inner.entrySet();
    }

    /**
     * Observe changes of a value represented by the key.
     * @param key the key values to observe
     */
    public void setGuard(String key) {
        guards.put(key, false);
    }

    /**
     * Get all the guarded keys
     * @return a {@link Set} of keys guarded.
     */
    public Set getGuards() {
        return guards.keySet();
    }

    /**
     * Return true when the value represented by the key has changed. Resets any observation - the operation is not idempotent.
     * @param key the Key observed.
     * @return whether the value represented by the key has changed.
     */
    public boolean isObservedAndReset(String key) {
        Boolean observed = guards.get(key);
        if (observed != null) {
            guards.put(key, false);
        }
        return observed != null && observed;
    }

    private void observe(String key) {
        for (Map.Entry guard : guards.entrySet()) {
            if (guard.getKey().equals(key)) {
                guard.setValue(true);
                break;
            }
        }
    }

    private void observeAll() {
        for (Map.Entry guard : guards.entrySet()) {
            guard.setValue(true);
        }
    }

    @Override
    public String toString() {
        return inner.toString();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        GuardianStringKeyMultivaluedMap that = (GuardianStringKeyMultivaluedMap) o;
        return inner.equals(that.inner) && guards.equals(that.guards);
    }

    @Override
    public int hashCode() {
        return Objects.hash(inner, guards);
    }

    private static class MutableGuardian {
        protected final Map.Entry guard;

        private MutableGuardian(Entry guard) {
            this.guard = guard;
        }

        protected V guardMutable(V mutable) {
            if (isMutable(mutable)) {
                guard.setValue(true);
            }
            return mutable;
        }
    }

    private static class GuardianList extends MutableGuardian implements List  {
        private final List guarded;

        public GuardianList(List guarded, Map.Entry guard) {
            super(guard);
            this.guarded = guarded;
        }

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

        @Override
        public boolean isEmpty() {
            return guarded.isEmpty();
        }

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

        @Override
        public Iterator iterator() {
            return new GuardianIterator<>(guarded.iterator(), guard);
        }

        @Override
        public Object[] toArray() {
            guard.setValue(true);
            return guarded.toArray();
        }

        @Override
        public  T[] toArray(T[] a) {
            guard.setValue(true);
            return guarded.toArray(a);
        }

        @Override
        public boolean add(V e) {
            guard.setValue(true);
            return guarded.add(e);
        }

        @Override
        public boolean remove(Object o) {
            guard.setValue(true);
            return guarded.remove(o);
        }

        @Override
        public boolean containsAll(Collection c) {
            return guarded.containsAll(c);
        }

        @Override
        public boolean addAll(Collection c) {
            guard.setValue(true);
            return guarded.addAll(c);
        }

        @Override
        public boolean addAll(int index, Collection c) {
            guard.setValue(true);
            return guarded.addAll(index, c);
        }

        @Override
        public boolean removeAll(Collection c) {
            guard.setValue(true);
            return guarded.removeAll(c);
        }

        @Override
        public boolean retainAll(Collection c) {
            guard.setValue(true);
            return guarded.retainAll(c);
        }

        @Override
        public void clear() {
            guard.setValue(true);
            guarded.clear();
        }

        @Override
        public V get(int index) {
            return guardMutable(guarded.get(index));
        }

        @Override
        public V set(int index, V element) {
            guard.setValue(true);
            return guarded.set(index, element);
        }

        @Override
        public void add(int index, V element) {
            guard.setValue(true);
            guarded.add(index, element);
        }

        @Override
        public V remove(int index) {
            guard.setValue(true);
            return guarded.remove(index);
        }

        @Override
        public int indexOf(Object o) {
            return guarded.indexOf(o);
        }

        @Override
        public int lastIndexOf(Object o) {
            return guarded.lastIndexOf(o);
        }

        @Override
        public ListIterator listIterator() {
            return new GuardianListIterator<>(guarded.listIterator(), guard);
        }

        @Override
        public ListIterator listIterator(int index) {
            return new GuardianListIterator<>(guarded.listIterator(index), guard);
        }

        @Override
        public List subList(int fromIndex, int toIndex) {
            final List sublist = guarded.subList(fromIndex, toIndex);
            return sublist != null ? new GuardianList<>(sublist, guard) : sublist;
        }

        @Override
        public String toString() {
            return guarded.toString();
        }

        @Override
        public boolean equals(Object obj) {
            if (GuardianList.class.isInstance(obj)) {
                return guarded.equals(((GuardianList) obj).guarded);
            }
            return guarded.equals(obj);
        }

        @Override
        public int hashCode() {
            return guarded.hashCode();
        }
    }

    private static class GuardianIterator extends MutableGuardian implements Iterator {
        protected final Iterator guarded;

        public GuardianIterator(Iterator guarded, Map.Entry guard) {
            super(guard);
            this.guarded = guarded;
        }

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

        @Override
        public V next() {
            return guardMutable(guarded.next());
        }

        @Override
        public void remove() {
            guard.setValue(true);
            guarded.remove();
        }

        @Override
        public void forEachRemaining(Consumer action) {
            guarded.forEachRemaining(action);
        }

        @Override
        public String toString() {
            return guarded.toString();
        }
    }

    private static class GuardianListIterator extends GuardianIterator implements ListIterator {

        public GuardianListIterator(Iterator guarded, Entry guard) {
            super(guarded, guard);
        }

        @Override
        public boolean hasPrevious() {
            return ((ListIterator) guarded).hasPrevious();
        }

        @Override
        public V previous() {
            return guardMutable(((ListIterator) guarded).previous());
        }

        @Override
        public int nextIndex() {
            return ((ListIterator) guarded).nextIndex();
        }

        @Override
        public int previousIndex() {
            return ((ListIterator) guarded).previousIndex();
        }

        @Override
        public void set(V v) {
            ((ListIterator) guarded).set(v);
            guard.setValue(true);
        }

        @Override
        public void add(V v) {
            ((ListIterator) guarded).add(v);
            guard.setValue(true);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy