2 // ========================================================================
3 // Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4 // ------------------------------------------------------------------------
5 // All rights reserved. This program and the accompanying materials
6 // are made available under the terms of the Eclipse Public License v1.0
7 // and Apache License v2.0 which accompanies this distribution.
9 // The Eclipse Public License is available at
10 // http://www.eclipse.org/legal/epl-v10.html
12 // The Apache License v2.0 is available at
13 // http://www.opensource.org/licenses/apache2.0.php
15 // You may elect to redistribute this code under either of these licenses.
16 // ========================================================================
19 package org.eclipse.jetty.util;
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.HashMap;
24 import java.util.Iterator;
25 import java.util.List;
27 import java.util.Map.Entry;
32 @SuppressWarnings("serial")
33 public class MultiMap<V> extends HashMap<String,List<V>>
40 public MultiMap(Map<String,List<V>> map)
45 public MultiMap(MultiMap<V> map)
51 /* ------------------------------------------------------------ */
52 /** Get multiple values.
53 * Single valued entries are converted to singleton lists.
54 * @param name The entry key.
55 * @return Unmodifieable List of values.
57 public List<V> getValues(String name)
59 List<V> vals = super.get(name);
60 if((vals == null) || vals.isEmpty()) {
66 /* ------------------------------------------------------------ */
67 /** Get a value from a multiple value.
68 * If the value is not a multivalue, then index 0 retrieves the
70 * @param name The entry key.
71 * @param i Index of element to get.
72 * @return Unmodifieable List of values.
74 public V getValue(String name,int i)
76 List<V> vals = getValues(name);
80 if (i==0 && vals.isEmpty()) {
87 /* ------------------------------------------------------------ */
88 /** Get value as String.
89 * Single valued items are converted to a String with the toString()
90 * Object method. Multi valued entries are converted to a comma separated
91 * List. No quoting of commas within values is performed.
92 * @param name The entry key.
93 * @return String value.
95 public String getString(String name)
97 List<V> vals =get(name);
98 if ((vals == null) || (vals.isEmpty()))
103 if (vals.size() == 1)
106 return vals.get(0).toString();
110 StringBuilder values=new StringBuilder(128);
115 if (values.length() > 0)
117 values.append(e.toString());
120 return values.toString();
124 * Put multi valued entry.
125 * @param name The entry key.
126 * @param value The simple value
127 * @return The previous value or null.
129 public List<V> put(String name, V value)
132 return super.put(name, null);
134 List<V> vals = new ArrayList<>();
136 return put(name,vals);
140 * Shorthand version of putAll
141 * @param input the input map
143 public void putAllValues(Map<String, V> input)
145 for(Map.Entry<String,V> entry: input.entrySet())
147 put(entry.getKey(), entry.getValue());
151 /* ------------------------------------------------------------ */
152 /** Put multi valued entry.
153 * @param name The entry key.
154 * @param values The List of multiple values.
155 * @return The previous value or null.
157 public List<V> putValues(String name, List<V> values)
159 return super.put(name,values);
162 /* ------------------------------------------------------------ */
163 /** Put multi valued entry.
164 * @param name The entry key.
165 * @param values The array of multiple values.
166 * @return The previous value or null.
169 public final List<V> putValues(String name, V... values)
171 List<V> list = new ArrayList<>();
172 list.addAll(Arrays.asList(values));
173 return super.put(name,list);
177 /* ------------------------------------------------------------ */
178 /** Add value to multi valued entry.
179 * If the entry is single valued, it is converted to the first
180 * value of a multi valued entry.
181 * @param name The entry key.
182 * @param value The entry value.
184 public void add(String name, V value)
186 List<V> lo = get(name);
188 lo = new ArrayList<>();
194 /* ------------------------------------------------------------ */
195 /** Add values to multi valued entry.
196 * If the entry is single valued, it is converted to the first
197 * value of a multi valued entry.
198 * @param name The entry key.
199 * @param values The List of multiple values.
201 public void addValues(String name, List<V> values)
203 List<V> lo = get(name);
205 lo = new ArrayList<>();
211 /* ------------------------------------------------------------ */
212 /** Add values to multi valued entry.
213 * If the entry is single valued, it is converted to the first
214 * value of a multi valued entry.
215 * @param name The entry key.
216 * @param values The String array of multiple values.
218 public void addValues(String name, V[] values)
220 List<V> lo = get(name);
222 lo = new ArrayList<>();
224 lo.addAll(Arrays.asList(values));
232 * the map to overlay on top of this one, merging together values if needed.
233 * @return true if an existing key was merged with potentially new values, false if either no change was made, or there were only new keys.
235 public boolean addAllValues(MultiMap<V> map)
237 boolean merged = false;
239 if ((map == null) || (map.isEmpty()))
245 for (Map.Entry<String, List<V>> entry : map.entrySet())
247 String name = entry.getKey();
248 List<V> values = entry.getValue();
250 if (this.containsKey(name))
255 this.addValues(name,values);
261 /* ------------------------------------------------------------ */
263 * @param name The entry key.
264 * @param value The entry value.
265 * @return true if it was removed.
267 public boolean removeValue(String name,V value)
269 List<V> lo = get(name);
270 if((lo == null)||(lo.isEmpty())) {
273 boolean ret = lo.remove(value);
283 * Test for a specific single value in the map.
285 * NOTE: This is a SLOW operation, and is actively discouraged.
287 * @return true if contains simple value
289 public boolean containsSimpleValue(V value)
291 for (List<V> vals : values())
293 if ((vals.size() == 1) && vals.contains(value))
302 public String toString()
304 Iterator<Entry<String, List<V>>> iter = entrySet().iterator();
305 StringBuilder sb = new StringBuilder();
307 boolean delim = false;
308 while (iter.hasNext())
310 Entry<String, List<V>> e = iter.next();
315 String key = e.getKey();
316 List<V> vals = e.getValue();
319 if (vals.size() == 1)
321 sb.append(vals.get(0));
330 return sb.toString();
333 /* ------------------------------------------------------------ */
335 * @return Map of String arrays
337 public Map<String,String[]> toStringArrayMap()
339 HashMap<String,String[]> map = new HashMap<String,String[]>(size()*3/2)
342 public String toString()
344 StringBuilder b=new StringBuilder();
346 for (String k:super.keySet())
352 b.append(Arrays.asList(super.get(k)));
360 for(Map.Entry<String,List<V>> entry: entrySet())
363 if (entry.getValue() != null)
365 a = new String[entry.getValue().size()];
366 a = entry.getValue().toArray(a);
368 map.put(entry.getKey(),a);