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    }