java_gen: implement HashValue protocol
diff --git a/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/U64Test.java b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/U64Test.java
index e45e8a0..a979fab 100644
--- a/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/U64Test.java
+++ b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/U64Test.java
@@ -1,6 +1,11 @@
 package org.projectfloodlight.openflow.types;
 
+import static org.hamcrest.CoreMatchers.equalTo;
 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 java.math.BigInteger;
 
@@ -18,9 +23,59 @@
 
     @Test
     public void testNegativeRaws() {
-        long minus_1 = 0xFFffFFffFFffFFffL;
+        long minus_1 = 0xFFFF_FFFF_FFFF_FFFFL;
         assertEquals(minus_1, U64.ofRaw(minus_1).getValue());
-        assertEquals(new BigInteger("FFffFFffFFffFFff", 16),  U64.ofRaw(minus_1).getBigInteger());
+        assertEquals(new BigInteger("FFFF_FFFF_FFFF_FFFF".replace("_", ""), 16),  U64.ofRaw(minus_1).getBigInteger());
         assertEquals(new BigInteger("18446744073709551615"),  U64.ofRaw(minus_1).getBigInteger());
     }
+
+    @Test
+    public void testEqualHashCode() {
+        U64 h1 = U64.of(0xdeafbeefdeadbeefL);
+        U64 h2 = U64.of(0xdeafbeefdeadbeefL);
+        U64 h3 = U64.of(0xeeafbeefdeadbeefL);
+
+        assertTrue(h1.equals(h1));
+        assertTrue(h1.equals(h2));
+        assertFalse(h1.equals(h3));
+        assertTrue(h2.equals(h1));
+
+        assertEquals(h1.hashCode(), h2.hashCode());
+        assertNotEquals(h1.hashCode(), h3.hashCode()); // not technically a requirement, but we'll hopefully be lucky.
+    }
+
+    @Test
+    public void testXor() {
+        U64 hNull = U64.of(0);
+        U64 hDeadBeef = U64.of(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));
+
+
+        U64 h1 = U64.of(1L);
+        U64 h8 = U64.of(0x8000000000000000L);
+        U64 h81 = U64.of(0x8000000000000001L);
+        assertThat(h1.xor(h8), equalTo(h81));
+    }
+
+    @Test
+    public void testCombine() {
+        long key = 0x1234567890abcdefL;
+        long val = 0xdeafbeefdeadbeefL;
+        U64 hkey = U64.of(key);
+        U64 hVal = U64.of(val);
+
+        assertThat(hkey.combineWithValue(hVal, 0), equalTo(hkey.xor(hVal)));
+        assertThat(hkey.combineWithValue(hVal, 64), equalTo(hkey));
+        long mask32 = 0x00000000FFFFFFFFL;
+        assertThat(hkey.combineWithValue(hVal, 32),
+                equalTo(U64.of(key & ~mask32| (key ^ val) & mask32)));
+
+        long tenMask = 0x003FFFFFFFFFFFFFL;
+        assertThat(hkey.combineWithValue(hVal, 10),
+                equalTo(U64.of(key & ~tenMask | (key ^ val) & tenMask)));
+    }
+
 }