Author: bayard Date: Thu Jul 21 08:00:28 2011 New Revision: 1149058 URL: http://svn.apache.org/viewvc?rev=1149058&view=rev Log: Adding Nelson Carpentier's patch adding an EnumSet to bit vector (and back again) to EnumUtils. LANG-730
Modified: commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/EnumUtils.java commons/proper/lang/trunk/src/site/changes/changes.xml 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=1149058&r1=1149057&r2=1149058&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 08:00:28 2011 @@ -21,6 +21,7 @@ import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.EnumSet; /** * <p>Utility library to provide helper methods for Java enums.</p> @@ -114,4 +115,66 @@ public class EnumUtils { } } + /** + * <p>Creates a long bit vector representation of the given subset of an Enum.</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 null + * @param set the set of enum values we want to convert + * @param <E> the type of the enumeration + * @return a long whose binary value represents the given set of enum values. + */ + 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."); + } + 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()); + } + } + } + } + return total; + } + + /** + * <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 value the long value representation of a set of enum values + * @param <E> the type of the enumeration + * @return a set of enum values + */ + 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); + } + } + } + return results; + } } Modified: commons/proper/lang/trunk/src/site/changes/changes.xml URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/site/changes/changes.xml?rev=1149058&r1=1149057&r2=1149058&view=diff ============================================================================== --- commons/proper/lang/trunk/src/site/changes/changes.xml (original) +++ commons/proper/lang/trunk/src/site/changes/changes.xml Thu Jul 21 08:00:28 2011 @@ -21,6 +21,10 @@ </properties> <body> + <release version="3.0.1" date="Unreleased" description="Next 3.x release"> + <action type="add" issue="LANG-730">EnumSet -> bit vector</action> + </release> + <release version="3.0" date="2011-07-18" description="Backwards incompatible update of Commons Lang to Java 5"> <action type="fix" issue="LANG-720">StringEscapeUtils.escapeXml(input) outputs wrong results when an input contains characters in Supplementary Planes.</action> <action type="update" issue="LANG-718">build.xml Java 1.5+ updates.</action> 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=1149058&r1=1149057&r2=1149058&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 08:00:28 2011 @@ -18,6 +18,7 @@ */ package org.apache.commons.lang3; +import java.util.EnumSet; import java.util.List; import java.util.Map; @@ -89,8 +90,69 @@ public class EnumUtilsTest extends TestC } } + public void test_generateBitVector_nullClass() { + try { + EnumUtils.generateBitVector(null, EnumSet.of(Traffic.RED)); + } catch (IllegalArgumentException ex) { + // ok + } + } + + public void test_generateBitVector_longClass() { + try { + EnumUtils.generateBitVector(TooMany.class, EnumSet.of(TooMany.A1)); + } catch (IllegalArgumentException ex) { + // ok + } + } + + 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))); + assertEquals(4L, EnumUtils.generateBitVector(Traffic.class, EnumSet.of(Traffic.GREEN))); + assertEquals(3L, EnumUtils.generateBitVector(Traffic.class, EnumSet.of(Traffic.RED, Traffic.AMBER))); + assertEquals(5L, EnumUtils.generateBitVector(Traffic.class, EnumSet.of(Traffic.RED, Traffic.GREEN))); + assertEquals(6L, EnumUtils.generateBitVector(Traffic.class, EnumSet.of(Traffic.AMBER, Traffic.GREEN))); + assertEquals(7L, EnumUtils.generateBitVector(Traffic.class, EnumSet.of(Traffic.RED, Traffic.AMBER, Traffic.GREEN))); + } + + public void test_processBitVector_nullClass() { + final Class<Traffic> empty = null; + try { + EnumUtils.processBitVector(empty, 0L); + } catch (IllegalArgumentException ex) { + // ok + } + } + + public void test_processBitVector_longClass() { + try { + EnumUtils.processBitVector(TooMany.class, 0L); + } catch (IllegalArgumentException ex) { + // ok + } + } + + public void test_processBitVector() { + assertEquals(EnumSet.noneOf(Traffic.class), EnumUtils.processBitVector(Traffic.class, 0L)); + assertEquals(EnumSet.of(Traffic.RED), EnumUtils.processBitVector(Traffic.class, 1L)); + assertEquals(EnumSet.of(Traffic.AMBER), EnumUtils.processBitVector(Traffic.class, 2L)); + assertEquals(EnumSet.of(Traffic.RED, Traffic.AMBER), EnumUtils.processBitVector(Traffic.class, 3L)); + assertEquals(EnumSet.of(Traffic.GREEN), EnumUtils.processBitVector(Traffic.class, 4L)); + assertEquals(EnumSet.of(Traffic.RED, Traffic.GREEN), EnumUtils.processBitVector(Traffic.class, 5L)); + assertEquals(EnumSet.of(Traffic.AMBER, Traffic.GREEN), EnumUtils.processBitVector(Traffic.class, 6L)); + assertEquals(EnumSet.of(Traffic.RED, Traffic.AMBER, Traffic.GREEN), EnumUtils.processBitVector(Traffic.class, 7L)); + } } enum Traffic { RED, AMBER, GREEN } + +enum TooMany{ + A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z, + A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1,L1,M1,N1,O1,P1,Q1,R1,S1,T1,U1,V1,W1,X1,Y1,Z1; + +}