java_gen: renamed OFChecksum128 to U128 + implement HashValue

This has the same semantics as our other Uxx types.
diff --git a/java_gen/java_type.py b/java_gen/java_type.py
index 452ac58..471f1a8 100644
--- a/java_gen/java_type.py
+++ b/java_gen/java_type.py
@@ -311,6 +311,10 @@
 u64 = JType('U64', 'long') \
         .op(read='U64.ofRaw(bb.readLong())', write='bb.writeLong($name.getValue())', default="U64.ZERO", pub_type=True) \
         .op(read='bb.readLong()', write='bb.writeLong($name)', pub_type=False)
+u128 = JType("U128") \
+        .op(read='U128.read16Bytes(bb)',
+            write='$name.write16Bytes(bb)',
+            default='U128.ZERO')
 of_port = JType("OFPort") \
          .op(version=1, read="OFPort.read2Bytes(bb)", write="$name.write2Bytes(bb)", default="OFPort.ANY") \
          .op(version=ANY, read="OFPort.read4Bytes(bb)", write="$name.write4Bytes(bb)", default="OFPort.ANY")
@@ -491,10 +495,6 @@
          .op(version=ANY, read="ClassId.read4Bytes(bb)", write="$name.write4Bytes(bb)", default="ClassId.NONE")
 boolean_value = JType('OFBooleanValue', 'OFBooleanValue') \
         .op(read='OFBooleanValue.of(bb.readByte() != 0)', write='bb.writeByte($name.getInt())', default="OFBooleanValue.FALSE")
