/* * ModeShape (http://www.modeshape.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.modeshape.common.collection; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.ListIterator; import java.util.Map; import org.junit.Before; import org.junit.Test; public class LinkedListMultimapTest extends AbstractMultimapTest { protected ListMultimap<String, String> listMultimap; @Override @Before public void beforeEach() { super.beforeEach(); listMultimap = (ListMultimap<String, String>)multimap; } @Override protected <K, V> LinkedListMultimap<K, V> createMultimap() { return LinkedListMultimap.create(); } /** * {@inheritDoc} * * @see org.modeshape.common.collection.AbstractMultimapTest#valuesAllowDuplicates() */ @Override protected boolean valuesAllowDuplicates() { return true; } @Test public void shouldAddEntryToEmtpyMap() { LinkedListMultimap<String, String> listMap = createMultimap(); assertThat(listMap.size(), is(0)); listMap.addEntryFor(keys[0], values[0]); assertThat(listMap.size(), is(1)); } @Test public void shouldMaintainOrderOfInsertionInKeysAndValues() { multimap.put(keys[0], values[0]); multimap.put(keys[1], values[1]); multimap.put(keys[0], values[0]); multimap.put(keys[1], values[2]); multimap.put(keys[0], values[0]); multimap.put(keys[1], values[3]); assertThat(multimap.isEmpty(), is(false)); assertThat(multimap.size(), is(6)); assertKeys(multimap, keys[0], keys[1]); assertValues(multimap, keys[0], values[0], values[0], values[0]); assertValues(multimap, keys[1], values[1], values[2], values[3]); Collection<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>(); entries.add(entry(keys[0], values[0])); entries.add(entry(keys[1], values[1])); entries.add(entry(keys[0], values[0])); entries.add(entry(keys[1], values[2])); entries.add(entry(keys[0], values[0])); entries.add(entry(keys[1], values[3])); assertEntries(multimap, entries); } @Test public void shouldMaintainOrderOfInsertionInKeysAndValuesAfterRemovalOfFirstKeyValuePair() { multimap.put(keys[0], values[0]); multimap.put(keys[1], values[0]); multimap.put(keys[0], values[1]); multimap.put(keys[1], values[1]); multimap.put(keys[0], values[2]); multimap.put(keys[1], values[2]); multimap.remove(keys[0], values[0]); assertThat(multimap.isEmpty(), is(false)); assertThat(multimap.size(), is(5)); assertKeys(multimap, keys[0], keys[1]); assertValues(multimap, keys[0], /*values[0],*/values[1], values[2]); assertValues(multimap, keys[1], values[0], values[1], values[2]); Collection<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>(); // entries.add(entry(keys[0], values[0])); entries.add(entry(keys[1], values[0])); entries.add(entry(keys[0], values[1])); entries.add(entry(keys[1], values[1])); entries.add(entry(keys[0], values[2])); entries.add(entry(keys[1], values[2])); assertEntries(multimap, entries); } @Test public void shouldMaintainOrderOfInsertionInKeysAndValuesAfterRemovalOfMiddleKeyValuePair() { multimap.put(keys[0], values[0]); multimap.put(keys[1], values[1]); multimap.put(keys[0], values[0]); multimap.put(keys[1], values[2]); multimap.put(keys[0], values[0]); multimap.put(keys[1], values[3]); multimap.remove(keys[1], values[2]); assertThat(multimap.isEmpty(), is(false)); assertThat(multimap.size(), is(5)); assertKeys(multimap, keys[0], keys[1]); assertValues(multimap, keys[0], values[0], values[0], values[0]); assertValues(multimap, keys[1], values[1], values[3]); Collection<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>(); entries.add(entry(keys[0], values[0])); entries.add(entry(keys[1], values[1])); entries.add(entry(keys[0], values[0])); entries.add(entry(keys[0], values[0])); entries.add(entry(keys[1], values[3])); assertEntries(multimap, entries); } @Test public void shouldMaintainOrderOfInsertionInKeysAndValuesAfterRemovalOfLastKeyValuePair() { multimap.put(keys[0], values[0]); multimap.put(keys[1], values[0]); multimap.put(keys[0], values[1]); multimap.put(keys[1], values[1]); multimap.put(keys[0], values[2]); multimap.put(keys[1], values[2]); multimap.remove(keys[1], values[2]); assertThat(multimap.isEmpty(), is(false)); assertThat(multimap.size(), is(5)); assertKeys(multimap, keys[0], keys[1]); assertValues(multimap, keys[0], values[0], values[1], values[2]); assertValues(multimap, keys[1], values[0], values[1] /*, values[2]*/); Collection<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>(); entries.add(entry(keys[0], values[0])); entries.add(entry(keys[1], values[0])); entries.add(entry(keys[0], values[1])); entries.add(entry(keys[1], values[1])); entries.add(entry(keys[0], values[2])); // entries.add(entry(keys[1], values[2])); assertEntries(multimap, entries); } @Test public void shouldMaintainOrderOfInsertionInKeysAndValuesAfterRemovalOfFirstValueFromKeyCollection() { multimap.put(keys[0], values[0]); multimap.put(keys[1], values[0]); multimap.put(keys[0], values[1]); multimap.put(keys[1], values[1]); multimap.put(keys[0], values[2]); multimap.put(keys[1], values[2]); multimap.get(keys[0]).remove(values[0]); assertThat(multimap.isEmpty(), is(false)); assertThat(multimap.size(), is(5)); assertKeys(multimap, keys[0], keys[1]); assertValues(multimap, keys[0], /*values[0],*/values[1], values[2]); assertValues(multimap, keys[1], values[0], values[1], values[2]); Collection<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>(); // entries.add(entry(keys[0], values[0])); entries.add(entry(keys[1], values[0])); entries.add(entry(keys[0], values[1])); entries.add(entry(keys[1], values[1])); entries.add(entry(keys[0], values[2])); entries.add(entry(keys[1], values[2])); assertEntries(multimap, entries); } @Test public void shouldMaintainOrderOfInsertionInKeysAndValuesAfterRemovalOfMiddleValueFromKeyCollection() { multimap.put(keys[0], values[0]); multimap.put(keys[1], values[0]); multimap.put(keys[0], values[1]); multimap.put(keys[1], values[1]); multimap.put(keys[0], values[2]); multimap.put(keys[1], values[2]); multimap.get(keys[1]).remove(values[1]); assertThat(multimap.isEmpty(), is(false)); assertThat(multimap.size(), is(5)); assertKeys(multimap, keys[0], keys[1]); assertValues(multimap, keys[0], values[0], values[1], values[2]); assertValues(multimap, keys[1], values[0], values[2]); Collection<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>(); entries.add(entry(keys[0], values[0])); entries.add(entry(keys[1], values[0])); entries.add(entry(keys[0], values[1])); entries.add(entry(keys[0], values[2])); entries.add(entry(keys[1], values[2])); assertEntries(multimap, entries); } @Test public void shouldMaintainOrderOfInsertionInKeysAndValuesAfterRemovalOfLastValueFromKeyCollection() { multimap.put(keys[0], values[0]); multimap.put(keys[1], values[0]); multimap.put(keys[0], values[1]); multimap.put(keys[1], values[1]); multimap.put(keys[0], values[2]); multimap.put(keys[1], values[2]); multimap.get(keys[1]).remove(values[2]); assertThat(multimap.isEmpty(), is(false)); assertThat(multimap.size(), is(5)); assertKeys(multimap, keys[0], keys[1]); assertValues(multimap, keys[0], values[0], values[1], values[2]); assertValues(multimap, keys[1], values[0], values[1] /*, values[2]*/); Collection<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>(); entries.add(entry(keys[0], values[0])); entries.add(entry(keys[1], values[0])); entries.add(entry(keys[0], values[1])); entries.add(entry(keys[1], values[1])); entries.add(entry(keys[0], values[2])); // entries.add(entry(keys[1], values[2])); assertEntries(multimap, entries); } @Test public void shouldMaintainOrderOfInsertionInKeysAndValuesAfterAddingValueAtBeginngingOfCollectionForKey() { multimap.put(keys[0], values[0]); multimap.put(keys[1], values[0]); multimap.put(keys[0], values[1]); multimap.put(keys[1], values[1]); multimap.put(keys[0], values[2]); multimap.put(keys[1], values[2]); addValueUsingCollection(listMultimap, keys[0], 0, values[3]); assertThat(multimap.isEmpty(), is(false)); assertThat(multimap.size(), is(7)); assertKeys(multimap, keys[0], keys[1]); assertValues(multimap, keys[0], values[3], values[0], values[1], values[2]); assertValues(multimap, keys[1], values[0], values[1], values[2]); Collection<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>(); entries.add(entry(keys[0], values[3])); entries.add(entry(keys[0], values[0])); entries.add(entry(keys[1], values[0])); entries.add(entry(keys[0], values[1])); entries.add(entry(keys[1], values[1])); entries.add(entry(keys[0], values[2])); entries.add(entry(keys[1], values[2])); assertEntries(multimap, entries); } @Test public void shouldMaintainOrderOfInsertionInKeysAndValuesAfterAddingValueAtMiddleOfCollectionForKey() { multimap.put(keys[0], values[0]); multimap.put(keys[1], values[0]); multimap.put(keys[0], values[1]); multimap.put(keys[1], values[1]); multimap.put(keys[0], values[2]); multimap.put(keys[1], values[2]); addValueUsingCollection(listMultimap, keys[1], 1, values[3]); assertThat(multimap.isEmpty(), is(false)); assertThat(multimap.size(), is(7)); assertKeys(multimap, keys[0], keys[1]); assertValues(multimap, keys[0], values[0], values[1], values[2]); assertValues(multimap, keys[1], values[0], values[3], values[1], values[2]); Collection<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>(); entries.add(entry(keys[0], values[0])); entries.add(entry(keys[1], values[0])); entries.add(entry(keys[0], values[1])); entries.add(entry(keys[1], values[3])); entries.add(entry(keys[1], values[1])); entries.add(entry(keys[0], values[2])); entries.add(entry(keys[1], values[2])); assertEntries(multimap, entries); } @Test public void shouldMaintainOrderOfInsertionInKeysAndValuesAfterAddingValueAtEndOfCollectionForKey() { multimap.put(keys[0], values[0]); multimap.put(keys[1], values[0]); multimap.put(keys[0], values[1]); multimap.put(keys[1], values[1]); multimap.put(keys[0], values[2]); multimap.put(keys[1], values[2]); addValueUsingCollection(listMultimap, keys[1], 3, values[3]); assertThat(multimap.isEmpty(), is(false)); assertThat(multimap.size(), is(7)); assertKeys(multimap, keys[0], keys[1]); assertValues(multimap, keys[0], values[0], values[1], values[2]); assertValues(multimap, keys[1], values[0], values[1], values[2], values[3]); Collection<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>(); entries.add(entry(keys[0], values[0])); entries.add(entry(keys[1], values[0])); entries.add(entry(keys[0], values[1])); entries.add(entry(keys[1], values[1])); entries.add(entry(keys[0], values[2])); entries.add(entry(keys[1], values[2])); entries.add(entry(keys[1], values[3])); assertEntries(multimap, entries); } @Test public void shouldMaintainOrderOfInsertionInKeysAndValuesAfterAddingValueAtBeginngingOfCollectionForKeyUsingIterator() { multimap.put(keys[0], values[0]); multimap.put(keys[1], values[0]); multimap.put(keys[0], values[1]); multimap.put(keys[1], values[1]); multimap.put(keys[0], values[2]); multimap.put(keys[1], values[2]); addValueUsingIterator(listMultimap, keys[0], 0, values[3]); assertThat(multimap.isEmpty(), is(false)); assertThat(multimap.size(), is(7)); assertKeys(multimap, keys[0], keys[1]); assertValues(multimap, keys[0], values[3], values[0], values[1], values[2]); assertValues(multimap, keys[1], values[0], values[1], values[2]); Collection<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>(); entries.add(entry(keys[0], values[3])); entries.add(entry(keys[0], values[0])); entries.add(entry(keys[1], values[0])); entries.add(entry(keys[0], values[1])); entries.add(entry(keys[1], values[1])); entries.add(entry(keys[0], values[2])); entries.add(entry(keys[1], values[2])); assertEntries(multimap, entries); } @Test public void shouldMaintainOrderOfInsertionInKeysAndValuesAfterAddingValueAtMiddleOfCollectionForKeyUsingIterator() { multimap.put(keys[0], values[0]); multimap.put(keys[1], values[0]); multimap.put(keys[0], values[1]); multimap.put(keys[1], values[1]); multimap.put(keys[0], values[2]); multimap.put(keys[1], values[2]); addValueUsingIterator(listMultimap, keys[1], 1, values[3]); assertThat(multimap.isEmpty(), is(false)); assertThat(multimap.size(), is(7)); assertKeys(multimap, keys[0], keys[1]); assertValues(multimap, keys[0], values[0], values[1], values[2]); assertValues(multimap, keys[1], values[0], values[3], values[1], values[2]); Collection<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>(); entries.add(entry(keys[0], values[0])); entries.add(entry(keys[1], values[0])); entries.add(entry(keys[0], values[1])); entries.add(entry(keys[1], values[3])); entries.add(entry(keys[1], values[1])); entries.add(entry(keys[0], values[2])); entries.add(entry(keys[1], values[2])); assertEntries(multimap, entries); } @Test public void shouldMaintainOrderOfInsertionInKeysAndValuesAfterAddingValueAtEndOfCollectionForKeyUsingIterator() { multimap.put(keys[0], values[0]); multimap.put(keys[1], values[0]); multimap.put(keys[0], values[1]); multimap.put(keys[1], values[1]); multimap.put(keys[0], values[2]); multimap.put(keys[1], values[2]); addValueUsingIterator(listMultimap, keys[1], 3, values[3]); assertThat(multimap.isEmpty(), is(false)); assertThat(multimap.size(), is(7)); assertKeys(multimap, keys[0], keys[1]); assertValues(multimap, keys[0], values[0], values[1], values[2]); assertValues(multimap, keys[1], values[0], values[1], values[2], values[3]); Collection<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>(); entries.add(entry(keys[0], values[0])); entries.add(entry(keys[1], values[0])); entries.add(entry(keys[0], values[1])); entries.add(entry(keys[1], values[1])); entries.add(entry(keys[0], values[2])); entries.add(entry(keys[1], values[2])); entries.add(entry(keys[1], values[3])); assertEntries(multimap, entries); } protected void addValueUsingCollection( ListMultimap<String, String> multimap, String key, int atPosition, String value ) { List<String> values = multimap.get(key); values.add(atPosition, value); } protected void addValueUsingIterator( ListMultimap<String, String> multimap, String key, int atPosition, String value ) { List<String> values = multimap.get(key); ListIterator<String> iter = values.listIterator(); while (iter.hasNext()) { if (iter.nextIndex() == atPosition) { iter.add(value); // will insert before the 'next' value that was at the 'atPosition' index return; } iter.next(); } iter.add(value); // at the end } protected void setValueUsingCollection( ListMultimap<String, String> multimap, String key, int atPosition, String value ) { List<String> values = multimap.get(key); values.set(atPosition, value); } protected void setValueUsingIterator( ListMultimap<String, String> multimap, String key, int atPosition, String value ) { List<String> values = multimap.get(key); ListIterator<String> iter = values.listIterator(); while (iter.hasNext()) { if (iter.nextIndex() == atPosition) { iter.set(value); break; } iter.next(); } } }