+ public String stringify(Object value) {
+ if (value == null) {
+ return null;
+ }
+
+ switch (this) {
+ case DL_DST:
+ case DL_SRC:
+ return HexEncode.bytesToHexStringFormat((byte[]) value);
+ case DL_TYPE:
+ case DL_VLAN:
+ return ((Integer) NetUtils.getUnsignedShort((Short) value)).toString();
+ case NW_SRC:
+ case NW_DST:
+ return ((InetAddress) value).getHostAddress();
+ case NW_TOS:
+ return ((Integer) NetUtils.getUnsignedByte((Byte) value)).toString();
+ case TP_SRC:
+ case TP_DST:
+ return ((Integer) NetUtils.getUnsignedShort((Short) value)).toString();
+ default:
+ break;
+ }
+ return value.toString();
+ }
+
+ public int valueHashCode(Object o) {
+ if (o == null) {
+ return 0;
+ }
+ switch (this) {
+ case DL_SRC:
+ case DL_DST:
+ return NetUtils.byteArray4ToInt((byte[])o);
+ default:
+ return o.hashCode();
+ }
+ }
+
+ public int hashCode(Object v, Object m) {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + this.calculateConsistentHashCode();
+
+ switch (this) {
+ case DL_SRC:
+ case DL_DST:
+ result = prime * result + ((v == null)? 0 : NetUtils.byteArray4ToInt((byte[])v));
+ result = prime * result + ((m == null)? 0 : NetUtils.byteArray4ToInt((byte[])m));
+ break;
+ case NW_SRC:
+ case NW_DST:
+ // Hash code has to take into account only prefix address
+ InetAddress ip = (InetAddress) v;
+ int maskLen = (m == null) ? ((ip instanceof Inet4Address) ? 32 : 128) : NetUtils
+ .getSubnetMaskLength((InetAddress) m);
+ InetAddress prefix = NetUtils.getSubnetPrefix(ip, maskLen);
+ result = prime * result + ((v == null)? 0 : prefix.hashCode());
+ break;
+ default:
+ result = prime * result + ((v == null)? 0 : v.hashCode());
+ result = prime * result + ((m == null)? 0 : m.hashCode());
+ }
+ return result;
+ }
+ public boolean equalValues(Object a, Object b) {
+ if (a == b) {
+ return true;
+ }
+ if (a == null || b == null) {
+ return false;
+ }
+ switch (this) {
+ case DL_DST:
+ case DL_SRC:
+ return Arrays.equals((byte[]) a, (byte[]) b);
+ default:
+ return a.equals(b);
+ }
+ }
+
+ public boolean equalMasks(Object a, Object b) {
+ if (a == b) {
+ return true;
+ }
+ switch (this) {
+ case NW_SRC:
+ case NW_DST:
+ /*
+ * For network address mask, network node may return full mask for
+ * flows the controller generated with a null mask object
+ */
+ if (a == null || b == null) {
+ InetAddress mask = (a == null) ? (InetAddress) b : (InetAddress) a;
+ int maxLength = (mask instanceof Inet4Address) ? 32 : 128;
+ return (NetUtils.getSubnetMaskLength(mask) == maxLength);
+ }
+ default:
+ if (a == null) {
+ return false;
+ }
+ return a.equals(b);
+ }
+ }
+
+ public boolean equals(Object value1, Object value2, Object mask1, Object mask2) {
+ switch (this) {
+ case NW_SRC:
+ case NW_DST:
+ // Equality to be checked against prefix addresses
+ InetAddress thisIP = (InetAddress) value1;
+ int thisMaskLen = (mask1 == null) ? ((thisIP instanceof Inet4Address) ? 32 : 128) : NetUtils
+ .getSubnetMaskLength((InetAddress) mask1);
+ InetAddress otherIP = (InetAddress) value2;
+ int otherMaskLen = (mask2 == null) ? ((otherIP instanceof Inet4Address) ? 32 : 128) : NetUtils
+ .getSubnetMaskLength((InetAddress) mask2);
+
+ return NetUtils.getSubnetPrefix(thisIP, thisMaskLen)
+ .equals(NetUtils.getSubnetPrefix(otherIP, otherMaskLen));
+ default:
+ return (this.equalValues(value1, value2) && this.equalMasks(mask1, mask2));
+ }
+ }
+
+ public int calculateConsistentHashCode() {
+ if (this.id != null) {
+ return this.id.hashCode();
+ } else {
+ return 0;
+ }
+ }