-checksum = JType("OFChecksum128") \
-        .op(read='OFChecksum128.read16Bytes(bb)',
-            write='$name.write16Bytes(bb)',
-            default='OFChecksum128.ZERO')
 gen_table_id = JType("GenTableId") \
         .op(read='GenTableId.read2Bytes(bb)',
             write='$name.write2Bytes(bb)',
@@ -536,7 +536,7 @@
         'of_oxm_t': oxm,
         'of_meter_features_t': meter_features,
         'of_bitmap_128_t': port_bitmap,
-        'of_checksum_128_t': checksum,
+        'of_checksum_128_t': u128,
         'of_bsn_vport_t': bsn_vport,
         }
 
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFChecksum128.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFChecksum128.java
deleted file mode 100644
index 7578dc6..0000000
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFChecksum128.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package org.projectfloodlight.openflow.types;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-
-import com.google.common.hash.PrimitiveSink;
-
-public class OFChecksum128 implements OFValueType<OFChecksum128> {
-
-    static final int LENGTH = 16;
-
-    private final long raw1; // MSBs
-    private final long raw2; // LSBs
-
-    public static final OFChecksum128 ZERO = new OFChecksum128(0, 0);
-
-    private OFChecksum128(long raw1, long raw2) {
-        this.raw1 = raw1;
-        this.raw2 = raw2;
-    }
-
-    public static OFChecksum128 of(long raw1, long raw2) {
-        if (raw1 == 0 && raw2 == 0)
-            return ZERO;
-        return new OFChecksum128(raw1, raw2);
-    }
-
-    @Override
-    public int getLength() {
-        return LENGTH;
-    }
-
-    @Override
-    public OFChecksum128 applyMask(OFChecksum128 mask) {
-        return of(this.raw1 & mask.raw1, this.raw2 & mask.raw2);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (!(obj instanceof OFChecksum128))
-            return false;
-        OFChecksum128 other = (OFChecksum128)obj;
-        return (other.raw1 == this.raw1 && other.raw2 == this.raw2);
-    }
-
-    @Override
-    public int hashCode() {
-        return (int)(31 * raw1 + raw2);
-    }
-
-    public void write16Bytes(ChannelBuffer cb) {
-        cb.writeLong(raw1);
-        cb.writeLong(raw2);
-    }
-
-    public static OFChecksum128 read16Bytes(ChannelBuffer cb) {
-        long raw1 = cb.readLong();
-        long raw2 = cb.readLong();
-        return of(raw1, raw2);
-    }
-
-    @Override
-    public String toString() {
-        return String.format("0x%016x%016x", raw1, raw2);
-    }
-
-    @Override
-    public int compareTo(OFChecksum128 o) {
-        long c = this.raw1 - o.raw1;
-        if (c != 0)
-            return Long.signum(c);
-        return Long.signum(this.raw2 - o.raw2);
-    }
-
-    @Override
-    public void putTo(PrimitiveSink sink) {
-        sink.putLong(raw1);
-        sink.putLong(raw2);
-    }
-
-}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U128.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U128.java
new file mode 100644
index 0000000..747e566
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U128.java
@@ -0,0 +1,142 @@
+package org.projectfloodlight.openflow.types;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+import com.google.common.base.Preconditions;
+import com.google.common.hash.PrimitiveSink;
+
+public class U128 implements OFValueType<U128>, HashValue<U128> {
+
+    static final int LENGTH = 16;
+
+    private final long raw1; // MSBs
+    private final long raw2; // LSBs
+
+    public static final U128 ZERO = new U128(0, 0);
+
+    private U128(long raw1, long raw2) {
+        this.raw1 = raw1;
+        this.raw2 = raw2;
+    }
+
+    public static U128 of(long raw1, long raw2) {
+        if (raw1 == 0 && raw2 == 0)
+            return ZERO;
+        return new U128(raw1, raw2);
+    }
+
+    @Override
+    public int getLength() {
+        return LENGTH;
+    }
+
+
+    public long getMsb() {
+        return raw1;
+    }
+
+    public long getLsb() {
+        return raw2;
+    }
+
+    @Override
+    public U128 applyMask(U128 mask) {
+        return and(mask);
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + (int) (raw1 ^ (raw1 >>> 32));
+        result = prime * result + (int) (raw2 ^ (raw2 >>> 32));
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        U128 other = (U128) obj;
+        if (raw1 != other.raw1)
+            return false;
+        if (raw2 != other.raw2)
+            return false;
+        return true;
+    }
+
+    public void write16Bytes(ChannelBuffer cb) {
+        cb.writeLong(raw1);
+        cb.writeLong(raw2);
+    }
+
+    public static U128 read16Bytes(ChannelBuffer cb) {
+        long raw1 = cb.readLong();
+        long raw2 = cb.readLong();
+        return of(raw1, raw2);
+    }
+
+    @Override
+    public String toString() {
+        return String.format("0x%016x%016x", raw1, raw2);
+    }
+
+    @Override
+    public int compareTo(U128 o) {
+        long c = this.raw1 - o.raw1;
+        if (c != 0)
+            return Long.signum(c);
+        return Long.signum(this.raw2 - o.raw2);
+    }
+
+    @Override
+    public void putTo(PrimitiveSink sink) {
+        sink.putLong(raw1);
+        sink.putLong(raw2);
+    }
+
+    @Override
+    public U128 inverse() {
+        return U128.of(~raw1, ~raw2);
+    }
+
+    @Override
+    public U128 or(U128 other) {
+        return U128.of(raw1 | other.raw1, raw2 | other.raw2);
+    }
+
+    @Override
+    public U128 and(U128 other) {
+        return U128.of(raw1 & other.raw1, raw2 & other.raw2);
+    }
+
+    @Override
+    public U128 xor(U128 other) {
+        return U128.of(raw1 ^ other.raw1, raw2 ^ other.raw2);
+    }
+
+    @Override
+    public int prefixBits(int numBits) {
+        Preconditions.checkArgument(numBits <= 31, "numBits must be <= 31");
+
+        Preconditions.checkArgument(numBits >= 0 && numBits < 32,
+                "numBits must be in range [0, 32[");
+
+        final int mask = (1 << numBits) -1;
+        final int shiftDown = 64 - numBits;
+
+        return (int) ((raw1 >>> shiftDown) & mask);
+    }
+
+    @Override
+    public U128 combineWithValue(U128 value, int keyBits) {
+        return U128.of(
+                HashValueUtils.combineWithValue(this.raw1, value.raw1, Math.min(64, keyBits)),
+                HashValueUtils.combineWithValue(this.raw2, value.raw2, Math.max(0,keyBits-64))
+        );
+    }
+}
diff --git a/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/U128Test.java b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/U128Test.java
new file mode 100644
index 0000000..2313d7c
--- /dev/null
+++ b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/U128Test.java
@@ -0,0 +1,105 @@
+package org.projectfloodlight.openflow.types;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import com.google.common.hash.HashCode;
+import com.google.common.hash.Hasher;
+import com.google.common.hash.Hashing;
+
+public class U128Test {
+    @Test
+    public void testPositiveRaws() {
+        assertThat(U128.of(0, 0).getMsb(), equalTo(0L));
+        assertThat(U128.of(0, 0).getLsb(), equalTo(0L));
+
+        assertThat(U128.of(1, 2).getMsb(), equalTo(1L));
+        assertThat(U128.of(1, 2).getLsb(), equalTo(2L));
+    }
+
+    @Test
+    public void testPutTo() {
+        U128 h         = U128.of(0x1234_5678_90ab_cdefL,0xdeafbeefdeadbeefL);
+        U128 hSame     = U128.of(0x1234_5678_90ab_cdefL,0xdeafbeefdeadbeefL);
+
+        U128 hBothDiff = U128.of(0x1234_5678_90ab_cdefL,0x1234_5678_90ab_cdefL);
+        U128 hMsbDiff  = U128.of(0x0234_5678_90ab_cdefL,0xdeafbeefdeadbeefL);
+        U128 hLsbDiff  = U128.of(0x1234_5678_90ab_cdefL,0xdeafbeefdeadbeeeL);
+
+        assertThat(hash(h), equalTo(hash(hSame)));
+        assertThat(hash(h), not(hash(hBothDiff)));
+        assertThat(hash(h), not(hash(hMsbDiff)));
+        assertThat(hash(h), not(hash(hLsbDiff)));
+    }
+
+    private HashCode hash(U128 f) {
+        Hasher hash = Hashing.murmur3_128().newHasher();
+        f.putTo(hash);
+        return hash.hash();
+
+    }
+
+    @Test
+    public void testEqualHashCode() {
+        U128 h1 = U128.of(0xdeafbeefdeadbeefL, 0xdeafbeefdeadbeefL);
+        U128 h2 = U128.of(0xdeafbeefdeadbeefL, 0xdeafbeefdeadbeefL);
+        U128 h3 = U128.of(0xeeafbeefdeadbeefL, 0xdeafbeefdeadbeefL);
+        U128 h3_2 = U128.of(0xdeafbeefdeadbeefL, 0xeeafbeefdeadbeefL);
+
+        assertTrue(h1.equals(h1));
+        assertTrue(h1.equals(h2));
+        assertFalse(h1.equals(h3));
+        assertFalse(h1.equals(h3_2));
+        assertTrue(h2.equals(h1));
+
+        assertEquals(h1.hashCode(), h2.hashCode());
+        assertNotEquals(h1.hashCode(), h3.hashCode()); // not technically a requirement, but we'll hopefully be lucky.
+        assertNotEquals(h1.hashCode(), h3_2.hashCode()); // not technically a requirement, but we'll hopefully be lucky.
+    }
+
+    @Test
+    public void testXor() {
+        U128 hNull = U128.of(0, 0);
+        U128 hDeadBeef = U128.of(0xdeafbeefdeadbeefL, 0xdeafbeefdeadbeefL);
+        assertThat(hNull.xor(hNull), equalTo(hNull));
+        assertThat(hNull.xor(hDeadBeef), equalTo(hDeadBeef));
+        assertThat(hDeadBeef.xor(hNull), equalTo(hDeadBeef));
+        assertThat(hDeadBeef.xor(hDeadBeef), equalTo(hNull));
+
+
+        U128 h1_0 = U128.of(1L, 0);
+        U128 h8_0 = U128.of(0x8000000000000000L, 0);
+        U128 h81_0 = U128.of(0x8000000000000001L, 0);
+        assertThat(h1_0.xor(h8_0), equalTo(h81_0));
+
+        U128 h0_1 = U128.of(0, 1L);
+        U128 h0_8 = U128.of(0, 0x8000000000000000L);
+        U128 h0_81 = U128.of(0, 0x8000000000000001L);
+        assertThat(h0_1.xor(h0_8), equalTo(h0_81));
+    }
+
+    @Test
+    public void testCombine() {
+        long key = 0x1234567890abcdefL;
+        long val = 0xdeafbeefdeadbeefL;
+        U128 hkey = U128.of(key, key*2);
+        U128 hVal = U128.of(val, val/2);
+
+        assertThat(hkey.combineWithValue(hVal, 0), equalTo(hkey.xor(hVal)));
+        assertThat(hkey.combineWithValue(hVal, 64), equalTo(U128.of(hkey.getMsb(), hkey.getLsb() ^ hVal.getLsb())));
+        assertThat(hkey.combineWithValue(hVal, 128), equalTo(hkey));
+
+        long mask8 = 0xFF00_0000_0000_0000L;
+
+        assertThat(hkey.combineWithValue(hVal, 8), equalTo(U128.of(hkey.getMsb() & mask8 |  hkey.getMsb() ^ hVal.getMsb() & ~mask8,
+                                                                   hkey.getLsb() ^ hVal.getLsb() )));
+    }
+
+}
diff --git a/test_data/of13/bsn_gentable_bucket_stats_reply.data b/test_data/of13/bsn_gentable_bucket_stats_reply.data
index 8e0772f..84a36a6 100644
--- a/test_data/of13/bsn_gentable_bucket_stats_reply.data
+++ b/test_data/of13/bsn_gentable_bucket_stats_reply.data
@@ -22,8 +22,8 @@
 builder.setXid(0x12345678)
     .setEntries(
         ImmutableList.<OFBsnGentableBucketStatsEntry>of(
-            factory.bsnGentableBucketStatsEntry(OFChecksum128.of(0x8877665544332211L, 0xFFEEDDCCBBAA9988L)),
-            factory.bsnGentableBucketStatsEntry(OFChecksum128.of(0x1234234534564567L, 0x56786789789A89ABL))
+            factory.bsnGentableBucketStatsEntry(U128.of(0x8877665544332211L, 0xFFEEDDCCBBAA9988L)),
+            factory.bsnGentableBucketStatsEntry(U128.of(0x1234234534564567L, 0x56786789789A89ABL))
         )
     )
 -- c
