[java-support] branch maint-7 updated: JSPT-82: Add method(s) to LockableClassToInstanceMultiMap which lock ...

Brent Putman putmanb at georgetown.edu
Tue Oct 2 19:40:33 EDT 2018


This is an automated email from the git hooks/post-receive script.

putmanb pushed a commit to branch maint-7
in repository java-support.

View the commit online:
http://git.shibboleth.net/view/?p=java-support.git;a=commit;h=72e5641796429fefb24311290c2bebf1ea3a45d3

The following commit(s) were added to refs/heads/maint-7 by this push:
       new  72e5641   JSPT-82: Add method(s) to LockableClassToInstanceMultiMap which lock ...
72e5641 is described below

commit 72e5641796429fefb24311290c2bebf1ea3a45d3
Author: Brent Putman <putmanb at georgetown.edu>
AuthorDate: Tue Oct 2 19:40:32 2018 -0400

    JSPT-82: Add method(s) to LockableClassToInstanceMultiMap which lock ...
---
 .../LockableClassToInstanceMultiMap.java           | 249 ++++++++++++++-
 .../LockableClassToInstanceMultiMapTest.java       | 351 +++++++++++++++++++++
 2 files changed, 597 insertions(+), 3 deletions(-)

diff --git a/src/main/java/net/shibboleth/utilities/java/support/collection/LockableClassToInstanceMultiMap.java b/src/main/java/net/shibboleth/utilities/java/support/collection/LockableClassToInstanceMultiMap.java
index 54935af..628da0f 100644
--- a/src/main/java/net/shibboleth/utilities/java/support/collection/LockableClassToInstanceMultiMap.java
+++ b/src/main/java/net/shibboleth/utilities/java/support/collection/LockableClassToInstanceMultiMap.java
@@ -17,16 +17,31 @@
 
 package net.shibboleth.utilities.java.support.collection;
 
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.shibboleth.utilities.java.support.annotation.constraint.Live;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
+import net.shibboleth.utilities.java.support.annotation.constraint.Unmodifiable;
 
 /**
  * A specialization of {@link ClassToInstanceMultiMap} which exposes a map-specific
- * instance of {@link ReadWriteLock}. Callers of the map are responsible for explicitly locking
- * (and unlocking) for reading and/or writing, based on application use cases and concurrency 
- * requirements.
+ * instance of {@link ReadWriteLock}.
+ * 
+ * <p>
+ * Callers of the map are generally responsible for explicitly locking
+ * and unlocking for reading and writing, based on application use cases and concurrency 
+ * requirements.  For simple single-statement atomic operations, convenience
+ * methods are supplied which execute the corresponding superclass operation under the 
+ * read or write lock, as appropriate.
+ * </p>
  * 
  * @param <B> a bound for the types of values in the map
  */
@@ -65,5 +80,233 @@ public class LockableClassToInstanceMultiMap<B> extends ClassToInstanceMultiMap<
     @Nonnull public ReadWriteLock getReadWriteLock() {
         return readWriteLock;
     }
