001 /*
002 * Copyright 2005,2009 Ivan SZKIBA
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.ini4j;
017
018 import org.ini4j.spi.Warnings;
019
020 import java.io.Serializable;
021
022 import java.util.ArrayList;
023 import java.util.Collection;
024 import java.util.HashSet;
025 import java.util.LinkedHashMap;
026 import java.util.List;
027 import java.util.Map;
028 import java.util.Map.Entry;
029 import java.util.Set;
030
031 public class BasicMultiMap<K, V> implements MultiMap<K, V>, Serializable
032 {
033 private static final long serialVersionUID = 4716749660560043989L;
034 private final Map<K, List<V>> _impl;
035
036 public BasicMultiMap()
037 {
038 this(new LinkedHashMap<K, List<V>>());
039 }
040
041 public BasicMultiMap(Map<K, List<V>> impl)
042 {
043 _impl = impl;
044 }
045
046 @Override public List<V> getAll(Object key)
047 {
048 return _impl.get(key);
049 }
050
051 @Override public boolean isEmpty()
052 {
053 return _impl.isEmpty();
054 }
055
056 @Override public void add(K key, V value)
057 {
058 getList(key, true).add(value);
059 }
060
061 @Override public void add(K key, V value, int index)
062 {
063 getList(key, true).add(index, value);
064 }
065
066 @Override public void clear()
067 {
068 _impl.clear();
069 }
070
071 @Override public boolean containsKey(Object key)
072 {
073 return _impl.containsKey(key);
074 }
075
076 @Override public boolean containsValue(Object value)
077 {
078 boolean ret = false;
079
080 for (List<V> all : _impl.values())
081 {
082 if (all.contains(value))
083 {
084 ret = true;
085
086 break;
087 }
088 }
089
090 return ret;
091 }
092
093 @Override public Set<Entry<K, V>> entrySet()
094 {
095 Set<Entry<K, V>> ret = new HashSet<Entry<K, V>>();
096
097 for (K key : keySet())
098 {
099 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 }