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/main/java/org/openflow/protocol/match/Match.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/Match.java
index d35f709..8f17845 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/protocol/match/Match.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/Match.java
@@ -4,89 +4,190 @@
 import org.openflow.types.Masked;
 import org.openflow.types.OFValueType;
 
-public interface Match extends OFObject {
-
-    /*
-     * Preconditions
-     * On preconditions (from the OF1.1 spec, page 28, the OF1.0 spec failed to explicitly
-     * specify this, but it is the behavior of Of1.0 switches):
-     * Protocol-specific fields within ofp_match will be ignored within a single table when
-     * the corresponding protocol is not specified in the match. The MPLS match fields will
-     * be ignored unless the Ethertype is specified as MPLS. Likewise, the IP header and
-     * transport header fields will be ignored unless the Ethertype is specified as either
-     * IPv4 or ARP. The tp_src and tp_dst fields will be ignored unless the network protocol
-     * specified is as TCP, UDP or SCTP. Fields that are ignored don�t need to be wildcarded
-     * and should be set to 0.
-     */
+/**
+ * Generic interface for version-agnostic immutable Match structure.
+ * The Match structure is defined in the OpenFlow protocol, and it contains information on
+ * the fields to be matched in a specific flow record.
+ * This interface does not assume anything on the fields in the Match structure. If in
+ * some version, the match structure cannot handle a certain field, it may return <code>false</code>
+ * for <code>supports(...)</code> calls, and throw <code>UnsupportedOperationException</code> from all
+ * other methods in such cases.
+ * <br><br>
+ * On wildcards and masks:<br>
+ * This interface defines the following masking notations for fields:
+ * <ul>
+ * <li><b>Exact</b>: field is matched exactly against a single, fixed value (no mask, or mask is all ones).
+ * <li><b>Wildcarded</b>: field is not being matched. It is fully masked (mask=0) and any value of it
+ * will match the flow record having this match.
+ * <li><b>Partially masked</b>: field is matched using a specified mask which is neither 0 nor all ones. Mask can
+ * be either arbitrary or require some specific structure.
+ * </ul>
+ * Implementing classes may or may not support all types of these masking types. They may also support
+ * them in part. For example, OF1.0 supports exact match and (full) wildcarding for all fields, but it
+ * does only supports partial masking for IP source/destination fields, and this partial masking must be
+ * in the CIDR prefix format. Thus, OF1.0 implementation may throw <code>UnsupportedOperationException</code> if given
+ * in <code>setMaksed</code> an IP mask of, for example, 255.0.255.0, or if <code>setMasked</code> is called for any field
+ * which is not IP source/destination address.
+ * <br><br>
+ * On prerequisites:<br>
+ * From the OF1.1 spec, page 28, the OF1.0 spec failed to explicitly specify this, but it
+ * is the behavior of OF1.0 switches:
+ * "Protocol-specific fields within ofp_match will be ignored within a single table when 
+ * the corresponding protocol is not specified in the match. The MPLS match fields will 
+ * be ignored unless the Ethertype is specified as MPLS. Likewise, the IP header and 
+ * transport header fields will be ignored unless the Ethertype is specified as either 
+ * IPv4 or ARP. The tp_src and tp_dst fields will be ignored unless the network protocol 
+ * specified is as TCP, UDP or SCTP. Fields that are ignored donÕt need to be wildcarded 
+ * and should be set to 0."
+ * <br><br>
+ * This interface uses generics to assure type safety in users code. However, implementing classes may have to suppress 
+ * 'unchecked cast' warnings while making sure they correctly cast base on their implementation details.
+ * 
+ * @author Yotam Harchol (yotam.harchol@bigswitch.com)
+ */
+public interface Match extends OFObject {    
 
     /**
-     * Returns the value for the given field from this match.
-     *
+     * Returns a value for the given field if:
+     * <ul>
+     * <li>Field is supported
+     * <li>Field is not fully wildcarded
+     * <li>Prerequisites are ok
+     * </ul>
+     * If one of the above conditions does not hold, returns null. Value is returned masked if partially wildcarded.
+     * 
      * @param field Match field to retrieve
-     * @return Value of match field
+     * @return Value of match field (may be masked), or <code>null</code> if field is one of the conditions above does not hold.
+     * @throws UnsupportedOperationException If field is not supported.
      */
     public <F extends OFValueType<F>> F get(MatchField<F> field) throws UnsupportedOperationException;
 
     /**
-     * Returns the masked value for the given field from this match.
-     * Precondition: field is partially wildcarded.
-     *
-     * @param field Match field to retrieve
-     * @return Masked value of match field or null if no mask
+     * Returns the masked value for the given field from this match, along with the mask itself.
+     * Prerequisite: field is partially masked.
+     * If prerequisite is not met, a <code>null</code> is returned.
+     * 
+     * @param field Match field to retrieve.
+     * @return Masked value of match field or null if no mask is set.
+     * @throws UnsupportedOperationException If field is not supported.
      */
     public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field) throws UnsupportedOperationException;
 
     /**
-     * Returns true if this match object supports the given match field.
-     *
+     * Returns true if and only if this match object supports the given match field.
+     * 
      * @param field Match field
-     * @return
+     * @return true if field is supported, false otherwise.
      */
     public boolean supports(MatchField<?> field);
 
     /**
-     * true iff field supports a bitmask mask that wildcards part of the field
+     * Returns true if and only if this match object supports partially bitmasking of the given field.
      * (note: not all possible values of this bitmask have to be acceptable)
-     *
-     * @param field Match field
-     * @return
+     * 
+     * @param field Match field.
+     * @return true if field can be partially masked, false otherwise.
+     * @throws UnsupportedOperationException If field is not supported.
      */
-    public boolean supportsMasked(MatchField<?> field);
+    public boolean supportsMasked(MatchField<?> field) throws UnsupportedOperationException;
 
     /**
-     * True iff this field is currently fully specified in the match, i.e., the
-     * match will only select packets that match the exact value of getField(field).
-     *
-     * @param field Match field
-     * @return
+     * Returns true if and only if this field is currently specified in the match with an exact value and
+     * no mask. I.e., the specified match will only select packets that match the exact value of getValue(field).
+     * 
+     * @param field Match field.
+     * @return true if field has a specific exact value, false if not.
+     * @throws UnsupportedOperationException If field is not supported.
      */
-    public boolean isExact(MatchField<?> field);
+    public boolean isExact(MatchField<?> field) throws UnsupportedOperationException;
 
     /**
-     * True if this field is currently logically unspecified in the match, i.e, the
-     * value returned by getValue(f) has no impact on whether a packet will be selected
+     * True if and only if this field is currently logically unspecified in the match, i.e, the 
+     * value returned by getValue(f) has no impact on whether a packet will be selected 
      * by the match or not.
-     *
-     * @param field
-     * @return
+     * 
+     * @param field Match field.
+     * @return true if field is fully wildcarded, false if not.
+     * @throws UnsupportedOperationException If field is not supported.
      */
-    public boolean isFullyWildcarded(MatchField<?> field);
+    public boolean isFullyWildcarded(MatchField<?> field) throws UnsupportedOperationException;
 
     /**
-     * True if this field is currently partially specified in the match, i.e, the
-     * match will select packets that match (p.value & getMask(field)) == getValue(field).
-     *
-     * @param field
-     * @return
+     * True if and only if this field is currently partially specified in the match, i.e, the 
+     * match will only select packets that match (p.value & getMask(field)) == getValue(field),
+     * and getMask(field) != 0.
+     * 
+     * @param field Match field.
+     * @return true if field is partially masked, false if not.
+     * @throws UnsupportedOperationException If field is not supported.
      */
-    public boolean isPartiallyMasked(MatchField<?> field);
-
+    public boolean isPartiallyMasked(MatchField<?> field) throws UnsupportedOperationException;
+    
     /**
      * Returns a builder to build new instances of this type of match object.
      * @return Match builder
      */
-    public MatchBuilder createBuilder();
+    public Builder createBuilder();
 
-    interface Builder extends MatchBuilder {
+    /**
+     * Builder interface for Match objects.
+     * Builder is used to create new Match objects and it creates the match according to the version it
+     * corresponds to. The builder uses the same notation of wildcards and masks, and can also throw
+     * <code>UnsupportedOperationException</code> if it is asked to create some matching that is not supported in
+     * the version it represents.
+     * 
+     * While used, MatchBuilder may not be consistent in terms of field prerequisites. However, user must
+     * solve these before using the generated Match object as these prerequisites should be enforced in the
+     * getters. 
+     * 
+     * @author Yotam Harchol (yotam.harchol@bigswitch.com)
+     */
+    interface Builder extends Match {
+        /**
+         * Sets a specific exact value for a field.
+         * 
+         * @param field Match field to set.
+         * @param value Value of match field.
+         * @return the Builder instance used.
+         * @throws UnsupportedOperationException If field is not supported.
+         */
+        public <F extends OFValueType<F>> Builder setExact(MatchField<F> field, F value) throws UnsupportedOperationException;
+
+        /**
+         * Sets a masked value for a field.
+         * 
+         * @param field Match field to set.
+         * @param value Value of field.
+         * @param mask Mask value.
+         * @return the Builder instance used.
+         * @throws UnsupportedOperationException If field is not supported, if field is supported but does not support masking, or if mask structure is not supported.
+         */
+        public <F extends OFValueType<F>> Builder setMasked(MatchField<F> field, F value, F mask) throws UnsupportedOperationException;
+
+        /**
+         * Sets a masked value for a field.
+         * 
+         * @param field Match field to set.
+         * @param valueWithMask Compound Masked object contains the value and the mask.
+         * @return the Builder instance used.
+         * @throws UnsupportedOperationException If field is not supported, if field is supported but does not support masking, or if mask structure is not supported.
+         */
+        public <F extends OFValueType<F>> Builder setMasked(MatchField<F> field, Masked<F> valueWithMask) throws UnsupportedOperationException;
+
+        /**
+         * Unsets any value given for the field and wildcards it so that it matches any value.
+         * 
+         * @param field Match field to unset.
+         * @return the Builder instance used.
+         * @throws UnsupportedOperationException If field is not supported.
+         */
+        public <F extends OFValueType<F>> Builder wildcard(MatchField<F> field) throws UnsupportedOperationException;
+
+        /**
+         * Returns the match created by this builder.
+         * 
+         * @return a Match object.
+         */
+        public Match getMatch();
     }
-}
+}
\ No newline at end of file
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchBuilder.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchBuilder.java
deleted file mode 100644
index be7b8b0..0000000
--- a/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchBuilder.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package org.openflow.protocol.match;
-
-import org.openflow.types.Masked;
-import org.openflow.types.OFValueType;
-
-public interface MatchBuilder {
-    /**
-     * Returns the value for the given field from this match.
-     *
-     * @param field Match field to retrieve
-     * @return Value of match field
-     */
-    public <F extends OFValueType<F>> F get(MatchField<F> field) throws UnsupportedOperationException;
-
-    /**
-     * Returns the masked value for the given field from this match.
-     * Precondition: field is partially wildcarded.
-     *
-     * @param field Match field to retrieve
-     * @return Masked value of match field or null if no mask
-     */
-    public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field) throws UnsupportedOperationException;
-
-    /**
-     * Returns true if this match object supports the given match field.
-     *
-     * @param field Match field
-     * @return
-     */
-    public boolean supports(MatchField<?> field);
-
-    /**
-     * true iff field supports a bitmask mask that wildcards part of the field
-     * (note: not all possible values of this bitmask have to be acceptable)
-     *
-     * @param field Match field
-     * @return
-     */
-    public boolean supportsMasked(MatchField<?> field);
-
-    /**
-     * True iff this field is currently fully specified in the match, i.e., the
-     * match will only select packets that match the exact value of getField(field).
-     *
-     * @param field Match field
-     * @return
-     */
-    public boolean isExact(MatchField<?> field);
-
-    /**
-     * True if this field is currently logically unspecified in the match, i.e, the
-     * value returned by getValue(f) has no impact on whether a packet will be selected
-     * by the match or not.
-     *
-     * @param field
-     * @return
-     */
-    public boolean isFullyWildcarded(MatchField<?> field);
-
-    /**
-     * True if this field is currently partially specified in the match, i.e, the
-     * match will select packets that match (p.value & getMask(field)) == getValue(field).
-     *
-     * @param field
-     * @return
-     */
-    public boolean isPartiallyMasked(MatchField<?> field);
-
-
-    public <F extends OFValueType<F>> MatchBuilder setExact(MatchField<F> field, F value);
-
-    public <F extends OFValueType<F>> MatchBuilder setMasked(MatchField<F> field, F value, F mask);
-
-    public <F extends OFValueType<F>> MatchBuilder setMasked(MatchField<F> field, Masked<F> valueWithMask);
-
-    public <F extends OFValueType<F>> MatchBuilder wildcard(MatchField<F> field);
-
-    public Match getMatch();
-}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchField.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchField.java
index 4d4935c..5913658 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchField.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchField.java
@@ -11,30 +11,38 @@
 import org.openflow.types.IpEcn;
 import org.openflow.types.IpProtocol;
 import org.openflow.types.MacAddress;
