001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2009 Sun Microsystems Inc.
015 * Portions Copyright 2010–2011 ApexIdentity Inc.
016 * Portions Copyright 2011-2014 ForgeRock AS.
017 */
018
019package org.forgerock.openig.util;
020
021import java.util.ArrayList;
022import java.util.Collection;
023import java.util.List;
024import java.util.Map;
025
026import org.forgerock.util.MapDecorator;
027
028/**
029 * Wraps a map for which the values are lists, providing a set of convenience methods for
030 * handling list values.
031 *
032 * @param <K> Key type
033 * @param <V> Value type (of the list)
034 */
035public class MultiValueMap<K, V> extends MapDecorator<K, List<V>> {
036
037    /**
038     * Creates a new multi-value map, wrapping an existing map with list values.
039     *
040     * @param map the map to wrap with a new multi-value map.
041     */
042    public MultiValueMap(Map<K, List<V>> map) {
043        super(map);
044    }
045
046    /**
047     * Adds the specified value to the list for the specified key. If no list for the key yet
048     * exists in the map, a new list is created and added.
049     *
050     * @param key the key of the list to add the value to.
051     * @param value the value to be added to the list.
052     */
053    public void add(K key, V value) {
054        List<V> list = get(key);
055        if (list == null) {
056            list = new ArrayList<V>();
057            put(key, list);
058        }
059        list.add(value);
060    }
061
062    /**
063     * Adds the specified values to the list for the specified key. If no list for the key
064     * yet exists in the map, a new list is created and added.
065     *
066     * @param key the key of the list to add the values to.
067     * @param values the values to be added to the list.
068     */
069    public void addAll(K key, Collection<? extends V> values) {
070        List<V> list = get(key);
071        if (list == null) {
072            list = new ArrayList<V>();
073            put(key, list);
074        }
075        list.addAll(values);
076    }
077
078    /**
079     * Adds the specified keys and values from the specified map into this map.
080     *
081     * @param map the map whose keys and values are to be added.
082     */
083    public void addAll(MultiValueMap<K, V> map) {
084        for (K key : map.keySet()) {
085            addAll(key, map.get(key));
086        }
087    }
088
089    /**
090     * Adds the specified keys and values from the specified map into this map.
091     *
092     * @param map the map whose keys and values are to be added.
093     */
094    public void addAll(Map<? extends K, Collection<? extends V>> map) {
095        for (K key : map.keySet()) {
096            addAll(key, map.get(key));
097        }
098    }
099
100    /**
101     * Returns the first value in the list of values for the matching key, or {@code null}
102     * if no such value exists.
103     *
104     * @param key the key whose associated first item is to be returned.
105     * @return the first value in the key's value list, or null if non-existent.
106     */
107    public V getFirst(K key) {
108        List<V> list = get(key);
109        if (list == null || list.size() == 0) {
110            return null;
111        } else {
112            return list.get(0);
113        }
114    }
115
116    /**
117     * Maps a single value to the specified key, replacing any value(s) that are already
118     * mapped to that key.
119     *
120     * @param key key with which the specified value is to be mapped.
121     * @param value the single value to be mapped to the specified key.
122     */
123    public void putSingle(K key, V value) {
124        remove(key);
125        add(key, value);
126    }
127}