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 }