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