diff --git a/test_data/of13/bsn_gentable_clear_request.data b/test_data/of13/bsn_gentable_clear_request.data
index 847af3c..853d463 100644
--- a/test_data/of13/bsn_gentable_clear_request.data
+++ b/test_data/of13/bsn_gentable_clear_request.data
@@ -16,8 +16,8 @@
     checksum_mask=0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000)
 -- java
 builder.setXid(0x12345678)
-    .setChecksum(OFChecksum128.of(0xFEDCBA9876543210L, 0xFFEECCBBAA990000L))
-    .setChecksumMask(OFChecksum128.of(0xFFFFFFFFFFFFFFFFL, 0xFFFFFFFFFFFF0000L))
+    .setChecksum(U128.of(0xFEDCBA9876543210L, 0xFFEECCBBAA990000L))
+    .setChecksumMask(U128.of(0xFFFFFFFFFFFFFFFFL, 0xFFFFFFFFFFFF0000L))
     .setTableId(GenTableId.of(20))
 -- c
 obj = of_bsn_gentable_clear_request_new(OF_VERSION_1_3);
diff --git a/test_data/of13/bsn_gentable_entry_add.data b/test_data/of13/bsn_gentable_entry_add.data
index 02c2bb4..f813dcd 100644
--- a/test_data/of13/bsn_gentable_entry_add.data
+++ b/test_data/of13/bsn_gentable_entry_add.data
@@ -38,7 +38,7 @@
     ])
 -- java
 builder.setXid(0x12345678)
