org.eclipse.jetty.util.MultiMap Maven / Gradle / Ivy
Show all versions of jetty-util Show documentation
//
// ========================================================================
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.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.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* A multi valued Map.
*
* @param the entry type for multimap values
*/
@SuppressWarnings("serial")
public class MultiMap extends LinkedHashMap>
{
// TODO review if this is really still needed or can we just use Map> instead?
// or org.eclipse.util.Fields ?
public MultiMap()
{
super();
}
public MultiMap(Map> map)
{
super(map);
}
public MultiMap(MultiMap map)
{
super(map);
}
/**
* Get multiple values.
* Single valued entries are converted to singleton lists.
*
* @param name The entry key.
* @return Unmodifieable List of values.
*/
public List getValues(String name)
{
List vals = super.get(name);
if ((vals == null) || vals.isEmpty())
{
return null;
}
return vals;
}
/**
* Get the first value from a multiple value.
*
* @param name The entry key.
* @return a value from index 0.
*/
public V getValue(String name)
{
return getValue(name, 0);
}
/**
* 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 a value.
*/
public V getValue(String name, int i)
{
List 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.
*
* @param name The entry key.
* @return String value.
*/
public String getString(String name)
{
List 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.
*
* @param name The entry key.
* @param value The simple value
* @return The previous value or null.
*/
public List put(String name, V value)
{
if (value == null)
{
return super.put(name, null);
}
List vals = new ArrayList<>();
vals.add(value);
return put(name, vals);
}
/**
* Shorthand version of putAll
*
* @param input the input map
*/
public void putAllValues(Map input)
{
for (Map.Entry entry : input.entrySet())
{
put(entry.getKey(), entry.getValue());
}
}
/**
* Put multi valued entry.
*
* @param name The entry key.
* @param values The List of multiple values.
* @return The previous value or null.
*/
public List putValues(String name, List values)
{
return super.put(name, values);
}
/**
* 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 putValues(String name, V... values)
{
List 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.
*
* @param name The entry key.
* @param value The entry value.
*/
public void add(String name, V value)
{
List 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.
*
* @param name The entry key.
* @param values The List of multiple values.
*/
public void addValues(String name, List values)
{
List 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.
*
* @param name The entry key.
* @param values The String array of multiple values.
*/
public void addValues(String name, V[] values)
{
List lo = get(name);
if (lo == null)
{
lo = new ArrayList<>();
}
lo.addAll(Arrays.asList(values));
put(name, lo);
}
/**
* 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 map)
{
boolean merged = false;
if ((map == null) || (map.isEmpty()))
{
// done
return merged;
}
for (Map.Entry> entry : map.entrySet())
{
String name = entry.getKey();
List values = entry.getValue();
if (this.containsKey(name))
{
merged = true;
}
this.addValues(name, values);
}
return merged;
}
/**
* 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 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.
*
* @param value the value to search for
* @return true if contains simple value
*/
public boolean containsSimpleValue(V value)
{
for (List vals : values())
{
if ((vals.size() == 1) && vals.contains(value))
{
return true;
}
}
return false;
}
@Override
public String toString()
{
Iterator>> iter = entrySet().iterator();
StringBuilder sb = new StringBuilder();
sb.append('{');
boolean delim = false;
while (iter.hasNext())
{
Map.Entry> e = iter.next();
if (delim)
{
sb.append(", ");
}
String key = e.getKey();
List 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();
}
/**
* @return Map of String arrays
*/
public Map toStringArrayMap()
{
Map map = new LinkedHashMap(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> 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;
}
}