org.glassfish.jersey.internal.guava.Multimaps Maven / Gradle / Ivy
Show all versions of jaxrs-ri Show documentation
/*
* 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 org.glassfish.jersey.internal.guava;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.AbstractCollection;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Supplier;
import static org.glassfish.jersey.internal.guava.Preconditions.checkNotNull;
/**
* Provides static methods acting on or generating a {@code Multimap}.
*
*
See the Guava User Guide article on
* {@code Multimaps}.
*
* @author Jared Levy
* @author Robert Konigsberg
* @author Mike Bostock
* @author Louis Wasserman
* @since 2.0 (imported from Google Collections Library)
*/
public final class Multimaps {
private Multimaps() {
}
/**
* Creates a new {@code ListMultimap} that uses the provided map and factory.
* It can generate a multimap based on arbitrary {@link Map} and {@link List}
* classes.
*
*
The {@code factory}-generated and {@code map} classes determine the
* multimap iteration order. They also specify the behavior of the
* {@code equals}, {@code hashCode}, and {@code toString} methods for the
* multimap and its returned views. The multimap's {@code get}, {@code
* removeAll}, and {@code replaceValues} methods return {@code RandomAccess}
* lists if the factory does. However, the multimap's {@code get} method
* returns instances of a different class than does {@code factory.get()}.
*
*
The multimap is serializable if {@code map}, {@code factory}, the
* lists generated by {@code factory}, and the multimap contents are all
* serializable.
*
*
The multimap is not threadsafe when any concurrent operations update the
* multimap, even if {@code map} and the instances generated by
* {@code factory} are. Concurrent read operations will work correctly. To
* allow concurrent update operations, wrap the multimap with a call to
* {@link #synchronizedListMultimap}.
*
*
Call this method only when the simpler methods
* {@link ArrayListMultimap#create()} and {@link LinkedListMultimap#create()}
* won't suffice.
*
*
Note: the multimap assumes complete ownership over of {@code map} and
* the lists returned by {@code factory}. Those objects should not be manually
* updated, they should be empty when provided, and they should not use soft,
* weak, or phantom references.
*
* @param map place to store the mapping from each key to its corresponding
* values
* @param factory supplier of new, empty lists that will each hold all values
* for a given key
* @throws IllegalArgumentException if {@code map} is not empty
*/
public static ListMultimap newListMultimap(
Map> map, final Supplier extends List> factory) {
return new CustomListMultimap(map, factory);
}
static boolean equalsImpl(Multimap, ?> multimap, Object object) {
if (object == multimap) {
return true;
}
if (object instanceof Multimap) {
Multimap, ?> that = (Multimap, ?>) object;
return multimap.asMap().equals(that.asMap());
}
return false;
}
private static class CustomListMultimap
extends AbstractListMultimap {
private static final long serialVersionUID = 0;
transient Supplier extends List> factory;
CustomListMultimap(Map> map,
Supplier extends List> factory) {
super(map);
this.factory = checkNotNull(factory);
}
@Override
protected List createCollection() {
return factory.get();
}
/**
* @serialData the factory and the backing map
*/
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
stream.writeObject(factory);
stream.writeObject(backingMap());
}
@SuppressWarnings("unchecked") // reading data stored by writeObject
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException {
stream.defaultReadObject();
factory = (Supplier extends List>) stream.readObject();
Map> map = (Map>) stream.readObject();
setMap(map);
}
}
/**
* A skeleton implementation of {@link Multimap#entries()}.
*/
abstract static class Entries extends
AbstractCollection> {
abstract Multimap multimap();
@Override
public int size() {
return multimap().size();
}
@Override
public boolean contains(Object o) {
if (o instanceof Map.Entry) {
Entry, ?> entry = (Entry, ?>) o;
return multimap().containsEntry(entry.getKey(), entry.getValue());
}
return false;
}
@Override
public boolean remove(Object o) {
if (o instanceof Map.Entry) {
Entry, ?> entry = (Entry, ?>) o;
return multimap().remove(entry.getKey(), entry.getValue());
}
return false;
}
@Override
public void clear() {
multimap().clear();
}
}
// TODO(jlevy): Create methods that filter a SortedSetMultimap.
}