1 12 package org.eclipse.jdt.internal.compiler.apt.util; 13 14 import java.util.Collections ; 15 import java.util.HashMap ; 16 import java.util.HashSet ; 17 import java.util.Map ; 18 import java.util.Set ; 19 20 37 public class ManyToMany<T1, T2> { 38 39 private final Map <T1, Set <T2>> _forward = new HashMap <T1, Set <T2>>(); 40 private final Map <T2, Set <T1>> _reverse = new HashMap <T2, Set <T1>>(); 41 private boolean _dirty = false; 42 43 48 public synchronized boolean clear() { 49 boolean hadContent = !_forward.isEmpty() || !_reverse.isEmpty(); 50 _reverse.clear(); 51 _forward.clear(); 52 _dirty |= hadContent; 53 return hadContent; 54 } 55 56 62 public synchronized void clearDirtyBit() { 63 _dirty = false; 64 } 65 66 70 public synchronized boolean containsKey(T1 key) { 71 return _forward.containsKey(key); 72 } 73 74 79 public synchronized boolean containsKeyValuePair(T1 key, T2 value) { 80 Set <T2> values = _forward.get(key); 81 if (null == values) { 82 return false; 83 } 84 return values.contains(value); 85 } 86 87 92 public synchronized boolean containsValue(T2 value) { 93 return _reverse.containsKey(value); 94 } 95 96 102 public synchronized Set <T1> getKeys(T2 value) { 103 Set <T1> keys = _reverse.get(value); 104 if (null == keys) { 105 return Collections.emptySet(); 106 } 107 return new HashSet <T1>(keys); 108 } 109 110 116 public synchronized Set <T2> getValues(T1 key) { 117 Set <T2> values = _forward.get(key); 118 if (null == values) { 119 return Collections.emptySet(); 120 } 121 return new HashSet <T2>(values); 122 } 123 124 130 public synchronized Set <T1> getKeySet() { 131 Set <T1> keys = new HashSet <T1>(_forward.keySet()); 132 return keys; 133 } 134 135 141 public synchronized Set <T2> getValueSet() { 142 Set <T2> values = new HashSet <T2>(_reverse.keySet()); 143 return values; 144 } 145 146 154 public synchronized boolean isDirty() { 155 return _dirty; 156 } 157 158 168 public synchronized boolean keyHasOtherValues(T1 key, T2 value) { 169 Set <T2> values = _forward.get(key); 170 if (values == null) 171 return false; 172 int size = values.size(); 173 if (size == 0) 174 return false; 175 else if (size > 1) 176 return true; 177 else return !values.contains(value); 179 } 180 181 191 public synchronized boolean put(T1 key, T2 value) { 192 Set <T2> values = _forward.get(key); 194 if (null == values) { 195 values = new HashSet <T2>(); 196 _forward.put(key, values); 197 } 198 boolean added = values.add(value); 199 _dirty |= added; 200 201 Set <T1> keys = _reverse.get(value); 203 if (null == keys) { 204 keys = new HashSet <T1>(); 205 _reverse.put(value, keys); 206 } 207 keys.add(key); 208 209 assert checkIntegrity(); 210 return added; 211 } 212 213 220 public synchronized boolean remove(T1 key, T2 value) { 221 Set <T2> values = _forward.get(key); 222 if (values == null) { 223 assert checkIntegrity(); 224 return false; 225 } 226 boolean removed = values.remove(value); 227 if (values.isEmpty()) { 228 _forward.remove(key); 229 } 230 if (removed) { 231 _dirty = true; 232 Set <T1> keys = _reverse.get(value); 234 keys.remove(key); 235 if (keys.isEmpty()) { 236 _reverse.remove(value); 237 } 238 } 239 assert checkIntegrity(); 240 return removed; 241 } 242 243 249 public synchronized boolean removeKey(T1 key) { 250 Set <T2> values = _forward.get(key); 252 if (null == values) { 253 assert checkIntegrity(); 255 return false; 256 } 257 for (T2 value : values) { 258 Set <T1> keys = _reverse.get(value); 259 if (null != keys) { 260 keys.remove(key); 261 if (keys.isEmpty()) { 262 _reverse.remove(value); 263 } 264 } 265 } 266 _forward.remove(key); 268 _dirty = true; 269 assert checkIntegrity(); 270 return true; 271 } 272 273 279 public synchronized boolean removeValue(T2 value) { 280 Set <T1> keys = _reverse.get(value); 282 if (null == keys) { 283 assert checkIntegrity(); 285 return false; 286 } 287 for (T1 key : keys) { 288 Set <T2> values = _forward.get(key); 289 if (null != values) { 290 values.remove(value); 291 if (values.isEmpty()) { 292 _forward.remove(key); 293 } 294 } 295 } 296 _reverse.remove(value); 298 _dirty = true; 299 assert checkIntegrity(); 300 return true; 301 } 302 303 313 public synchronized boolean valueHasOtherKeys(T2 value, T1 key) { 314 Set <T1> keys = _reverse.get(key); 315 if (keys == null) 316 return false; 317 int size = keys.size(); 318 if (size == 0) 319 return false; 320 else if (size > 1) 321 return true; 322 else return !keys.contains(key); 324 } 325 326 333 private boolean checkIntegrity() { 334 for (Map.Entry <T1, Set <T2>> entry : _forward.entrySet()) { 337 Set <T2> values = entry.getValue(); 338 if (values.isEmpty()) { 339 throw new IllegalStateException ("Integrity compromised: forward map contains an empty set"); } 341 for (T2 value : values) { 342 Set <T1> keys = _reverse.get(value); 343 if (null == keys || !keys.contains(entry.getKey())) { 344 throw new IllegalStateException ("Integrity compromised: forward map contains an entry missing from reverse map: " + value); } 346 } 347 } 348 for (Map.Entry <T2, Set <T1>> entry : _reverse.entrySet()) { 350 Set <T1> keys = entry.getValue(); 351 if (keys.isEmpty()) { 352 throw new IllegalStateException ("Integrity compromised: reverse map contains an empty set"); } 354 for (T1 key : keys) { 355 Set <T2> values = _forward.get(key); 356 if (null == values || !values.contains(entry.getKey())) { 357 throw new IllegalStateException ("Integrity compromised: reverse map contains an entry missing from forward map: " + key); } 359 } 360 } 361 return true; 362 } 363 364 } 365 | Popular Tags |