001/*-------------------------------------------------------------------------+
002|                                                                          |
003| Copyright 2005-2011 The ConQAT Project                                   |
004|                                                                          |
005| Licensed under the Apache License, Version 2.0 (the "License");          |
006| you may not use this file except in compliance with the License.         |
007| You may obtain a copy of the License at                                  |
008|                                                                          |
009|    http://www.apache.org/licenses/LICENSE-2.0                            |
010|                                                                          |
011| Unless required by applicable law or agreed to in writing, software      |
012| distributed under the License is distributed on an "AS IS" BASIS,        |
013| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
014| See the License for the specific language governing permissions and      |
015| limitations under the License.                                           |
016+-------------------------------------------------------------------------*/
017package org.conqat.lib.commons.collections;
018
019import java.util.Arrays;
020import java.util.HashSet;
021import java.util.Map;
022import java.util.Set;
023import java.util.function.Supplier;
024
025/**
026 * Manages a map of sets, i.e. each key can store multiple elements.
027 * 
028 * @param <K>
029 *            the key type.
030 * @param <V>
031 *            the value type (i.e. the values stored in the collections).
032 */
033public class SetMap<K, V> extends CollectionMap<K, V, Set<V>> {
034
035        private static final long serialVersionUID = 1L;
036
037        private final Supplier<Set<V>> setFactory;
038
039        public SetMap() {
040                this(HashSet::new);
041        }
042
043        public SetMap(Supplier<Set<V>> setFactory) {
044                this.setFactory = setFactory;
045        }
046
047        @SafeVarargs
048        public SetMap(SetMap<K, V>... otherMaps) {
049                this(determineFactory(otherMaps));
050                for (SetMap<K, V> otherMap : otherMaps) {
051                        addAll(otherMap);
052                }
053        }
054
055        private static <K, V> Supplier<Set<V>> determineFactory(SetMap<K, V>[] otherMaps) {
056                if (otherMaps.length > 0) {
057                        return otherMaps[0].setFactory;
058                }
059                return HashSet::new;
060        }
061
062        @SafeVarargs
063        public SetMap(Map<K, Set<V>>... otherMaps) {
064                this();
065                for (Map<K, Set<V>> otherMap : otherMaps) {
066                        addAll(otherMap);
067                }
068        }
069
070        @Override
071        protected Set<V> createNewCollection() {
072                return setFactory.get();
073        }
074
075        /** Inverts this SetMap, i.e. switches the keys and values. */
076        public SetMap<V, K> invert() {
077                SetMap<V, K> invertedMap = new SetMap<>();
078                for (K nowValue : this.getKeys()) {
079                        for (V nowKey : this.getCollection(nowValue)) {
080                                invertedMap.add(nowKey, nowValue);
081                        }
082                }
083                return invertedMap;
084        }
085
086        /** Factory function for a {@link SetMap} with one entry. */
087        public static <K, V> SetMap<K, V> of(K key, V... values) {
088                SetMap<K, V> result = new SetMap<>();
089                result.addAll(key, Arrays.asList(values));
090                return result;
091        }
092}