//
// ========================================================================
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under
// the terms of the Eclipse Public License 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0
//
// This Source Code may also be made available under the following
// Secondary Licenses when the conditions for such availability set
// forth in the Eclipse Public License, v. 2.0 are satisfied:
// the Apache License v2.0 which is available at
// https://www.apache.org/licenses/LICENSE-2.0
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//
package org.eclipse.jetty.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
A multi valued Map.
Type parameters: - <V> – the entry type for multimap values
/**
* A multi valued Map.
*
* @param <V> the entry type for multimap values
*/
@SuppressWarnings("serial")
public class MultiMap<V> extends HashMap<String, List<V>>
{
public MultiMap()
{
super();
}
public MultiMap(Map<String, List<V>> map)
{
super(map);
}
public MultiMap(MultiMap<V> map)
{
super(map);
}
Get multiple values.
Single valued entries are converted to singleton lists.
Params: - name – The entry key.
Returns: Unmodifieable List of values.
/**
* Get multiple values.
* Single valued entries are converted to singleton lists.
*
* @param name The entry key.
* @return Unmodifieable List of values.
*/
public List<V> getValues(String name)
{
List<V> vals = super.get(name);
if ((vals == null) || vals.isEmpty())
{
return null;
}
return vals;
}
Get a value from a multiple value.
If the value is not a multivalue, then index 0 retrieves the
value or null.
Params: - name – The entry key.
- i – Index of element to get.
Returns: Unmodifieable List of values.
/**
* Get a value from a multiple value.
* If the value is not a multivalue, then index 0 retrieves the
* value or null.
*
* @param name The entry key.
* @param i Index of element to get.
* @return Unmodifieable List of values.
*/
public V getValue(String name, int i)
{
List<V> vals = getValues(name);
if (vals == null)
{
return null;
}
if (i == 0 && vals.isEmpty())
{
return null;
}
return vals.get(i);
}
Get value as String.
Single valued items are converted to a String with the toString()
Object method. Multi valued entries are converted to a comma separated
List. No quoting of commas within values is performed.
Params: - name – The entry key.
Returns: String value.
/**
* Get value as String.
* Single valued items are converted to a String with the toString()
* Object method. Multi valued entries are converted to a comma separated
* List. No quoting of commas within values is performed.
*
* @param name The entry key.
* @return String value.
*/
public String getString(String name)
{
List<V> vals = get(name);
if ((vals == null) || (vals.isEmpty()))
{
return null;
}
if (vals.size() == 1)
{
// simple form.
return vals.get(0).toString();
}
// delimited form
StringBuilder values = new StringBuilder(128);
for (V e : vals)
{
if (e != null)
{
if (values.length() > 0)
values.append(',');
values.append(e.toString());
}
}
return values.toString();
}
Put multi valued entry.
Params: - name – The entry key.
- value – The simple value
Returns: The previous value or null.
/**
* Put multi valued entry.
*
* @param name The entry key.
* @param value The simple value
* @return The previous value or null.
*/
public List<V> put(String name, V value)
{
if (value == null)
{
return super.put(name, null);
}
List<V> vals = new ArrayList<>();
vals.add(value);
return put(name, vals);
}
Shorthand version of putAll
Params: - input – the input map
/**
* Shorthand version of putAll
*
* @param input the input map
*/
public void putAllValues(Map<String, V> input)
{
for (Map.Entry<String, V> entry : input.entrySet())
{
put(entry.getKey(), entry.getValue());
}
}
Put multi valued entry.
Params: - name – The entry key.
- values – The List of multiple values.
Returns: The previous value or null.
/**
* Put multi valued entry.
*
* @param name The entry key.
* @param values The List of multiple values.
* @return The previous value or null.
*/
public List<V> putValues(String name, List<V> values)
{
return super.put(name, values);
}
Put multi valued entry.
Params: - name – The entry key.
- values – The array of multiple values.
Returns: The previous value or null.
/**
* Put multi valued entry.
*
* @param name The entry key.
* @param values The array of multiple values.
* @return The previous value or null.
*/
@SafeVarargs
public final List<V> putValues(String name, V... values)
{
List<V> list = new ArrayList<>();
list.addAll(Arrays.asList(values));
return super.put(name, list);
}
Add value to multi valued entry.
If the entry is single valued, it is converted to the first
value of a multi valued entry.
Params: - name – The entry key.
- value – The entry value.
/**
* Add value to multi valued entry.
* If the entry is single valued, it is converted to the first
* value of a multi valued entry.
*
* @param name The entry key.
* @param value The entry value.
*/
public void add(String name, V value)
{
List<V> lo = get(name);
if (lo == null)
{
lo = new ArrayList<>();
}
lo.add(value);
super.put(name, lo);
}
Add values to multi valued entry.
If the entry is single valued, it is converted to the first
value of a multi valued entry.
Params: - name – The entry key.
- values – The List of multiple values.
/**
* Add values to multi valued entry.
* If the entry is single valued, it is converted to the first
* value of a multi valued entry.
*
* @param name The entry key.
* @param values The List of multiple values.
*/
public void addValues(String name, List<V> values)
{
List<V> lo = get(name);
if (lo == null)
{
lo = new ArrayList<>();
}
lo.addAll(values);
put(name, lo);
}
Add values to multi valued entry.
If the entry is single valued, it is converted to the first
value of a multi valued entry.
Params: - name – The entry key.
- values – The String array of multiple values.
/**
* Add values to multi valued entry.
* If the entry is single valued, it is converted to the first
* value of a multi valued entry.
*
* @param name The entry key.
* @param values The String array of multiple values.
*/
public void addValues(String name, V[] values)
{
List<V> lo = get(name);
if (lo == null)
{
lo = new ArrayList<>();
}
lo.addAll(Arrays.asList(values));
put(name, lo);
}
Merge values.
Params: - map – the map to overlay on top of this one, merging together values if needed.
Returns: true if an existing key was merged with potentially new values, false if either no change was made, or there were only new keys.
/**
* Merge values.
*
* @param map the map to overlay on top of this one, merging together values if needed.
* @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.
*/
public boolean addAllValues(MultiMap<V> map)
{
boolean merged = false;
if ((map == null) || (map.isEmpty()))
{
// done
return merged;
}
for (Map.Entry<String, List<V>> entry : map.entrySet())
{
String name = entry.getKey();
List<V> values = entry.getValue();
if (this.containsKey(name))
{
merged = true;
}
this.addValues(name, values);
}
return merged;
}
Remove value.
Params: - name – The entry key.
- value – The entry value.
Returns: true if it was removed.
/**
* Remove value.
*
* @param name The entry key.
* @param value The entry value.
* @return true if it was removed.
*/
public boolean removeValue(String name, V value)
{
List<V> lo = get(name);
if ((lo == null) || (lo.isEmpty()))
{
return false;
}
boolean ret = lo.remove(value);
if (lo.isEmpty())
{
remove(name);
}
else
{
put(name, lo);
}
return ret;
}
Test for a specific single value in the map.
NOTE: This is a SLOW operation, and is actively discouraged.
Params: - value – the value to search for
Returns: true if contains simple value
/**
* Test for a specific single value in the map.
* <p>
* NOTE: This is a SLOW operation, and is actively discouraged.
*
* @param value the value to search for
* @return true if contains simple value
*/
public boolean containsSimpleValue(V value)
{
for (List<V> vals : values())
{
if ((vals.size() == 1) && vals.contains(value))
{
return true;
}
}
return false;
}
@Override
public String toString()
{
Iterator<Entry<String, List<V>>> iter = entrySet().iterator();
StringBuilder sb = new StringBuilder();
sb.append('{');
boolean delim = false;
while (iter.hasNext())
{
Entry<String, List<V>> e = iter.next();
if (delim)
{
sb.append(", ");
}
String key = e.getKey();
List<V> vals = e.getValue();
sb.append(key);
sb.append('=');
if (vals.size() == 1)
{
sb.append(vals.get(0));
}
else
{
sb.append(vals);
}
delim = true;
}
sb.append('}');
return sb.toString();
}
Returns: Map of String arrays
/**
* @return Map of String arrays
*/
public Map<String, String[]> toStringArrayMap()
{
HashMap<String, String[]> map = new HashMap<String, String[]>(size() * 3 / 2)
{
@Override
public String toString()
{
StringBuilder b = new StringBuilder();
b.append('{');
for (String k : super.keySet())
{
if (b.length() > 1)
b.append(',');
b.append(k);
b.append('=');
b.append(Arrays.asList(super.get(k)));
}
b.append('}');
return b.toString();
}
};
for (Map.Entry<String, List<V>> entry : entrySet())
{
String[] a = null;
if (entry.getValue() != null)
{
a = new String[entry.getValue().size()];
a = entry.getValue().toArray(a);
}
map.put(entry.getKey(), a);
}
return map;
}
}