+import org.openflow.types.OFMetadata;
 import org.openflow.types.OFPort;
 import org.openflow.types.OFValueType;
 import org.openflow.types.TransportPort;
 import org.openflow.types.VlanPcp;
 import org.openflow.types.VlanVid;
 
+@SuppressWarnings("unchecked")
 public class MatchField<F extends OFValueType<F>> {
     private final String name;
     public final MatchFields id;
+    private final Prerequisite<?>[] prerequisites;
 
-    private MatchField(final String name, final MatchFields id) {
+    private MatchField(final String name, final MatchFields id, Prerequisite<?>... prerequisites) {
         this.name = name;
         this.id = id;
+        this.prerequisites = prerequisites;
     }
 
     public final static MatchField<OFPort> IN_PORT =
             new MatchField<OFPort>("in_port", MatchFields.IN_PORT);
+    
     public final static MatchField<OFPort> IN_PHY_PORT =
-            new MatchField<OFPort>("in_phy_port", MatchFields.PHYSICAL_PORT);
-    public final static MatchField<OFPort> METADATA =
-            new MatchField<OFPort>("metadata", MatchFields.METADATA);
+            new MatchField<OFPort>("in_phy_port", MatchFields.PHYSICAL_PORT,
+                    new Prerequisite<OFPort>(MatchField.IN_PORT));
+    
+    public final static MatchField<OFMetadata> METADATA =
+            new MatchField<OFMetadata>("metadata", MatchFields.METADATA);
 
     public final static MatchField<MacAddress> ETH_DST =
             new MatchField<MacAddress>("eth_dst", MatchFields.ETH_DST);
+    
     public final static MatchField<MacAddress> ETH_SRC =
             new MatchField<MacAddress>("eth_src", MatchFields.ETH_SRC);
 
@@ -43,63 +51,106 @@
     
     public final static MatchField<VlanVid> VLAN_VID =
             new MatchField<VlanVid>("vlan_vid", MatchFields.VLAN_VID);
-    public final static MatchField<VlanPcp> VLAN_PCP =
-            new MatchField<VlanPcp>("vlan_pcp", MatchFields.VLAN_PCP);
     
+    public final static MatchField<VlanPcp> VLAN_PCP =
+            new MatchField<VlanPcp>("vlan_pcp", MatchFields.VLAN_PCP,
+                    new Prerequisite<VlanVid>(MatchField.VLAN_VID));
     
     public final static MatchField<IpDscp> IP_DSCP =
-            new MatchField<IpDscp>("ip_dscp", MatchFields.IP_DSCP);
+            new MatchField<IpDscp>("ip_dscp", MatchFields.IP_DSCP,
+                    new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.ETH_TYPE_IPv4, EthType.ETH_TYPE_IPv6));
+    
     public final static MatchField<IpEcn> IP_ECN =
-            new MatchField<IpEcn>("ip_dscp", MatchFields.IP_ECN);
+            new MatchField<IpEcn>("ip_dscp", MatchFields.IP_ECN,
+                    new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.ETH_TYPE_IPv4, EthType.ETH_TYPE_IPv6));
+    
     public final static MatchField<IpProtocol> IP_PROTO =
