]> WPIA git - gigi.git/blobdiff - lib/jetty/org/eclipse/jetty/util/MultiMap.java
Importing upstream Jetty jetty-9.2.1.v20140609
[gigi.git] / lib / jetty / org / eclipse / jetty / util / MultiMap.java
diff --git a/lib/jetty/org/eclipse/jetty/util/MultiMap.java b/lib/jetty/org/eclipse/jetty/util/MultiMap.java
new file mode 100644 (file)
index 0000000..a3c905a
--- /dev/null
@@ -0,0 +1,373 @@
+//
+//  ========================================================================
+//  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+//  ------------------------------------------------------------------------
+//  All rights reserved. This program and the accompanying materials
+//  are made available under the terms of the Eclipse Public License v1.0
+//  and Apache License v2.0 which accompanies this distribution.
+//
+//      The Eclipse Public License is available at
+//      http://www.eclipse.org/legal/epl-v10.html
+//
+//      The Apache License v2.0 is available at
+//      http://www.opensource.org/licenses/apache2.0.php
+//
+//  You may elect to redistribute this code under either of these licenses.
+//  ========================================================================
+//
+
+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;
+import java.util.Map.Entry;
+
+/** 
+ * A multi valued Map.
+ */
+@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.
+     * @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.
+     * @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.
+     * @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.
+     * @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
+     * @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.
+     * @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.
+     * @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.
+     * @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.
+     * @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.
+     * @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.
+     * 
+     * @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.
+     * @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.
+     * <p>
+     * NOTE: This is a SLOW operation, and is actively discouraged.
+     * @param value
+     * @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();
+    }
+    
+    /* ------------------------------------------------------------ */
+    /** 
+     * @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;
+    }
+
+}