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    }