001/*
002 * ModeShape (http://www.modeshape.org)
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *       http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.modeshape.common.collection;
017
018import java.util.Collection;
019import java.util.Map;
020import java.util.Set;
021
022/**
023 * A collection similar to {@link Map}, but which may associate multiple values with any single key.
024 * <p>
025 * Some implementation may not allow duplicate key-value pairs. In such implementations, calling #pu
026 * </p>
027 * 
028 * @param <K> the key type
029 * @param <V> the value type
030 */
031public interface Multimap<K, V> {
032
033    /**
034     * Return the number of key-value pairs in this multimap.
035     * 
036     * @return the size of this multimap.
037     */
038    int size();
039
040    boolean isEmpty();
041
042    /**
043     * Associate the supplied value with the given key, returning true if the size of this multimap was increased.
044     * <p>
045     * Some implementations allow duplicate key-value pairs, and in these cases this method will always increase the size of the
046     * multimap and will thus always return true. Other implementations will not allow duplicate key-value pairs, and may return
047     * false if the multimap already contains the supplied key-value pair.
048     * </p>
049     * 
050     * @param key the key
051     * @param value the value
052     * @return {@code true} if the size of this multimap was increased as a result of this call, or {@code false} if the multimap
053     *         already contained the key-value pair and doesn't allow duplicates
054     */
055    boolean put( K key,
056                 V value );
057
058    /**
059     * Remove the supplied key-value pair from this multi-map.
060     * 
061     * @param key the key
062     * @param value the value
063     * @return {@code true} if the size of this multimap was decreased as a result of this call, or {@code false} if the multimap
064     *         did not contain the key-value pair
065     */
066    boolean remove( K key,
067                    V value );
068
069    /**
070     * Remove all of the key-value pairs that use the supplied key, returning the collection of values. The resulting collection
071     * may be modifiable, but changing it will have no effect on this multimap.
072     * 
073     * @param key the key
074     * @return the collection of values that were removed, or an empty collection if there were none; never null
075     */
076    Collection<V> removeAll( K key );
077
078    /**
079     * Get the collection of values that are associated with the supplied key.
080     * <p>
081     * Changes to the returned collection will update the values that this multimap associates with the key.
082     * </p>
083     * 
084     * @param key the key
085     * @return the collection of values, or an empty collection if the supplied key was not associated with any values
086     */
087    Collection<V> get( K key );
088
089    /**
090     * Determine whether this multimap associates any values with the supplied key.
091     * 
092     * @param key the key
093     * @return {@code true} if there is at least one value associated with the supplied key, or {@code false} otherwise
094     */
095    boolean containsKey( K key );
096
097    /**
098     * Determine whether this multimap associates at least one key with the supplied value.
099     * 
100     * @param value the value
101     * @return {@code true} if there is at least one key associated with the supplied value, or {@code false} otherwise
102     */
103    boolean containsValue( Object value );
104
105    /**
106     * Determine whether this multimap contains the supplied key-value pair.
107     * 
108     * @param key the key
109     * @param value the value
110     * @return {@code true} if this multimap contains an entry with the supplied key and value, or {@code false} otherwise
111     */
112    boolean containsEntry( Object key,
113                           Object value );
114
115    /**
116     * Return the set of keys in this multimap.
117     * 
118     * @return the set of keys; never null but possible empty
119     */
120    Set<K> keySet();
121
122    /**
123     * Return a collection of all values in this multimap. Changes to the returned collection will update the underlying multimap,
124     * and vice versa.
125     * 
126     * @return the collection of values, which may include the same value multiple times if it occurs in multiple mappings; never
127     *         null but possibly empty
128     */
129    Collection<V> values();
130
131    /**
132     * Return a collection of all key-value pairs. Changes to the returned collection will update the underlying multimap, and
133     * vice versa. The entries collection does not support the {@code add} or {@code addAll} operations.
134     * 
135     * @return the collection of map entries consisting of key-value pairs; never null but possibly empty
136     */
137    Collection<Map.Entry<K, V>> entries();
138
139    /**
140     * Return a map view that associates each key with the corresponding values in the multimap. Changes to the returned map, such
141     * as element removal, will update the underlying multimap. The map does not support {@code setValue()} on its entries,
142     * {@code put}, or {@code putAll}.
143     * <p>
144     * The collections returned by {@code asMap().get(Object)} have the same behavior as those returned by {@link #get}.
145     * 
146     * @return a map view from a key to its collection of values
147     */
148    Map<K, Collection<V>> asMap();
149
150    /**
151     * Remove all key-value pairs from this multimap.
152     */
153    void clear();
154}