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}