Cleanup and rearrangements in Match structure and fields.
1. Added full documentation for the Match interface
2. Added Builder into Match interface and removed the separate class
3. Added ability to declare field prerequisites in the MatchField class and then check that they are
met using a given Match object
4. Fixed some small issues in value types and added a value type for Metadata
diff --git a/java_gen/pre-written/src/test/java/org/openflow/types/IPv4Test.java b/java_gen/pre-written/src/test/java/org/openflow/types/IPv4Test.java
index d344021..a5ac1be 100644
--- a/java_gen/pre-written/src/test/java/org/openflow/types/IPv4Test.java
+++ b/java_gen/pre-written/src/test/java/org/openflow/types/IPv4Test.java
@@ -108,29 +108,23 @@
         }
     }
     
-    @SuppressWarnings("unchecked")
     @Test
-    public void testOfPossiblyMasked() throws OFParseError, OFShortRead {
+    public void testOfMasked() throws OFParseError, OFShortRead {
         for (int i = 0; i < ipsWithMask.length; i++) {
-            OFValueType value = IPv4WithMask.ofPossiblyMasked(ipsWithMask[i]);
-            if (value instanceof IPv4 && !hasMask[i]) {
-                // Types OK, check values
-                IPv4 ip = (IPv4)value;
+            IPv4WithMask value = IPv4WithMask.of(ipsWithMask[i]);
+            if (!hasMask[i]) {
+                IPv4 ip = value.getValue();
                 assertArrayEquals(ipsWithMaskValues[i][0], ip.getBytes());
-            } else if (value instanceof Masked && hasMask[i]) {
-                Masked<IPv4> ip = null;
-                try {
-                    ip = (Masked<IPv4>)value;
-                } catch (ClassCastException e) {
-                    fail("Invalid Masked<T> type.");
+            } else if (hasMask[i]) {
+                byte[] ipBytes = new byte[4];
+                System.arraycopy(ipsWithMaskValues[i][0], 0, ipBytes, 0, 4);
+                assertEquals(ipBytes.length, value.getValue().getBytes().length);
+                for (int j = 0; j < ipBytes.length; j++) {
+                    ipBytes[j] &= ipsWithMaskValues[i][1][j];
                 }
-                // Types OK, check values
-                assertArrayEquals(ipsWithMaskValues[i][0], ip.getValue().getBytes());
-                assertArrayEquals(ipsWithMaskValues[i][1], ip.getMask().getBytes());
-            } else if (value instanceof IPv4) {
-                fail("Expected masked IPv4, got unmasked IPv4.");
-            } else {
-                fail("Expected unmasked IPv4, got masked IPv4.");
+                
+                assertArrayEquals(ipBytes, value.getValue().getBytes());
+                assertArrayEquals(ipsWithMaskValues[i][1], value.getMask().getBytes());
             }
         }
     }
diff --git a/java_gen/pre-written/src/test/java/org/openflow/types/IPv6Test.java b/java_gen/pre-written/src/test/java/org/openflow/types/IPv6Test.java
index f2f6fe8..71ab28e 100644
--- a/java_gen/pre-written/src/test/java/org/openflow/types/IPv6Test.java
+++ b/java_gen/pre-written/src/test/java/org/openflow/types/IPv6Test.java
@@ -58,31 +58,25 @@
     @Test
     public void testMasked() throws UnknownHostException {
         for(int i=0; i < ipsWithMask.length; i++ ) {
-            OFValueType value = IPv6WithMask.ofPossiblyMasked(ipsWithMask[i]);
-            if (value instanceof IPv6 && !hasMask[i]) {
-                // Types OK, check values
-                IPv6 ip = (IPv6)value;
+            IPv6WithMask value = IPv6WithMask.of(ipsWithMask[i]);
+            if (!hasMask[i]) {
+                IPv6 ip = value.getValue();
                 InetAddress inetAddress = InetAddress.getByName(ipsWithMask[i]);
 
                 assertArrayEquals(ip.getBytes(), inetAddress.getAddress());
                 assertEquals(ipsWithMask[i], ip.toString());
             } else if (value instanceof IPv6WithMask && hasMask[i]) {
-                IPv6WithMask ip = null;
-                try {
-                    ip = (IPv6WithMask)value;
-                } catch (ClassCastException e) {
-                    fail("Invalid Masked<T> type.");
-                }
-                // Types OK, check values
                 InetAddress inetAddress = InetAddress.getByName(ipsWithMask[i].substring(0, ipsWithMask[i].indexOf('/')));
 
-                assertArrayEquals(ip.value.getBytes(), inetAddress.getAddress());
-                assertEquals(ipsWithMask[i].substring(0, ipsWithMask[i].indexOf('/')), ip.value.toString());
-                assertArrayEquals(masks[i], ip.mask.getBytes());
-            } else if (value instanceof IPv6) {
-                fail("Expected masked IPv6, got unmasked IPv6.");
-            } else {
-                fail("Expected unmasked IPv6, got masked IPv6.");
+                byte[] address = inetAddress.getAddress();
+                assertEquals(address.length, value.getValue().getBytes().length);
+                
+                for (int j = 0; j < address.length; j++) {
+                    address[j] &= masks[i][j];
+                }
+                
+                assertArrayEquals(value.getValue().getBytes(), address);
+                assertArrayEquals(masks[i], value.getMask().getBytes());
             }
         }
     }