001/* 002 * ModeShape (http://www.modeshape.org) 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.modeshape.common.collection; 017 018import static org.hamcrest.core.Is.is; 019import static org.junit.Assert.assertThat; 020import java.util.ArrayList; 021import java.util.Collection; 022import java.util.List; 023import java.util.ListIterator; 024import java.util.Map; 025import org.junit.Before; 026import org.junit.Test; 027 028public class LinkedListMultimapTest extends AbstractMultimapTest { 029 030 protected ListMultimap<String, String> listMultimap; 031 032 @Override 033 @Before 034 public void beforeEach() { 035 super.beforeEach(); 036 listMultimap = (ListMultimap<String, String>)multimap; 037 } 038 039 @Override 040 protected <K, V> LinkedListMultimap<K, V> createMultimap() { 041 return LinkedListMultimap.create(); 042 } 043 044 /** 045 * {@inheritDoc} 046 * 047 * @see org.modeshape.common.collection.AbstractMultimapTest#valuesAllowDuplicates() 048 */ 049 @Override 050 protected boolean valuesAllowDuplicates() { 051 return true; 052 } 053 054 @Test 055 public void shouldAddEntryToEmtpyMap() { 056 LinkedListMultimap<String, String> listMap = createMultimap(); 057 assertThat(listMap.size(), is(0)); 058 listMap.addEntryFor(keys[0], values[0]); 059 assertThat(listMap.size(), is(1)); 060 } 061 062 @Test 063 public void shouldMaintainOrderOfInsertionInKeysAndValues() { 064 multimap.put(keys[0], values[0]); 065 multimap.put(keys[1], values[1]); 066 multimap.put(keys[0], values[0]); 067 multimap.put(keys[1], values[2]); 068 multimap.put(keys[0], values[0]); 069 multimap.put(keys[1], values[3]); 070 assertThat(multimap.isEmpty(), is(false)); 071 assertThat(multimap.size(), is(6)); 072 assertKeys(multimap, keys[0], keys[1]); 073 assertValues(multimap, keys[0], values[0], values[0], values[0]); 074 assertValues(multimap, keys[1], values[1], values[2], values[3]); 075 Collection<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>(); 076 entries.add(entry(keys[0], values[0])); 077 entries.add(entry(keys[1], values[1])); 078 entries.add(entry(keys[0], values[0])); 079 entries.add(entry(keys[1], values[2])); 080 entries.add(entry(keys[0], values[0])); 081 entries.add(entry(keys[1], values[3])); 082 assertEntries(multimap, entries); 083 } 084 085 @Test 086 public void shouldMaintainOrderOfInsertionInKeysAndValuesAfterRemovalOfFirstKeyValuePair() { 087 multimap.put(keys[0], values[0]); 088 multimap.put(keys[1], values[0]); 089 multimap.put(keys[0], values[1]); 090 multimap.put(keys[1], values[1]); 091 multimap.put(keys[0], values[2]); 092 multimap.put(keys[1], values[2]); 093 multimap.remove(keys[0], values[0]); 094 assertThat(multimap.isEmpty(), is(false)); 095 assertThat(multimap.size(), is(5)); 096 assertKeys(multimap, keys[0], keys[1]); 097 assertValues(multimap, keys[0], /*values[0],*/values[1], values[2]); 098 assertValues(multimap, keys[1], values[0], values[1], values[2]); 099 Collection<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>(); 100 // entries.add(entry(keys[0], values[0])); 101 entries.add(entry(keys[1], values[0])); 102 entries.add(entry(keys[0], values[1])); 103 entries.add(entry(keys[1], values[1])); 104 entries.add(entry(keys[0], values[2])); 105 entries.add(entry(keys[1], values[2])); 106 assertEntries(multimap, entries); 107 } 108 109 @Test 110 public void shouldMaintainOrderOfInsertionInKeysAndValuesAfterRemovalOfMiddleKeyValuePair() { 111 multimap.put(keys[0], values[0]); 112 multimap.put(keys[1], values[1]); 113 multimap.put(keys[0], values[0]); 114 multimap.put(keys[1], values[2]); 115 multimap.put(keys[0], values[0]); 116 multimap.put(keys[1], values[3]); 117 multimap.remove(keys[1], values[2]); 118 assertThat(multimap.isEmpty(), is(false)); 119 assertThat(multimap.size(), is(5)); 120 assertKeys(multimap, keys[0], keys[1]); 121 assertValues(multimap, keys[0], values[0], values[0], values[0]); 122 assertValues(multimap, keys[1], values[1], values[3]); 123 Collection<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>(); 124 entries.add(entry(keys[0], values[0])); 125 entries.add(entry(keys[1], values[1])); 126 entries.add(entry(keys[0], values[0])); 127 entries.add(entry(keys[0], values[0])); 128 entries.add(entry(keys[1], values[3])); 129 assertEntries(multimap, entries); 130 } 131 132 @Test 133 public void shouldMaintainOrderOfInsertionInKeysAndValuesAfterRemovalOfLastKeyValuePair() { 134 multimap.put(keys[0], values[0]); 135 multimap.put(keys[1], values[0]); 136 multimap.put(keys[0], values[1]); 137 multimap.put(keys[1], values[1]); 138 multimap.put(keys[0], values[2]); 139 multimap.put(keys[1], values[2]); 140 multimap.remove(keys[1], values[2]); 141 assertThat(multimap.isEmpty(), is(false)); 142 assertThat(multimap.size(), is(5)); 143 assertKeys(multimap, keys[0], keys[1]); 144 assertValues(multimap, keys[0], values[0], values[1], values[2]); 145 assertValues(multimap, keys[1], values[0], values[1] /*, values[2]*/); 146 Collection<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>(); 147 entries.add(entry(keys[0], values[0])); 148 entries.add(entry(keys[1], values[0])); 149 entries.add(entry(keys[0], values[1])); 150 entries.add(entry(keys[1], values[1])); 151 entries.add(entry(keys[0], values[2])); 152 // entries.add(entry(keys[1], values[2])); 153 assertEntries(multimap, entries); 154 } 155 156 @Test 157 public void shouldMaintainOrderOfInsertionInKeysAndValuesAfterRemovalOfFirstValueFromKeyCollection() { 158 multimap.put(keys[0], values[0]); 159 multimap.put(keys[1], values[0]); 160 multimap.put(keys[0], values[1]); 161 multimap.put(keys[1], values[1]); 162 multimap.put(keys[0], values[2]); 163 multimap.put(keys[1], values[2]); 164 multimap.get(keys[0]).remove(values[0]); 165 assertThat(multimap.isEmpty(), is(false)); 166 assertThat(multimap.size(), is(5)); 167 assertKeys(multimap, keys[0], keys[1]); 168 assertValues(multimap, keys[0], /*values[0],*/values[1], values[2]); 169 assertValues(multimap, keys[1], values[0], values[1], values[2]); 170 Collection<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>(); 171 // entries.add(entry(keys[0], values[0])); 172 entries.add(entry(keys[1], values[0])); 173 entries.add(entry(keys[0], values[1])); 174 entries.add(entry(keys[1], values[1])); 175 entries.add(entry(keys[0], values[2])); 176 entries.add(entry(keys[1], values[2])); 177 assertEntries(multimap, entries); 178 } 179 180 @Test 181 public void shouldMaintainOrderOfInsertionInKeysAndValuesAfterRemovalOfMiddleValueFromKeyCollection() { 182 multimap.put(keys[0], values[0]); 183 multimap.put(keys[1], values[0]); 184 multimap.put(keys[0], values[1]); 185 multimap.put(keys[1], values[1]); 186 multimap.put(keys[0], values[2]); 187 multimap.put(keys[1], values[2]); 188 multimap.get(keys[1]).remove(values[1]); 189 assertThat(multimap.isEmpty(), is(false)); 190 assertThat(multimap.size(), is(5)); 191 assertKeys(multimap, keys[0], keys[1]); 192 assertValues(multimap, keys[0], values[0], values[1], values[2]); 193 assertValues(multimap, keys[1], values[0], values[2]); 194 Collection<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>(); 195 entries.add(entry(keys[0], values[0])); 196 entries.add(entry(keys[1], values[0])); 197 entries.add(entry(keys[0], values[1])); 198 entries.add(entry(keys[0], values[2])); 199 entries.add(entry(keys[1], values[2])); 200 assertEntries(multimap, entries); 201 } 202 203 @Test 204 public void shouldMaintainOrderOfInsertionInKeysAndValuesAfterRemovalOfLastValueFromKeyCollection() { 205 multimap.put(keys[0], values[0]); 206 multimap.put(keys[1], values[0]); 207 multimap.put(keys[0], values[1]); 208 multimap.put(keys[1], values[1]); 209 multimap.put(keys[0], values[2]); 210 multimap.put(keys[1], values[2]); 211 multimap.get(keys[1]).remove(values[2]); 212 assertThat(multimap.isEmpty(), is(false)); 213 assertThat(multimap.size(), is(5)); 214 assertKeys(multimap, keys[0], keys[1]); 215 assertValues(multimap, keys[0], values[0], values[1], values[2]); 216 assertValues(multimap, keys[1], values[0], values[1] /*, values[2]*/); 217 Collection<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>(); 218 entries.add(entry(keys[0], values[0])); 219 entries.add(entry(keys[1], values[0])); 220 entries.add(entry(keys[0], values[1])); 221 entries.add(entry(keys[1], values[1])); 222 entries.add(entry(keys[0], values[2])); 223 // entries.add(entry(keys[1], values[2])); 224 assertEntries(multimap, entries); 225 } 226 227 @Test 228 public void shouldMaintainOrderOfInsertionInKeysAndValuesAfterAddingValueAtBeginngingOfCollectionForKey() { 229 multimap.put(keys[0], values[0]); 230 multimap.put(keys[1], values[0]); 231 multimap.put(keys[0], values[1]); 232 multimap.put(keys[1], values[1]); 233 multimap.put(keys[0], values[2]); 234 multimap.put(keys[1], values[2]); 235 addValueUsingCollection(listMultimap, keys[0], 0, values[3]); 236 assertThat(multimap.isEmpty(), is(false)); 237 assertThat(multimap.size(), is(7)); 238 assertKeys(multimap, keys[0], keys[1]); 239 assertValues(multimap, keys[0], values[3], values[0], values[1], values[2]); 240 assertValues(multimap, keys[1], values[0], values[1], values[2]); 241 Collection<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>(); 242 entries.add(entry(keys[0], values[3])); 243 entries.add(entry(keys[0], values[0])); 244 entries.add(entry(keys[1], values[0])); 245 entries.add(entry(keys[0], values[1])); 246 entries.add(entry(keys[1], values[1])); 247 entries.add(entry(keys[0], values[2])); 248 entries.add(entry(keys[1], values[2])); 249 assertEntries(multimap, entries); 250 } 251 252 @Test 253 public void shouldMaintainOrderOfInsertionInKeysAndValuesAfterAddingValueAtMiddleOfCollectionForKey() { 254 multimap.put(keys[0], values[0]); 255 multimap.put(keys[1], values[0]); 256 multimap.put(keys[0], values[1]); 257 multimap.put(keys[1], values[1]); 258 multimap.put(keys[0], values[2]); 259 multimap.put(keys[1], values[2]); 260 addValueUsingCollection(listMultimap, keys[1], 1, values[3]); 261 assertThat(multimap.isEmpty(), is(false)); 262 assertThat(multimap.size(), is(7)); 263 assertKeys(multimap, keys[0], keys[1]); 264 assertValues(multimap, keys[0], values[0], values[1], values[2]); 265 assertValues(multimap, keys[1], values[0], values[3], values[1], values[2]); 266 Collection<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>(); 267 entries.add(entry(keys[0], values[0])); 268 entries.add(entry(keys[1], values[0])); 269 entries.add(entry(keys[0], values[1])); 270 entries.add(entry(keys[1], values[3])); 271 entries.add(entry(keys[1], values[1])); 272 entries.add(entry(keys[0], values[2])); 273 entries.add(entry(keys[1], values[2])); 274 assertEntries(multimap, entries); 275 } 276 277 @Test 278 public void shouldMaintainOrderOfInsertionInKeysAndValuesAfterAddingValueAtEndOfCollectionForKey() { 279 multimap.put(keys[0], values[0]); 280 multimap.put(keys[1], values[0]); 281 multimap.put(keys[0], values[1]); 282 multimap.put(keys[1], values[1]); 283 multimap.put(keys[0], values[2]); 284 multimap.put(keys[1], values[2]); 285 addValueUsingCollection(listMultimap, keys[1], 3, values[3]); 286 assertThat(multimap.isEmpty(), is(false)); 287 assertThat(multimap.size(), is(7)); 288 assertKeys(multimap, keys[0], keys[1]); 289 assertValues(multimap, keys[0], values[0], values[1], values[2]); 290 assertValues(multimap, keys[1], values[0], values[1], values[2], values[3]); 291 Collection<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>(); 292 entries.add(entry(keys[0], values[0])); 293 entries.add(entry(keys[1], values[0])); 294 entries.add(entry(keys[0], values[1])); 295 entries.add(entry(keys[1], values[1])); 296 entries.add(entry(keys[0], values[2])); 297 entries.add(entry(keys[1], values[2])); 298 entries.add(entry(keys[1], values[3])); 299 assertEntries(multimap, entries); 300 } 301 302 @Test 303 public void shouldMaintainOrderOfInsertionInKeysAndValuesAfterAddingValueAtBeginngingOfCollectionForKeyUsingIterator() { 304 multimap.put(keys[0], values[0]); 305 multimap.put(keys[1], values[0]); 306 multimap.put(keys[0], values[1]); 307 multimap.put(keys[1], values[1]); 308 multimap.put(keys[0], values[2]); 309 multimap.put(keys[1], values[2]); 310 addValueUsingIterator(listMultimap, keys[0], 0, values[3]); 311 assertThat(multimap.isEmpty(), is(false)); 312 assertThat(multimap.size(), is(7)); 313 assertKeys(multimap, keys[0], keys[1]); 314 assertValues(multimap, keys[0], values[3], values[0], values[1], values[2]); 315 assertValues(multimap, keys[1], values[0], values[1], values[2]); 316 Collection<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>(); 317 entries.add(entry(keys[0], values[3])); 318 entries.add(entry(keys[0], values[0])); 319 entries.add(entry(keys[1], values[0])); 320 entries.add(entry(keys[0], values[1])); 321 entries.add(entry(keys[1], values[1])); 322 entries.add(entry(keys[0], values[2])); 323 entries.add(entry(keys[1], values[2])); 324 assertEntries(multimap, entries); 325 } 326 327 @Test 328 public void shouldMaintainOrderOfInsertionInKeysAndValuesAfterAddingValueAtMiddleOfCollectionForKeyUsingIterator() { 329 multimap.put(keys[0], values[0]); 330 multimap.put(keys[1], values[0]); 331 multimap.put(keys[0], values[1]); 332 multimap.put(keys[1], values[1]); 333 multimap.put(keys[0], values[2]); 334 multimap.put(keys[1], values[2]); 335 addValueUsingIterator(listMultimap, keys[1], 1, values[3]); 336 assertThat(multimap.isEmpty(), is(false)); 337 assertThat(multimap.size(), is(7)); 338 assertKeys(multimap, keys[0], keys[1]); 339 assertValues(multimap, keys[0], values[0], values[1], values[2]); 340 assertValues(multimap, keys[1], values[0], values[3], values[1], values[2]); 341 Collection<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>(); 342 entries.add(entry(keys[0], values[0])); 343 entries.add(entry(keys[1], values[0])); 344 entries.add(entry(keys[0], values[1])); 345 entries.add(entry(keys[1], values[3])); 346 entries.add(entry(keys[1], values[1])); 347 entries.add(entry(keys[0], values[2])); 348 entries.add(entry(keys[1], values[2])); 349 assertEntries(multimap, entries); 350 } 351 352 @Test 353 public void shouldMaintainOrderOfInsertionInKeysAndValuesAfterAddingValueAtEndOfCollectionForKeyUsingIterator() { 354 multimap.put(keys[0], values[0]); 355 multimap.put(keys[1], values[0]); 356 multimap.put(keys[0], values[1]); 357 multimap.put(keys[1], values[1]); 358 multimap.put(keys[0], values[2]); 359 multimap.put(keys[1], values[2]); 360 addValueUsingIterator(listMultimap, keys[1], 3, values[3]); 361 assertThat(multimap.isEmpty(), is(false)); 362 assertThat(multimap.size(), is(7)); 363 assertKeys(multimap, keys[0], keys[1]); 364 assertValues(multimap, keys[0], values[0], values[1], values[2]); 365 assertValues(multimap, keys[1], values[0], values[1], values[2], values[3]); 366 Collection<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>(); 367 entries.add(entry(keys[0], values[0])); 368 entries.add(entry(keys[1], values[0])); 369 entries.add(entry(keys[0], values[1])); 370 entries.add(entry(keys[1], values[1])); 371 entries.add(entry(keys[0], values[2])); 372 entries.add(entry(keys[1], values[2])); 373 entries.add(entry(keys[1], values[3])); 374 assertEntries(multimap, entries); 375 } 376 377 protected void addValueUsingCollection( ListMultimap<String, String> multimap, 378 String key, 379 int atPosition, 380 String value ) { 381 List<String> values = multimap.get(key); 382 values.add(atPosition, value); 383 } 384 385 protected void addValueUsingIterator( ListMultimap<String, String> multimap, 386 String key, 387 int atPosition, 388 String value ) { 389 List<String> values = multimap.get(key); 390 ListIterator<String> iter = values.listIterator(); 391 while (iter.hasNext()) { 392 if (iter.nextIndex() == atPosition) { 393 iter.add(value); // will insert before the 'next' value that was at the 'atPosition' index 394 return; 395 } 396 iter.next(); 397 } 398 iter.add(value); // at the end 399 } 400 401 protected void setValueUsingCollection( ListMultimap<String, String> multimap, 402 String key, 403 int atPosition, 404 String value ) { 405 List<String> values = multimap.get(key); 406 values.set(atPosition, value); 407 } 408 409 protected void setValueUsingIterator( ListMultimap<String, String> multimap, 410 String key, 411 int atPosition, 412 String value ) { 413 List<String> values = multimap.get(key); 414 ListIterator<String> iter = values.listIterator(); 415 while (iter.hasNext()) { 416 if (iter.nextIndex() == atPosition) { 417 iter.set(value); 418 break; 419 } 420 iter.next(); 421 } 422 } 423 424}