Author: desruisseaux
Date: Tue Feb 26 19:50:05 2013
New Revision: 1450374
URL: http://svn.apache.org/r1450374
Log:
Convenience constructor for creating a CodeListSet filled with all known
elements.
Modified:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/CodeListSet.java
sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/collection/CodeListSetTest.java
Modified:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/CodeListSet.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/CodeListSet.java?rev=1450374&r1=1450373&r2=1450374&view=diff
==============================================================================
---
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/CodeListSet.java
[UTF-8] (original)
+++
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/CodeListSet.java
[UTF-8] Tue Feb 26 19:50:05 2013
@@ -23,6 +23,7 @@ import java.util.Iterator;
import java.util.NoSuchElementException;
import java.io.Serializable;
import java.lang.reflect.Modifier;
+import net.jcip.annotations.NotThreadSafe;
import org.opengis.util.CodeList;
import org.apache.sis.util.iso.Types;
import org.apache.sis.util.resources.Errors;
@@ -30,7 +31,23 @@ import org.apache.sis.util.resources.Err
/**
* A specialized {@code Set} implementation for use with {@link CodeList}
values.
- * This implementation uses a bit mask for efficient storage.
+ * All elements in a {@code CodeListSet} are of the same {@code CodeList}
class,
+ * which must be final. Iterators traverse the elements in the order in which
the
+ * code list constants are declared.
+ *
+ * {@section Implementation note}
+ * {@code CodeListSet} is implemented internally by bit vectors for compact
and efficient storage.
+ * All bulk operations ({@code addAll}, {@code removeAll}, {@code
containsAll}) are very quick if
+ * their argument is also a {@code CodeListSet} instance.
+ *
+ * {@section Usage example}
+ * The following example creates a set of {@link
org.opengis.referencing.cs.AxisDirection}s
+ * for a (<var>x</var>,<var>y</var>,<var>z</var>) coordinate system:
+ *
+ * {@preformat java
+ * CodeListSet<AxisDirection> codes = new CodeListSet<>(AxisDirection.class);
+ * Collections.addAll(codes, AxisDirection.EAST, AxisDirection.NORTH,
AxisDirection.UP),
+ * }
*
* @param <E> The type of code list elements in the set.
*
@@ -38,7 +55,10 @@ import org.apache.sis.util.resources.Err
* @since 0.3
* @version 0.3
* @module
+ *
+ * @see java.util.EnumSet
*/
+@NotThreadSafe
public class CodeListSet<E extends CodeList<E>> extends AbstractSet<E>
implements CheckedContainer<E>, Cloneable, Serializable
{
@@ -48,6 +68,12 @@ public class CodeListSet<E extends CodeL
private static final long serialVersionUID = 3648460713432430695L;
/**
+ * A pool of code list arrays. When many {@code CodeListSet} instances are
for the
+ * same code list type, this allows those instances to share the same
arrays.
+ */
+ private static final WeakHashSet<CodeList[]> POOL = new
WeakHashSet<>(CodeList[].class);
+
+ /**
* The type of code list elements.
*
* @see #getElementType()
@@ -95,6 +121,35 @@ public class CodeListSet<E extends CodeL
}
/**
+ * Creates set for code lists of the given type. If the {@code fill}
argument is {@code false},
+ * then the new set will be initially empty. Otherwise the new set will be
filled with all code
+ * list elements of the given type that are known at construction time.
Note that if new code
+ * list elements are created after the invocation of this {@code
CodeListSet} constructor, then
+ * those new elements will <em>not</em> be in this set.
+ *
+ * @param elementType The type of code list elements to be included in
this set.
+ * @param fill {@code true} for filling the set with all known elements
if the given type,
+ * or {@code false} for leaving the set empty.
+ * @throws IllegalArgumentException If the given class is not final.
+ */
+ public CodeListSet(final Class<E> elementType, final boolean fill) throws
IllegalArgumentException {
+ this(elementType);
+ if (fill) {
+ codes = POOL.unique(Types.getCodeValues(elementType));
+ int n = codes.length;
+ if (n < Long.SIZE) {
+ values = (1L << n) - 1;
+ } else {
+ values = -1;
+ if ((n -= Long.SIZE) != 0) {
+ supplementary = new BitSet(n);
+ supplementary.set(0, n);
+ }
+ }
+ }
+ }
+
+ /**
* Returns the type of code list elements in this set.
*
* @return The type of code list elements in this set.
@@ -111,7 +166,7 @@ public class CodeListSet<E extends CodeL
final E valueOf(final int ordinal) {
E[] array = codes;
if (array == null || ordinal >= array.length) {
- codes = array = Types.getCodeValues(elementType);
+ codes = array = POOL.unique(Types.getCodeValues(elementType));
}
return array[ordinal];
}
Modified:
sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/collection/CodeListSetTest.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/collection/CodeListSetTest.java?rev=1450374&r1=1450373&r2=1450374&view=diff
==============================================================================
---
sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/collection/CodeListSetTest.java
[UTF-8] (original)
+++
sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/collection/CodeListSetTest.java
[UTF-8] Tue Feb 26 19:50:05 2013
@@ -212,6 +212,23 @@ public final strictfp class CodeListSetT
}
/**
+ * Tests the creation of a set filled with with all known values.
+ */
+ @Test
+ @DependsOnMethod("testContains")
+ public void testFill() {
+ final CodeListSet<AxisDirection> c = new
CodeListSet<>(AxisDirection.class, true);
+ assertTrue("Expect at least 32 elements as of GeoAPI 3.0.0.", c.size()
>= 32);
+ assertTrue(c.toString().startsWith("[AxisDirection[OTHER],
AxisDirection[NORTH], "));
+ /*
+ * Testing the full array would be too long and may change in future
GeoAPI version
+ * anyway. Actually the main interest of this test is to ensure that
the toString()
+ * method doesn't throw an IndexOutOfBoundsException (as it would be
the case if
+ * the constructor had set too many bits).
+ */
+ }
+
+ /**
* Tests the various methods with a code list containing more than 64
elements.
*/
@Test
@@ -233,6 +250,7 @@ public final strictfp class CodeListSetT
final CodeListSet<LargeCodeList> clone = c.clone();
assertNotSame("Clone shall be a new instance.", c, clone);
assertEquals("Clone shall be equal to the original.", master, clone);
+ assertEquals(clone, new CodeListSet<>(LargeCodeList.class, true));
/*
* Tests contains(Object) and remove(Object). We also remove elements
* from the master set, then we verify that the result is the same.