View Javadoc

1   /*
2    * Copyright 2005,2009 Ivan SZKIBA
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    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.ini4j;
17  
18  import org.ini4j.spi.Warnings;
19  
20  import java.io.Serializable;
21  
22  import java.util.ArrayList;
23  import java.util.Collection;
24  import java.util.HashSet;
25  import java.util.LinkedHashMap;
26  import java.util.List;
27  import java.util.Map;
28  import java.util.Map.Entry;
29  import java.util.Set;
30  
31  public class BasicMultiMap<K, V> implements MultiMap<K, V>, Serializable
32  {
33      private static final long serialVersionUID = 4716749660560043989L;
34      private final Map<K, List<V>> _impl;
35  
36      public BasicMultiMap()
37      {
38          this(new LinkedHashMap<K, List<V>>());
39      }
40  
41      public BasicMultiMap(Map<K, List<V>> impl)
42      {
43          _impl = impl;
44      }
45  
46      @Override public List<V> getAll(Object key)
47      {
48          return _impl.get(key);
49      }
50  
51      @Override public boolean isEmpty()
52      {
53          return _impl.isEmpty();
54      }
55  
56      @Override public void add(K key, V value)
57      {
58          getList(key, true).add(value);
59      }
60  
61      @Override public void add(K key, V value, int index)
62      {
63          getList(key, true).add(index, value);
64      }
65  
66      @Override public void clear()
67      {
68          _impl.clear();
69      }
70  
71      @Override public boolean containsKey(Object key)
72      {
73          return _impl.containsKey(key);
74      }
75  
76      @Override public boolean containsValue(Object value)
77      {
78          boolean ret = false;
79  
80          for (List<V> all : _impl.values())
81          {
82              if (all.contains(value))
83              {
84                  ret = true;
85  
86                  break;
87              }
88          }
89  
90          return ret;
91      }
92  
93      @Override public Set<Entry<K, V>> entrySet()
94      {
95          Set<Entry<K, V>> ret = new HashSet<Entry<K, V>>();
96  
97          for (K key : keySet())
98          {
99              ret.add(new ShadowEntry(key));
100         }
101 
102         return ret;
103     }
104 
105     @Override public V get(Object key)
106     {
107         List<V> values = getList(key, false);
108 
109         return (values == null) ? null : values.get(values.size() - 1);
110     }
111 
112     @Override public V get(Object key, int index)
113     {
114         List<V> values = getList(key, false);
115 
116         return (values == null) ? null : values.get(index);
117     }
118 
119     @Override public Set<K> keySet()
120     {
121         return _impl.keySet();
122     }
123 
124     @Override public int length(Object key)
125     {
126         List<V> values = getList(key, false);
127 
128         return (values == null) ? 0 : values.size();
129     }
130 
131     @Override public V put(K key, V value)
132     {
133         V ret = null;
134         List<V> values = getList(key, true);
135 
136         if (values.isEmpty())
137         {
138             values.add(value);
139         }
140         else
141         {
142             ret = values.set(values.size() - 1, value);
143         }
144 
145         return ret;
146     }
147 
148     @Override public V put(K key, V value, int index)
149     {
150         return getList(key, false).set(index, value);
151     }
152 
153     @SuppressWarnings(Warnings.UNCHECKED)
154     @Override public void putAll(Map<? extends K, ? extends V> map)
155     {
156         if (map instanceof MultiMap)
157         {
158             MultiMap<K, V> mm = (MultiMap<K, V>) map;
159 
160             for (Object key : mm.keySet())
161             {
162                 putAll((K) key, mm.getAll(key));
163             }
164         }
165         else
166         {
167             for (K key : map.keySet())
168             {
169                 put(key, map.get(key));
170             }
171         }
172     }
173 
174     @Override public List<V> putAll(K key, List<V> values)
175     {
176         List<V> ret = _impl.get(key);
177 
178         _impl.put(key, new ArrayList<V>(values));
179 
180         return ret;
181     }
182 
183     @Override public V remove(Object key)
184     {
185         List<V> prev = _impl.remove(key);
186 
187         return (prev == null) ? null : prev.get(0);
188     }
189 
190     @Override public V remove(Object key, int index)
191     {
192         V ret = null;
193         List<V> values = getList(key, false);
194 
195         if (values != null)
196         {
197             ret = values.remove(index);
198             if (values.isEmpty())
199             {
200                 _impl.remove(key);
201             }
202         }
203 
204         return ret;
205     }
206 
207     @Override public int size()
208     {
209         return _impl.size();
210     }
211 
212     @Override public String toString()
213     {
214         return _impl.toString();
215     }
216 
217     @Override public Collection<V> values()
218     {
219         List<V> all = new ArrayList<V>(_impl.size());
220 
221         for (List<V> values : _impl.values())
222         {
223             all.addAll(values);
224         }
225 
226         return all;
227     }
228 
229     @SuppressWarnings(Warnings.UNCHECKED)
230     private List<V> getList(Object key, boolean create)
231     {
232         List<V> values = _impl.get(key);
233 
234         if ((values == null) && create)
235         {
236             values = new ArrayList<V>();
237             _impl.put((K) key, values);
238         }
239 
240         return values;
241     }
242 
243     class ShadowEntry implements Map.Entry<K, V>
244     {
245         private final K _key;
246 
247         ShadowEntry(K key)
248         {
249             _key = key;
250         }
251 
252         @Override public K getKey()
253         {
254             return _key;
255         }
256 
257         @Override public V getValue()
258         {
259             return get(_key);
260         }
261 
262         @Override public V setValue(V value)
263         {
264             return put(_key, value);
265         }
266     }
267 }