-            new MatchField<IpProtocol>("ip_proto", MatchFields.IP_PROTO);
+            new MatchField<IpProtocol>("ip_proto", MatchFields.IP_PROTO,
+                    new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.ETH_TYPE_IPv4, EthType.ETH_TYPE_IPv6));
 
     public final static MatchField<IPv4> IPV4_SRC =
-            new MatchField<IPv4>("ipv4_src", MatchFields.IPV4_SRC);
+            new MatchField<IPv4>("ipv4_src", MatchFields.IPV4_SRC,
+                    new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.ETH_TYPE_IPv4));
+    
     public final static MatchField<IPv4> IPV4_DST =
-            new MatchField<IPv4>("ipv4_dst", MatchFields.IPV4_DST);
+            new MatchField<IPv4>("ipv4_dst", MatchFields.IPV4_DST,
+                    new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.ETH_TYPE_IPv4));
 
     public final static MatchField<TransportPort> TCP_SRC = new MatchField<TransportPort>(
-            "tcp_src", MatchFields.TCP_SRC);
+            "tcp_src", MatchFields.TCP_SRC,
+            new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.IP_PROTO_TCP));
+    
     public final static MatchField<TransportPort> TCP_DST = new MatchField<TransportPort>(
-            "tcp_dst", MatchFields.TCP_DST);
+            "tcp_dst", MatchFields.TCP_DST,
+            new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.IP_PROTO_TCP));
 
     public final static MatchField<TransportPort> UDP_SRC = new MatchField<TransportPort>(
-            "udp_src", MatchFields.UDP_SRC);
+            "udp_src", MatchFields.UDP_SRC,
+            new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.IP_PROTO_UDP));
+    
     public final static MatchField<TransportPort> UDP_DST = new MatchField<TransportPort>(
-            "udp_dst", MatchFields.UDP_DST);
+            "udp_dst", MatchFields.UDP_DST,
+            new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.IP_PROTO_UDP));
 
     public final static MatchField<TransportPort> SCTP_SRC = new MatchField<TransportPort>(
-            "sctp_src", MatchFields.SCTP_SRC);
+            "sctp_src", MatchFields.SCTP_SRC,
+            new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.IP_PROTO_SCTP));
+    
     public final static MatchField<TransportPort> SCTP_DST = new MatchField<TransportPort>(
-            "sctp_dst", MatchFields.SCTP_DST);
+            "sctp_dst", MatchFields.SCTP_DST,
+            new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.IP_PROTO_SCTP));
 
     public final static MatchField<ICMPv4Type> ICMPV4_TYPE = new MatchField<ICMPv4Type>(
-            "icmpv4_src", MatchFields.ICMPV4_TYPE);
+            "icmpv4_src", MatchFields.ICMPV4_TYPE,
+            new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.IP_PROTO_ICMP));
+    
     public final static MatchField<ICMPv4Code> ICMPV4_CODE = new MatchField<ICMPv4Code>(
-            "icmpv4_dst", MatchFields.ICMPV4_CODE);
+            "icmpv4_dst", MatchFields.ICMPV4_CODE,
+            new Prerequisite<IpProtocol>(MatchField.IP_PROTO, IpProtocol.IP_PROTO_ICMP));
 
     public final static MatchField<ArpOpcode> ARP_OP = new MatchField<ArpOpcode>(
-            "arp_op", MatchFields.ARP_OP);
+            "arp_op", MatchFields.ARP_OP,
+            new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.ETH_TYPE_ARP));
+    
     public final static MatchField<IPv4> ARP_SPA =