+    
+    /**
+     * Convenience method which executes the like-named method from superclass {@link ClassToInstanceMultiMap}
+     * under a write lock.
+     */
+    public void clearWithLock() {
+        final Lock writeLock = getReadWriteLock().writeLock();
+        try {
+            writeLock.lock();
+            clear();
+        } finally {
+            writeLock.unlock();
+        }
+    }
+    
+    /**
+     * Convenience method which executes the like-named method from superclass {@link ClassToInstanceMultiMap}
+     * under a read lock.
+     * 
+     * @param key key to check for in the map
+     * 
+     * @return true if the map contains a mapping for the specified key
+     */
+    public boolean containsKeyWithLock(@Nullable final Class<?> key) {
+        final Lock readLock = getReadWriteLock().readLock();
+        try {
+            readLock.lock();
+            return containsKey(key);
+        } finally {
+            readLock.unlock();
+        }
+    }
+    
+    /**
+     * Convenience method which executes the like-named method from superclass {@link ClassToInstanceMultiMap}
+     * under a read lock.
+     * 
+     * @param value value to check for in this map
+     * 
+     * @return true if the map contains a mapping to the specified value
+     */
+    public boolean containsValueWithLock(@Nonnull final B value) {
+        final Lock readLock = getReadWriteLock().readLock();
+        try {
+            readLock.lock();
+            return containsValue(value);
+        } finally {
+            readLock.unlock();
+        }
+    }
+    
+    /**
+     * Convenience method which executes the like-named method from superclass {@link ClassToInstanceMultiMap}
+     * under a read lock.
+     * 
+     * @param <T> type identifier
+     * @param type map key
+     * 
+     * @return instances mapped to the given type or an empty list
+     */
+    @Nonnull @NonnullElements @Unmodifiable @Live public <T> List<T> getWithLock(@Nullable final Class<T> type) {
+        final Lock readLock = getReadWriteLock().readLock();
+        try {
+            readLock.lock();
+            return get(type);
+        } finally {
+            readLock.unlock();
+        }
+    }
+    
+    /**
+     * Convenience method which executes the like-named method from superclass {@link ClassToInstanceMultiMap}
+     * under a read lock.
+     * 
+     * @return true if this map contains no entries, false otherwise
+     */
+    public boolean isEmptyWithLock() {
+        final Lock readLock = getReadWriteLock().readLock();
+        try {
+            readLock.lock();
+            return isEmpty();
+        } finally {
+            readLock.unlock();
+        }
+    }
+    
+    /**
+     * Convenience method which executes the like-named method from superclass {@link ClassToInstanceMultiMap}
+     * under a read lock.
+     * 
+     * @return set of keys contained in this map
+     */
+    @Nonnull @NonnullElements @Unmodifiable @Live public Set<Class<?>> keysWithLock() {
+        final Lock readLock = getReadWriteLock().readLock();
+        try {
+            readLock.lock();
+            return keys();
+        } finally {
+            readLock.unlock();
+        }
+    }
+    
+    /**
+     * Convenience method which executes the like-named method from superclass {@link ClassToInstanceMultiMap}
+     * under a write lock.
+     * 
+     * @param value value to be stored in the map
+     */
+    public void putWithLock(@Nonnull final B value) {
+        final Lock writeLock = getReadWriteLock().writeLock();
+        try {
+            writeLock.lock();
+            put(value);
+        } finally {
+            writeLock.unlock();
+        }
+    }
+    
+    /**
+     * Convenience method which executes the like-named method from superclass {@link ClassToInstanceMultiMap}
+     * under a write lock.
+     * 
+     * @param map map containing values to be added
+     */
+    public void putAllWithLock(@Nullable @NonnullElements final ClassToInstanceMultiMap<? extends B> map) {
+        final Lock writeLock = getReadWriteLock().writeLock();
+        try {
+            writeLock.lock();
+            putAll(map);
+        } finally {
+            writeLock.unlock();
+        }
+    }
+    
+    /**
+     * Convenience method which executes the like-named method from superclass {@link ClassToInstanceMultiMap}
+     * under a write lock.
+     * 
+     * @param newValues values to be added
+     */
+    public void putAllWithLock(@Nullable @NonnullElements final Iterable<? extends B> newValues) {
+        final Lock writeLock = getReadWriteLock().writeLock();
+        try {
+            writeLock.lock();
+            putAll(newValues);
+        } finally {
+            writeLock.unlock();
+        }
+    }
+    
+    /**
+     * Convenience method which executes the like-named method from superclass {@link ClassToInstanceMultiMap}
+     * under a write lock.
+     * 
+     * @param value the value to remove
+     */
+    public void removeWithLock(@Nonnull final B value) {
+        final Lock writeLock = getReadWriteLock().writeLock();
+        try {
+            writeLock.lock();
+            remove(value);
+        } finally {
+            writeLock.unlock();
+        }
+    }
+    
+    /**
+     * Convenience method which executes the like-named method from superclass {@link ClassToInstanceMultiMap}
+     * under a write lock.
+     * 
+     * @param type the type of values to remove
+     */
+    public void removeWithLock(@Nullable final Class<?> type) {
+        final Lock writeLock = getReadWriteLock().writeLock();
+        try {
+            writeLock.lock();
+            remove(type);
+        } finally {
+            writeLock.unlock();
+        }
+    }
+    
+    /**
+     * Convenience method which executes the like-named method from superclass {@link ClassToInstanceMultiMap}
+     * under a write lock.
+     * 
+     * @param map the map containing the values to remove
+     */
+    public void removeAllWithLock(@Nullable @NonnullElements final ClassToInstanceMultiMap<? extends B> map) {
+        final Lock writeLock = getReadWriteLock().writeLock();
+        try {
+            writeLock.lock();
+            removeAll(map);
+        } finally {
+            writeLock.unlock();
+        }
+    }
+    /**
+     * Convenience method which executes the like-named method from superclass {@link ClassToInstanceMultiMap}
+     * under a write lock.
+     * 
+     * @param removeValues the values to remove
+     */ 
+    public void removeAllWithLock(@Nullable @NonnullElements final Iterable<? extends B> removeValues) {
+        final Lock writeLock = getReadWriteLock().writeLock();
+        try {
+            writeLock.lock();
+            removeAll(removeValues);
+        } finally {
+            writeLock.unlock();
+        }
+    }
 
