Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.google.common.collect.MapConstraints Maven / Gradle / Ivy
Go to download
This artifact provides a single jar that contains all classes required to use remote Jakarta Enterprise Beans and Jakarta Messaging, including
all dependencies. It is intended for use by those not using maven, maven users should just import the Jakarta Enterprise Beans and
Jakarta Messaging BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up
with different versions on classes on the class path).
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import java.io.Serializable;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedSet;
import javax.annotation.Nullable;
/**
* Factory and utilities pertaining to the {@code MapConstraint} interface.
*
* @see Constraints
* @author Mike Bostock
* @since 3.0
*/
@Beta
@GwtCompatible
public final class MapConstraints {
private MapConstraints() {}
/**
* Returns a constraint that verifies that neither the key nor the value is
* null. If either is null, a {@link NullPointerException} is thrown.
*/
public static MapConstraint notNull() {
return NotNullMapConstraint.INSTANCE;
}
// enum singleton pattern
private enum NotNullMapConstraint implements MapConstraint {
INSTANCE;
@Override
public void checkKeyValue(Object key, Object value) {
checkNotNull(key);
checkNotNull(value);
}
@Override public String toString() {
return "Not null";
}
}
/**
* Returns a constrained view of the specified map, using the specified
* constraint. Any operations that add new mappings will call the provided
* constraint. However, this method does not verify that existing mappings
* satisfy the constraint.
*
* The returned map is not serializable.
*
* @param map the map to constrain
* @param constraint the constraint that validates added entries
* @return a constrained view of the specified map
*/
public static Map constrainedMap(
Map map, MapConstraint super K, ? super V> constraint) {
return new ConstrainedMap(map, constraint);
}
/**
* Returns a constrained view of the specified multimap, using the specified
* constraint. Any operations that add new mappings will call the provided
* constraint. However, this method does not verify that existing mappings
* satisfy the constraint.
*
* Note that the generated multimap's {@link Multimap#removeAll} and
* {@link Multimap#replaceValues} methods return collections that are not
* constrained.
*
*
The returned multimap is not serializable.
*
* @param multimap the multimap to constrain
* @param constraint the constraint that validates added entries
* @return a constrained view of the multimap
*/
public static Multimap constrainedMultimap(
Multimap multimap, MapConstraint super K, ? super V> constraint) {
return new ConstrainedMultimap(multimap, constraint);
}
/**
* Returns a constrained view of the specified list multimap, using the
* specified constraint. Any operations that add new mappings will call the
* provided constraint. However, this method does not verify that existing
* mappings satisfy the constraint.
*
* Note that the generated multimap's {@link Multimap#removeAll} and
* {@link Multimap#replaceValues} methods return collections that are not
* constrained.
*
*
The returned multimap is not serializable.
*
* @param multimap the multimap to constrain
* @param constraint the constraint that validates added entries
* @return a constrained view of the specified multimap
*/
public static ListMultimap constrainedListMultimap(
ListMultimap multimap,
MapConstraint super K, ? super V> constraint) {
return new ConstrainedListMultimap(multimap, constraint);
}
/**
* Returns a constrained view of the specified set multimap, using the
* specified constraint. Any operations that add new mappings will call the
* provided constraint. However, this method does not verify that existing
* mappings satisfy the constraint.
*
* Note that the generated multimap's {@link Multimap#removeAll} and
* {@link Multimap#replaceValues} methods return collections that are not
* constrained.
*
The returned multimap is not serializable.
*
* @param multimap the multimap to constrain
* @param constraint the constraint that validates added entries
* @return a constrained view of the specified multimap
*/
public static SetMultimap constrainedSetMultimap(
SetMultimap multimap,
MapConstraint super K, ? super V> constraint) {
return new ConstrainedSetMultimap(multimap, constraint);
}
/**
* Returns a constrained view of the specified sorted-set multimap, using the
* specified constraint. Any operations that add new mappings will call the
* provided constraint. However, this method does not verify that existing
* mappings satisfy the constraint.
*
* Note that the generated multimap's {@link Multimap#removeAll} and
* {@link Multimap#replaceValues} methods return collections that are not
* constrained.
*
The returned multimap is not serializable.
*
* @param multimap the multimap to constrain
* @param constraint the constraint that validates added entries
* @return a constrained view of the specified multimap
*/
public static SortedSetMultimap constrainedSortedSetMultimap(
SortedSetMultimap multimap,
MapConstraint super K, ? super V> constraint) {
return new ConstrainedSortedSetMultimap(multimap, constraint);
}
/**
* Returns a constrained view of the specified entry, using the specified
* constraint. The {@link Entry#setValue} operation will be verified with the
* constraint.
*
* @param entry the entry to constrain
* @param constraint the constraint for the entry
* @return a constrained view of the specified entry
*/
private static Entry constrainedEntry(
final Entry entry,
final MapConstraint super K, ? super V> constraint) {
checkNotNull(entry);
checkNotNull(constraint);
return new ForwardingMapEntry() {
@Override protected Entry delegate() {
return entry;
}
@Override public V setValue(V value) {
constraint.checkKeyValue(getKey(), value);
return entry.setValue(value);
}
};
}
/**
* Returns a constrained view of the specified {@code asMap} entry, using the
* specified constraint. The {@link Entry#setValue} operation will be verified
* with the constraint, and the collection returned by {@link Entry#getValue}
* will be similarly constrained.
*
* @param entry the {@code asMap} entry to constrain
* @param constraint the constraint for the entry
* @return a constrained view of the specified entry
*/
private static Entry> constrainedAsMapEntry(
final Entry> entry,
final MapConstraint super K, ? super V> constraint) {
checkNotNull(entry);
checkNotNull(constraint);
return new ForwardingMapEntry>() {
@Override protected Entry> delegate() {
return entry;
}
@Override public Collection getValue() {
return Constraints.constrainedTypePreservingCollection(
entry.getValue(), new Constraint() {
@Override
public V checkElement(V value) {
constraint.checkKeyValue(getKey(), value);
return value;
}
});
}
};
}
/**
* Returns a constrained view of the specified set of {@code asMap} entries,
* using the specified constraint. The {@link Entry#setValue} operation will
* be verified with the constraint, and the collection returned by {@link
* Entry#getValue} will be similarly constrained. The {@code add} and {@code
* addAll} operations simply forward to the underlying set, which throws an
* {@link UnsupportedOperationException} per the multimap specification.
*
* @param entries the entries to constrain
* @param constraint the constraint for the entries
* @return a constrained view of the entries
*/
private static Set>> constrainedAsMapEntries(
Set>> entries,
MapConstraint super K, ? super V> constraint) {
return new ConstrainedAsMapEntries(entries, constraint);
}
/**
* Returns a constrained view of the specified collection (or set) of entries,
* using the specified constraint. The {@link Entry#setValue} operation will
* be verified with the constraint, along with add operations on the returned
* collection. The {@code add} and {@code addAll} operations simply forward to
* the underlying collection, which throws an {@link
* UnsupportedOperationException} per the map and multimap specification.
*
* @param entries the entries to constrain
* @param constraint the constraint for the entries
* @return a constrained view of the specified entries
*/
private static Collection> constrainedEntries(
Collection> entries,
MapConstraint super K, ? super V> constraint) {
if (entries instanceof Set) {
return constrainedEntrySet((Set>) entries, constraint);
}
return new ConstrainedEntries(entries, constraint);
}
/**
* Returns a constrained view of the specified set of entries, using the
* specified constraint. The {@link Entry#setValue} operation will be verified
* with the constraint, along with add operations on the returned set. The
* {@code add} and {@code addAll} operations simply forward to the underlying
* set, which throws an {@link UnsupportedOperationException} per the map and
* multimap specification.
*
* The returned multimap is not serializable.
*
* @param entries the entries to constrain
* @param constraint the constraint for the entries
* @return a constrained view of the specified entries
*/
private static Set> constrainedEntrySet(
Set> entries,
MapConstraint super K, ? super V> constraint) {
return new ConstrainedEntrySet(entries, constraint);
}
/** @see MapConstraints#constrainedMap */
static class ConstrainedMap extends ForwardingMap {
private final Map delegate;
final MapConstraint super K, ? super V> constraint;
private transient Set> entrySet;
ConstrainedMap(
Map delegate, MapConstraint super K, ? super V> constraint) {
this.delegate = checkNotNull(delegate);
this.constraint = checkNotNull(constraint);
}
@Override protected Map delegate() {
return delegate;
}
@Override public Set> entrySet() {
Set> result = entrySet;
if (result == null) {
entrySet = result =
constrainedEntrySet(delegate.entrySet(), constraint);
}
return result;
}
@Override public V put(K key, V value) {
constraint.checkKeyValue(key, value);
return delegate.put(key, value);
}
@Override public void putAll(Map extends K, ? extends V> map) {
delegate.putAll(checkMap(map, constraint));
}
}
/**
* Returns a constrained view of the specified bimap, using the specified
* constraint. Any operations that modify the bimap will have the associated
* keys and values verified with the constraint.
*
* The returned bimap is not serializable.
*
* @param map the bimap to constrain
* @param constraint the constraint that validates added entries
* @return a constrained view of the specified bimap
*/
public static BiMap constrainedBiMap(
BiMap map, MapConstraint super K, ? super V> constraint) {
return new ConstrainedBiMap(map, null, constraint);
}
/** @see MapConstraints#constrainedBiMap */
private static class ConstrainedBiMap extends ConstrainedMap
implements BiMap {
/*
* We could switch to racy single-check lazy init and remove volatile, but
* there's a downside. That's because this field is also written in the
* constructor. Without volatile, the constructor's write of the existing
* inverse BiMap could occur after inverse()'s read of the field's initial
* null value, leading inverse() to overwrite the existing inverse with a
* doubly indirect version. This wouldn't be catastrophic, but it's
* something to keep in mind if we make the change.
*
* Note that UnmodifiableBiMap *does* use racy single-check lazy init.
* TODO(cpovirk): pick one and standardize
*/
volatile BiMap inverse;
ConstrainedBiMap(BiMap delegate, @Nullable BiMap inverse,
MapConstraint super K, ? super V> constraint) {
super(delegate, constraint);
this.inverse = inverse;
}
@Override protected BiMap delegate() {
return (BiMap) super.delegate();
}
@Override
public V forcePut(K key, V value) {
constraint.checkKeyValue(key, value);
return delegate().forcePut(key, value);
}
@Override
public BiMap inverse() {
if (inverse == null) {
inverse = new ConstrainedBiMap(delegate().inverse(), this,
new InverseConstraint(constraint));
}
return inverse;
}
@Override public Set values() {
return delegate().values();
}
}
/** @see MapConstraints#constrainedBiMap */
private static class InverseConstraint implements MapConstraint {
final MapConstraint super V, ? super K> constraint;
public InverseConstraint(MapConstraint super V, ? super K> constraint) {
this.constraint = checkNotNull(constraint);
}
@Override
public void checkKeyValue(K key, V value) {
constraint.checkKeyValue(value, key);
}
}
/** @see MapConstraints#constrainedMultimap */
private static class ConstrainedMultimap
extends ForwardingMultimap implements Serializable {
final MapConstraint super K, ? super V> constraint;
final Multimap delegate;
transient Collection> entries;
transient Map> asMap;
public ConstrainedMultimap(Multimap delegate,
MapConstraint super K, ? super V> constraint) {
this.delegate = checkNotNull(delegate);
this.constraint = checkNotNull(constraint);
}
@Override protected Multimap delegate() {
return delegate;
}
@Override public Map> asMap() {
Map> result = asMap;
if (result == null) {
final Map> asMapDelegate = delegate.asMap();
asMap = result = new ForwardingMap>() {
Set>> entrySet;
Collection> values;
@Override protected Map> delegate() {
return asMapDelegate;
}
@Override public Set>> entrySet() {
Set>> result = entrySet;
if (result == null) {
entrySet = result = constrainedAsMapEntries(
asMapDelegate.entrySet(), constraint);
}
return result;
}
@SuppressWarnings("unchecked")
@Override public Collection get(Object key) {
try {
Collection collection = ConstrainedMultimap.this.get((K) key);
return collection.isEmpty() ? null : collection;
} catch (ClassCastException e) {
return null; // key wasn't a K
}
}
@Override public Collection> values() {
Collection> result = values;
if (result == null) {
values = result = new ConstrainedAsMapValues(
delegate().values(), entrySet());
}
return result;
}
@Override public boolean containsValue(Object o) {
return values().contains(o);
}
};
}
return result;
}
@Override public Collection> entries() {
Collection> result = entries;
if (result == null) {
entries = result = constrainedEntries(delegate.entries(), constraint);
}
return result;
}
@Override public Collection get(final K key) {
return Constraints.constrainedTypePreservingCollection(
delegate.get(key), new Constraint() {
@Override
public V checkElement(V value) {
constraint.checkKeyValue(key, value);
return value;
}
});
}
@Override public boolean put(K key, V value) {
constraint.checkKeyValue(key, value);
return delegate.put(key, value);
}
@Override public boolean putAll(K key, Iterable extends V> values) {
return delegate.putAll(key, checkValues(key, values, constraint));
}
@Override public boolean putAll(
Multimap extends K, ? extends V> multimap) {
boolean changed = false;
for (Entry extends K, ? extends V> entry : multimap.entries()) {
changed |= put(entry.getKey(), entry.getValue());
}
return changed;
}
@Override public Collection replaceValues(
K key, Iterable extends V> values) {
return delegate.replaceValues(key, checkValues(key, values, constraint));
}
}
/** @see ConstrainedMultimap#asMap */
private static class ConstrainedAsMapValues
extends ForwardingCollection> {
final Collection> delegate;
final Set>> entrySet;
/**
* @param entrySet map entries, linking each key with its corresponding
* values, that already enforce the constraint
*/
ConstrainedAsMapValues(Collection> delegate,
Set>> entrySet) {
this.delegate = delegate;
this.entrySet = entrySet;
}
@Override protected Collection> delegate() {
return delegate;
}
@Override public Iterator> iterator() {
final Iterator>> iterator = entrySet.iterator();
return new Iterator>() {
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public Collection next() {
return iterator.next().getValue();
}
@Override
public void remove() {
iterator.remove();
}
};
}
@Override public Object[] toArray() {
return standardToArray();
}
@Override public T[] toArray(T[] array) {
return standardToArray(array);
}
@Override public boolean contains(Object o) {
return standardContains(o);
}
@Override public boolean containsAll(Collection> c) {
return standardContainsAll(c);
}
@Override public boolean remove(Object o) {
return standardRemove(o);
}
@Override public boolean removeAll(Collection> c) {
return standardRemoveAll(c);
}
@Override public boolean retainAll(Collection> c) {
return standardRetainAll(c);
}
}
/** @see MapConstraints#constrainedEntries */
private static class ConstrainedEntries
extends ForwardingCollection> {
final MapConstraint super K, ? super V> constraint;
final Collection> entries;
ConstrainedEntries(Collection> entries,
MapConstraint super K, ? super V> constraint) {
this.entries = entries;
this.constraint = constraint;
}
@Override protected Collection> delegate() {
return entries;
}
@Override public Iterator> iterator() {
final Iterator> iterator = entries.iterator();
return new ForwardingIterator>() {
@Override public Entry next() {
return constrainedEntry(iterator.next(), constraint);
}
@Override protected Iterator> delegate() {
return iterator;
}
};
}
// See Collections.CheckedMap.CheckedEntrySet for details on attacks.
@Override public Object[] toArray() {
return standardToArray();
}
@Override public T[] toArray(T[] array) {
return standardToArray(array);
}
@Override public boolean contains(Object o) {
return Maps.containsEntryImpl(delegate(), o);
}
@Override public boolean containsAll(Collection> c) {
return standardContainsAll(c);
}
@Override public boolean remove(Object o) {
return Maps.removeEntryImpl(delegate(), o);
}
@Override public boolean removeAll(Collection> c) {
return standardRemoveAll(c);
}
@Override public boolean retainAll(Collection> c) {
return standardRetainAll(c);
}
}
/** @see MapConstraints#constrainedEntrySet */
static class ConstrainedEntrySet
extends ConstrainedEntries implements Set> {
ConstrainedEntrySet(Set> entries,
MapConstraint super K, ? super V> constraint) {
super(entries, constraint);
}
// See Collections.CheckedMap.CheckedEntrySet for details on attacks.
@Override public boolean equals(@Nullable Object object) {
return Sets.equalsImpl(this, object);
}
@Override public int hashCode() {
return Sets.hashCodeImpl(this);
}
}
/** @see MapConstraints#constrainedAsMapEntries */
static class ConstrainedAsMapEntries
extends ForwardingSet>> {
private final MapConstraint super K, ? super V> constraint;
private final Set>> entries;
ConstrainedAsMapEntries(Set>> entries,
MapConstraint super K, ? super V> constraint) {
this.entries = entries;
this.constraint = constraint;
}
@Override protected Set>> delegate() {
return entries;
}
@Override public Iterator>> iterator() {
final Iterator>> iterator = entries.iterator();
return new ForwardingIterator>>() {
@Override public Entry> next() {
return constrainedAsMapEntry(iterator.next(), constraint);
}
@Override protected Iterator>> delegate() {
return iterator;
}
};
}
// See Collections.CheckedMap.CheckedEntrySet for details on attacks.
@Override public Object[] toArray() {
return standardToArray();
}
@Override public T[] toArray(T[] array) {
return standardToArray(array);
}
@Override public boolean contains(Object o) {
return Maps.containsEntryImpl(delegate(), o);
}
@Override public boolean containsAll(Collection> c) {
return standardContainsAll(c);
}
@Override public boolean equals(@Nullable Object object) {
return standardEquals(object);
}
@Override public int hashCode() {
return standardHashCode();
}
@Override public boolean remove(Object o) {
return Maps.removeEntryImpl(delegate(), o);
}
@Override public boolean removeAll(Collection> c) {
return standardRemoveAll(c);
}
@Override public boolean retainAll(Collection> c) {
return standardRetainAll(c);
}
}
private static class ConstrainedListMultimap
extends ConstrainedMultimap implements ListMultimap {
ConstrainedListMultimap(ListMultimap delegate,
MapConstraint super K, ? super V> constraint) {
super(delegate, constraint);
}
@Override public List get(K key) {
return (List) super.get(key);
}
@Override public List removeAll(Object key) {
return (List) super.removeAll(key);
}
@Override public List replaceValues(
K key, Iterable extends V> values) {
return (List) super.replaceValues(key, values);
}
}
private static class ConstrainedSetMultimap
extends ConstrainedMultimap implements SetMultimap {
ConstrainedSetMultimap(SetMultimap delegate,
MapConstraint super K, ? super V> constraint) {
super(delegate, constraint);
}
@Override public Set get(K key) {
return (Set) super.get(key);
}
@Override public Set> entries() {
return (Set>) super.entries();
}
@Override public Set removeAll(Object key) {
return (Set) super.removeAll(key);
}
@Override public Set replaceValues(
K key, Iterable extends V> values) {
return (Set) super.replaceValues(key, values);
}
}
private static class ConstrainedSortedSetMultimap
extends ConstrainedSetMultimap implements SortedSetMultimap {
ConstrainedSortedSetMultimap(SortedSetMultimap delegate,
MapConstraint super K, ? super V> constraint) {
super(delegate, constraint);
}
@Override public SortedSet get(K key) {
return (SortedSet) super.get(key);
}
@Override public SortedSet removeAll(Object key) {
return (SortedSet) super.removeAll(key);
}
@Override public SortedSet replaceValues(
K key, Iterable extends V> values) {
return (SortedSet) super.replaceValues(key, values);
}
@Override
public Comparator super V> valueComparator() {
return ((SortedSetMultimap) delegate()).valueComparator();
}
}
private static Collection checkValues(K key,
Iterable extends V> values,
MapConstraint super K, ? super V> constraint) {
Collection copy = Lists.newArrayList(values);
for (V value : copy) {
constraint.checkKeyValue(key, value);
}
return copy;
}
private static Map checkMap(Map extends K, ? extends V> map,
MapConstraint super K, ? super V> constraint) {
Map copy = new LinkedHashMap(map);
for (Entry entry : copy.entrySet()) {
constraint.checkKeyValue(entry.getKey(), entry.getValue());
}
return copy;
}
}