103928aee4356845252ac6b662d5c72c29903813eJake Slack//
203928aee4356845252ac6b662d5c72c29903813eJake Slack//  ========================================================================
303928aee4356845252ac6b662d5c72c29903813eJake Slack//  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
403928aee4356845252ac6b662d5c72c29903813eJake Slack//  ------------------------------------------------------------------------
503928aee4356845252ac6b662d5c72c29903813eJake Slack//  All rights reserved. This program and the accompanying materials
603928aee4356845252ac6b662d5c72c29903813eJake Slack//  are made available under the terms of the Eclipse Public License v1.0
703928aee4356845252ac6b662d5c72c29903813eJake Slack//  and Apache License v2.0 which accompanies this distribution.
803928aee4356845252ac6b662d5c72c29903813eJake Slack//
903928aee4356845252ac6b662d5c72c29903813eJake Slack//      The Eclipse Public License is available at
1003928aee4356845252ac6b662d5c72c29903813eJake Slack//      http://www.eclipse.org/legal/epl-v10.html
1103928aee4356845252ac6b662d5c72c29903813eJake Slack//
1203928aee4356845252ac6b662d5c72c29903813eJake Slack//      The Apache License v2.0 is available at
1303928aee4356845252ac6b662d5c72c29903813eJake Slack//      http://www.opensource.org/licenses/apache2.0.php
1403928aee4356845252ac6b662d5c72c29903813eJake Slack//
1503928aee4356845252ac6b662d5c72c29903813eJake Slack//  You may elect to redistribute this code under either of these licenses.
1603928aee4356845252ac6b662d5c72c29903813eJake Slack//  ========================================================================
1703928aee4356845252ac6b662d5c72c29903813eJake Slack//
1803928aee4356845252ac6b662d5c72c29903813eJake Slack
1903928aee4356845252ac6b662d5c72c29903813eJake Slackpackage org.eclipse.jetty.util;
2003928aee4356845252ac6b662d5c72c29903813eJake Slack
2103928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.Serializable;
2203928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Arrays;
2303928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Collection;
2403928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.HashMap;
2503928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.List;
2603928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Map;
2703928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Set;
2803928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.concurrent.ConcurrentHashMap;
2903928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.concurrent.ConcurrentMap;
3003928aee4356845252ac6b662d5c72c29903813eJake Slack
3103928aee4356845252ac6b662d5c72c29903813eJake Slack/* ------------------------------------------------------------ */
3203928aee4356845252ac6b662d5c72c29903813eJake Slack/** A multi valued Map.
3303928aee4356845252ac6b662d5c72c29903813eJake Slack * This Map specializes HashMap and provides methods
3403928aee4356845252ac6b662d5c72c29903813eJake Slack * that operate on multi valued items.
3503928aee4356845252ac6b662d5c72c29903813eJake Slack * <P>
3603928aee4356845252ac6b662d5c72c29903813eJake Slack * Implemented as a map of LazyList values
3703928aee4356845252ac6b662d5c72c29903813eJake Slack * @param <K> The key type of the map.
3803928aee4356845252ac6b662d5c72c29903813eJake Slack *
3903928aee4356845252ac6b662d5c72c29903813eJake Slack * @see LazyList
4003928aee4356845252ac6b662d5c72c29903813eJake Slack *
4103928aee4356845252ac6b662d5c72c29903813eJake Slack */
4203928aee4356845252ac6b662d5c72c29903813eJake Slackpublic class MultiMap<K> implements ConcurrentMap<K,Object>, Serializable
4303928aee4356845252ac6b662d5c72c29903813eJake Slack{
4403928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final long serialVersionUID = -6878723138353851005L;
4503928aee4356845252ac6b662d5c72c29903813eJake Slack    Map<K,Object> _map;
4603928aee4356845252ac6b662d5c72c29903813eJake Slack    ConcurrentMap<K, Object> _cmap;
4703928aee4356845252ac6b662d5c72c29903813eJake Slack
4803928aee4356845252ac6b662d5c72c29903813eJake Slack    public MultiMap()
4903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
5003928aee4356845252ac6b662d5c72c29903813eJake Slack        _map=new HashMap<K, Object>();
5103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
5203928aee4356845252ac6b662d5c72c29903813eJake Slack
5303928aee4356845252ac6b662d5c72c29903813eJake Slack    public MultiMap(Map<K,Object> map)
5403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
5503928aee4356845252ac6b662d5c72c29903813eJake Slack        if (map instanceof ConcurrentMap)
5603928aee4356845252ac6b662d5c72c29903813eJake Slack            _map=_cmap=new ConcurrentHashMap<K, Object>(map);
5703928aee4356845252ac6b662d5c72c29903813eJake Slack        else
5803928aee4356845252ac6b662d5c72c29903813eJake Slack            _map=new HashMap<K, Object>(map);
5903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
6003928aee4356845252ac6b662d5c72c29903813eJake Slack
6103928aee4356845252ac6b662d5c72c29903813eJake Slack    public MultiMap(MultiMap<K> map)
6203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
6303928aee4356845252ac6b662d5c72c29903813eJake Slack        if (map._cmap!=null)
6403928aee4356845252ac6b662d5c72c29903813eJake Slack            _map=_cmap=new ConcurrentHashMap<K, Object>(map._cmap);
6503928aee4356845252ac6b662d5c72c29903813eJake Slack        else
6603928aee4356845252ac6b662d5c72c29903813eJake Slack            _map=new HashMap<K,Object>(map._map);
6703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
6803928aee4356845252ac6b662d5c72c29903813eJake Slack
6903928aee4356845252ac6b662d5c72c29903813eJake Slack    public MultiMap(int capacity)
7003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
7103928aee4356845252ac6b662d5c72c29903813eJake Slack        _map=new HashMap<K, Object>(capacity);
7203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
7303928aee4356845252ac6b662d5c72c29903813eJake Slack
7403928aee4356845252ac6b662d5c72c29903813eJake Slack    public MultiMap(boolean concurrent)
7503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
7603928aee4356845252ac6b662d5c72c29903813eJake Slack        if (concurrent)
7703928aee4356845252ac6b662d5c72c29903813eJake Slack            _map=_cmap=new ConcurrentHashMap<K, Object>();
7803928aee4356845252ac6b662d5c72c29903813eJake Slack        else
7903928aee4356845252ac6b662d5c72c29903813eJake Slack            _map=new HashMap<K, Object>();
8003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
8103928aee4356845252ac6b662d5c72c29903813eJake Slack
8203928aee4356845252ac6b662d5c72c29903813eJake Slack
8303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
8403928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Get multiple values.
8503928aee4356845252ac6b662d5c72c29903813eJake Slack     * Single valued entries are converted to singleton lists.
8603928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param name The entry key.
8703928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return Unmodifieable List of values.
8803928aee4356845252ac6b662d5c72c29903813eJake Slack     */
8903928aee4356845252ac6b662d5c72c29903813eJake Slack    public List getValues(Object name)
9003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
9103928aee4356845252ac6b662d5c72c29903813eJake Slack        return LazyList.getList(_map.get(name),true);
9203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
9303928aee4356845252ac6b662d5c72c29903813eJake Slack
9403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
9503928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Get a value from a multiple value.
9603928aee4356845252ac6b662d5c72c29903813eJake Slack     * If the value is not a multivalue, then index 0 retrieves the
9703928aee4356845252ac6b662d5c72c29903813eJake Slack     * value or null.
9803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param name The entry key.
9903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param i Index of element to get.
10003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return Unmodifieable List of values.
10103928aee4356845252ac6b662d5c72c29903813eJake Slack     */
10203928aee4356845252ac6b662d5c72c29903813eJake Slack    public Object getValue(Object name,int i)
10303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
10403928aee4356845252ac6b662d5c72c29903813eJake Slack        Object l=_map.get(name);
10503928aee4356845252ac6b662d5c72c29903813eJake Slack        if (i==0 && LazyList.size(l)==0)
10603928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
10703928aee4356845252ac6b662d5c72c29903813eJake Slack        return LazyList.get(l,i);
10803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
10903928aee4356845252ac6b662d5c72c29903813eJake Slack
11003928aee4356845252ac6b662d5c72c29903813eJake Slack
11103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
11203928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Get value as String.
11303928aee4356845252ac6b662d5c72c29903813eJake Slack     * Single valued items are converted to a String with the toString()
11403928aee4356845252ac6b662d5c72c29903813eJake Slack     * Object method. Multi valued entries are converted to a comma separated
11503928aee4356845252ac6b662d5c72c29903813eJake Slack     * List.  No quoting of commas within values is performed.
11603928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param name The entry key.
11703928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return String value.
11803928aee4356845252ac6b662d5c72c29903813eJake Slack     */
11903928aee4356845252ac6b662d5c72c29903813eJake Slack    public String getString(Object name)
12003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
12103928aee4356845252ac6b662d5c72c29903813eJake Slack        Object l=_map.get(name);
12203928aee4356845252ac6b662d5c72c29903813eJake Slack        switch(LazyList.size(l))
12303928aee4356845252ac6b662d5c72c29903813eJake Slack        {
12403928aee4356845252ac6b662d5c72c29903813eJake Slack          case 0:
12503928aee4356845252ac6b662d5c72c29903813eJake Slack              return null;
12603928aee4356845252ac6b662d5c72c29903813eJake Slack          case 1:
12703928aee4356845252ac6b662d5c72c29903813eJake Slack              Object o=LazyList.get(l,0);
12803928aee4356845252ac6b662d5c72c29903813eJake Slack              return o==null?null:o.toString();
12903928aee4356845252ac6b662d5c72c29903813eJake Slack          default:
13003928aee4356845252ac6b662d5c72c29903813eJake Slack          {
13103928aee4356845252ac6b662d5c72c29903813eJake Slack              StringBuilder values=new StringBuilder(128);
13203928aee4356845252ac6b662d5c72c29903813eJake Slack              for (int i=0; i<LazyList.size(l); i++)
13303928aee4356845252ac6b662d5c72c29903813eJake Slack              {
13403928aee4356845252ac6b662d5c72c29903813eJake Slack                  Object e=LazyList.get(l,i);
13503928aee4356845252ac6b662d5c72c29903813eJake Slack                  if (e!=null)
13603928aee4356845252ac6b662d5c72c29903813eJake Slack                  {
13703928aee4356845252ac6b662d5c72c29903813eJake Slack                      if (values.length()>0)
13803928aee4356845252ac6b662d5c72c29903813eJake Slack                          values.append(',');
13903928aee4356845252ac6b662d5c72c29903813eJake Slack                      values.append(e.toString());
14003928aee4356845252ac6b662d5c72c29903813eJake Slack                  }
14103928aee4356845252ac6b662d5c72c29903813eJake Slack              }
14203928aee4356845252ac6b662d5c72c29903813eJake Slack              return values.toString();
14303928aee4356845252ac6b662d5c72c29903813eJake Slack          }
14403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
14503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
14603928aee4356845252ac6b662d5c72c29903813eJake Slack
14703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
14803928aee4356845252ac6b662d5c72c29903813eJake Slack    public Object get(Object name)
14903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
15003928aee4356845252ac6b662d5c72c29903813eJake Slack        Object l=_map.get(name);
15103928aee4356845252ac6b662d5c72c29903813eJake Slack        switch(LazyList.size(l))
15203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
15303928aee4356845252ac6b662d5c72c29903813eJake Slack          case 0:
15403928aee4356845252ac6b662d5c72c29903813eJake Slack              return null;
15503928aee4356845252ac6b662d5c72c29903813eJake Slack          case 1:
15603928aee4356845252ac6b662d5c72c29903813eJake Slack              Object o=LazyList.get(l,0);
15703928aee4356845252ac6b662d5c72c29903813eJake Slack              return o;
15803928aee4356845252ac6b662d5c72c29903813eJake Slack          default:
15903928aee4356845252ac6b662d5c72c29903813eJake Slack              return LazyList.getList(l,true);
16003928aee4356845252ac6b662d5c72c29903813eJake Slack        }
16103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
16203928aee4356845252ac6b662d5c72c29903813eJake Slack
16303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
16403928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Put and entry into the map.
16503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param name The entry key.
16603928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param value The entry value.
16703928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return The previous value or null.
16803928aee4356845252ac6b662d5c72c29903813eJake Slack     */
16903928aee4356845252ac6b662d5c72c29903813eJake Slack    public Object put(K name, Object value)
17003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
17103928aee4356845252ac6b662d5c72c29903813eJake Slack        return _map.put(name,LazyList.add(null,value));
17203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
17303928aee4356845252ac6b662d5c72c29903813eJake Slack
17403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
17503928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Put multi valued entry.
17603928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param name The entry key.
17703928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param values The List of multiple values.
17803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return The previous value or null.
17903928aee4356845252ac6b662d5c72c29903813eJake Slack     */
18003928aee4356845252ac6b662d5c72c29903813eJake Slack    public Object putValues(K name, List<? extends Object> values)
18103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
18203928aee4356845252ac6b662d5c72c29903813eJake Slack        return _map.put(name,values);
18303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
18403928aee4356845252ac6b662d5c72c29903813eJake Slack
18503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
18603928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Put multi valued entry.
18703928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param name The entry key.
18803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param values The String array of multiple values.
18903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return The previous value or null.
19003928aee4356845252ac6b662d5c72c29903813eJake Slack     */
19103928aee4356845252ac6b662d5c72c29903813eJake Slack    public Object putValues(K name, String... values)
19203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
19303928aee4356845252ac6b662d5c72c29903813eJake Slack        Object list=null;
19403928aee4356845252ac6b662d5c72c29903813eJake Slack        for (int i=0;i<values.length;i++)
19503928aee4356845252ac6b662d5c72c29903813eJake Slack            list=LazyList.add(list,values[i]);
19603928aee4356845252ac6b662d5c72c29903813eJake Slack        return _map.put(name,list);
19703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
19803928aee4356845252ac6b662d5c72c29903813eJake Slack
19903928aee4356845252ac6b662d5c72c29903813eJake Slack
20003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
20103928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Add value to multi valued entry.
20203928aee4356845252ac6b662d5c72c29903813eJake Slack     * If the entry is single valued, it is converted to the first
20303928aee4356845252ac6b662d5c72c29903813eJake Slack     * value of a multi valued entry.
20403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param name The entry key.
20503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param value The entry value.
20603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
20703928aee4356845252ac6b662d5c72c29903813eJake Slack    public void add(K name, Object value)
20803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
20903928aee4356845252ac6b662d5c72c29903813eJake Slack        Object lo = _map.get(name);
21003928aee4356845252ac6b662d5c72c29903813eJake Slack        Object ln = LazyList.add(lo,value);
21103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (lo!=ln)
21203928aee4356845252ac6b662d5c72c29903813eJake Slack            _map.put(name,ln);
21303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
21403928aee4356845252ac6b662d5c72c29903813eJake Slack
21503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
21603928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Add values to multi valued entry.
21703928aee4356845252ac6b662d5c72c29903813eJake Slack     * If the entry is single valued, it is converted to the first
21803928aee4356845252ac6b662d5c72c29903813eJake Slack     * value of a multi valued entry.
21903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param name The entry key.
22003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param values The List of multiple values.
22103928aee4356845252ac6b662d5c72c29903813eJake Slack     */
22203928aee4356845252ac6b662d5c72c29903813eJake Slack    public void addValues(K name, List<? extends Object> values)
22303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
22403928aee4356845252ac6b662d5c72c29903813eJake Slack        Object lo = _map.get(name);
22503928aee4356845252ac6b662d5c72c29903813eJake Slack        Object ln = LazyList.addCollection(lo,values);
22603928aee4356845252ac6b662d5c72c29903813eJake Slack        if (lo!=ln)
22703928aee4356845252ac6b662d5c72c29903813eJake Slack            _map.put(name,ln);
22803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
22903928aee4356845252ac6b662d5c72c29903813eJake Slack
23003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
23103928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Add values to multi valued entry.
23203928aee4356845252ac6b662d5c72c29903813eJake Slack     * If the entry is single valued, it is converted to the first
23303928aee4356845252ac6b662d5c72c29903813eJake Slack     * value of a multi valued entry.
23403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param name The entry key.
23503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param values The String array of multiple values.
23603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
23703928aee4356845252ac6b662d5c72c29903813eJake Slack    public void addValues(K name, String[] values)
23803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
23903928aee4356845252ac6b662d5c72c29903813eJake Slack        Object lo = _map.get(name);
24003928aee4356845252ac6b662d5c72c29903813eJake Slack        Object ln = LazyList.addCollection(lo,Arrays.asList(values));
24103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (lo!=ln)
24203928aee4356845252ac6b662d5c72c29903813eJake Slack            _map.put(name,ln);
24303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
24403928aee4356845252ac6b662d5c72c29903813eJake Slack
24503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
24603928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Remove value.
24703928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param name The entry key.
24803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param value The entry value.
24903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return true if it was removed.
25003928aee4356845252ac6b662d5c72c29903813eJake Slack     */
25103928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean removeValue(K name,Object value)
25203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
25303928aee4356845252ac6b662d5c72c29903813eJake Slack        Object lo = _map.get(name);
25403928aee4356845252ac6b662d5c72c29903813eJake Slack        Object ln=lo;
25503928aee4356845252ac6b662d5c72c29903813eJake Slack        int s=LazyList.size(lo);
25603928aee4356845252ac6b662d5c72c29903813eJake Slack        if (s>0)
25703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
25803928aee4356845252ac6b662d5c72c29903813eJake Slack            ln=LazyList.remove(lo,value);
25903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (ln==null)
26003928aee4356845252ac6b662d5c72c29903813eJake Slack                _map.remove(name);
26103928aee4356845252ac6b662d5c72c29903813eJake Slack            else
26203928aee4356845252ac6b662d5c72c29903813eJake Slack                _map.put(name, ln);
26303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
26403928aee4356845252ac6b662d5c72c29903813eJake Slack        return LazyList.size(ln)!=s;
26503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
26603928aee4356845252ac6b662d5c72c29903813eJake Slack
26703928aee4356845252ac6b662d5c72c29903813eJake Slack
26803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
26903928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Put all contents of map.
27003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param m Map
27103928aee4356845252ac6b662d5c72c29903813eJake Slack     */
27203928aee4356845252ac6b662d5c72c29903813eJake Slack    public void putAll(Map<? extends K, ? extends Object> m)
27303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
27403928aee4356845252ac6b662d5c72c29903813eJake Slack        boolean multi = (m instanceof MultiMap);
27503928aee4356845252ac6b662d5c72c29903813eJake Slack
27603928aee4356845252ac6b662d5c72c29903813eJake Slack        if (multi)
27703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
27803928aee4356845252ac6b662d5c72c29903813eJake Slack            for (Map.Entry<? extends K, ? extends Object> entry : m.entrySet())
27903928aee4356845252ac6b662d5c72c29903813eJake Slack            {
28003928aee4356845252ac6b662d5c72c29903813eJake Slack                _map.put(entry.getKey(),LazyList.clone(entry.getValue()));
28103928aee4356845252ac6b662d5c72c29903813eJake Slack            }
28203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
28303928aee4356845252ac6b662d5c72c29903813eJake Slack        else
28403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
28503928aee4356845252ac6b662d5c72c29903813eJake Slack            _map.putAll(m);
28603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
28703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
28803928aee4356845252ac6b662d5c72c29903813eJake Slack
28903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
29003928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
29103928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return Map of String arrays
29203928aee4356845252ac6b662d5c72c29903813eJake Slack     */
29303928aee4356845252ac6b662d5c72c29903813eJake Slack    public Map<K,String[]> toStringArrayMap()
29403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
29503928aee4356845252ac6b662d5c72c29903813eJake Slack        HashMap<K,String[]> map = new HashMap<K,String[]>(_map.size()*3/2)
29603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
29703928aee4356845252ac6b662d5c72c29903813eJake Slack            public String toString()
29803928aee4356845252ac6b662d5c72c29903813eJake Slack            {
29903928aee4356845252ac6b662d5c72c29903813eJake Slack                StringBuilder b=new StringBuilder();
30003928aee4356845252ac6b662d5c72c29903813eJake Slack                b.append('{');
30103928aee4356845252ac6b662d5c72c29903813eJake Slack                for (K k:keySet())
30203928aee4356845252ac6b662d5c72c29903813eJake Slack                {
30303928aee4356845252ac6b662d5c72c29903813eJake Slack                    if(b.length()>1)
30403928aee4356845252ac6b662d5c72c29903813eJake Slack                        b.append(',');
30503928aee4356845252ac6b662d5c72c29903813eJake Slack                    b.append(k);
30603928aee4356845252ac6b662d5c72c29903813eJake Slack                    b.append('=');
30703928aee4356845252ac6b662d5c72c29903813eJake Slack                    b.append(Arrays.asList(get(k)));
30803928aee4356845252ac6b662d5c72c29903813eJake Slack                }
30903928aee4356845252ac6b662d5c72c29903813eJake Slack
31003928aee4356845252ac6b662d5c72c29903813eJake Slack                b.append('}');
31103928aee4356845252ac6b662d5c72c29903813eJake Slack                return b.toString();
31203928aee4356845252ac6b662d5c72c29903813eJake Slack            }
31303928aee4356845252ac6b662d5c72c29903813eJake Slack        };
31403928aee4356845252ac6b662d5c72c29903813eJake Slack
31503928aee4356845252ac6b662d5c72c29903813eJake Slack        for(Map.Entry<K,Object> entry: _map.entrySet())
31603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
31703928aee4356845252ac6b662d5c72c29903813eJake Slack            String[] a = LazyList.toStringArray(entry.getValue());
31803928aee4356845252ac6b662d5c72c29903813eJake Slack            map.put(entry.getKey(),a);
31903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
32003928aee4356845252ac6b662d5c72c29903813eJake Slack        return map;
32103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
32203928aee4356845252ac6b662d5c72c29903813eJake Slack
32303928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
32403928aee4356845252ac6b662d5c72c29903813eJake Slack    public String toString()
32503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
32603928aee4356845252ac6b662d5c72c29903813eJake Slack        return _cmap==null?_map.toString():_cmap.toString();
32703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
32803928aee4356845252ac6b662d5c72c29903813eJake Slack
32903928aee4356845252ac6b662d5c72c29903813eJake Slack    public void clear()
33003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
33103928aee4356845252ac6b662d5c72c29903813eJake Slack        _map.clear();
33203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
33303928aee4356845252ac6b662d5c72c29903813eJake Slack
33403928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean containsKey(Object key)
33503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
33603928aee4356845252ac6b662d5c72c29903813eJake Slack        return _map.containsKey(key);
33703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
33803928aee4356845252ac6b662d5c72c29903813eJake Slack
33903928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean containsValue(Object value)
34003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
34103928aee4356845252ac6b662d5c72c29903813eJake Slack        return _map.containsValue(value);
34203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
34303928aee4356845252ac6b662d5c72c29903813eJake Slack
34403928aee4356845252ac6b662d5c72c29903813eJake Slack    public Set<Entry<K, Object>> entrySet()
34503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
34603928aee4356845252ac6b662d5c72c29903813eJake Slack        return _map.entrySet();
34703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
34803928aee4356845252ac6b662d5c72c29903813eJake Slack
34903928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
35003928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean equals(Object o)
35103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
35203928aee4356845252ac6b662d5c72c29903813eJake Slack        return _map.equals(o);
35303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
35403928aee4356845252ac6b662d5c72c29903813eJake Slack
35503928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
35603928aee4356845252ac6b662d5c72c29903813eJake Slack    public int hashCode()
35703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
35803928aee4356845252ac6b662d5c72c29903813eJake Slack        return _map.hashCode();
35903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
36003928aee4356845252ac6b662d5c72c29903813eJake Slack
36103928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isEmpty()
36203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
36303928aee4356845252ac6b662d5c72c29903813eJake Slack        return _map.isEmpty();
36403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
36503928aee4356845252ac6b662d5c72c29903813eJake Slack
36603928aee4356845252ac6b662d5c72c29903813eJake Slack    public Set<K> keySet()
36703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
36803928aee4356845252ac6b662d5c72c29903813eJake Slack        return _map.keySet();
36903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
37003928aee4356845252ac6b662d5c72c29903813eJake Slack
37103928aee4356845252ac6b662d5c72c29903813eJake Slack    public Object remove(Object key)
37203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
37303928aee4356845252ac6b662d5c72c29903813eJake Slack        return _map.remove(key);
37403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
37503928aee4356845252ac6b662d5c72c29903813eJake Slack
37603928aee4356845252ac6b662d5c72c29903813eJake Slack    public int size()
37703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
37803928aee4356845252ac6b662d5c72c29903813eJake Slack        return _map.size();
37903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
38003928aee4356845252ac6b662d5c72c29903813eJake Slack
38103928aee4356845252ac6b662d5c72c29903813eJake Slack    public Collection<Object> values()
38203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
38303928aee4356845252ac6b662d5c72c29903813eJake Slack        return _map.values();
38403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
38503928aee4356845252ac6b662d5c72c29903813eJake Slack
38603928aee4356845252ac6b662d5c72c29903813eJake Slack
38703928aee4356845252ac6b662d5c72c29903813eJake Slack
38803928aee4356845252ac6b662d5c72c29903813eJake Slack    public Object putIfAbsent(K key, Object value)
38903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
39003928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_cmap==null)
39103928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new UnsupportedOperationException();
39203928aee4356845252ac6b662d5c72c29903813eJake Slack        return _cmap.putIfAbsent(key,value);
39303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
39403928aee4356845252ac6b662d5c72c29903813eJake Slack
39503928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean remove(Object key, Object value)
39603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
39703928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_cmap==null)
39803928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new UnsupportedOperationException();
39903928aee4356845252ac6b662d5c72c29903813eJake Slack        return _cmap.remove(key,value);
40003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
40103928aee4356845252ac6b662d5c72c29903813eJake Slack
40203928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean replace(K key, Object oldValue, Object newValue)
40303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
40403928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_cmap==null)
40503928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new UnsupportedOperationException();
40603928aee4356845252ac6b662d5c72c29903813eJake Slack        return _cmap.replace(key,oldValue,newValue);
40703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
40803928aee4356845252ac6b662d5c72c29903813eJake Slack
40903928aee4356845252ac6b662d5c72c29903813eJake Slack    public Object replace(K key, Object value)
41003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
41103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_cmap==null)
41203928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new UnsupportedOperationException();
41303928aee4356845252ac6b662d5c72c29903813eJake Slack        return _cmap.replace(key,value);
41403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
41503928aee4356845252ac6b662d5c72c29903813eJake Slack}
416