+    /**
+     * Convenience method which executes the like-named method from superclass {@link ClassToInstanceMultiMap}
+     * under a read lock.
+     * 
+     * @return collection of values currently present in the map
+     */
+    @Nonnull @NonnullElements @Unmodifiable @Live public Collection<? extends B> valuesWithLock() {
+        final Lock readLock = getReadWriteLock().readLock();
+        try {
+            readLock.lock();
+            return values();
+        } finally {
+            readLock.unlock();
+        }
+    }
+    
 }
\ No newline at end of file
diff --git a/src/test/java/net/shibboleth/utilities/java/support/collection/LockableClassToInstanceMultiMapTest.java b/src/test/java/net/shibboleth/utilities/java/support/collection/LockableClassToInstanceMultiMapTest.java
new file mode 100644
index 0000000..476d085
--- /dev/null
+++ b/src/test/java/net/shibboleth/utilities/java/support/collection/LockableClassToInstanceMultiMapTest.java
@@ -0,0 +1,351 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You 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 net.shibboleth.utilities.java.support.collection;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.List;
+
+import org.joda.time.Chronology;
+import org.joda.time.DateTime;
+import org.joda.time.Instant;
+import org.joda.time.ReadableDateTime;
+import org.joda.time.ReadableInstant;
+import org.joda.time.base.AbstractDateTime;
+import org.joda.time.base.AbstractInstant;
+import org.joda.time.base.BaseDateTime;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/** Unit test for {@link LockableClassToInstanceMultiMap}. */
+public class LockableClassToInstanceMultiMapTest {
+
+    @Test public void testClearIsEmpty() {
+        LockableClassToInstanceMultiMap<Object> map = new LockableClassToInstanceMultiMap<>();
+
+        map.clear();
+        Assert.assertTrue(map.isEmptyWithLock());
+
+        map.put(new Object());
+        Assert.assertFalse(map.isEmptyWithLock());
+
+        map.clear();
+        Assert.assertTrue(map.isEmptyWithLock());
+    }
+
+    @Test public void testKeysAndContainsKey() {
+        LockableClassToInstanceMultiMap<AbstractInstant> map = new LockableClassToInstanceMultiMap<>();
+        populate(map);
+        Assert.assertEquals(map.keysWithLock().size(), 2);
+        Assert.assertFalse(map.containsKeyWithLock(null));
+        Assert.assertFalse(map.containsKeyWithLock(Chronology.class));
+        Assert.assertFalse(map.containsKeyWithLock(AbstractInstant.class));
+        Assert.assertFalse(map.containsKeyWithLock(AbstractDateTime.class));
+        Assert.assertFalse(map.containsKeyWithLock(BaseDateTime.class));
+        Assert.assertTrue(map.containsKeyWithLock(DateTime.class));
+        Assert.assertFalse(map.containsKeyWithLock(Comparable.class));
+        Assert.assertFalse(map.containsKeyWithLock(ReadableDateTime.class));
+        Assert.assertFalse(map.containsKeyWithLock(ReadableInstant.class));
+        Assert.assertFalse(map.containsKeyWithLock(Serializable.class));
+        Assert.assertTrue(map.containsKeyWithLock(Instant.class));
+
+        map = new LockableClassToInstanceMultiMap<>(true);
+        populate(map);
+        Assert.assertEquals(map.keysWithLock().size(), 9);
+        Assert.assertFalse(map.containsKeyWithLock(null));
+        Assert.assertFalse(map.containsKeyWithLock(Chronology.class));
+        Assert.assertTrue(map.containsKeyWithLock(AbstractInstant.class));
+        Assert.assertTrue(map.containsKeyWithLock(AbstractDateTime.class));
+        Assert.assertTrue(map.containsKeyWithLock(BaseDateTime.class));
+        Assert.assertTrue(map.containsKeyWithLock(DateTime.class));
+        Assert.assertTrue(map.containsKeyWithLock(Comparable.class));
+        Assert.assertTrue(map.containsKeyWithLock(ReadableDateTime.class));
+        Assert.assertTrue(map.containsKeyWithLock(ReadableInstant.class));
+        Assert.assertTrue(map.containsKeyWithLock(Serializable.class));
+        Assert.assertTrue(map.containsKeyWithLock(Instant.class));
+    }
+
+    @Test public void testValuesAndContainsValues() {
+        LockableClassToInstanceMultiMap<AbstractInstant> map = new LockableClassToInstanceMultiMap<>();
+
+        DateTime now = new DateTime();
+        map.putWithLock(now);
+
+        DateTime now100 = now.plus(100);
+        map.putWithLock(now100);
+
+        Instant instant = new Instant();
+        map.putWithLock(instant);
+
+        Assert.assertEquals(map.valuesWithLock().size(), 3);
+        Assert.assertFalse(map.containsValueWithLock(null));
+        Assert.assertFalse(map.containsValueWithLock(now.minus(100)));
+        Assert.assertFalse(map.containsValueWithLock(instant.minus(100)));
+        Assert.assertTrue(map.containsValueWithLock(instant));
+        Assert.assertTrue(map.containsValueWithLock(now));
+        Assert.assertTrue(map.containsValueWithLock(now100));
+    }
+
+    @Test public void testEquals() {
+        final LockableClassToInstanceMultiMap<AbstractInstant> map = new LockableClassToInstanceMultiMap<>();
+        final LockableClassToInstanceMultiMap<AbstractInstant> map2 = new LockableClassToInstanceMultiMap<>();
+        final LockableClassToInstanceMultiMap<AbstractInstant> map3 = new LockableClassToInstanceMultiMap<>();
+
+        final DateTime now = new DateTime();
+        map.putWithLock(now);
+        map2.putWithLock(now);
+        map3.putWithLock(now);
+
+        final DateTime now100 = now.plus(100);
+        map.putWithLock(now100);
+        map2.putWithLock(now100);
+        map3.putWithLock(now100);
+
+        final Instant instant = new Instant();
+        map.putWithLock(instant);
+        map2.putWithLock(instant);
+
+        Assert.assertTrue(map.equals(map2));
+        Assert.assertFalse(map.equals(map3));
+
+        Assert.assertEquals(map.hashCode(), map2.hashCode());
+        Assert.assertNotEquals(map.hashCode(), map3.hashCode());
+
+    }
+
+    @Test public void testGet() {
+        LockableClassToInstanceMultiMap<AbstractInstant> map = new LockableClassToInstanceMultiMap<>();
+        populate(map);
+
+        List<?> values = map.getWithLock(null);
+        Assert.assertEquals(values.size(), 0);
+
+        values = map.getWithLock(DateTime.class);
+        Assert.assertEquals(values.size(), 2);
+
+        values = map.getWithLock(Instant.class);
+        Assert.assertEquals(values.size(), 1);
+    }
+
+    @Test public void testNoIndexedDuplicateValues() {
+        LockableClassToInstanceMultiMap<Object> map = new LockableClassToInstanceMultiMap<>(true);
+
+        map.putWithLock(new FooBarImpl());
+
+        Assert.assertEquals(map.getWithLock(Foo.class).size(), 1);
+        Assert.assertEquals(map.getWithLock(Bar.class).size(), 1);
+        Assert.assertEquals(map.getWithLock(AbstractFoo.class).size(), 1);
+        Assert.assertEquals(map.getWithLock(AbstractFooBar.class).size(), 1);
+        Assert.assertEquals(map.getWithLock(FooBarImpl.class).size(), 1);
+    }
+
+    @Test public void testDuplicateInsertions() {
+        LockableClassToInstanceMultiMap<Object> map = new LockableClassToInstanceMultiMap<>(true);
+
+        FooBarImpl fb = new FooBarImpl();
+
+        map.putWithLock(fb);
+        map.putWithLock(fb);
+
+        Assert.assertEquals(map.valuesWithLock().size(), 1);
+
+        Assert.assertEquals(map.getWithLock(Foo.class).size(), 1);
+        Assert.assertEquals(map.getWithLock(Bar.class).size(), 1);
+        Assert.assertEquals(map.getWithLock(AbstractFoo.class).size(), 1);
+        Assert.assertEquals(map.getWithLock(AbstractFooBar.class).size(), 1);
+        Assert.assertEquals(map.getWithLock(FooBarImpl.class).size(), 1);
+    }
+
+    @Test public void testRemoveValue() {
+        LockableClassToInstanceMultiMap<Object> map = new LockableClassToInstanceMultiMap<>(true);
+
+        FooBarImpl fb = new FooBarImpl();
+        FooImpl f = new FooImpl();
+
+        map.putWithLock(fb); // This is what we'll remove.
+        map.putWithLock(f); // This is canary to test that its indexes don't disappear.
+
+        Assert.assertTrue(map.containsValueWithLock(fb));
+        Assert.assertTrue(map.containsValueWithLock(f));
+
+        Assert.assertTrue(map.containsKeyWithLock(Foo.class));
+        Assert.assertTrue(map.containsKeyWithLock(AbstractFoo.class));
+        Assert.assertTrue(map.containsKeyWithLock(FooImpl.class));
+
+        Assert.assertEquals(map.getWithLock(Foo.class).size(), 2);
+        Assert.assertEquals(map.getWithLock(AbstractFoo.class).size(), 2);
+        Assert.assertEquals(map.getWithLock(FooImpl.class).size(), 1);
+
+        Assert.assertTrue(map.containsKeyWithLock(Bar.class));
+        Assert.assertTrue(map.containsKeyWithLock(AbstractFooBar.class));
+        Assert.assertTrue(map.containsKeyWithLock(FooBarImpl.class));
+
+        Assert.assertEquals(map.getWithLock(Bar.class).size(), 1);
+        Assert.assertEquals(map.getWithLock(AbstractFooBar.class).size(), 1);
+        Assert.assertEquals(map.getWithLock(FooBarImpl.class).size(), 1);
+
+        map.remove(fb);
+
+        Assert.assertFalse(map.containsValueWithLock(fb));
+        Assert.assertTrue(map.containsValueWithLock(f));
+
+        Assert.assertTrue(map.containsKeyWithLock(Foo.class));
+        Assert.assertTrue(map.containsKeyWithLock(AbstractFoo.class));
+        Assert.assertTrue(map.containsKeyWithLock(FooImpl.class));
+
+        Assert.assertEquals(map.getWithLock(Foo.class).size(), 1);
+        Assert.assertEquals(map.getWithLock(AbstractFoo.class).size(), 1);
+        Assert.assertEquals(map.getWithLock(FooImpl.class).size(), 1);
+
+        Assert.assertFalse(map.containsKeyWithLock(Bar.class));
+        Assert.assertFalse(map.containsKeyWithLock(AbstractFooBar.class));
+        Assert.assertFalse(map.containsKeyWithLock(FooBarImpl.class));
+
+        Assert.assertEquals(map.getWithLock(Bar.class).size(), 0);
+        Assert.assertEquals(map.getWithLock(AbstractFooBar.class).size(), 0);
+        Assert.assertEquals(map.getWithLock(FooBarImpl.class).size(), 0);
+    }
+
+    @Test public void testRemoveByType() {
+        LockableClassToInstanceMultiMap<Object> map = new LockableClassToInstanceMultiMap<>(true);
+
+        FooBarImpl fb = new FooBarImpl();
+        FooImpl f = new FooImpl();
+
+        map.putWithLock(fb);
+        map.putWithLock(f);
+
+        Assert.assertTrue(map.containsValueWithLock(fb));
+        Assert.assertTrue(map.containsValueWithLock(f));
+
+        Assert.assertTrue(map.containsKeyWithLock(Foo.class));
+        Assert.assertTrue(map.containsKeyWithLock(AbstractFoo.class));
+        Assert.assertTrue(map.containsKeyWithLock(FooImpl.class));
+
+        Assert.assertEquals(map.getWithLock(Foo.class).size(), 2);
+        Assert.assertEquals(map.getWithLock(AbstractFoo.class).size(), 2);
+        Assert.assertEquals(map.getWithLock(FooImpl.class).size(), 1);
+
+        Assert.assertTrue(map.containsKeyWithLock(Bar.class));
+        Assert.assertTrue(map.containsKeyWithLock(AbstractFooBar.class));
+        Assert.assertTrue(map.containsKeyWithLock(FooBarImpl.class));
+
+        Assert.assertEquals(map.getWithLock(Bar.class).size(), 1);
+        Assert.assertEquals(map.getWithLock(AbstractFooBar.class).size(), 1);
+        Assert.assertEquals(map.getWithLock(FooBarImpl.class).size(), 1);
+
+        map.removeWithLock(Bar.class);
+
+        Assert.assertFalse(map.containsValueWithLock(fb));
+        Assert.assertTrue(map.containsValueWithLock(f));
+
+        Assert.assertTrue(map.containsKeyWithLock(Foo.class));
+        Assert.assertTrue(map.containsKeyWithLock(AbstractFoo.class));
+        Assert.assertTrue(map.containsKeyWithLock(FooImpl.class));
+
+        Assert.assertEquals(map.getWithLock(Foo.class).size(), 1);
+        Assert.assertEquals(map.getWithLock(AbstractFoo.class).size(), 1);
+        Assert.assertEquals(map.getWithLock(FooImpl.class).size(), 1);
+
+        Assert.assertFalse(map.containsKeyWithLock(Bar.class));
+        Assert.assertFalse(map.containsKeyWithLock(AbstractFooBar.class));
+        Assert.assertFalse(map.containsKeyWithLock(FooBarImpl.class));
+
+        Assert.assertEquals(map.getWithLock(Bar.class).size(), 0);
+        Assert.assertEquals(map.getWithLock(AbstractFooBar.class).size(), 0);
+        Assert.assertEquals(map.getWithLock(FooBarImpl.class).size(), 0);
+
+    }
+
+    @Test public void testRemoveAll() {
+        LockableClassToInstanceMultiMap<Object> map = new LockableClassToInstanceMultiMap<>(true);
+
+        FooImpl f1 = new FooImpl();
+        FooImpl f2 = new FooImpl();
+        FooImpl f3 = new FooImpl();
+
+        FooBarImpl fb1 = new FooBarImpl();
+        FooBarImpl fb2 = new FooBarImpl();
+        FooBarImpl fb3 = new FooBarImpl();
+
+        map.putWithLock(f1);
+        map.putWithLock(f2);
+        map.putWithLock(f3);
+        map.putWithLock(fb1);
+        map.putWithLock(fb2);
+        map.putWithLock(fb3);
+
+        Assert.assertEquals(map.valuesWithLock().size(), 6);
+        Assert.assertEquals(map.getWithLock(Foo.class).size(), 6);
+        Assert.assertEquals(map.getWithLock(Bar.class).size(), 3);
+
+        map.removeAllWithLock(Arrays.asList(f1, f2, fb1));
+
+        Assert.assertEquals(map.valuesWithLock().size(), 3);
+        Assert.assertEquals(map.getWithLock(Foo.class).size(), 3);
+        Assert.assertEquals(map.getWithLock(Bar.class).size(), 2);
+
+        map.removeAllWithLock(Arrays.asList(fb2, fb3));
+
+        Assert.assertEquals(map.valuesWithLock().size(), 1);
+        Assert.assertEquals(map.getWithLock(Foo.class).size(), 1);
+        Assert.assertEquals(map.getWithLock(Bar.class).size(), 0);
+        Assert.assertFalse(map.containsKeyWithLock(Bar.class));
+
+        map.removeAllWithLock(Arrays.asList(f3));
+
+        Assert.assertEquals(map.valuesWithLock().size(), 0);
+        Assert.assertTrue(map.isEmptyWithLock());
+        Assert.assertEquals(map.getWithLock(Foo.class).size(), 0);
+        Assert.assertEquals(map.getWithLock(Bar.class).size(), 0);
+        Assert.assertFalse(map.containsKeyWithLock(Foo.class));
+        Assert.assertFalse(map.containsKeyWithLock(Bar.class));
+    }
+
+    protected void populate(LockableClassToInstanceMultiMap<AbstractInstant> map) {
+        DateTime now = new DateTime();
+        map.putWithLock(now);
+
+        DateTime now100 = now.plus(100);
+        map.putWithLock(now100);
+
+        Instant instant = new Instant();
+        map.putWithLock(instant);
+    }
+
+    // Test classes and interfaces
+
+    public interface Foo {
+    };
+
+    public interface Bar extends Foo {
+    };
+
+    public abstract class AbstractFoo implements Foo {
+    };
+
+    public class FooImpl extends AbstractFoo {
+    };
+
+    public abstract class AbstractFooBar extends AbstractFoo implements Bar {
+    };
+
+    public class FooBarImpl extends AbstractFooBar {
+    };
+
+}
\ No newline at end of file

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list