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.util.ArrayList;
021 import java.util.Collection;
022 import java.util.HashSet;
023 import java.util.LinkedHashMap;
024 import java.util.List;
025 import java.util.Map;
026 import java.util.Map.Entry;
027 import java.util.Set;
028
029 public class MultiMapImpl<K, V> implements MultiMap<K, V>
030 {
031 private final Map<K, List<V>> _impl;
032
033 public MultiMapImpl()
034 {
035 this(new LinkedHashMap<K, List<V>>());
036 }
037
038 public MultiMapImpl(Map<K, List<V>> impl)
039 {
040 _impl = impl;
041 }
042
043 @Override public List<V> getAll(Object key)
044 {
045 return _impl.get(key);
046 }
047
048 @Override public boolean isEmpty()
049 {
050 return _impl.isEmpty();
051 }
052
053 @Override public void add(K key, V value)
054 {
055 getList(key, true).add(value);
056 }
057
058 @Override public void add(K key, V value, int index)
059 {
060 getList(key, true).add(index, value);
061 }
062
063 @Override public void clear()
064 {
065 _impl.clear();
066 }
067
068 @Override public boolean containsKey(Object key)
069 {
070 return _impl.containsKey(key);
071 }
072
073 @Override public boolean containsValue(Object value)
074 {
075 boolean ret = false;
076
077 for (List<V> all : _impl.values())
078 {
079 if (all.contains(value))
080 {
081 ret = true;
082
083 break;
084 }
085 }
086
087 return ret;
088 }
089
090 @Override public Set<Entry<K, V>> entrySet()
091 {
092 Set<Entry<K, V>> ret = new HashSet<Entry<K, V>>();
093
094 for (K key : keySet())
095 {
096 ret.add(new ShadowEntry(key));
097 }
098
099 return ret;
100 }
101
102 @Override public V get(Object key)
103 {
104 List<V> values = getList(key, false);
105
106 return (values == null) ? null : values.get(values.size() - 1);
107 }
108
109 @Override public V get(Object key, int index)
110 {
111 List<V> values = getList(key, false);
112
113 return (values == null) ? null : values.get(index);
114 }
115
116 @Override public Set<K> keySet()
117 {
118 return _impl.keySet();
119 }
120
121 @Override public int length(Object key)
122 {
123 List<V> values = getList(key, false);
124
125 return (values == null) ? 0 : values.size();
126 }
127
128 @Override public V put(K key, V value)
129 {
130 V ret = null;
131 List<V> values = getList(key, true);
132
133 if (values.isEmpty())
134 {
135 values.add(value);
136 }
137 else
138 {
139 ret = values.set(values.size() - 1, value);
140 }
141
142 return ret;
143 }
144
145 @Override public V put(K key, V value, int index)
146 {
147 return getList(key, false).set(index, value);
148 }
149
150 @SuppressWarnings(Warnings.UNCHECKED)
151 @Override public void putAll(Map<? extends K, ? extends V> map)
152 {
153 if (map instanceof MultiMap)
154 {
155 MultiMap<K, V> mm = (MultiMap<K, V>) map;
156
157 for (Object key : mm.keySet())
158 {
159 putAll((K) key, mm.getAll(key));
160 }
161 }
162 else
163 {
164 for (K key : map.keySet())
165 {
166 put(key, map.get(key));
167 }
168 }
169 }
170
171 @Override public List<V> putAll(K key, List<V> values)
172 {
173 List<V> ret = _impl.get(key);
174
175 _impl.put(key, new ArrayList<V>(values));
176
177 return ret;
178 }
179
180 @Override public V remove(Object key)
181 {
182 List<V> prev = _impl.remove(key);
183
184 return (prev == null) ? null : prev.get(0);
185 }
186
187 @Override public V remove(Object key, int index)
188 {
189 V ret = null;
190 List<V> values = getList(key, false);
191
192 if (values != null)
193 {
194 ret = values.remove(index);
195 if (values.isEmpty())
196 {
197 _impl.remove(key);
198 }
199 }
200
201 return ret;
202 }
203
204 @Override public int size()
205 {
206 return _impl.size();
207 }
208
209 @Override public Collection<V> values()
210 {
211 List<V> all = new ArrayList<V>(_impl.size());
212
213 for (List<V> values : _impl.values())
214 {
215 all.addAll(values);
216 }
217
218 return all;
219 }
220
221 @SuppressWarnings(Warnings.UNCHECKED)
222 private List<V> getList(Object key, boolean create)
223 {
224 List<V> values = _impl.get(key);
225
226 if ((values == null) && create)
227 {
228 values = new ArrayList<V>();
229 _impl.put((K) key, values);
230 }
231
232 return values;
233 }
234
235 class ShadowEntry implements Map.Entry<K, V>
236 {
237 private final K _key;
238
239 ShadowEntry(K key)
240 {
241 _key = key;
242 }
243
244 @Override public K getKey()
245 {
246 return _key;
247 }
248
249 @Override public V getValue()
250 {
251 return get(_key);
252 }
253
254 @Override public V setValue(V value)
255 {
256 return put(_key, value);
257 }
258 }
259 }