Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame] | 1 | package net.floodlightcontroller.util; |
| 2 | |
| 3 | import java.util.EnumSet; |
| 4 | import java.util.Set; |
| 5 | |
| 6 | /** |
| 7 | * A utility class to convert between integer based bitmaps for (OpenFlow) |
| 8 | * flags and Enum and EnumSet based representations. |
| 9 | * |
| 10 | * The enum used to represent individual flags needs to implement the |
| 11 | * BitmapableEnum interface. |
| 12 | * |
| 13 | * Example: |
| 14 | * {@code |
| 15 | * int bitmap = 0x11; // OFPPC_PORT_DOWN | OFPPC_NO_STP |
| 16 | * EnumSet<OFPortConfig> s = toEnumSet(OFPortConfig.class, bitmap); |
| 17 | * // s will contain OFPPC_PORT_DOWN and OFPPC_NO_STP |
| 18 | * } |
| 19 | * |
| 20 | * {@code |
| 21 | * EnumSet<OFPortConfig> s = EnumSet.of(OFPPC_NO_STP, OFPPC_PORT_DOWN); |
| 22 | * int bitmap = toBitmap(s); // returns 0x11 |
| 23 | * } |
| 24 | * @author gregor |
| 25 | * |
| 26 | */ |
| 27 | public class EnumBitmaps { |
| 28 | /** |
| 29 | * Enums used to represent individual flags needs to implement this |
| 30 | * interface |
| 31 | */ |
| 32 | public interface BitmapableEnum { |
| 33 | /** Return the value in the bitmap that the enum constant represents. |
| 34 | * The returned value must have only a single bit set. E.g.,1<<3 |
| 35 | */ |
| 36 | int getValue(); |
| 37 | } |
| 38 | |
| 39 | /** |
| 40 | * Convert an integer bitmap to an EnumSet. |
| 41 | * |
| 42 | * See class description for example |
| 43 | * @param type The Enum class to use. Must implement BitmapableEnum |
| 44 | * @param bitmap The integer bitmap |
| 45 | * @return A newly allocated EnumSet representing the bits set in the |
| 46 | * bitmap |
| 47 | * @throws NullPointerException if type is null |
| 48 | * @throws IllegalArgumentException if any enum constant from type has |
| 49 | * more than one bit set. |
| 50 | * @throws IllegalArgumentException if the bitmap has any bits set not |
| 51 | * represented by an enum constant. |
| 52 | */ |
| 53 | public static <E extends Enum<E> & BitmapableEnum> |
| 54 | EnumSet<E> toEnumSet(Class<E> type, int bitmap) { |
| 55 | if (type == null) |
| 56 | throw new NullPointerException("Given enum type must not be null"); |
| 57 | EnumSet<E> s = EnumSet.noneOf(type); |
| 58 | // allSetBitmap will eventually have all valid bits for the given |
| 59 | // type set. |
| 60 | int allSetBitmap = 0; |
| 61 | for (E element: type.getEnumConstants()) { |
| 62 | if (Integer.bitCount(element.getValue()) != 1) { |
| 63 | String msg = String.format("The %s (%x) constant of the " + |
| 64 | "enum %s is supposed to represent a bitmap entry but " + |
| 65 | "has more than one bit set.", |
| 66 | element.toString(), element.getValue(), type.getName()); |
| 67 | throw new IllegalArgumentException(msg); |
| 68 | } |
| 69 | allSetBitmap |= element.getValue(); |
| 70 | if ((bitmap & element.getValue()) != 0) |
| 71 | s.add(element); |
| 72 | } |
| 73 | if (((~allSetBitmap) & bitmap) != 0) { |
| 74 | // check if only valid flags are set in the given bitmap |
| 75 | String msg = String.format("The bitmap %x for enum %s has " + |
| 76 | "bits set that are presented by any enum constant", |
| 77 | bitmap, type.getName()); |
| 78 | throw new IllegalArgumentException(msg); |
| 79 | } |
| 80 | return s; |
| 81 | } |
| 82 | |
| 83 | /** |
| 84 | * Return the bitmap mask with all possible bits set. E.g., If a bitmap |
| 85 | * has the individual flags 0x1, 0x2, and 0x8 (note the missing 0x4) then |
| 86 | * the mask will be 0xb (1011 binary) |
| 87 | * |
| 88 | * @param type The Enum class to use. Must implement BitmapableEnum |
| 89 | * @throws NullPointerException if type is null |
| 90 | * @throws IllegalArgumentException if any enum constant from type has |
| 91 | * more than one bit set |
| 92 | * @return an integer with all possible bits for the given bitmap enum |
| 93 | * type set. |
| 94 | */ |
| 95 | public static <E extends Enum<E> & BitmapableEnum> |
| 96 | int getMask(Class<E> type) { |
| 97 | if (type == null) |
| 98 | throw new NullPointerException("Given enum type must not be null"); |
| 99 | // allSetBitmap will eventually have all valid bits for the given |
| 100 | // type set. |
| 101 | int allSetBitmap = 0; |
| 102 | for (E element: type.getEnumConstants()) { |
| 103 | if (Integer.bitCount(element.getValue()) != 1) { |
| 104 | String msg = String.format("The %s (%x) constant of the " + |
| 105 | "enum %s is supposed to represent a bitmap entry but " + |
| 106 | "has more than one bit set.", |
| 107 | element.toString(), element.getValue(), type.getName()); |
| 108 | throw new IllegalArgumentException(msg); |
| 109 | } |
| 110 | allSetBitmap |= element.getValue(); |
| 111 | } |
| 112 | return allSetBitmap; |
| 113 | } |
| 114 | |
| 115 | /** |
| 116 | * Convert the given EnumSet to the integer bitmap representation |
| 117 | * @param set The EnumSet to convert. The enum must implement |
| 118 | * BitmapableEnum |
| 119 | * @return the integer bitmap |
| 120 | * @throws IllegalArgumentException if an enum constant from the set (!) has |
| 121 | * more than one bit set |
| 122 | * @throws NullPointerException if the set is null |
| 123 | */ |
| 124 | public static <E extends Enum<E> & BitmapableEnum> |
| 125 | int toBitmap(Set<E> set) { |
| 126 | if (set == null) |
| 127 | throw new NullPointerException("Given set must not be null"); |
| 128 | int bitmap = 0; |
| 129 | for (E element: set) { |
| 130 | if (Integer.bitCount(element.getValue()) != 1) { |
| 131 | String msg = String.format("The %s (%x) constant in the set " + |
| 132 | "is supposed to represent a bitmap entry but " + |
| 133 | "has more than one bit set.", |
| 134 | element.toString(), element.getValue()); |
| 135 | throw new IllegalArgumentException(msg); |
| 136 | } |
| 137 | bitmap |= element.getValue(); |
| 138 | } |
| 139 | return bitmap; |
| 140 | } |
| 141 | } |