View Javadoc

    1   // ========================================================================
    2   // Copyright 2004-2005 Mort Bay Consulting Pty. Ltd.
    3   // ------------------------------------------------------------------------
    4   // Licensed under the Apache License, Version 2.0 (the "License");
    5   // you may not use this file except in compliance with the License.
    6   // You may obtain a copy of the License at
    7   // http://www.apache.org/licenses/LICENSE-2.0
    8   // Unless required by applicable law or agreed to in writing, software
    9   // distributed under the License is distributed on an "AS IS" BASIS,
    10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  // ========================================================================
    14
    15  package org.mortbay.util;
    16
    17  import java.util.Arrays;
    18  import java.util.HashMap;
    19  import java.util.Iterator;
    20  import java.util.List;
    21  import java.util.Map;
    22
    23  /* ------------------------------------------------------------ */
    24  /** A multi valued Map.
    25   * This Map specializes HashMap and provides methods
    26   * that operate on multi valued items.
    27   * <P>
    28   * Implemented as a map of LazyList values
    29   *
    30   * @see LazyList
    31   * @author Greg Wilkins (gregw)
    32   */
    33  public class MultiMap extends HashMap
    34      implements Cloneable
    35  {
    36      /* ------------------------------------------------------------ */
    37      /** Constructor.
    38       */
    39      public MultiMap()
    40      {}
    41
    42      /* ------------------------------------------------------------ */
    43      /** Constructor.
    44       * @param size Capacity of the map
    45       */
    46      public MultiMap(int size)
    47      {
    48          super(size);
    49      }
    50
    51      /* ------------------------------------------------------------ */
    52      /** Constructor.
    53       * @param map
    54       */
    55      public MultiMap(Map map)
    56      {
    57          super((map.size()*3)/2);
    58          putAll(map);
    59      }
    60
    61      /* ------------------------------------------------------------ */
    62      /** Get multiple values.
    63       * Single valued entries are converted to singleton lists.
    64       * @param name The entry key.
    65       * @return Unmodifieable List of values.
    66       */
    67      public List getValues(Object name)
    68      {
    69          return LazyList.getList(super.get(name),true);
    70      }
    71
    72      /* ------------------------------------------------------------ */
    73      /** Get a value from a multiple value.
    74       * If the value is not a multivalue, then index 0 retrieves the
    75       * value or null.
    76       * @param name The entry key.
    77       * @param i Index of element to get.
    78       * @return Unmodifieable List of values.
    79       */
    80      public Object getValue(Object name,int i)
    81      {
    82          Object l=super.get(name);
    83          if (i==0 && LazyList.size(l)==0)
    84              return null;
    85          return LazyList.get(l,i);
    86      }
    87
    88
    89      /* ------------------------------------------------------------ */
    90      /** Get value as String.
    91       * Single valued items are converted to a String with the toString()
    92       * Object method. Multi valued entries are converted to a comma separated
    93       * List.  No quoting of commas within values is performed.
    94       * @param name The entry key.
    95       * @return String value.
    96       */
    97      public String getString(Object name)
    98      {
    99          Object l=super.get(name);
    100         switch(LazyList.size(l))
    101         {
    102           case 0:
    103               return null;
    104           case 1:
    105               Object o=LazyList.get(l,0);
    106               return o==null?null:o.toString();
    107           default:
    108               StringBuffer values=new StringBuffer(128);
    109               synchronized(values)
    110               {
    111                   for (int i=0; i<LazyList.size(l); i++)
    112                   {
    113                       Object e=LazyList.get(l,i);
    114                       if (e!=null)
    115                       {
    116                           if (values.length()>0)
    117                               values.append(',');
    118                           values.append(e.toString());
    119                       }
    120                   }
    121                   return values.toString();
    122               }
    123         }
    124     }
    125
    126     /* ------------------------------------------------------------ */
    127     public Object get(Object name)
    128     {
    129         Object l=super.get(name);
    130         switch(LazyList.size(l))
    131         {
    132           case 0:
    133               return null;
    134           case 1:
    135               Object o=LazyList.get(l,0);
    136               return o;
    137           default:
    138               return LazyList.getList(l,true);
    139         }
    140     }
    141
    142     /* ------------------------------------------------------------ */
    143     /** Put and entry into the map.
    144      * @param name The entry key.
    145      * @param value The entry value.
    146      * @return The previous value or null.
    147      */
    148     public Object put(Object name, Object value)
    149     {
    150         return super.put(name,LazyList.add(null,value));
    151     }
    152
    153     /* ------------------------------------------------------------ */
    154     /** Put multi valued entry.
    155      * @param name The entry key.
    156      * @param values The List of multiple values.
    157      * @return The previous value or null.
    158      */
    159     public Object putValues(Object name, List values)
    160     {
    161         return super.put(name,values);
    162     }
    163
    164     /* ------------------------------------------------------------ */
    165     /** Put multi valued entry.
    166      * @param name The entry key.
    167      * @param values The String array of multiple values.
    168      * @return The previous value or null.
    169      */
    170     public Object putValues(Object name, String[] values)
    171     {
    172         Object list=null;
    173         for (int i=0;i<values.length;i++)
    174             list=LazyList.add(list,values[i]);
    175         return put(name,list);
    176     }
    177
    178
    179     /* ------------------------------------------------------------ */
    180     /** Add value to multi valued entry.
    181      * If the entry is single valued, it is converted to the first
    182      * value of a multi valued entry.
    183      * @param name The entry key.
    184      * @param value The entry value.
    185      */
    186     public void add(Object name, Object value)
    187     {
    188         Object lo = super.get(name);
    189         Object ln = LazyList.add(lo,value);
    190         if (lo!=ln)
    191             super.put(name,ln);
    192     }
    193
    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.
    200      */
    201     public void addValues(Object name, List values)
    202     {
    203         Object lo = super.get(name);
    204         Object ln = LazyList.addCollection(lo,values);
    205         if (lo!=ln)
    206             super.put(name,ln);
    207     }
    208
    209     /* ------------------------------------------------------------ */
    210     /** Add values to multi valued entry.
    211      * If the entry is single valued, it is converted to the first
    212      * value of a multi valued entry.
    213      * @param name The entry key.
    214      * @param values The String array of multiple values.
    215      */
    216     public void addValues(Object name, String[] values)
    217     {
    218         Object lo = super.get(name);
    219         Object ln = LazyList.addCollection(lo,Arrays.asList(values));
    220         if (lo!=ln)
    221             super.put(name,ln);
    222     }
    223
    224     /* ------------------------------------------------------------ */
    225     /** Remove value.
    226      * @param name The entry key.
    227      * @param value The entry value.
    228      * @return true if it was removed.
    229      */
    230     public boolean removeValue(Object name,Object value)
    231     {
    232         Object lo = super.get(name);
    233         Object ln=lo;
    234         int s=LazyList.size(lo);
    235         if (s>0)
    236         {
    237             ln=LazyList.remove(lo,value);
    238             if (ln==null)
    239                 super.remove(name);
    240             else
    241                 super.put(name, ln);
    242         }
    243         return LazyList.size(ln)!=s;
    244     }
    245
    246     /* ------------------------------------------------------------ */
    247     /** Put all contents of map.
    248      * @param m Map
    249      */
    250     public void putAll(Map m)
    251     {
    252         Iterator i = m.entrySet().iterator();
    253         boolean multi=m instanceof MultiMap;
    254         while(i.hasNext())
    255         {
    256             Map.Entry entry =
    257                 (Map.Entry)i.next();
    258             if (multi)
    259                 super.put(entry.getKey(),LazyList.clone(entry.getValue()));
    260             else
    261                 put(entry.getKey(),entry.getValue());
    262         }
    263     }
    264
    265     /* ------------------------------------------------------------ */
    266     /**
    267      * @return Map of String arrays
    268      */
    269     public Map toStringArrayMap()
    270     {
    271         HashMap map = new HashMap(size()*3/2);
    272
    273         Iterator i = super.entrySet().iterator();
    274         while(i.hasNext())
    275         {
    276             Map.Entry entry = (Map.Entry)i.next();
    277             Object l = entry.getValue();
    278             String[] a = LazyList.toStringArray(l);
    279             // for (int j=a.length;j-->0;)
    280             //    if (a[j]==null)
    281             //         a[j]="";
    282             map.put(entry.getKey(),a);
    283         }
    284         return map;
    285     }
    286
    287     /* ------------------------------------------------------------ */
    288     public Object clone()
    289     {
    290         MultiMap mm = (MultiMap) super.clone();
    291
    292         Iterator iter = mm.entrySet().iterator();
    293         while (iter.hasNext())
    294         {
    295             Map.Entry entry = (Map.Entry)iter.next();
    296             entry.setValue(LazyList.clone(entry.getValue()));
    297         }
    298
    299         return mm;
    300     }
    301 }