-            new MatchField<IPv4>("arp_spa", MatchFields.ARP_SPA);
+            new MatchField<IPv4>("arp_spa", MatchFields.ARP_SPA,
+                    new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.ETH_TYPE_ARP));
+    
     public final static MatchField<IPv4> ARP_TPA =
-            new MatchField<IPv4>("arp_tpa", MatchFields.ARP_TPA);
+            new MatchField<IPv4>("arp_tpa", MatchFields.ARP_TPA,
+                    new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.ETH_TYPE_ARP));
+    
     public final static MatchField<MacAddress> ARP_SHA =
-            new MatchField<MacAddress>("arp_sha", MatchFields.ARP_SHA);
+            new MatchField<MacAddress>("arp_sha", MatchFields.ARP_SHA,
+                    new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.ETH_TYPE_ARP));
+    
     public final static MatchField<MacAddress> ARP_THA =
-            new MatchField<MacAddress>("arp_tha", MatchFields.ARP_THA);
+            new MatchField<MacAddress>("arp_tha", MatchFields.ARP_THA,
+                    new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.ETH_TYPE_ARP));
 
     public final static MatchField<IPv6> IPV6_SRC =
-            new MatchField<IPv6>("ipv6_src", MatchFields.IPV6_SRC);
+            new MatchField<IPv6>("ipv6_src", MatchFields.IPV6_SRC,
+                    new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.ETH_TYPE_IPv6));
+    
     public final static MatchField<IPv6> IPV6_DST =
