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-2015 ForgeRock AS. 017 */ 018 019package org.forgerock.http.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<>(); 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<>(); 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}