Author: mbenson
Date: Thu Jul 21 19:11:47 2011
New Revision: 1149320

URL: http://svn.apache.org/viewvc?rev=1149320&view=rev
Log:
require values parameter when generating bit vectors from enums, throwing 
NullPointerException if omitted; merge check for type eligibility; add E... 
generateBitVector() variant; alter generateBitVector(Class<E>, EnumSet<E>) to 
(Class<E>, Iterable<E>) by using |= << instead of + to accumulate values; 
process only specified values

Modified:
    
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/EnumUtils.java
    
commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/EnumUtilsTest.java

Modified: 
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/EnumUtils.java
URL: 
http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/EnumUtils.java?rev=1149320&r1=1149319&r2=1149320&view=diff
==============================================================================
--- 
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/EnumUtils.java 
(original)
+++ 
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/EnumUtils.java 
Thu Jul 21 19:11:47 2011
@@ -123,58 +123,86 @@ public class EnumUtils {
      * <p>Do not use this method if you have more than 64 values in your Enum, 
as this
      * would create a value greater than a long can hold.</p>
      *
-     * @param enumClass the class of the enum we are working with, not null
-     * @param set       the set of enum values we want to convert
+     * @param enumClass the class of the enum we are working with, not {@code 
null}
+     * @param values    the values we want to convert, not {@code null}
      * @param <E>       the type of the enumeration
      * @return a long whose binary value represents the given set of enum 
values.
+     * @throws NullPointerException if {@code enumClass} or {@code values} is 
{@code null}
+     * @throws IllegalArgumentException if {@code enumClass} is not an enum 
class or has more than 64 values
+     * @since 3.0.1
      */
-    public static <E extends Enum<E>> long generateBitVector(Class<E> 
enumClass, EnumSet<E> set) {
-        if (enumClass == null) {
-            throw new IllegalArgumentException("EnumClass must be defined.");
-        }
-        final E[] constants = enumClass.getEnumConstants();
-        if (constants != null && constants.length > 64) {
-            throw new IllegalArgumentException("EnumClass is too big to be 
stored in a 64-bit value.");
-        }
+    public static <E extends Enum<E>> long generateBitVector(Class<E> 
enumClass, Iterable<E> values) {
+        checkBitVectorable(enumClass);
+        Validate.notNull(values);
         long total = 0;
-        if (set != null) {
-            if (constants != null && constants.length > 0) {
-                for (E constant : constants) {
-                    if (set.contains(constant)) {
-                        total += Math.pow(2, constant.ordinal());
-                    }
-                }
-            }
+        for (E constant : values) {
+            total |= (1 << constant.ordinal());
         }
         return total;
     }
 
     /**
+     * <p>Creates a long bit vector representation of the given array of Enum 
values.</p>
+     *
+     * <p>This generates a value that is usable by {@link 
EnumUtils#processBitVector}.</p>
+     *
+     * <p>Do not use this method if you have more than 64 values in your Enum, 
as this
+     * would create a value greater than a long can hold.</p>
+     *
+     * @param enumClass the class of the enum we are working with, not {@code 
null}
+     * @param values    the values we want to convert, not {@code null}
+     * @param <E>       the type of the enumeration
+     * @return a long whose binary value represents the given set of enum 
values.
+     * @throws NullPointerException if {@code enumClass} or {@code values} is 
{@code null}
+     * @throws IllegalArgumentException if {@code enumClass} is not an enum 
class or has more than 64 values
+     * @since 3.0.1
+     */
+    public static <E extends Enum<E>> long generateBitVector(Class<E> 
enumClass, E... values) {
+        Validate.noNullElements(values);
+        return generateBitVector(enumClass, Arrays.<E> asList(values));
+    }
+
+    /**
      * <p>Convert a long value created by {@link EnumUtils#generateBitVector} 
into the set of
      * enum values that it represents.</p>
      *
      * <p>If you store this value, beware any changes to the enum that would 
affect ordinal values.</p>
-     * @param enumClass the class of the enum we are working with, not null
+     * @param enumClass the class of the enum we are working with, not {@code 
null}
      * @param value     the long value representation of a set of enum values
      * @param <E>       the type of the enumeration
      * @return a set of enum values
+     * @throws NullPointerException if {@code enumClass} is {@code null}
+     * @throws IllegalArgumentException if {@code enumClass} is not an enum 
class or has more than 64 values
+     * @since 3.0.1
      */
     public static <E extends Enum<E>> EnumSet<E> processBitVector(Class<E> 
enumClass, long value) {
-        if (enumClass == null) {
-            throw new IllegalArgumentException("EnumClass must be defined.");
-        }
-        final E[] constants = enumClass.getEnumConstants();
-        if (constants != null && constants.length > 64) {
-            throw new IllegalArgumentException("EnumClass is too big to be 
stored in a 64-bit value.");
-        }
-        final EnumSet results = EnumSet.noneOf(enumClass);
-        if (constants != null && constants.length > 0) {
-            for (E constant : constants) {
-                if ((value & (1 << constant.ordinal())) != 0) {
-                    results.add(constant);
-                }
+        final E[] constants = checkBitVectorable(enumClass).getEnumConstants();
+        final EnumSet<E> results = EnumSet.noneOf(enumClass);
+        for (E constant : constants) {
+            if ((value & (1 << constant.ordinal())) != 0) {
+                results.add(constant);
             }
         }
         return results;
     }
+
+    /**
+     * Validate that {@code enumClass} is compatible with representation in a 
{@code long}.
+     * @param <E> the type of the enumeration
+     * @param enumClass to check
+     * @return {@code enumClass}
+     * @throws NullPointerException if {@code enumClass} is {@code null}
+     * @throws IllegalArgumentException if {@code enumClass} is not an enum 
class or has more than 64 values
+     * @since 3.0.1
+     */
+    private static <E extends Enum<E>> Class<E> checkBitVectorable(Class<E> 
enumClass) {
+        Validate.notNull(enumClass, "EnumClass must be defined.");
+
+        final E[] constants = enumClass.getEnumConstants();
+        Validate.isTrue(constants != null, "%s does not seem to be an Enum 
type", enumClass);
+        Validate.isTrue(constants.length <= Long.SIZE, "Cannot store %s %s 
values in %s bits", constants.length,
+            enumClass.getSimpleName(), Long.SIZE);
+
+        return enumClass;
+    }
 }

Modified: 
commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/EnumUtilsTest.java
URL: 
http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/EnumUtilsTest.java?rev=1149320&r1=1149319&r2=1149320&view=diff
==============================================================================
--- 
commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/EnumUtilsTest.java
 (original)
+++ 
commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/EnumUtilsTest.java
 Thu Jul 21 19:11:47 2011
@@ -20,6 +20,7 @@ package org.apache.commons.lang3;
 
 import static org.junit.Assert.*;
 
+import java.util.ArrayList;
 import java.util.EnumSet;
 import java.util.List;
 import java.util.Map;
@@ -89,19 +90,56 @@ public class EnumUtilsTest {
         EnumUtils.getEnum((Class<Traffic>) null, "PURPLE");
     }
 
-    @Test(expected=IllegalArgumentException.class)
+    @Test(expected=NullPointerException.class)
     public void test_generateBitVector_nullClass() {
         EnumUtils.generateBitVector(null, EnumSet.of(Traffic.RED));
     }
 
+    @Test(expected=NullPointerException.class)
+    public void test_generateBitVector_nullIterable() {
+        EnumUtils.generateBitVector(null, (Iterable<Traffic>) null);
+    }
+
+    @Test(expected=NullPointerException.class)
+    public void test_generateBitVector_nullClassWithArray() {
+        EnumUtils.generateBitVector(null, Traffic.RED);
+    }
+    
+    @Test(expected=NullPointerException.class)
+    public void test_generateBitVector_nullArray() {
+        EnumUtils.generateBitVector(null, (Traffic[]) null);
+    }
+
     @Test(expected=IllegalArgumentException.class)
     public void test_generateBitVector_longClass() {
         EnumUtils.generateBitVector(TooMany.class, EnumSet.of(TooMany.A1));
     }
 
+    @Test(expected=IllegalArgumentException.class)
+    public void test_generateBitVector_longClassWithArray() {
+        EnumUtils.generateBitVector(TooMany.class, TooMany.A1);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test(expected=IllegalArgumentException.class)
+    public void test_generateBitVector_nonEnumClass() {
+        @SuppressWarnings("rawtypes")
+        Class rawType = Object.class;
+        @SuppressWarnings("rawtypes")
+        List rawList = new ArrayList();
+        EnumUtils.generateBitVector(rawType, rawList);
+    }
+    
+    @SuppressWarnings("unchecked")
+    @Test(expected=IllegalArgumentException.class)
+    public void test_generateBitVector_nonEnumClassWithArray() {
+        @SuppressWarnings("rawtypes")
+        Class rawType = Object.class;
+        EnumUtils.generateBitVector(rawType);
+    }
+    
     @Test
     public void test_generateBitVector() {
-        assertEquals(0L, EnumUtils.generateBitVector(Traffic.class, null));
         assertEquals(0L, EnumUtils.generateBitVector(Traffic.class, 
EnumSet.noneOf(Traffic.class)));
         assertEquals(1L, EnumUtils.generateBitVector(Traffic.class, 
EnumSet.of(Traffic.RED)));
         assertEquals(2L, EnumUtils.generateBitVector(Traffic.class, 
EnumSet.of(Traffic.AMBER)));
@@ -112,7 +150,21 @@ public class EnumUtilsTest {
         assertEquals(7L, EnumUtils.generateBitVector(Traffic.class, 
EnumSet.of(Traffic.RED, Traffic.AMBER, Traffic.GREEN)));
     }
 
-    @Test(expected=IllegalArgumentException.class)
+    @Test
+    public void test_generateBitVectorFromArray() {
+        assertEquals(0L, EnumUtils.generateBitVector(Traffic.class));
+        assertEquals(1L, EnumUtils.generateBitVector(Traffic.class, 
Traffic.RED));
+        assertEquals(2L, EnumUtils.generateBitVector(Traffic.class, 
Traffic.AMBER));
+        assertEquals(4L, EnumUtils.generateBitVector(Traffic.class, 
Traffic.GREEN));
+        assertEquals(3L, EnumUtils.generateBitVector(Traffic.class, 
Traffic.RED, Traffic.AMBER));
+        assertEquals(5L, EnumUtils.generateBitVector(Traffic.class, 
Traffic.RED, Traffic.GREEN));
+        assertEquals(6L, EnumUtils.generateBitVector(Traffic.class, 
Traffic.AMBER, Traffic.GREEN));
+        assertEquals(7L, EnumUtils.generateBitVector(Traffic.class, 
Traffic.RED, Traffic.AMBER, Traffic.GREEN));
+        //gracefully handles duplicates:
+        assertEquals(7L, EnumUtils.generateBitVector(Traffic.class, 
Traffic.RED, Traffic.AMBER, Traffic.GREEN, Traffic.GREEN));
+    }
+    
+    @Test(expected=NullPointerException.class)
     public void test_processBitVector_nullClass() {
         final Class<Traffic> empty = null;
         EnumUtils.processBitVector(empty, 0L);


Reply via email to