-    .setChecksum(OFChecksum128.of(0xFEDCBA9876543210L, 0xFFEECCBBAA998877L))
+    .setChecksum(U128.of(0xFEDCBA9876543210L, 0xFFEECCBBAA998877L))
     .setTableId(GenTableId.of(20))
     .setKey(
         ImmutableList.<OFBsnTlv>of(
diff --git a/test_data/of13/bsn_gentable_entry_desc_stats_reply.data b/test_data/of13/bsn_gentable_entry_desc_stats_reply.data
index 4035f4c..21291ed 100644
--- a/test_data/of13/bsn_gentable_entry_desc_stats_reply.data
+++ b/test_data/of13/bsn_gentable_entry_desc_stats_reply.data
@@ -55,7 +55,7 @@
     .setEntries(
         ImmutableList.<OFBsnGentableEntryDescStatsEntry>of(
             factory.buildBsnGentableEntryDescStatsEntry()
-                .setChecksum(OFChecksum128.of(0xFEDCBA9876543210L, 0xFFEECCBBAA998800L))
+                .setChecksum(U128.of(0xFEDCBA9876543210L, 0xFFEECCBBAA998800L))
                 .setKey(ImmutableList.<OFBsnTlv>of(
                     factory.bsnTlvs().port(OFPort.of(5))
                 ))
@@ -64,7 +64,7 @@
                 ))
                 .build(),
             factory.buildBsnGentableEntryDescStatsEntry()
-                .setChecksum(OFChecksum128.of(0xFEDCBA9876543210L, 0xFFEECCBBAA998801L))
+                .setChecksum(U128.of(0xFEDCBA9876543210L, 0xFFEECCBBAA998801L))
                 .setKey(ImmutableList.<OFBsnTlv>of(
                     factory.bsnTlvs().port(OFPort.of(6))
                 ))