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

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

/*
 * 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 jakarta.ws.rs.core.MultivaluedMap;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * 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<>();

    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) {
        return inner.getFirst(key);
    }

    @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) {
        return inner.get(key);
    }

    @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() {
        return inner.values();
    }

    @Override
    public Set>> entrySet() {
        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);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy