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);
}
}