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 */
016package org.ini4j;
017
018import org.ini4j.spi.Warnings;
019
020import java.io.Serializable;
021
022import java.util.ArrayList;
023import java.util.Collection;
024import java.util.HashSet;
025import java.util.LinkedHashMap;
026import java.util.List;
027import java.util.Map;
028import java.util.Map.Entry;
029import java.util.Set;
030
031public 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}