-            new MatchField<IPv6>("ipv6_dst", MatchFields.IPV6_DST);
+            new MatchField<IPv6>("ipv6_dst", MatchFields.IPV6_DST,
+                    new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.ETH_TYPE_IPv6));
 
     public final static MatchField<IPv6FlowLabel> IPV6_FLABEL =
-            new MatchField<IPv6FlowLabel>("ipv6_flabel", MatchFields.IPV6_FLOWLABEL);
+            new MatchField<IPv6FlowLabel>("ipv6_flabel", MatchFields.IPV6_FLOWLABEL,
+                    new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.ETH_TYPE_IPv6));
 
     public String getName() {
         return name;
     }
+    
+    public boolean arePrerequisitesOK(Match match) {
+        for (Prerequisite<?> p : this.prerequisites) {
+            if (!p.isStaisfied(match)) {
+                return false;
+            }
+        }
+        return true;
+    }
 
 }
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchFields.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchFields.java
index 21043f2..309f91f 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchFields.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchFields.java
@@ -1,5 +1,6 @@
 package org.openflow.protocol.match;
 
+// MUST BE ORDERED BY THE ORDER OF OF SPEC!!!
 public enum MatchFields {
     IN_PORT,
     PHYSICAL_PORT,
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/match/Prerequisite.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/Prerequisite.java
new file mode 100644
index 0000000..f518925
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/Prerequisite.java
@@ -0,0 +1,44 @@
+package org.openflow.protocol.match;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.openflow.types.OFValueType;
+
+public class Prerequisite<T extends OFValueType<T>> {
+    private MatchField<T> field;
+    private Set<OFValueType<T>> values;
+    private boolean any;
+    
+    public Prerequisite(MatchField<T> field, OFValueType<T>... values) {
+        this.values = new HashSet<OFValueType<T>>();
+        this.field = field;
+        if (values == null || values.length == 0) {
+            this.any = true;
+        } else {
+            this.any = false;
+            for (OFValueType<T> value : values) {
+                this.values.add(value);
+            }
+        }
+    }
+    
+    /**
+     * Returns true if this prerequisite is satisfied by the given match object.
+     * 
+     * @param match Match object
+     * @return true iff prerequisite is satisfied.
+     */
+    public boolean isStaisfied(Match match) {
+        OFValueType<T> res = match.get(this.field);
+        if (res == null)
+            return false;
+        if (this.any)
+            return true;
+        if (this.values.contains(res)) {
+            return true;
+        }
+        return false;
+    }
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/IPv4WithMask.java b/java_gen/pre-written/src/main/java/org/openflow/types/IPv4WithMask.java
index c24c4fd..0a1a6d3 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/IPv4WithMask.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/IPv4WithMask.java
@@ -36,7 +36,7 @@
         return res.toString();
     }
     
-    public static OFValueType<?> ofPossiblyMasked(final String string) {
+    public static IPv4WithMask of(final String string) {
         int slashPos;
         String ip = string;
         int maskBits = 0;
@@ -72,7 +72,7 @@
             return IPv4WithMask.of(ipv4, maskAddress);
         } else if (maskBits == 0) {
             // No mask
-            return ipv4;
+            return IPv4WithMask.of(ipv4, IPv4.of(0xFFFFFFFF));
         } else {
             // With mask
             int mask = (-1) << (32 - maskBits);
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/IPv6WithMask.java b/java_gen/pre-written/src/main/java/org/openflow/types/IPv6WithMask.java
index 72319e3..453507a 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/IPv6WithMask.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/IPv6WithMask.java
@@ -31,7 +31,7 @@
         return res.toString();
     }
     
-    public static OFValueType<?> ofPossiblyMasked(final String string) {
+    public static IPv6WithMask of(final String string) {
         int slashPos;
         String ip = string;
         int maskBits = 0;
@@ -67,7 +67,7 @@
             return IPv6WithMask.of(ipv6, maskAddress);
         } else if (maskBits == 0) {
             // No mask
-            return ipv6;
+            return IPv6WithMask.of(ipv6, IPv6.of(0xFFFFFFFFFFFFFFFFl, 0xFFFFFFFFFFFFFFFFl));
         } else {
             // With mask
             BigInteger mask = BigInteger.ONE.negate().shiftLeft(128 - maskBits);
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/OFMetadata.java b/java_gen/pre-written/src/main/java/org/openflow/types/OFMetadata.java
new file mode 100644
index 0000000..83d02da
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/OFMetadata.java
@@ -0,0 +1,34 @@
+package org.openflow.types;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public class OFMetadata extends U64 implements OFValueType<OFMetadata> {
+    
+    private static int LENGTH = 8;
+
+    protected OFMetadata(long raw) {
+        super(raw);
+    }
+
+    public static OFMetadata of(long raw) {
+        return new OFMetadata(raw);
+    }
+    
+    public static OFMetadata read8Bytes(ChannelBuffer cb) {
+        return OFMetadata.of(cb.readLong());
+    }
+    
+    public void write8Bytes(ChannelBuffer cb) {
+        cb.writeLong(super.getValue());
+    }
+
+    @Override
+    public int getLength() {
+        return LENGTH;
+    }
+
+    @Override
+    public OFMetadata applyMask(OFMetadata mask) {
+        return OFMetadata.of(this.getValue() & mask.getValue());
+    }
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/U64.java b/java_gen/pre-written/src/main/java/org/openflow/types/U64.java
index 750398f..7871445 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/U64.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/U64.java
@@ -24,7 +24,7 @@
 
     private final long raw;
 
-    private U64(final long raw) {
+    protected U64(final long raw) {
         this.raw = raw;
     }
 
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/VlanVid.java b/java_gen/pre-written/src/main/java/org/openflow/types/VlanVid.java
index ca2c3c2..e36a5dd 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/VlanVid.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/VlanVid.java
@@ -70,7 +70,7 @@
         c.writeShort(this.vid);
     }
 
-    public VlanVid read2Bytes(ChannelBuffer c) throws OFParseError {
+    public static VlanVid read2Bytes(ChannelBuffer c) throws OFParseError {
         return VlanVid.of(c.readShort());
     }
 
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());
             }
         }
     }