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 }