Merge remote-tracking branch 'rlane/explicit-inheritance2'

Conflicts:
	loxi_front_end/frontend.py
	loxi_front_end/parser.py
	loxi_ir.py
diff --git a/generic_utils.py b/generic_utils.py
index eeb26d6..0bf289e 100644
--- a/generic_utils.py
+++ b/generic_utils.py
@@ -31,6 +31,7 @@
 Intended to be imported into another namespace
 """
 
+import collections
 import functools
 import sys
 import of_g
@@ -99,8 +100,6 @@
 #
 ################################################################
 
-import collections
-
 class OrderedSet(collections.MutableSet):
     """
     A set implementations that retains insertion order.  From the receipe
@@ -164,6 +163,59 @@
             return len(self) == len(other) and list(self) == list(other)
         return set(self) == set(other)
 
+################################################################
+#
+# OrderedDefaultDict
+#
+################################################################
+
+class OrderedDefaultDict(collections.OrderedDict):
+    """
+    A Dictionary that maintains insertion order where missing values
+    are provided by a factory function, i.e., a combination of
+    the semantics of collections.defaultdict and collections.OrderedDict.
+    """
+    def __init__(self, default_factory=None, *a, **kw):
+        if (default_factory is not None and
+                not callable(default_factory)):
+            raise TypeError('first argument must be callable')
+        collections.OrderedDict.__init__(self, *a, **kw)
+        self.default_factory = default_factory
+
+    def __getitem__(self, key):
+        try:
+            return collections.OrderedDict.__getitem__(self, key)
+        except KeyError:
+            return self.__missing__(key)
+
+    def __missing__(self, key):
+        if self.default_factory is None:
+            raise KeyError(key)
+        self[key] = value = self.default_factory()
+        return value
+
+    def __reduce__(self):
+        if self.default_factory is None:
+            args = tuple()
+        else:
+            args = self.default_factory,
+        return type(self), args, None, None, self.items()
+
+    def copy(self):
+        return self.__copy__()
+
+    def __copy__(self):
+        return type(self)(self.default_factory, self)
+
+    def __deepcopy__(self, memo):
+        import copy
+        return type(self)(self.default_factory,
+                          copy.deepcopy(self.items()))
+    def __repr__(self):
+        return 'OrderedDefaultDict(%s, %s)' % (self.default_factory,
+                                        collections.OrderedDict.__repr__(self))
+
+
 def find(iterable, func):
     """
     find the first item in iterable for which func returns something true'ish.
diff --git a/java_gen/codegen.py b/java_gen/codegen.py
index 0765c91..07b910a 100644
--- a/java_gen/codegen.py
+++ b/java_gen/codegen.py
@@ -36,6 +36,7 @@
 import of_g
 from loxi_ir import *
 import lang_java
+import test_data
 
 import loxi_utils.loxi_utils as loxi_utils
 
@@ -43,17 +44,17 @@
 
 def gen_all_java(out, name):
     basedir= '%s/openflowj' % of_g.options.install_dir
-    srcdir = "%s/src/main/java/" % basedir
     print "Outputting to %s" % basedir
     if os.path.exists(basedir):
         shutil.rmtree(basedir)
     os.makedirs(basedir)
     copy_prewrite_tree(basedir)
 
-    gen = JavaGenerator(srcdir)
+    gen = JavaGenerator(basedir)
     gen.create_of_interfaces()
     gen.create_of_classes()
     gen.create_of_const_enums()
+    gen.create_of_factories()
 
     with open('%s/README.java-lang' % os.path.dirname(__file__)) as readme_src:
         out.writelines(readme_src.readlines())
@@ -67,11 +68,15 @@
         self.basedir = basedir
         self.java_model = java_model.model
 
-    def render_class(self, clazz, template, **context):
+    def render_class(self, clazz, template, src_dir=None, **context):
+        if not src_dir:
+            src_dir = "src/main/java/"
+
         context['class_name'] = clazz.name
         context['package'] = clazz.package
+        context['template_dir'] = self.templates_dir
 
-        filename = os.path.join(self.basedir, "%s/%s.java" % (clazz.package.replace(".", "/"), clazz.name))
+        filename = os.path.join(self.basedir, src_dir, "%s/%s.java" % (clazz.package.replace(".", "/"), clazz.name))
         dirname = os.path.dirname(filename)
         if not os.path.exists(dirname):
             os.makedirs(dirname)
@@ -87,6 +92,10 @@
             self.render_class(clazz=enum,
                     template='const.java', enum=enum, all_versions=self.java_model.versions)
 
+            for version in enum.versions:
+                clazz = java_model.OFGenericClass(package="org.openflow.protocol.ver{}".format(version.of_version), name="{}SerializerVer{}".format(enum.name, version.of_version))
+                self.render_class(clazz=clazz, template="const_serializer.java", enum=enum, version=version)
+
     def create_of_interfaces(self):
         """ Create the base interfaces for of classes"""
         for interface in self.java_model.interfaces:
@@ -98,15 +107,30 @@
     def create_of_classes(self):
         """ Create the OF classes with implementations for each of the interfaces and versions """
         for interface in self.java_model.interfaces:
-            if interface.name == "OFTableMod":
-                continue
-            if not loxi_utils.class_is_message(interface.c_name) and not loxi_utils.class_is_oxm(interface.c_name):
-                continue
             for java_class in interface.versioned_classes:
+                if not self.java_model.generate_class(java_class):
+                    continue
                 self.render_class(clazz=java_class,
                         template='of_class.java', version=java_class.version, msg=java_class,
                         impl_class=java_class.name)
 
+                self.create_unit_test(java_class.unit_test)
+
+    def create_unit_test(self, unit_test):
+        if unit_test.has_test_data:
+            self.render_class(clazz=unit_test,
+                    template='unit_test.java', src_dir="src/test/java",
+                    version=unit_test.java_class.version,
+                    test=unit_test, msg=unit_test.java_class,
+                    test_data=unit_test.test_data)
+
+    def create_of_factories(self):
+        factory = self.java_model.of_factory
+        self.render_class(clazz=factory, template="of_factory_interface.java", factory=factory)
+        for factory_class in factory.factory_classes:
+            self.render_class(clazz=factory_class, template="of_factory_class.java", factory=factory_class, model=self.java_model)
+        self.render_class(clazz=java_model.OFGenericClass(package="org.openflow.protocol", name="OFFactories"), template="of_factories.java", versions=self.java_model.versions)
+
 def copy_prewrite_tree(basedir):
     """ Recursively copy the directory structure from ./java_gen/pre-write
        into $basedir"""
diff --git a/java_gen/java_model.py b/java_gen/java_model.py
index 35f334c..a894179 100644
--- a/java_gen/java_model.py
+++ b/java_gen/java_model.py
@@ -29,24 +29,27 @@
 # A lot of this stuff could/should probably be merged with the python utilities
 
 import collections
-from collections import namedtuple, defaultdict
+from collections import namedtuple, defaultdict, OrderedDict
 import logging
 import os
 import pdb
 import re
 
-from generic_utils import find, memoize, OrderedSet
+from generic_utils import find, memoize, OrderedSet, OrderedDefaultDict
 import of_g
 from loxi_ir import *
 import loxi_front_end.type_maps as type_maps
-import loxi_utils.loxi_utils as utils
+import loxi_utils.loxi_utils as loxi_utils
 import py_gen.util as py_utils
+import test_data
 
 import java_gen.java_type as java_type
 
 class JavaModel(object):
-    write_blacklist = defaultdict(lambda: set(), OFOxm=set(('typeLen',)))
-    virtual_interfaces = set(['OFOxm' ])
+    enum_blacklist = set(("OFDefinitions",))
+    enum_entry_blacklist = defaultdict(lambda: set(), OFFlowWildcards=set([ "NW_DST_BITS", "NW_SRC_BITS", "NW_SRC_SHIFT", "NW_DST_SHIFT" ]))
+    write_blacklist = defaultdict(lambda: set(), OFOxm=set(('typeLen',)), OFAction=set(('type',)), OFInstruction=set(('type',)))
+    virtual_interfaces = set(['OFOxm', 'OFAction', 'OFInstruction' ])
 
     @property
     @memoize
@@ -56,12 +59,15 @@
     @property
     @memoize
     def interfaces(self):
-        version_map_per_class = collections.defaultdict(lambda: {})
+        version_map_per_class = collections.OrderedDict()
 
         for raw_version, of_protocol in of_g.ir.items():
             jversion = JavaOFVersion(of_protocol.wire_version)
 
             for of_class in of_protocol.classes:
+                if not of_class.name in version_map_per_class:
+                    version_map_per_class[of_class.name] = collections.OrderedDict()
+
                 version_map_per_class[of_class.name][jversion] = of_class
 
         interfaces = []
@@ -73,17 +79,18 @@
     @property
     @memoize
     def enums(self):
-        enum_entry_version_value_map = collections.defaultdict(lambda: collections.defaultdict(lambda: collections.OrderedDict()))
+        name_version_enum_map = OrderedDefaultDict(lambda: OrderedDict())
 
         for version in self.versions:
             of_protocol = of_g.ir[version.int_version]
             for enum in of_protocol.enums:
-                for entry_name, entry_value in enum.values:
-                    enum_entry_version_value_map[enum.name][entry_name][version] = entry_value
+                name_version_enum_map[enum.name][version] = enum
 
-        enums = [ JavaEnum(name, entry_version_value_map) for name, entry_version_value_map
-                        in enum_entry_version_value_map.items() ]
+        enums = [ JavaEnum(name, version_enum_map) for name, version_enum_map,
+                        in name_version_enum_map.items() ]
 
+        # inelegant - need java name here
+        enums = [ enum for enum in enums if enum.name not in self.enum_blacklist ]
         return enums
 
     @memoize
@@ -93,6 +100,47 @@
         except KeyError:
             raise KeyError("Could not find enum with name %s" % name)
 
+    @property
+    @memoize
+    def of_factory(self):
+           return OFFactory(
+                    package="org.openflow.protocol",
+                    name="OFFactory",
+                    members=self.interfaces)
+
+    def generate_class(self, clazz):
+        if clazz.interface.is_virtual:
+            return False
+        if clazz.interface.name == "OFTableMod":
+            return False
+        if clazz.interface.name.startswith("OFMatchV"):
+            return True
+        if loxi_utils.class_is_message(clazz.interface.c_name):
+            return True
+        if loxi_utils.class_is_oxm(clazz.interface.c_name):
+            return True
+        if loxi_utils.class_is_action(clazz.interface.c_name):
+            return True
+        if loxi_utils.class_is_instruction(clazz.interface.c_name):
+            return True
+        else:
+            return False
+
+
+class OFFactory(namedtuple("OFFactory", ("package", "name", "members"))):
+    @property
+    def factory_classes(self):
+            return [ OFFactoryClass(
+                    package="org.openflow.protocol.ver{}".format(version.of_version),
+                    name="OFFactoryVer{}".format(version.of_version),
+                    interface=self,
+                    version=version
+                    ) for version in model.versions ]
+
+
+OFGenericClass = namedtuple("OFGenericClass", ("package", "name"))
+OFFactoryClass = namedtuple("OFFactory", ("package", "name", "interface", "version"))
+
 model = JavaModel()
 
 #######################################################################
@@ -139,7 +187,7 @@
         self.c_name = c_name
         self.version_map = version_map
         self.name = java_type.name_c_to_caps_camel(c_name)
-        self.builder_name = self.name + "Builder"
+        self.variable_name = self.name[2].lower() + self.name[3:]
         self.constant_name = c_name.upper().replace("OF_", "")
 
         pck_suffix, parent_interface = self.class_info()
@@ -152,15 +200,17 @@
     def class_info(self):
         if re.match(r'OFFlow(Add|Modify(Strict)?|Delete(Strict)?)$', self.name):
             return ("", "OFFlowMod")
-        elif utils.class_is_message(self.c_name):
+        elif re.match(r'OFMatch.*', self.name):
+            return ("", "Match")
+        elif loxi_utils.class_is_message(self.c_name):
             return ("", "OFMessage")
-        elif utils.class_is_action(self.c_name):
+        elif loxi_utils.class_is_action(self.c_name):
             return ("action", "OFAction")
-        elif utils.class_is_oxm(self.c_name):
+        elif loxi_utils.class_is_oxm(self.c_name):
             return ("oxm", "OFOxm")
-        elif utils.class_is_instruction(self.c_name):
+        elif loxi_utils.class_is_instruction(self.c_name):
             return ("instruction", "OFInstruction")
-        elif utils.class_is_meter_band(self.c_name):
+        elif loxi_utils.class_is_meter_band(self.c_name):
             return ("meterband", "OFMeterBand")
         else:
             return ("", None)
@@ -188,10 +238,17 @@
         return self.name in model.virtual_interfaces
 
     @property
+    def is_universal(self):
+        return len(self.all_versions) == len(model.versions)
+
+    @property
     @memoize
     def all_versions(self):
         return self.version_map.keys()
 
+    def has_version(self, version):
+        return version in self.version_map
+
     def versioned_class(self, version):
         return JavaOFClass(self, version, self.version_map[version])
 
@@ -218,12 +275,22 @@
         self.version = version
         self.constant_name = self.c_name.upper().replace("OF_", "")
         self.package = "org.openflow.protocol.ver%s" % version.of_version
+        self.generated = False
+
+    @property
+    @memoize
+    def unit_test(self):
+        return JavaUnitTest(self)
 
     @property
     def name(self):
         return "%sVer%s" % (self.interface.name, self.version.of_version)
 
     @property
+    def variable_name(self):
+        return self.name[3:]
+
+    @property
     def length(self):
         if self.is_fixed_length:
             return self.min_length
@@ -287,6 +354,10 @@
     def is_extension(self):
         return type_maps.message_is_extension(self.c_name, -1)
 
+    @property
+    def align(self):
+        return int(self.ir_class.params['align']) if 'align' in self.ir_class.params else 0
+
 #######################################################################
 ### Member
 #######################################################################
@@ -403,7 +474,7 @@
         if hasattr(self.member, "length"):
             return self.member.length
         else:
-            count, base = utils.type_dec_to_count_base(self.member.type)
+            count, base = loxi_utils.type_dec_to_count_base(self.member.type)
             return of_g.of_base_types[base]['bytes'] * count
 
     @staticmethod
@@ -441,22 +512,72 @@
             return False
         return (self.name,) == (other.name,)
 
+
+#######################################################################
+### Unit Test
+#######################################################################
+
+class JavaUnitTest(object):
+    def __init__(self, java_class):
+        self.java_class = java_class
+        self.data_file_name = "of{version}/{name}.data".format(version=java_class.version.of_version,
+                                                     name=java_class.c_name[3:])
+    @property
+    def package(self):
+        return self.java_class.package
+
+    @property
+    def name(self):
+        return self.java_class.name + "Test"
+
+    @property
+    def has_test_data(self):
+        return test_data.exists(self.data_file_name)
+
+    @property
+    @memoize
+    def test_data(self):
+        return test_data.read(self.data_file_name)
+
+
 #######################################################################
 ### Enums
 #######################################################################
 
 class JavaEnum(object):
-    def __init__(self, c_name, entry_version_value_map):
+    def __init__(self, c_name, version_enum_map):
         self.c_name = c_name
         self.name   = "OF" + java_type.name_c_to_caps_camel("_".join(c_name.split("_")[1:]))
 
         # Port_features has constants that start with digits
         self.name_prefix = "PF_" if self.name == "OFPortFeatures" else ""
 
+        self.version_enums = version_enum_map
+
+        entry_name_version_value_map = OrderedDefaultDict(lambda: OrderedDict())
+        for version, ir_enum in version_enum_map.items():
+            for ir_entry in ir_enum.entries:
+                if "virtual" in ir_entry.params:
+                    continue
+                entry_name_version_value_map[ir_entry.name][version] = ir_entry.value
+
         self.entries = [ JavaEnumEntry(self, name, version_value_map)
-                         for (name, version_value_map) in entry_version_value_map.items() ]
+                         for (name, version_value_map) in entry_name_version_value_map.items() ]
+
+        self.entries = [ e for e in self.entries if e.name not in model.enum_entry_blacklist[self.name] ]
         self.package = "org.openflow.protocol"
 
+    def wire_type(self, version):
+        ir_enum = self.version_enums[version]
+        if "wire_type" in ir_enum.params:
+            return java_type.convert_enum_wire_type_to_jtype(ir_enum.params["wire_type"])
+        else:
+            return java_type.u8
+
+    @property
+    def versions(self):
+        return self.version_enums.keys()
+
     @memoize
     def entry_by_name(self, name):
         try:
@@ -481,11 +602,18 @@
 # values: Map JavaVersion->Value
 class JavaEnumEntry(object):
     def __init__(self, enum, name, values):
+        self.enum = enum
         self.name = enum.name_prefix + "_".join(name.split("_")[1:]).upper()
         self.values = values
 
+    def has_value(self, version):
+        return version in self.values
+
     def value(self, version):
-        res = self.version_value_map[version]
+        return self.values[version]
+
+    def format_value(self, version):
+        res = self.enum.wire_type(version).format_value(self.values[version])
         return res
 
     def all_values(self, versions, not_present=None):
diff --git a/java_gen/java_type.py b/java_gen/java_type.py
index 8580f37..75bde01 100644
--- a/java_gen/java_type.py
+++ b/java_gen/java_type.py
@@ -21,19 +21,19 @@
         return camel
 
 
-ANY = 0xFFFFFFFFFFFFFFFF
+java_primitive_types = set("byte char short int long".split(" "))
 
+ANY = 0xFFFFFFFFFFFFFFFF
 
 class VersionOp:
     def __init__(self, version=ANY, read=None, write=None):
         self.version = version
         self.read = read
         self.write = write
-        
+
     def __str__(self):
         return "[Version: %d, Read: '%s', Write: '%s']" % (self.version, self.read, self.write)
 
-
 class JType(object):
     """ Wrapper class to hold C to Java type conversion information """
     def __init__(self, pub_type, priv_type=None, size=None, read_op=None, write_op=None):
@@ -44,9 +44,9 @@
         self.size = size            # bytes on the wire; None == variable length or hard to calc
         self.ops = {}
 #        if read_op is None:
-#            read_op = 'ChannelUtils.read%s(bb)' % self.pub_type
+#            read_op = 'ChannelUtilsVer$version.read%s(bb)' % self.pub_type
 #        if write_op is None:
-#            write_op = 'ChannelUtils.write%s(bb, $name)'  % self.pub_type
+#            write_op = 'ChannelUtilsVer$version.write%s(bb, $name)'  % self.pub_type
 #        self._read_op = read_op
 #        self._write_op = write_op
 
@@ -54,6 +54,21 @@
         self.ops[version] = VersionOp(version, read, write)
         return self
 
+    def cast(self, min):
+        """ declares that the value has to be cast to itself for values >= min.
+            This is to deal with Java signedness """
+        def format_cast_value(value):
+            if value >= min:
+                return "(%s) 0x%x" % (self.pub_type, value)
+            else:
+                return "0x%x" % (value)
+
+        self.format_value = format_cast_value
+        return self
+
+    def format_value(self, value):
+        return value
+
     @property
     def public_type(self):
         """ return the public type """
@@ -74,11 +89,11 @@
         ver = ANY if version is None else version.int_version
         _read_op = None
         if ver in self.ops:
-            _read_op = self.ops[ver].read or self.ops[ANY].read 
+            _read_op = self.ops[ver].read or self.ops[ANY].read
         elif ANY in self.ops:
             _read_op = self.ops[ANY].read
         if _read_op is None:
-            _read_op = 'ChannelUtils.read%s(bb)' % self.pub_type
+            _read_op = 'ChannelUtilsVer$version.read%s(bb)' % self.pub_type
         if callable(_read_op):
             return _read_op(version)
         else:
@@ -92,14 +107,21 @@
         elif ANY in self.ops:
             _write_op = self.ops[ANY].write
         if _write_op is None:
-            _write_op = 'ChannelUtils.write%s(bb, $name)' % self.pub_type
+            _write_op = 'ChannelUtilsVer$version.write%s(bb, $name)' % self.pub_type
         if callable(_write_op):
             return _write_op(version, name)
         else:
             return _write_op.replace("$name", str(name)).replace("$version", version.of_version)
 
-hello_elem_list = JType("List<OFHelloElement>") \
-        .op(read='ChannelUtils.readHelloElementList(bb)', write='ChannelUtils.writeHelloElementList(bb)')
+    @property
+    def is_primitive(self):
+        return self.pub_type in java_primitive_types
+
+    @property
+    def is_array(self):
+        return self.pub_type.endswith("[]")
+
+
 u8 =  JType('byte',  size=1) \
         .op(read='bb.readByte()', write='bb.writeByte($name)')
 u8_list =  JType('List<U8>',  size=1) \
@@ -116,42 +138,42 @@
          .op(version=1, read="OFPort.read2Bytes(bb)", write="$name.write2Bytes(bb)") \
          .op(version=ANY, read="OFPort.read4Bytes(bb)", write="$name.write4Bytes(bb)")
 one_byte_array = JType('byte[]', size=1) \
-        .op(read='ChannelUtils.readBytes(bb, 1)', write='ChannelUtils.writeBytes(bb, $name)')
+        .op(read='ChannelUtilsVer$version.readBytes(bb, 1)', write='ChannelUtilsVer$version.writeBytes(bb, $name)')
 two_byte_array = JType('byte[]', size=2) \
-        .op(read='ChannelUtils.readBytes(bb, 2)', write='ChannelUtils.writeBytes(bb, $name)')
+        .op(read='ChannelUtilsVer$version.readBytes(bb, 2)', write='ChannelUtilsVer$version.writeBytes(bb, $name)')
 three_byte_array = JType('byte[]', size=3) \
-        .op(read='ChannelUtils.readBytes(bb, 3)', write='ChannelUtils.writeBytes(bb, $name)')
+        .op(read='ChannelUtilsVer$version.readBytes(bb, 3)', write='ChannelUtilsVer$version.writeBytes(bb, $name)')
 four_byte_array = JType('byte[]', size=4) \
-        .op(read='ChannelUtils.readBytes(bb, 4)', write='ChannelUtils.writeBytes(bb, $name)')
+        .op(read='ChannelUtilsVer$version.readBytes(bb, 4)', write='ChannelUtilsVer$version.writeBytes(bb, $name)')
 five_byte_array = JType('byte[]', size=5) \
-        .op(read='ChannelUtils.readBytes(bb, 5)', write='ChannelUtils.writeBytes(bb, $name)')
+        .op(read='ChannelUtilsVer$version.readBytes(bb, 5)', write='ChannelUtilsVer$version.writeBytes(bb, $name)')
 six_byte_array = JType('byte[]', size=6) \
-        .op(read='ChannelUtils.readBytes(bb, 6)', write='ChannelUtils.writeBytes(bb, $name)')
+        .op(read='ChannelUtilsVer$version.readBytes(bb, 6)', write='ChannelUtilsVer$version.writeBytes(bb, $name)')
 seven_byte_array = JType('byte[]', size=7) \
-        .op(read='ChannelUtils.readBytes(bb, 7)', write='ChannelUtils.writeBytes(bb, $name)')
-actions_list = JType('List<OFAction>', size='ChannelUtils.calcListSize($name)') \
-        .op(read='ChannelUtils.readActionsList(bb, $length)', write='ChannelUtils.writeActionsList(bb, $name);')
-instructions_list = JType('List<OFInstruction>', size='ChannelUtils.calcListSize($name)') \
-        .op(read='ChannelUtils.readInstructionsList(bb, $length)', \
-            write='ChannelUtils.writeList(bb, $name)')
-buckets_list = JType('List<OFBucket>', size='ChannelUtils.calcListSize($name)') \
-        .op(read='ChannelUtils.readBucketList(bb, $length)', \
-            write='ChannelUtils.writeList(bb, $name)')
-port_desc_list = JType('List<OFPhysicalPort>', size='ChannelUtils.calcListSize($name)') \
-        .op(read='ChannelUtils.readPhysicalPortList(bb, $length)', \
-            write='ChannelUtils.writeList(bb, $name)')
+        .op(read='ChannelUtilsVer$version.readBytes(bb, 7)', write='ChannelUtilsVer$version.writeBytes(bb, $name)')
+actions_list = JType('List<OFAction>', size='ChannelUtilsVer$version.calcListSize($name)') \
+        .op(read='ChannelUtilsVer$version.readActionsList(bb, $length)', write='ChannelUtilsVer$version.writeActionsList(bb, $name);')
+instructions_list = JType('List<OFInstruction>', size='ChannelUtilsVer$version.calcListSize($name)') \
+        .op(read='ChannelUtilsVer$version.readInstructionsList(bb, $length)', \
+            write='ChannelUtilsVer$version.writeList(bb, $name)')
+buckets_list = JType('List<OFBucket>', size='ChannelUtilsVer$version.calcListSize($name)') \
+        .op(read='ChannelUtilsVer$version.readBucketList(bb, $length)', \
+            write='ChannelUtilsVer$version.writeList(bb, $name)')
+port_desc_list = JType('List<OFPhysicalPort>', size='ChannelUtilsVer$version.calcListSize($name)') \
+        .op(read='ChannelUtilsVer$version.readPhysicalPortList(bb, $length)', \
+            write='ChannelUtilsVer$version.writePhysicalPortList(bb, $name)')
 port_desc = JType('OFPortDesc', size='$name.getLength()') \
         .op(read='null; // TODO OFPortDescVer$version.READER.read(bb)', \
             write='$name.writeTo(bb)')
-packet_queue_list = JType('List<OFPacketQueue>', size='ChannelUtils.calcListSize($name)') \
-        .op(read='ChannelUtils.readPacketQueueList(bb, $length)', \
-            write='ChannelUtils.writeList(bb, $name)')
+packet_queue_list = JType('List<OFPacketQueue>', size='ChannelUtilsVer$version.calcListSize($name)') \
+        .op(read='ChannelUtilsVer$version.readPacketQueueList(bb, $length)', \
+            write='ChannelUtilsVer$version.writeList(bb, $name)')
 octets = JType('byte[]', size="$length") \
-        .op(read='ChannelUtils.readBytes(bb, $length)', \
+        .op(read='ChannelUtilsVer$version.readBytes(bb, $length)', \
             write='bb.writeBytes($name)')
 of_match = JType('Match', size="$name.getLength()") \
-        .op(read='ChannelUtils.readOFMatch(bb)', \
-            write='ChannelUtils.writeOFMatch(bb, $name)')
+        .op(read='ChannelUtilsVer$version.readOFMatch(bb)', \
+            write='ChannelUtilsVer$version.writeOFMatch(bb, $name)')
 flow_mod_cmd = JType('OFFlowModCommand', 'short', size="$name.getLength()") \
         .op(version=1, read="bb.readShort()", write="bb.writeShort($name)") \
         .op(version=ANY, read="bb.readByte()", write="bb.writeByte($name)")
@@ -159,23 +181,25 @@
         .op(read="MacAddress.read6Bytes(bb)", \
             write="$name.write6Bytes(bb)")
 port_name = JType('String', size=16) \
-        .op(read='ChannelUtils.readFixedLengthString(bb, 16)', \
-            write='ChannelUtils.writeFixedLengthString(bb, $name, 16)')
+        .op(read='ChannelUtilsVer$version.readFixedLengthString(bb, 16)', \
+            write='ChannelUtilsVer$version.writeFixedLengthString(bb, $name, 16)')
 desc_str = JType('String', size=256) \
-        .op(read='ChannelUtils.readFixedLengthString(bb, 256)', \
-            write='ChannelUtils.writeFixedLengthString(bb, $name, 256)')
+        .op(read='ChannelUtilsVer$version.readFixedLengthString(bb, 256)', \
+            write='ChannelUtilsVer$version.writeFixedLengthString(bb, $name, 256)')
 serial_num = JType('String', size=32) \
-        .op(read='ChannelUtils.readFixedLengthString(bb, 32)', \
-            write='ChannelUtils.writeFixedLengthString(bb, $name, 32)')
+        .op(read='ChannelUtilsVer$version.readFixedLengthString(bb, 32)', \
+            write='ChannelUtilsVer$version.writeFixedLengthString(bb, $name, 32)')
 table_name = JType('String', size=32) \
-        .op(read='ChannelUtils.readFixedLengthString(bb, 32)', \
-            write='ChannelUtils.writeFixedLengthString(bb, $name, 32)')
+        .op(read='ChannelUtilsVer$version.readFixedLengthString(bb, 32)', \
+            write='ChannelUtilsVer$version.writeFixedLengthString(bb, $name, 32)')
 ipv4 = JType("IPv4") \
         .op(read="IPv4.read4Bytes(bb)", \
             write="$name.write4Bytes(bb)")
 ipv6 = JType("IPv6") \
         .op(read="IPv6.read16Bytes(bb)", \
             write="$name.write16Bytes(bb)")
+packetin_reason = JType("OFPacketInReason")\
+        .op(read="OFPacketInReasonSerializerVer$version.readFrom(bb)", write="OFPacketInReasonSerializerVer$version.writeTo(bb, $name)")
 
 default_mtype_to_jtype_convert_map = {
         'uint8_t' : u8,
@@ -213,12 +237,23 @@
 
 ## This is where we drop in special case handling for certain types
 exceptions = {
-        'OFPacketIn': {
-            'data' : octets
+        'of_packet_in': {
+            'data' : octets,
+            'reason': packetin_reason
             },
 }
 
 
+enum_wire_types = {
+        "uint8_t": JType("byte").op(read="bb.readByte()", write="bb.writeByte($name)").cast(min=1<<7),
+        "uint16_t": JType("short").op(read="bb.readShort()", write="bb.writeShort($name)").cast(min=1<<15),
+        "uint32_t": JType("int").op(read="bb.readInt()", write="bb.writeInt($name)").cast(min=1<<31),
+        "uint64_t": JType("long").op(read="bb.readLong()", write="bb.writeLong($name)").cast(min=1<<31)
+}
+
+def convert_enum_wire_type_to_jtype(wire_type):
+    return enum_wire_types[wire_type]
+
 def make_standard_list_jtype(c_type):
     m = re.match(r'list\(of_([a-zA-Z_]+)_t\)', c_type)
     if not m:
@@ -226,8 +261,8 @@
     base_name = m.group(1)
     java_base_name = name_c_to_caps_camel(base_name)
     return JType("List<OF%s>" % java_base_name) \
-        .op(read='ChannelUtils.read%sList(bb)' % java_base_name, \
-            write='ChannelUtils.write%sList(bb, $name)' % java_base_name)
+        .op(read='ChannelUtilsVer$version.read%sList(bb, $length)' % java_base_name, \
+            write='ChannelUtilsVer$version.write%sList(bb, $name)' % java_base_name)
 
 def convert_to_jtype(obj_name, field_name, c_type):
     """ Convert from a C type ("uint_32") to a java type ("U32")
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/OFMessage.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFMessage.java
index c1e4456..32319fa 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/protocol/OFMessage.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFMessage.java
@@ -1,6 +1,6 @@
 package org.openflow.protocol;
 
-public interface OFMessage {
+public interface OFMessage extends OFObject {
     int getXid();
 
     OFType getType();
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/OFMessageWriter.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFMessageWriter.java
index 84e5507..bcca1fd 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/protocol/OFMessageWriter.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFMessageWriter.java
@@ -4,5 +4,5 @@
 import org.openflow.exceptions.OFParseError;
 
 public interface OFMessageWriter<T> {
-    public int write(ChannelBuffer bb, T message) throws OFParseError;
+    public void write(ChannelBuffer bb, T message) throws OFParseError;
 }
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/OFObject.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFObject.java
index 4a7557f..140182b 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/protocol/OFObject.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFObject.java
@@ -3,17 +3,15 @@
 import org.jboss.netty.buffer.ChannelBuffer;
 
 /**
- *  Base interface of all OpenFlow objects (e.g., messages, actions, stats, etc.)
+ * Base interface of all OpenFlow objects (e.g., messages, actions, stats, etc.)
  *
- *  All objects have a length and can be read and written from a buffer.
- *  When writing, the length field is dynamically updated, so it need not be
- *  managed manually.  However, you can override the auto calculated length with
- *  overrideLength() call, if, for example, you want to intentionally create
- *  malformed packets, for example, for negative testing.
+ * All objects have a length and can be read and written from a buffer. When
+ * writing, the length field is dynamically updated, so it need not be managed
+ * manually. However, you can override the auto calculated length with
+ * overrideLength() call, if, for example, you want to intentionally create
+ * malformed packets, for example, for negative testing.
  */
 
-
 public interface OFObject {
     void writeTo(ChannelBuffer bb);
-    int getLength();
 }
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/Wildcards.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/Wildcards.java
index 25b2c21..e1993f5 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/protocol/Wildcards.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/Wildcards.java
@@ -1,5 +1,656 @@
+/**
+ *    Copyright 2013, Big Switch Networks, Inc.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *    not use this file except in compliance with the License. You may obtain
+ *    a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *    License for the specific language governing permissions and limitations
+ *    under the License.
+ **/
+
 package org.openflow.protocol;
 
-public class Wildcards {
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
 
-}
+import com.google.common.base.Joiner;
+
+/**
+ * a more user friendly representation of the wildcards bits in an OpenFlow
+ * match. The Wildcards object is
+ * <ul>
+ * <li>immutable (i.e., threadsafe)</li>
+ * <li>instance managed (don't instantiate it yourself), instead call "of"</li>
+ * <ul>
+ * <p>
+ * You can construct a Wildcard object from either its integer representation
+ * </p>
+ * <code>
+ *    Wildcard.of(0x3820e0);
+ *  </code>
+ * <p>
+ * Or start with either an empty or full wildcard, and select/unselect foo.
+ * </p>
+ * <code>
+ *  Wildcard w = Wildcards.NONE
+ *                .set(Flag.DL_SRC, Flag. DL_DST, Flag.DL_VLAN_PCP)
+ *                .setNwDstMask(8)
+ *                .setNwSrcMask(8);
+ *  </code>
+ * <p>
+ * <b>Remember:</b> Wildcards objects are immutable. set... operations have
+ * <b>NO EFFECT</b> on the current wildcard object. You HAVE to use the returned
+ * changed object.
+ * </p>
+ *
+ * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+ */
+public class Wildcards {
+    public class OFWildcardFlags {
+        final public static int OFPFW_ALL = ((1 << 22) - 1);
+
+        final public static int OFPFW_IN_PORT = 1 << 0; /* Switch input port. */
+        final public static int OFPFW_DL_VLAN = 1 << 1; /* VLAN id. */
+        final public static int OFPFW_DL_SRC = 1 << 2; /* Ethernet source address. */
+        final public static int OFPFW_DL_DST = 1 << 3; /*
+                                                        * Ethernet destination
+                                                        * address.
+                                                        */
+        final public static int OFPFW_DL_TYPE = 1 << 4; /* Ethernet frame type. */
+        final public static int OFPFW_NW_PROTO = 1 << 5; /* IP protocol. */
+        final public static int OFPFW_TP_SRC = 1 << 6; /* TCP/UDP source port. */
+        final public static int OFPFW_TP_DST = 1 << 7; /* TCP/UDP destination port. */
+
+        /*
+         * IP source address wildcard bit count. 0 is exact match, 1 ignores the
+         * LSB, 2 ignores the 2 least-significant bits, ..., 32 and higher wildcard
+         * the entire field. This is the *opposite* of the usual convention where
+         * e.g. /24 indicates that 8 bits (not 24 bits) are wildcarded.
+         */
+        final public static int OFPFW_NW_SRC_SHIFT = 8;
+        final public static int OFPFW_NW_SRC_BITS = 6;
+        final public static int OFPFW_NW_SRC_MASK = ((1 << OFPFW_NW_SRC_BITS) - 1) << OFPFW_NW_SRC_SHIFT;
+        final public static int OFPFW_NW_SRC_ALL = 32 << OFPFW_NW_SRC_SHIFT;
+
+        /* IP destination address wildcard bit count. Same format as source. */
+        final public static int OFPFW_NW_DST_SHIFT = 14;
+        final public static int OFPFW_NW_DST_BITS = 6;
+        final public static int OFPFW_NW_DST_MASK = ((1 << OFPFW_NW_DST_BITS) - 1) << OFPFW_NW_DST_SHIFT;
+        final public static int OFPFW_NW_DST_ALL = 32 << OFPFW_NW_DST_SHIFT;
+
+        final public static int OFPFW_DL_VLAN_PCP = 1 << 20; /* VLAN priority. */
+        final public static int OFPFW_NW_TOS = 1 << 21; /*
+                                                         * IP ToS (DSCP field, 6
+                                                         * bits).
+                                                         */
+
+        final public static int OFPFW_ALL_SANITIZED = (((1 << 22) - 1)
+                                                       & ~OFPFW_NW_SRC_MASK & ~OFPFW_NW_DST_MASK)
+                                                      | OFPFW_NW_SRC_ALL
+                                                      | OFPFW_NW_DST_ALL;
+
+
+    }
+
+    public final static Wildcards FULL = new Wildcards(OFWildcardFlags.OFPFW_ALL_SANITIZED);
+    private static final int FULL_INT = FULL.getInt();
+
+    public final static Wildcards EXACT = new Wildcards(0);
+
+    // floodlight common case: matches on inport + l2
+    public final static int INT_INPORT_L2_MATCH = 0x3820e0;
+    public final static Wildcards INPORT_L2_MATCH = new Wildcards(
+            INT_INPORT_L2_MATCH);
+
+    /**
+     * enum type for the binary flags that can be set in the wildcards field of
+     * an OFWildcardFlags. Replaces the unwieldy c-ish int constants in OFWildcardFlags.
+     */
+    public static enum Flag {
+        IN_PORT(OFWildcardFlags.OFPFW_IN_PORT),  /* Switch input port. */
+        DL_VLAN(OFWildcardFlags.OFPFW_DL_VLAN), /* VLAN id. */
+        DL_SRC(OFWildcardFlags.OFPFW_DL_SRC), /* Ethernet source address. */
+        DL_DST(OFWildcardFlags.OFPFW_DL_DST), /* Ethernet destination addr */
+        DL_TYPE(OFWildcardFlags.OFPFW_DL_TYPE), /* Ethernet frame type. */
+        NW_PROTO(OFWildcardFlags.OFPFW_NW_PROTO), /* IP protocol. */
+        TP_SRC(OFWildcardFlags.OFPFW_TP_SRC), /* TCP/UDP source port. */
+        TP_DST(OFWildcardFlags.OFPFW_TP_DST), /* TCP/UDP destination port. */
+        DL_VLAN_PCP(OFWildcardFlags.OFPFW_DL_VLAN_PCP), /* VLAN priority. */
+        NW_SRC(-1) { /*
+                      * virtual NW_SRC flag => translates to the strange 6 bits
+                      * in the header
+                      */
+            @Override
+            boolean isBolean() {
+                return false;
+            }
+
+            @Override
+            int getInt(int flags) {
+                return ((flags & OFWildcardFlags.OFPFW_NW_SRC_MASK) >> OFWildcardFlags.OFPFW_NW_SRC_SHIFT);
+            }
+
+            @Override
+            int setInt(int flags, int srcMask) {
+                return (flags & ~OFWildcardFlags.OFPFW_NW_SRC_MASK) | (srcMask << OFWildcardFlags.OFPFW_NW_SRC_SHIFT);
+            }
+
+            @Override
+            int wildcard(int flags) {
+                return flags & ~OFWildcardFlags.OFPFW_NW_SRC_MASK;
+            }
+
+            @Override
+            int matchOn(int flags) {
+                return flags | OFWildcardFlags.OFPFW_NW_SRC_ALL;
+            }
+
+            @Override
+            boolean isPartiallyOn(int flags) {
+                int intValue = getInt(flags);
+                return intValue > 0 && intValue < 32;
+            }
+
+            @Override
+            boolean isFullyOn(int flags) {
+                return getInt(flags) >= 32;
+            }
+
+        },
+        NW_DST(-1) { /*
+                      * virtual NW_SRC flag => translates to the strange 6 bits
+                      * in the header
+                      */
+            @Override
+            boolean isBolean() {
+                return false;
+            }
+
+            @Override
+            int getInt(int flags) {
+                return ((flags & OFWildcardFlags.OFPFW_NW_DST_MASK) >> OFWildcardFlags.OFPFW_NW_DST_SHIFT);
+            }
+
+            @Override
+            int setInt(int flags, int srcMask) {
+                return (flags & ~OFWildcardFlags.OFPFW_NW_DST_MASK) | (srcMask << OFWildcardFlags.OFPFW_NW_DST_SHIFT);
+            }
+
+            @Override
+            int wildcard(int flags) {
+                return flags & ~OFWildcardFlags.OFPFW_NW_DST_MASK;
+            }
+
+            @Override
+            int matchOn(int flags) {
+                return flags | OFWildcardFlags.OFPFW_NW_DST_ALL;
+            }
+
+            @Override
+            boolean isFullyOn(int flags) {
+                return getInt(flags) >= 32;
+            }
+        },
+        NW_TOS(OFWildcardFlags.OFPFW_NW_TOS); /* IP ToS (DSCP field, 6 bits). */
+
+        final int bitPosition;
+
+        Flag(int bitPosition) {
+            this.bitPosition = bitPosition;
+        }
+
+        /**
+         * @return a modified OF-1.0 flags field with this flag cleared (match
+         *         on this field)
+         */
+        int matchOn(int flags) {
+            return flags & ~this.bitPosition;
+        }
+
+        /**
+         * @return a modified OF-1.0 flags field with this flag set (wildcard
+         *         this field)
+         */
+        int wildcard(int flags) {
+            return flags | this.bitPosition;
+        }
+
+        /**
+         * @return true iff this is a true boolean flag that can either be off
+         *         or on.True in OF-1.0 for all fields except NW_SRC and NW_DST
+         */
+        boolean isBolean() {
+            return false;
+        }
+
+        /**
+         * @return true iff this wildcard field is currently 'partially on'.
+         *         Always false for true Boolean Flags. Can be true in OF-1.0
+         *         for NW_SRC, NW_DST.
+         */
+        boolean isPartiallyOn(int flags) {
+            return false;
+        }
+
+        /**
+         * @return true iff this wildcard field currently fully on (fully
+         *         wildcarded). Equivalent to the boolean flag being set in the
+         *         bitmask for bit flags, and to the wildcarded bit length set
+         *         to >=32 for NW_SRC and NW_DST
+         * @param flags
+         * @return
+         */
+        boolean isFullyOn(int flags) {
+            return (flags & this.bitPosition) != 0;
+        }
+
+        /**
+         * set the integer representation of this flag. only for NW_SRC and
+         * NW_DST
+         */
+        int setInt(int flags, int srcMask) {
+            throw new UnsupportedOperationException();
+        }
+
+        /**
+         * set the integer representation of this flag. only for NW_SRC and
+         * NW_DST
+         */
+        int getInt(int flags) {
+            throw new UnsupportedOperationException();
+        }
+
+
+    }
+
+    private final int flags;
+
+    /** private constructor. use Wildcard.of() instead */
+    private Wildcards(int flags) {
+        this.flags = flags;
+    }
+
+    /**
+     * return a wildcard object matching the given int flags. May reuse / cache
+     * frequently used wildcard instances. Don't rely on it though (use equals
+     * not ==).
+     *
+     * @param flags
+     * @return
+     */
+    public static Wildcards of(int paramFlags) {
+        int flags = sanitizeInt(paramFlags);
+        switch(flags) {
+            case 0x0000:
+                return EXACT;
+            case OFWildcardFlags.OFPFW_ALL_SANITIZED:
+                return FULL;
+            case INT_INPORT_L2_MATCH:
+                return INPORT_L2_MATCH;
+            default:
+                return new Wildcards(flags);
+        }
+    }
+
+    /** convience method return a wildcard for exactly one set flag */
+    public static Wildcards of(Wildcards.Flag setFlag) {
+        return Wildcards.of(setFlag.wildcard(0));
+    }
+
+    /** convience method return a wildcard for exactly two set flags */
+    public static Wildcards of(Wildcards.Flag setFlag, Wildcards.Flag setFlag2) {
+        return Wildcards.of(setFlag.wildcard(setFlag2.wildcard(0)));
+    }
+
+    /** convience method return a wildcard for an arbitrary number of set flags */
+    public static Wildcards of(Wildcards.Flag... setFlags) {
+        int flags = 0;
+        for (Wildcards.Flag flag : setFlags)
+            flags = flag.wildcard(0);
+        return Wildcards.of(flags);
+    }
+
+    /** convience method return a wildcards for ofmatches that match on one flag */
+    public static Wildcards ofMatches(Wildcards.Flag setFlag) {
+        return Wildcards.of(setFlag.matchOn(FULL_INT));
+    }
+
+    /**
+     * convience method return a wildcard for for an ofmatch that match on two
+     * flags
+     */
+    public static Wildcards ofMatches(Wildcards.Flag setFlag, Wildcards.Flag setFlag2) {
+        return Wildcards.of(setFlag.matchOn(setFlag2.matchOn(FULL_INT)));
+    }
+
+    /**
+     * convience method return a wildcard for an ofmatch that amtch on an
+     * arbitrary number of set flags
+     */
+    public static Wildcards ofMatches(Wildcards.Flag... setFlags) {
+        int flags = FULL_INT;
+        for (Wildcards.Flag flag : setFlags)
+           flags = flag.matchOn(flags);
+        return Wildcards.of(flags);
+    }
+
+    public static Wildcards ofMatches(Set<Wildcards.Flag> wSet) {
+        int flags = FULL_INT;
+        for (Wildcards.Flag flag : wSet)
+           flags = flag.matchOn(flags);
+        return Wildcards.of(flags);
+    }
+
+    /**
+     * return a Wildcards object that has the given flags set
+     * <p>
+     * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
+     * unmodified. </b>
+     */
+    public Wildcards wildcard(Wildcards.Flag flag) {
+        int flags = flag.wildcard(this.flags);
+        if (flags == this.flags)
+            return this;
+        else
+            return new Wildcards(flags);
+    }
+
+    /**
+     * return a Wildcards object that has the given flags set
+     * <p>
+     * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
+     * unmodified. </b>
+     */
+    public Wildcards wildcard(Wildcards.Flag flag, Wildcards.Flag flag2) {
+        int flags = flag.wildcard(flag2.wildcard(this.flags));
+        if (flags == this.flags)
+            return this;
+        else
+            return new Wildcards(flags);
+    }
+
+    /**
+     * return a Wildcards object that has the given flags wildcarded
+     * <p>
+     * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
+     * unmodified. </b>
+     */
+    public Wildcards wildcard(Wildcards.Flag... setFlags) {
+        int flags = this.flags;
+        for (Wildcards.Flag flag : setFlags)
+            flags = flag.wildcard(flags);
+        if (flags == this.flags)
+            return this;
+        else
+            return new Wildcards(flags);
+    }
+
+    /**
+     * return a Wildcards object that matches on exactly the given flag
+     * <p>
+     * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
+     * unmodified. </b>
+     */
+    public Wildcards matchOn(Wildcards.Flag flag) {
+        int flags = flag.matchOn(this.flags);
+        if (flags == this.flags)
+            return this;
+        else
+            return new Wildcards(flags);
+    }
+
+    /**
+     * return a Wildcards object that matches on exactly the given flags
+     * <p>
+     * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
+     * unmodified. </b>
+     */
+    public Wildcards matchOn(Wildcards.Flag flag, Wildcards.Flag flag2) {
+        int flags = flag.matchOn(flag2.matchOn(this.flags));
+        if (flags == this.flags)
+            return this;
+        else
+            return new Wildcards(flags);
+    }
+
+    /**
+     * return a Wildcards object that matches on exactly the given flags
+     * <p>
+     * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
+     * unmodified. </b>
+     */
+    public Wildcards matchOn(Wildcards.Flag... setFlags) {
+        int flags = this.flags;
+        for (Wildcards.Flag flag : setFlags)
+            flags = flag.matchOn(flags);
+        if (flags == this.flags)
+            return this;
+        else
+            return new Wildcards(flags);
+    }
+
+    /**
+     * return the nw src mask in normal CIDR style, e.g., 8 means x.x.x.x/8
+     * means 8 bits wildcarded
+     */
+    public int getNwSrcMask() {
+        return Math.max(0, 32 - Flag.NW_SRC.getInt(flags));
+    }
+
+    /**
+     * return the nw dst mask in normal CIDR style, e.g., 8 means x.x.x.x/8
+     * means 8 bits wildcarded
+     */
+    public int getNwDstMask() {
+        return Math.max(0, 32 - Flag.NW_DST.getInt(flags));
+    }
+
+    /**
+     * return a Wildcard object that has the given nwSrcCidrMask set.
+     * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
+     * unmodified. </b>
+     *
+     * @param srcCidrMask
+     *            source mask to set in <b>normal CIDR notation</b>, i.e., 8
+     *            means x.x.x.x/8
+     * @return a modified object
+     */
+    public Wildcards withNwSrcMask(int srcCidrMask) {
+        int flags = Flag.NW_SRC.setInt(this.flags, Math.max(0, 32 - srcCidrMask));
+        if (flags == this.flags)
+            return this;
+        else
+            return new Wildcards(flags);
+    }
+
+    /**
+     * return a Wildcard object that has the given nwDstCidrMask set.
+     * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
+     * unmodified. </b>
+     *
+     * @param dstCidrMask
+     *            dest mask to set in <b>normal CIDR notation</b>, i.e., 8 means
+     *            x.x.x.x/8
+     * @return a modified object
+     */
+    public Wildcards withNwDstMask(int dstCidrMask) {
+        int flags = Flag.NW_DST.setInt(this.flags, Math.max(0, 32 - dstCidrMask));
+        if (flags == this.flags)
+            return this;
+        else
+            return new Wildcards(flags);
+    }
+
+    /**
+     * return a Wildcard object that is inverted to this wildcard object.
+     * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
+     * unmodified. </b>
+     * @return a modified object
+     */
+    public Wildcards inverted() {
+        return Wildcards.of(flags ^ OFWildcardFlags.OFPFW_ALL_SANITIZED);
+    }
+
+    public boolean isWildcarded(Flag flag) {
+        return flag.isFullyOn(flags);
+    }
+
+    /**
+     * return all wildcard flags that are fully wildcarded as an EnumSet. Do not
+     * modify. Note: some flags (like NW_SRC and NW_DST) that are partially
+     * wildcarded are not returned in this set.
+     *
+     * @return the EnumSet of wildcards
+     */
+    public EnumSet<Wildcards.Flag> getWildcardedFlags() {
+        EnumSet<Wildcards.Flag> res = EnumSet.noneOf(Wildcards.Flag.class);
+        for (Wildcards.Flag flag : Flag.values()) {
+            if (flag.isFullyOn(flags)) {
+                res.add(flag);
+            }
+        }
+        return res;
+    }
+
+    /** return the OpenFlow 'wire' integer representation of these wildcards */
+    public int getInt() {
+        return flags;
+    }
+
+    /**
+     * return the OpenFlow 'wire' integer representation of these wildcards.
+     * Sanitize nw_src and nw_dst to be max. 32 (values > 32 are technically
+     * possible, but don't make semantic sense)
+     */
+    public static int sanitizeInt(int flags) {
+        if (((flags & OFWildcardFlags.OFPFW_NW_SRC_MASK) >> OFWildcardFlags.OFPFW_NW_SRC_SHIFT) > 32) {
+            flags = (flags & ~OFWildcardFlags.OFPFW_NW_SRC_MASK) | OFWildcardFlags.OFPFW_NW_SRC_ALL;
+        }
+        if (((flags & OFWildcardFlags.OFPFW_NW_DST_MASK) >> OFWildcardFlags.OFPFW_NW_DST_SHIFT) > 32) {
+            flags = (flags & ~OFWildcardFlags.OFPFW_NW_DST_MASK) | OFWildcardFlags.OFPFW_NW_DST_ALL;
+        }
+        return flags;
+    }
+
+    /**
+     * is this a wildcard set that has all flags set + and full (/0) nw_src and
+     * nw_dst wildcarding ?
+     */
+    public boolean isFull() {
+        return flags == OFWildcardFlags.OFPFW_ALL || flags == OFWildcardFlags.OFPFW_ALL_SANITIZED;
+    }
+
+    /** is this a wildcard of an exact match */
+    public boolean isExact() {
+        return flags == 0;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + flags;
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        Wildcards other = (Wildcards) obj;
+        if (flags != other.flags)
+            return false;
+        return true;
+    }
+
+    private final static Joiner pipeJoiner = Joiner.on("|");
+
+    @Override
+    public String toString() {
+        List<String> res = new ArrayList<String>();
+        for (Wildcards.Flag flag : Flag.values()) {
+            if (flag.isFullyOn(flags)) {
+                res.add(flag.name().toLowerCase());
+            }
+        }
+
+        if (Flag.NW_SRC.isPartiallyOn(flags)) {
+            res.add("nw_src(/" + getNwSrcMask() + ")");
+        }
+
+        if (Flag.NW_DST.isPartiallyOn(flags)) {
+            res.add("nw_dst(/" + getNwDstMask() + ")");
+        }
+
+        return pipeJoiner.join(res);
+    }
+
+    private final static Joiner commaJoiner = Joiner.on(", ");
+
+    /** a Java expression that constructs 'this' wildcards set */
+    public String toJava() {
+        if(isFull()) {
+            return "Wildcards.FULL";
+        } else  if (isExact()){
+            return "Wildcards.EXACT";
+        }
+
+        StringBuilder b = new StringBuilder();
+
+        EnumSet<Flag> myFlags = getWildcardedFlags();
+        if (myFlags.size() < 3) {
+            // default to start with empty
+            b.append("Wildcards.of("
+                     + commaJoiner.join(prefix("Flag.", myFlags.iterator())) + ")");
+        } else {
+            // too many - start with full
+
+            EnumSet<Flag> invFlags = inverted().getWildcardedFlags();
+            b.append("Wildcards.ofMatches("
+                     + commaJoiner.join(prefix("Flag.", invFlags.iterator())) + ")");
+        }
+        if (Flag.NW_SRC.isPartiallyOn(flags)) {
+            b.append(".setNwSrcMask(" + getNwSrcMask() + ")");
+        }
+        if (Flag.NW_DST.isPartiallyOn(flags)) {
+            b.append(".setNwDstMask(" + getNwDstMask() + ")");
+        }
+        return b.toString();
+    }
+
+    private Iterator<String> prefix(final String prefix, final Iterator<?> i) {
+        return new Iterator<String>() {
+
+            @Override
+            public boolean hasNext() {
+                return i.hasNext();
+            }
+
+            @Override
+            public String next() {
+                Object next = i.next();
+                return next == null ? null : prefix + next.toString();
+            }
+
+            @Override
+            public void remove() {
+                i.remove();
+            }
+        };
+    }
+
+
+}
\ No newline at end of file
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 fa42737..d35f709 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
@@ -1,20 +1,92 @@
 package org.openflow.protocol.match;
 
 import org.openflow.protocol.OFObject;
+import org.openflow.types.Masked;
 import org.openflow.types.OFValueType;
 
 public interface Match extends OFObject {
-    public <F extends OFValueType> F get(MatchField<F> match);
 
+    /*
+     * 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.
+     */
+
+    /**
+     * 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 MatchBuilder getBuilder();
+    /**
+     * Returns a builder to build new instances of this type of match object.
+     * @return Match builder
+     */
+    public MatchBuilder createBuilder();
+
+    interface Builder extends MatchBuilder {
+    }
 }
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
index 3c601f8..be7b8b0 100644
--- 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
@@ -1,11 +1,79 @@
 package org.openflow.protocol.match;
 
+import org.openflow.types.Masked;
 import org.openflow.types.OFValueType;
 
-public interface MatchBuilder extends Match {
-    public <F extends OFValueType> MatchBuilder set(MatchField<F> match, F value);
+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;
 
-    //public <M> void setMasked(MatchField<?, M> match, M value);
+    /**
+     * 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/MatchBuilderVer10.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchBuilderVer10.java
deleted file mode 100644
index 0fbe84b..0000000
--- a/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchBuilderVer10.java
+++ /dev/null
@@ -1,170 +0,0 @@
-package org.openflow.protocol.match;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.types.EthType;
-import org.openflow.types.IPv4;
-import org.openflow.types.IpDscp;
-import org.openflow.types.IpProtocol;
-import org.openflow.types.MacAddress;
-import org.openflow.types.OFPort;
-import org.openflow.types.OFValueType;
-import org.openflow.types.U16;
-import org.openflow.types.VlanPcp;
-import org.openflow.types.VlanVid;
-
-public class MatchBuilderVer10 implements MatchBuilder {
-
-    interface BuilderParamHandler<T> {
-        public T get(MatchBuilderVer10 builder);
-
-        public void set(MatchBuilderVer10 builder, T value);
-    }
-
-    // public static Map<MatchField<?,?>, BuilderParamHandler<?>>
-    // handlerMap = new HashMap();
-    static BuilderParamHandler<?>[] handlers = new BuilderParamHandler<?>[2];
-
-    static {
-        handlers[MatchField.IN_PORT.id] = new BuilderParamHandler<OFPort>() {
-            @Override
-            public void set(final MatchBuilderVer10 builder, final OFPort value) {
-                builder.inputPort = value;
-            }
-
-            @Override
-            public OFPort get(final MatchBuilderVer10 builder) {
-                return builder.inputPort;
-            }
-        };
-
-        handlers[MatchField.ETH_SRC.id] = new BuilderParamHandler<MacAddress>() {
-            @Override
-            public void set(final MatchBuilderVer10 builder, final MacAddress value) {
-                builder.dataLayerSource = value;
-            }
-
-            @Override
-            public MacAddress get(final MatchBuilderVer10 builder) {
-                return builder.dataLayerSource;
-            }
-        };
-    }
-
-    protected int wildcards;
-    protected OFPort inputPort;
-    protected MacAddress dataLayerSource;
-    protected MacAddress dataLayerDestination;
-    protected VlanVid dataLayerVirtualLan;
-    protected VlanPcp dataLayerVirtualLanPriorityCodePoint;
-    protected EthType dataLayerType;
-    protected IpDscp ipDscp;
-    protected IpProtocol networkProtocol;
-    protected IPv4 networkSource;
-    protected IPv4 networkDestination;
-    protected U16 transportSource;
-    protected U16 transportDestination;
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public <F extends OFValueType> F get(final MatchField<F> match) {
-        switch (match.id) {
-            case 0:
-                return (F) inputPort;
-            case 1:
-                return (F) dataLayerSource;
-            default:
-                return null;
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public <F extends OFValueType> MatchBuilder set(final MatchField<F> match, final F value) {
-        switch (match.id) {
-            case 0:
-                inputPort = (OFPort) value;
-                break;
-            case 1:
-                dataLayerSource = (MacAddress) value;
-                break;
-        }
-        return this;
-    }
-
-    public OFPort getInputPort() {
-        return inputPort;
-    }
-
-    public void setInputPort(final OFPort inputPort) {
-        this.inputPort = inputPort;
-    }
-
-    public MacAddress getDataLayerSource() {
-        return dataLayerSource;
-    }
-
-    public void setDataLayerSource(final MacAddress dataLayerSource) {
-        this.dataLayerSource = dataLayerSource;
-    }
-
-    @Override
-    public boolean supports(final MatchField<?> field) {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public boolean supportsMasked(final MatchField<?> field) {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public boolean isExact(final MatchField<?> field) {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public boolean isFullyWildcarded(final MatchField<?> field) {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public boolean isPartiallyMasked(final MatchField<?> field) {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public MatchBuilder getBuilder() {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public int getLength() {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public void writeTo(final ChannelBuffer bb) {
-        // TODO Auto-generated method stub
-
-    }
-/*
-    @Override
-    public <M> void setMasked(final MatchField<?, M> match, final M value) {
-        // TODO Auto-generated method stub
-
-    }
-*/
-    @Override
-    public Match getMatch() {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-}
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 d9d68ec..4d4935c 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
@@ -4,105 +4,99 @@
 import org.openflow.types.EthType;
 import org.openflow.types.ICMPv4Code;
 import org.openflow.types.ICMPv4Type;
-import org.openflow.types.IPv4WithMask;
+import org.openflow.types.IPv4;
+import org.openflow.types.IPv6;
 import org.openflow.types.IPv6FlowLabel;
-import org.openflow.types.IPv6WithMask;
 import org.openflow.types.IpDscp;
 import org.openflow.types.IpEcn;
 import org.openflow.types.IpProtocol;
 import org.openflow.types.MacAddress;
-import org.openflow.types.Masked;
 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;
 
-public class MatchField<F extends OFValueType> {
+public class MatchField<F extends OFValueType<F>> {
     private final String name;
-    public final int id;
+    public final MatchFields id;
 
-    public MatchField(final String name) {
-        this.name = name;
-        this.id = -1;
-    }
-
-    public MatchField(final String name, final int id) {
+    private MatchField(final String name, final MatchFields id) {
         this.name = name;
         this.id = id;
     }
 
     public final static MatchField<OFPort> IN_PORT =
-            new MatchField<OFPort>("in_port", 0);
+            new MatchField<OFPort>("in_port", MatchFields.IN_PORT);
     public final static MatchField<OFPort> IN_PHY_PORT =
-            new MatchField<OFPort>("in_phy_port");
+            new MatchField<OFPort>("in_phy_port", MatchFields.PHYSICAL_PORT);
     public final static MatchField<OFPort> METADATA =
-            new MatchField<OFPort>("metadata");
+            new MatchField<OFPort>("metadata", MatchFields.METADATA);
 
-    public final static MatchField<Masked<MacAddress>> ETH_DST =
-            new MatchField<Masked<MacAddress>>("eth_dst");
-    public final static MatchField<Masked<MacAddress>> ETH_SRC =
-            new MatchField<Masked<MacAddress>>("eth_src", 1);
+    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);
 
     public final static MatchField<EthType> ETH_TYPE =
-            new MatchField<EthType>("eth_type");
+            new MatchField<EthType>("eth_type", MatchFields.ETH_TYPE);
     
-    public final static MatchField<Masked<VlanVid>> VLAN_VID =
-            new MatchField<Masked<VlanVid>>("vlan_vid");
+    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");
+            new MatchField<VlanPcp>("vlan_pcp", MatchFields.VLAN_PCP);
     
     
     public final static MatchField<IpDscp> IP_DSCP =
-            new MatchField<IpDscp>("ip_dscp");
+            new MatchField<IpDscp>("ip_dscp", MatchFields.IP_DSCP);
     public final static MatchField<IpEcn> IP_ECN =
-            new MatchField<IpEcn>("ip_dscp");
+            new MatchField<IpEcn>("ip_dscp", MatchFields.IP_ECN);
     public final static MatchField<IpProtocol> IP_PROTO =
-            new MatchField<IpProtocol>("ip_proto");
+            new MatchField<IpProtocol>("ip_proto", MatchFields.IP_PROTO);
 
-    public final static MatchField<IPv4WithMask> IPV4_SRC =
-            new MatchField<IPv4WithMask>("ipv4_src");
-    public final static MatchField<IPv4WithMask> IPV4_DST =
-            new MatchField<IPv4WithMask>("ipv4_dst");
+    public final static MatchField<IPv4> IPV4_SRC =
+            new MatchField<IPv4>("ipv4_src", MatchFields.IPV4_SRC);
+    public final static MatchField<IPv4> IPV4_DST =
+            new MatchField<IPv4>("ipv4_dst", MatchFields.IPV4_DST);
 
     public final static MatchField<TransportPort> TCP_SRC = new MatchField<TransportPort>(
-            "tcp_src");
+            "tcp_src", MatchFields.TCP_SRC);
     public final static MatchField<TransportPort> TCP_DST = new MatchField<TransportPort>(
-            "tcp_dst");
+            "tcp_dst", MatchFields.TCP_DST);
 
     public final static MatchField<TransportPort> UDP_SRC = new MatchField<TransportPort>(
-            "udp_src");
+            "udp_src", MatchFields.UDP_SRC);
     public final static MatchField<TransportPort> UDP_DST = new MatchField<TransportPort>(
-            "udp_dst");
+            "udp_dst", MatchFields.UDP_DST);
 
     public final static MatchField<TransportPort> SCTP_SRC = new MatchField<TransportPort>(
-            "sctp_src");
+            "sctp_src", MatchFields.SCTP_SRC);
     public final static MatchField<TransportPort> SCTP_DST = new MatchField<TransportPort>(
-            "sctp_dst");
+            "sctp_dst", MatchFields.SCTP_DST);
 
     public final static MatchField<ICMPv4Type> ICMPV4_TYPE = new MatchField<ICMPv4Type>(
-            "icmpv4_src");
+            "icmpv4_src", MatchFields.ICMPV4_TYPE);
     public final static MatchField<ICMPv4Code> ICMPV4_CODE = new MatchField<ICMPv4Code>(
-            "icmpv4_dst");
+            "icmpv4_dst", MatchFields.ICMPV4_CODE);
 
     public final static MatchField<ArpOpcode> ARP_OP = new MatchField<ArpOpcode>(
-            "arp_op");
-    public final static MatchField<IPv4WithMask> ARP_SPA =
-            new MatchField<IPv4WithMask>("arp_spa");
-    public final static MatchField<IPv4WithMask> ARP_TPA =
-            new MatchField<IPv4WithMask>("arp_tpa");
-    public final static MatchField<Masked<MacAddress>> ARP_SHA =
-            new MatchField<Masked<MacAddress>>("arp_sha");
-    public final static MatchField<Masked<MacAddress>> ARP_THA =
-            new MatchField<Masked<MacAddress>>("arp_tha");
+            "arp_op", MatchFields.ARP_OP);
+    public final static MatchField<IPv4> ARP_SPA =
+            new MatchField<IPv4>("arp_spa", MatchFields.ARP_SPA);
+    public final static MatchField<IPv4> ARP_TPA =
+            new MatchField<IPv4>("arp_tpa", MatchFields.ARP_TPA);
+    public final static MatchField<MacAddress> ARP_SHA =
+            new MatchField<MacAddress>("arp_sha", MatchFields.ARP_SHA);
+    public final static MatchField<MacAddress> ARP_THA =
+            new MatchField<MacAddress>("arp_tha", MatchFields.ARP_THA);
 
-    public final static MatchField<IPv6WithMask> IPV6_SRC =
-            new MatchField<IPv6WithMask>("ipv6_src");
-    public final static MatchField<IPv6WithMask> IPV6_DST =
-            new MatchField<IPv6WithMask>("ipv6_dst");
+    public final static MatchField<IPv6> IPV6_SRC =
+            new MatchField<IPv6>("ipv6_src", MatchFields.IPV6_SRC);
+    public final static MatchField<IPv6> IPV6_DST =
+            new MatchField<IPv6>("ipv6_dst", MatchFields.IPV6_DST);
 
-    public final static MatchField<Masked<IPv6FlowLabel>> IPV6_FLABEL =
-            new MatchField<Masked<IPv6FlowLabel>>("ipv6_flabel");
+    public final static MatchField<IPv6FlowLabel> IPV6_FLABEL =
+            new MatchField<IPv6FlowLabel>("ipv6_flabel", MatchFields.IPV6_FLOWLABEL);
 
     public String getName() {
         return name;
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
new file mode 100644
index 0000000..21043f2
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchFields.java
@@ -0,0 +1,33 @@
+package org.openflow.protocol.match;
+
+public enum MatchFields {
+    IN_PORT,
+    PHYSICAL_PORT,
+    METADATA,
+    ETH_DST,
+    ETH_SRC,
+    ETH_TYPE,
+    VLAN_VID,
+    VLAN_PCP,
+    IP_DSCP,
+    IP_ECN,
+    IP_PROTO,
+    IPV4_SRC,
+    IPV4_DST,
+    TCP_SRC,
+    TCP_DST,
+    UDP_SRC,
+    UDP_DST,
+    SCTP_SRC,
+    SCTP_DST,
+    ICMPV4_TYPE,
+    ICMPV4_CODE,
+    ARP_OP,
+    ARP_SPA,
+    ARP_TPA,
+    ARP_SHA,
+    ARP_THA,
+    IPV6_SRC,
+    IPV6_DST,
+    IPV6_FLOWLABEL,
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/util/ChannelUtils.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/ver10/ChannelUtilsVer10.java
similarity index 75%
copy from java_gen/pre-written/src/main/java/org/openflow/util/ChannelUtils.java
copy to java_gen/pre-written/src/main/java/org/openflow/protocol/ver10/ChannelUtilsVer10.java
index dab6ff2..67c914d 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/util/ChannelUtils.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/ver10/ChannelUtilsVer10.java
@@ -1,4 +1,4 @@
-package org.openflow.util;
+package org.openflow.protocol.ver10;
 
 import java.util.List;
 
@@ -13,18 +13,21 @@
 import org.openflow.protocol.OFHelloElem;
 import org.openflow.protocol.OFMeterFeatures;
 import org.openflow.protocol.OFMeterStats;
+import org.openflow.protocol.OFObject;
 import org.openflow.protocol.OFPacketQueue;
 import org.openflow.protocol.OFPortStatsEntry;
 import org.openflow.protocol.OFQueueStatsEntry;
 import org.openflow.protocol.OFTableFeature;
 import org.openflow.protocol.OFTableFeatures;
 import org.openflow.protocol.OFTableStatsEntry;
+import org.openflow.protocol.Wildcards;
 import org.openflow.protocol.action.OFAction;
 import org.openflow.protocol.instruction.OFInstruction;
 import org.openflow.protocol.match.Match;
+import org.openflow.protocol.meterband.OFMeterBand;
+import org.openflow.protocol.oxm.OFOxm;
 import org.openflow.types.OFFlowModCmd;
 import org.openflow.types.OFHelloElement;
-import org.openflow.types.OFMeterBand;
 import org.openflow.types.OFPhysicalPort;
 
 import com.google.common.base.Charsets;
@@ -35,7 +38,7 @@
  * @author capveg
  */
 
-public class ChannelUtils {
+public class ChannelUtilsVer10 {
 
     static public byte[] readBytes(final ChannelBuffer bb, final int length) {
         byte byteArray[] = new byte[length];
@@ -43,18 +46,19 @@
         return byteArray;
     }
 
-    static public void writeBytes(final ChannelBuffer bb, final byte byteArray[]) {
+    static public void writeBytes(final ChannelBuffer bb,
+            final byte byteArray[]) {
         bb.writeBytes(byteArray);
     }
 
-    public static List<OFPhysicalPort> readPhysicalPortList(final ChannelBuffer bb,
-            final int i) {
+    public static List<OFPhysicalPort> readPhysicalPortList(
+            final ChannelBuffer bb, final int i) {
         // TODO Auto-generated method stub
         return null;
     }
 
-    public static List<OFInstruction> readInstructionsList(final ChannelBuffer bb,
-            final int i) {
+    public static List<OFInstruction> readInstructionsList(
+            final ChannelBuffer bb, final int i) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -69,12 +73,14 @@
         return null;
     }
 
-    public static List<OFAction> readActionsList(final ChannelBuffer bb, final int i) {
+    public static List<OFAction> readActionsList(final ChannelBuffer bb,
+            final int i) {
         // TODO Auto-generated method stub
         return null;
     }
 
-    public static List<OFBsnInterface> readBsnInterfaceList(final ChannelBuffer bb) {
+    public static List<OFBsnInterface> readBsnInterfaceList(
+            final ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -84,23 +90,25 @@
         return null;
     }
 
-    public static List<OFPacketQueue> readPacketQueueList(final ChannelBuffer bb,
-            final int i) {
+    public static List<OFPacketQueue> readPacketQueueList(
+            final ChannelBuffer bb, final int i) {
         // TODO Auto-generated method stub
         return null;
     }
 
-    public static List<OFHelloElement> readHelloElementList(final ChannelBuffer bb) {
+    public static List<OFHelloElement> readHelloElementList(
+            final ChannelBuffer bb) {
         // TODO Auto-generated method stub
         return null;
     }
 
-    public static List<OFBucket> readBucketList(final ChannelBuffer bb, final int i) {
+    public static List<OFBucket> readBucketList(final ChannelBuffer bb,
+            final int length) {
         // TODO Auto-generated method stub
         return null;
     }
 
-    public static List<OFMeterBand> readMeterBandList(final ChannelBuffer bb) {
+    public static List<OFMeterBand> readMeterBandList(final ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -110,9 +118,10 @@
 
     }
 
-    public static void writeList(ChannelBuffer bb, List<?> ports) {
-        // TODO Auto-generated method stub
-
+    public static void writeList(ChannelBuffer bb, List<? extends OFObject> objects) {
+        for(OFObject o : objects) {
+            o.writeTo(bb);
+        }
     }
 
     public static void writeOFFlowModCmd(ChannelBuffer bb, OFFlowModCmd command) {
@@ -126,18 +135,21 @@
         return new String(dst, Charsets.US_ASCII);
     }
 
-    public static void writeFixedLengthString(ChannelBuffer bb, String string, int length) {
+    public static void writeFixedLengthString(ChannelBuffer bb, String string,
+            int length) {
         int l = string.length();
-        if(l > length) {
-            throw new IllegalArgumentException("Error writing string: length="+l+" > max Length="+length);
+        if (l > length) {
+            throw new IllegalArgumentException("Error writing string: length="
+                    + l + " > max Length=" + length);
         }
         bb.writeBytes(string.getBytes(Charsets.US_ASCII));
-        if(l < length) {
+        if (l < length) {
             bb.writeZero(length - l);
         }
     }
 
-    public static void writeBsnInterfaceList(ChannelBuffer bb, List<OFBsnInterface> interfaces) {
+    public static void writeBsnInterfaceList(ChannelBuffer bb,
+            List<OFBsnInterface> interfaces) {
         // TODO Auto-generated method stub
 
     }
@@ -172,12 +184,12 @@
     }
 
     public static List<OFTableStatsEntry> readTableStatsEntryList(
-            ChannelBuffer bb) {
+            ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
 
-    public static List<OFFlowStatsEntry> readFlowStatsEntryList(ChannelBuffer bb) {
+    public static List<OFFlowStatsEntry> readFlowStatsEntryList(ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -195,7 +207,7 @@
     }
 
     public static List<OFGroupDescStatsEntry> readGroupDescStatsEntryList(
-            ChannelBuffer bb) {
+            ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -233,7 +245,7 @@
 
     }
 
-    public static List<OFPortStatsEntry> readPortStatsEntryList(ChannelBuffer bb) {
+    public static List<OFPortStatsEntry> readPortStatsEntryList(ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -244,7 +256,7 @@
 
     }
 
-    public static List<OFHelloElem> readHelloElemList(ChannelBuffer bb) {
+    public static List<OFHelloElem> readHelloElemList(ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -268,7 +280,7 @@
     }
 
     public static List<OFQueueStatsEntry> readQueueStatsEntryList(
-            ChannelBuffer bb) {
+            ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -290,7 +302,7 @@
 
     }
 
-    public static List<OFMeterStats> readMeterStatsList(ChannelBuffer bb) {
+    public static List<OFMeterStats> readMeterStatsList(ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -301,7 +313,7 @@
 
     }
 
-    public static List<OFTableFeatures> readTableFeaturesList(ChannelBuffer bb) {
+    public static List<OFTableFeatures> readTableFeaturesList(ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -312,5 +324,39 @@
 
     }
 
+    public static OFOxm readOFOxm(ChannelBuffer bb) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public static void writeOFOxm(ChannelBuffer bb, OFOxm field) {
+        // TODO Auto-generated method stub
+
+    }
+
+    public static void writeOxmList(ChannelBuffer bb, List<OFOxm> oxmList) {
+        for(OFOxm o: oxmList) {
+            o.writeTo(bb);
+        }
+    }
+
+    public static List<OFOxm> readOxmList(ChannelBuffer bb, int length) {
+        return null;
+    }
+
+    public static Wildcards readWildcards(ChannelBuffer bb) {
+        return Wildcards.of(bb.readInt());
+    }
+
+    public static void writeWildcards(ChannelBuffer bb, Wildcards wildcards) {
+        // TODO Auto-generated method stub
+
+    }
+
+    public static void writePhysicalPortList(ChannelBuffer bb,
+            List<OFPhysicalPort> ports) {
+        // TODO Auto-generated method stub
+
+    }
 
 }
diff --git a/java_gen/pre-written/src/main/java/org/openflow/util/ChannelUtils.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/ver11/ChannelUtilsVer11.java
similarity index 75%
copy from java_gen/pre-written/src/main/java/org/openflow/util/ChannelUtils.java
copy to java_gen/pre-written/src/main/java/org/openflow/protocol/ver11/ChannelUtilsVer11.java
index dab6ff2..1a0df58 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/util/ChannelUtils.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/ver11/ChannelUtilsVer11.java
@@ -1,4 +1,4 @@
-package org.openflow.util;
+package org.openflow.protocol.ver11;
 
 import java.util.List;
 
@@ -13,18 +13,21 @@
 import org.openflow.protocol.OFHelloElem;
 import org.openflow.protocol.OFMeterFeatures;
 import org.openflow.protocol.OFMeterStats;
+import org.openflow.protocol.OFObject;
 import org.openflow.protocol.OFPacketQueue;
 import org.openflow.protocol.OFPortStatsEntry;
 import org.openflow.protocol.OFQueueStatsEntry;
 import org.openflow.protocol.OFTableFeature;
 import org.openflow.protocol.OFTableFeatures;
 import org.openflow.protocol.OFTableStatsEntry;
+import org.openflow.protocol.Wildcards;
 import org.openflow.protocol.action.OFAction;
 import org.openflow.protocol.instruction.OFInstruction;
 import org.openflow.protocol.match.Match;
+import org.openflow.protocol.meterband.OFMeterBand;
+import org.openflow.protocol.oxm.OFOxm;
 import org.openflow.types.OFFlowModCmd;
 import org.openflow.types.OFHelloElement;
-import org.openflow.types.OFMeterBand;
 import org.openflow.types.OFPhysicalPort;
 
 import com.google.common.base.Charsets;
@@ -35,7 +38,7 @@
  * @author capveg
  */
 
-public class ChannelUtils {
+public class ChannelUtilsVer11 {
 
     static public byte[] readBytes(final ChannelBuffer bb, final int length) {
         byte byteArray[] = new byte[length];
@@ -43,18 +46,19 @@
         return byteArray;
     }
 
-    static public void writeBytes(final ChannelBuffer bb, final byte byteArray[]) {
+    static public void writeBytes(final ChannelBuffer bb,
+            final byte byteArray[]) {
         bb.writeBytes(byteArray);
     }
 
-    public static List<OFPhysicalPort> readPhysicalPortList(final ChannelBuffer bb,
-            final int i) {
+    public static List<OFPhysicalPort> readPhysicalPortList(
+            final ChannelBuffer bb, final int i) {
         // TODO Auto-generated method stub
         return null;
     }
 
-    public static List<OFInstruction> readInstructionsList(final ChannelBuffer bb,
-            final int i) {
+    public static List<OFInstruction> readInstructionsList(
+            final ChannelBuffer bb, final int i) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -69,12 +73,14 @@
         return null;
     }
 
-    public static List<OFAction> readActionsList(final ChannelBuffer bb, final int i) {
+    public static List<OFAction> readActionsList(final ChannelBuffer bb,
+            final int i) {
         // TODO Auto-generated method stub
         return null;
     }
 
-    public static List<OFBsnInterface> readBsnInterfaceList(final ChannelBuffer bb) {
+    public static List<OFBsnInterface> readBsnInterfaceList(
+            final ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -84,23 +90,25 @@
         return null;
     }
 
-    public static List<OFPacketQueue> readPacketQueueList(final ChannelBuffer bb,
-            final int i) {
+    public static List<OFPacketQueue> readPacketQueueList(
+            final ChannelBuffer bb, final int i) {
         // TODO Auto-generated method stub
         return null;
     }
 
-    public static List<OFHelloElement> readHelloElementList(final ChannelBuffer bb) {
+    public static List<OFHelloElement> readHelloElementList(
+            final ChannelBuffer bb) {
         // TODO Auto-generated method stub
         return null;
     }
 
-    public static List<OFBucket> readBucketList(final ChannelBuffer bb, final int i) {
+    public static List<OFBucket> readBucketList(final ChannelBuffer bb,
+            final int length) {
         // TODO Auto-generated method stub
         return null;
     }
 
-    public static List<OFMeterBand> readMeterBandList(final ChannelBuffer bb) {
+    public static List<OFMeterBand> readMeterBandList(final ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -110,9 +118,10 @@
 
     }
 
-    public static void writeList(ChannelBuffer bb, List<?> ports) {
-        // TODO Auto-generated method stub
-
+    public static void writeList(ChannelBuffer bb, List<? extends OFObject> objects) {
+        for(OFObject o : objects) {
+            o.writeTo(bb);
+        }
     }
 
     public static void writeOFFlowModCmd(ChannelBuffer bb, OFFlowModCmd command) {
@@ -126,18 +135,21 @@
         return new String(dst, Charsets.US_ASCII);
     }
 
-    public static void writeFixedLengthString(ChannelBuffer bb, String string, int length) {
+    public static void writeFixedLengthString(ChannelBuffer bb, String string,
+            int length) {
         int l = string.length();
-        if(l > length) {
-            throw new IllegalArgumentException("Error writing string: length="+l+" > max Length="+length);
+        if (l > length) {
+            throw new IllegalArgumentException("Error writing string: length="
+                    + l + " > max Length=" + length);
         }
         bb.writeBytes(string.getBytes(Charsets.US_ASCII));
-        if(l < length) {
+        if (l < length) {
             bb.writeZero(length - l);
         }
     }
 
-    public static void writeBsnInterfaceList(ChannelBuffer bb, List<OFBsnInterface> interfaces) {
+    public static void writeBsnInterfaceList(ChannelBuffer bb,
+            List<OFBsnInterface> interfaces) {
         // TODO Auto-generated method stub
 
     }
@@ -172,12 +184,12 @@
     }
 
     public static List<OFTableStatsEntry> readTableStatsEntryList(
-            ChannelBuffer bb) {
+            ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
 
-    public static List<OFFlowStatsEntry> readFlowStatsEntryList(ChannelBuffer bb) {
+    public static List<OFFlowStatsEntry> readFlowStatsEntryList(ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -195,7 +207,7 @@
     }
 
     public static List<OFGroupDescStatsEntry> readGroupDescStatsEntryList(
-            ChannelBuffer bb) {
+            ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -233,7 +245,7 @@
 
     }
 
-    public static List<OFPortStatsEntry> readPortStatsEntryList(ChannelBuffer bb) {
+    public static List<OFPortStatsEntry> readPortStatsEntryList(ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -244,7 +256,7 @@
 
     }
 
-    public static List<OFHelloElem> readHelloElemList(ChannelBuffer bb) {
+    public static List<OFHelloElem> readHelloElemList(ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -256,7 +268,7 @@
     }
 
     public static List<OFGroupStatsEntry> readGroupStatsEntryList(
-            ChannelBuffer bb) {
+            ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -268,7 +280,7 @@
     }
 
     public static List<OFQueueStatsEntry> readQueueStatsEntryList(
-            ChannelBuffer bb) {
+            ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -290,7 +302,7 @@
 
     }
 
-    public static List<OFMeterStats> readMeterStatsList(ChannelBuffer bb) {
+    public static List<OFMeterStats> readMeterStatsList(ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -301,7 +313,7 @@
 
     }
 
-    public static List<OFTableFeatures> readTableFeaturesList(ChannelBuffer bb) {
+    public static List<OFTableFeatures> readTableFeaturesList(ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -312,5 +324,40 @@
 
     }
 
+    public static OFOxm readOFOxm(ChannelBuffer bb) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public static void writeOFOxm(ChannelBuffer bb, OFOxm field) {
+        // TODO Auto-generated method stub
+
+    }
+
+    public static void writeOxmList(ChannelBuffer bb, List<OFOxm> oxmList) {
+        for(OFOxm o: oxmList) {
+            o.writeTo(bb);
+        }
+    }
+
+    public static List<OFOxm> readOxmList(ChannelBuffer bb, int length) {
+        return null;
+    }
+
+    public static void writePhysicalPortList(ChannelBuffer bb,
+            List<OFPhysicalPort> ports) {
+        // TODO Auto-generated method stub
+
+    }
+
+    public static Wildcards readWildcards(ChannelBuffer bb) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public static void writeWildcards(ChannelBuffer bb, Wildcards wildcards) {
+        // TODO Auto-generated method stub
+
+    }
 
 }
diff --git a/java_gen/pre-written/src/main/java/org/openflow/util/ChannelUtils.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/ver12/ChannelUtilsVer12.java
similarity index 77%
rename from java_gen/pre-written/src/main/java/org/openflow/util/ChannelUtils.java
rename to java_gen/pre-written/src/main/java/org/openflow/protocol/ver12/ChannelUtilsVer12.java
index dab6ff2..a66fb70 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/util/ChannelUtils.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/ver12/ChannelUtilsVer12.java
@@ -1,4 +1,4 @@
-package org.openflow.util;
+package org.openflow.protocol.ver12;
 
 import java.util.List;
 
@@ -13,6 +13,7 @@
 import org.openflow.protocol.OFHelloElem;
 import org.openflow.protocol.OFMeterFeatures;
 import org.openflow.protocol.OFMeterStats;
+import org.openflow.protocol.OFObject;
 import org.openflow.protocol.OFPacketQueue;
 import org.openflow.protocol.OFPortStatsEntry;
 import org.openflow.protocol.OFQueueStatsEntry;
@@ -22,9 +23,10 @@
 import org.openflow.protocol.action.OFAction;
 import org.openflow.protocol.instruction.OFInstruction;
 import org.openflow.protocol.match.Match;
+import org.openflow.protocol.meterband.OFMeterBand;
+import org.openflow.protocol.oxm.OFOxm;
 import org.openflow.types.OFFlowModCmd;
 import org.openflow.types.OFHelloElement;
-import org.openflow.types.OFMeterBand;
 import org.openflow.types.OFPhysicalPort;
 
 import com.google.common.base.Charsets;
@@ -35,7 +37,7 @@
  * @author capveg
  */
 
-public class ChannelUtils {
+public class ChannelUtilsVer12 {
 
     static public byte[] readBytes(final ChannelBuffer bb, final int length) {
         byte byteArray[] = new byte[length];
@@ -43,18 +45,19 @@
         return byteArray;
     }
 
-    static public void writeBytes(final ChannelBuffer bb, final byte byteArray[]) {
+    static public void writeBytes(final ChannelBuffer bb,
+            final byte byteArray[]) {
         bb.writeBytes(byteArray);
     }
 
-    public static List<OFPhysicalPort> readPhysicalPortList(final ChannelBuffer bb,
-            final int i) {
+    public static List<OFPhysicalPort> readPhysicalPortList(
+            final ChannelBuffer bb, final int i) {
         // TODO Auto-generated method stub
         return null;
     }
 
-    public static List<OFInstruction> readInstructionsList(final ChannelBuffer bb,
-            final int i) {
+    public static List<OFInstruction> readInstructionsList(
+            final ChannelBuffer bb, final int i) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -69,12 +72,14 @@
         return null;
     }
 
-    public static List<OFAction> readActionsList(final ChannelBuffer bb, final int i) {
+    public static List<OFAction> readActionsList(final ChannelBuffer bb,
+            final int i) {
         // TODO Auto-generated method stub
         return null;
     }
 
-    public static List<OFBsnInterface> readBsnInterfaceList(final ChannelBuffer bb) {
+    public static List<OFBsnInterface> readBsnInterfaceList(
+            final ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -84,23 +89,25 @@
         return null;
     }
 
-    public static List<OFPacketQueue> readPacketQueueList(final ChannelBuffer bb,
-            final int i) {
+    public static List<OFPacketQueue> readPacketQueueList(
+            final ChannelBuffer bb, final int i) {
         // TODO Auto-generated method stub
         return null;
     }
 
-    public static List<OFHelloElement> readHelloElementList(final ChannelBuffer bb) {
+    public static List<OFHelloElement> readHelloElementList(
+            final ChannelBuffer bb) {
         // TODO Auto-generated method stub
         return null;
     }
 
-    public static List<OFBucket> readBucketList(final ChannelBuffer bb, final int i) {
+    public static List<OFBucket> readBucketList(final ChannelBuffer bb,
+            final int length) {
         // TODO Auto-generated method stub
         return null;
     }
 
-    public static List<OFMeterBand> readMeterBandList(final ChannelBuffer bb) {
+    public static List<OFMeterBand> readMeterBandList(final ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -110,9 +117,10 @@
 
     }
 
-    public static void writeList(ChannelBuffer bb, List<?> ports) {
-        // TODO Auto-generated method stub
-
+    public static void writeList(ChannelBuffer bb, List<? extends OFObject> objects) {
+        for(OFObject o : objects) {
+            o.writeTo(bb);
+        }
     }
 
     public static void writeOFFlowModCmd(ChannelBuffer bb, OFFlowModCmd command) {
@@ -126,18 +134,21 @@
         return new String(dst, Charsets.US_ASCII);
     }
 
-    public static void writeFixedLengthString(ChannelBuffer bb, String string, int length) {
+    public static void writeFixedLengthString(ChannelBuffer bb, String string,
+            int length) {
         int l = string.length();
-        if(l > length) {
-            throw new IllegalArgumentException("Error writing string: length="+l+" > max Length="+length);
+        if (l > length) {
+            throw new IllegalArgumentException("Error writing string: length="
+                    + l + " > max Length=" + length);
         }
         bb.writeBytes(string.getBytes(Charsets.US_ASCII));
-        if(l < length) {
+        if (l < length) {
             bb.writeZero(length - l);
         }
     }
 
-    public static void writeBsnInterfaceList(ChannelBuffer bb, List<OFBsnInterface> interfaces) {
+    public static void writeBsnInterfaceList(ChannelBuffer bb,
+            List<OFBsnInterface> interfaces) {
         // TODO Auto-generated method stub
 
     }
@@ -172,12 +183,12 @@
     }
 
     public static List<OFTableStatsEntry> readTableStatsEntryList(
-            ChannelBuffer bb) {
+            ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
 
-    public static List<OFFlowStatsEntry> readFlowStatsEntryList(ChannelBuffer bb) {
+    public static List<OFFlowStatsEntry> readFlowStatsEntryList(ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -195,7 +206,7 @@
     }
 
     public static List<OFGroupDescStatsEntry> readGroupDescStatsEntryList(
-            ChannelBuffer bb) {
+            ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -233,7 +244,7 @@
 
     }
 
-    public static List<OFPortStatsEntry> readPortStatsEntryList(ChannelBuffer bb) {
+    public static List<OFPortStatsEntry> readPortStatsEntryList(ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -244,7 +255,7 @@
 
     }
 
-    public static List<OFHelloElem> readHelloElemList(ChannelBuffer bb) {
+    public static List<OFHelloElem> readHelloElemList(ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -256,7 +267,7 @@
     }
 
     public static List<OFGroupStatsEntry> readGroupStatsEntryList(
-            ChannelBuffer bb) {
+            ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -268,7 +279,7 @@
     }
 
     public static List<OFQueueStatsEntry> readQueueStatsEntryList(
-            ChannelBuffer bb) {
+            ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -290,7 +301,7 @@
 
     }
 
-    public static List<OFMeterStats> readMeterStatsList(ChannelBuffer bb) {
+    public static List<OFMeterStats> readMeterStatsList(ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -301,7 +312,7 @@
 
     }
 
-    public static List<OFTableFeatures> readTableFeaturesList(ChannelBuffer bb) {
+    public static List<OFTableFeatures> readTableFeaturesList(ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -312,5 +323,30 @@
 
     }
 
+    public static OFOxm readOFOxm(ChannelBuffer bb) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public static void writeOFOxm(ChannelBuffer bb, OFOxm field) {
+        // TODO Auto-generated method stub
+
+    }
+
+    public static void writeOxmList(ChannelBuffer bb, List<OFOxm> oxmList) {
+        for(OFOxm o: oxmList) {
+            o.writeTo(bb);
+        }
+    }
+
+    public static List<OFOxm> readOxmList(ChannelBuffer bb, int length) {
+        return null;
+    }
+
+    public static void writePhysicalPortList(ChannelBuffer bb,
+            List<OFPhysicalPort> ports) {
+        // TODO Auto-generated method stub
+
+    }
 
 }
diff --git a/java_gen/pre-written/src/main/java/org/openflow/util/ChannelUtils.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/ver13/ChannelUtilsVer13.java
similarity index 76%
copy from java_gen/pre-written/src/main/java/org/openflow/util/ChannelUtils.java
copy to java_gen/pre-written/src/main/java/org/openflow/protocol/ver13/ChannelUtilsVer13.java
index dab6ff2..73b240e 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/util/ChannelUtils.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/ver13/ChannelUtilsVer13.java
@@ -1,8 +1,9 @@
-package org.openflow.util;
+package org.openflow.protocol.ver13;
 
 import java.util.List;
 
 import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.exceptions.OFParseError;
 import org.openflow.protocol.OFBsnInterface;
 import org.openflow.protocol.OFBsnVportQInQ;
 import org.openflow.protocol.OFBsnVportQInQT;
@@ -13,6 +14,7 @@
 import org.openflow.protocol.OFHelloElem;
 import org.openflow.protocol.OFMeterFeatures;
 import org.openflow.protocol.OFMeterStats;
+import org.openflow.protocol.OFObject;
 import org.openflow.protocol.OFPacketQueue;
 import org.openflow.protocol.OFPortStatsEntry;
 import org.openflow.protocol.OFQueueStatsEntry;
@@ -22,9 +24,10 @@
 import org.openflow.protocol.action.OFAction;
 import org.openflow.protocol.instruction.OFInstruction;
 import org.openflow.protocol.match.Match;
+import org.openflow.protocol.meterband.OFMeterBand;
+import org.openflow.protocol.oxm.OFOxm;
 import org.openflow.types.OFFlowModCmd;
 import org.openflow.types.OFHelloElement;
-import org.openflow.types.OFMeterBand;
 import org.openflow.types.OFPhysicalPort;
 
 import com.google.common.base.Charsets;
@@ -35,7 +38,7 @@
  * @author capveg
  */
 
-public class ChannelUtils {
+public class ChannelUtilsVer13 {
 
     static public byte[] readBytes(final ChannelBuffer bb, final int length) {
         byte byteArray[] = new byte[length];
@@ -43,25 +46,25 @@
         return byteArray;
     }
 
-    static public void writeBytes(final ChannelBuffer bb, final byte byteArray[]) {
+    static public void writeBytes(final ChannelBuffer bb,
+            final byte byteArray[]) {
         bb.writeBytes(byteArray);
     }
 
-    public static List<OFPhysicalPort> readPhysicalPortList(final ChannelBuffer bb,
-            final int i) {
+    public static List<OFPhysicalPort> readPhysicalPortList(
+            final ChannelBuffer bb, final int i) {
         // TODO Auto-generated method stub
         return null;
     }
 
-    public static List<OFInstruction> readInstructionsList(final ChannelBuffer bb,
-            final int i) {
+    public static List<OFInstruction> readInstructionsList(
+            final ChannelBuffer bb, final int i) {
         // TODO Auto-generated method stub
         return null;
     }
 
-    public static Match readOFMatch(final ChannelBuffer bb) {
-        // TODO Auto-generated method stub
-        return null;
+    public static Match readOFMatch(final ChannelBuffer bb) throws OFParseError {
+        return OFMatchV3Ver13.READER.readFrom(bb);
     }
 
     public static OFFlowModCmd readOFFlowModCmd(final ChannelBuffer bb) {
@@ -69,12 +72,14 @@
         return null;
     }
 
-    public static List<OFAction> readActionsList(final ChannelBuffer bb, final int i) {
+    public static List<OFAction> readActionsList(final ChannelBuffer bb,
+            final int i) {
         // TODO Auto-generated method stub
         return null;
     }
 
-    public static List<OFBsnInterface> readBsnInterfaceList(final ChannelBuffer bb) {
+    public static List<OFBsnInterface> readBsnInterfaceList(
+            final ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -84,35 +89,37 @@
         return null;
     }
 
-    public static List<OFPacketQueue> readPacketQueueList(final ChannelBuffer bb,
-            final int i) {
+    public static List<OFPacketQueue> readPacketQueueList(
+            final ChannelBuffer bb, final int i) {
         // TODO Auto-generated method stub
         return null;
     }
 
-    public static List<OFHelloElement> readHelloElementList(final ChannelBuffer bb) {
+    public static List<OFHelloElement> readHelloElementList(
+            final ChannelBuffer bb) {
         // TODO Auto-generated method stub
         return null;
     }
 
-    public static List<OFBucket> readBucketList(final ChannelBuffer bb, final int i) {
+    public static List<OFBucket> readBucketList(final ChannelBuffer bb,
+            final int length) {
         // TODO Auto-generated method stub
         return null;
     }
 
-    public static List<OFMeterBand> readMeterBandList(final ChannelBuffer bb) {
+    public static List<OFMeterBand> readMeterBandList(final ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
 
     public static void writeOFMatch(ChannelBuffer bb, Match match) {
-        // TODO Auto-generated method stub
-
+        match.writeTo(bb);
     }
 
-    public static void writeList(ChannelBuffer bb, List<?> ports) {
-        // TODO Auto-generated method stub
-
+    public static void writeList(ChannelBuffer bb, List<? extends OFObject> objects) {
+        for(OFObject o : objects) {
+            o.writeTo(bb);
+        }
     }
 
     public static void writeOFFlowModCmd(ChannelBuffer bb, OFFlowModCmd command) {
@@ -126,18 +133,21 @@
         return new String(dst, Charsets.US_ASCII);
     }
 
-    public static void writeFixedLengthString(ChannelBuffer bb, String string, int length) {
+    public static void writeFixedLengthString(ChannelBuffer bb, String string,
+            int length) {
         int l = string.length();
-        if(l > length) {
-            throw new IllegalArgumentException("Error writing string: length="+l+" > max Length="+length);
+        if (l > length) {
+            throw new IllegalArgumentException("Error writing string: length="
+                    + l + " > max Length=" + length);
         }
         bb.writeBytes(string.getBytes(Charsets.US_ASCII));
-        if(l < length) {
+        if (l < length) {
             bb.writeZero(length - l);
         }
     }
 
-    public static void writeBsnInterfaceList(ChannelBuffer bb, List<OFBsnInterface> interfaces) {
+    public static void writeBsnInterfaceList(ChannelBuffer bb,
+            List<OFBsnInterface> interfaces) {
         // TODO Auto-generated method stub
 
     }
@@ -172,12 +182,12 @@
     }
 
     public static List<OFTableStatsEntry> readTableStatsEntryList(
-            ChannelBuffer bb) {
+            ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
 
-    public static List<OFFlowStatsEntry> readFlowStatsEntryList(ChannelBuffer bb) {
+    public static List<OFFlowStatsEntry> readFlowStatsEntryList(ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -195,7 +205,7 @@
     }
 
     public static List<OFGroupDescStatsEntry> readGroupDescStatsEntryList(
-            ChannelBuffer bb) {
+            ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -233,7 +243,7 @@
 
     }
 
-    public static List<OFPortStatsEntry> readPortStatsEntryList(ChannelBuffer bb) {
+    public static List<OFPortStatsEntry> readPortStatsEntryList(ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -244,7 +254,7 @@
 
     }
 
-    public static List<OFHelloElem> readHelloElemList(ChannelBuffer bb) {
+    public static List<OFHelloElem> readHelloElemList(ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -256,7 +266,7 @@
     }
 
     public static List<OFGroupStatsEntry> readGroupStatsEntryList(
-            ChannelBuffer bb) {
+            ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -268,7 +278,7 @@
     }
 
     public static List<OFQueueStatsEntry> readQueueStatsEntryList(
-            ChannelBuffer bb) {
+            ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -290,7 +300,7 @@
 
     }
 
-    public static List<OFMeterStats> readMeterStatsList(ChannelBuffer bb) {
+    public static List<OFMeterStats> readMeterStatsList(ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -301,7 +311,7 @@
 
     }
 
-    public static List<OFTableFeatures> readTableFeaturesList(ChannelBuffer bb) {
+    public static List<OFTableFeatures> readTableFeaturesList(ChannelBuffer bb, int length) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -312,5 +322,30 @@
 
     }
 
+    public static OFOxm readOFOxm(ChannelBuffer bb) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public static void writeOFOxm(ChannelBuffer bb, OFOxm field) {
+        // TODO Auto-generated method stub
+
+    }
+
+    public static void writeOxmList(ChannelBuffer bb, List<OFOxm> oxmList) {
+        for(OFOxm o: oxmList) {
+            o.writeTo(bb);
+        }
+    }
+
+    public static List<OFOxm> readOxmList(ChannelBuffer bb, int length) {
+        return null;
+    }
+
+    public static void writePhysicalPortList(ChannelBuffer bb,
+            List<OFPhysicalPort> entries) {
+        // TODO Auto-generated method stub
+
+    }
 
 }
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/ArpOpcode.java b/java_gen/pre-written/src/main/java/org/openflow/types/ArpOpcode.java
index 852aa20..6ebf447 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/ArpOpcode.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/ArpOpcode.java
@@ -2,7 +2,7 @@
 
 import org.jboss.netty.buffer.ChannelBuffer;
 
-public class ArpOpcode implements OFValueType {
+public class ArpOpcode implements OFValueType<ArpOpcode> {
 
     final static int LENGTH = 2;
 
@@ -142,4 +142,14 @@
     public static ArpOpcode read2Bytes(ChannelBuffer c) {
         return ArpOpcode.of(c.readUnsignedShort());
     }
+
+    @Override
+    public ArpOpcode applyMask(ArpOpcode mask) {
+        return ArpOpcode.of(this.opcode & mask.opcode);
+    }
+    
+    public int getOpCode() {
+        return opcode;
+    }
+    
 }
\ No newline at end of file
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/EthType.java b/java_gen/pre-written/src/main/java/org/openflow/types/EthType.java
index f0f0a2c..ea16e67 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/EthType.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/EthType.java
@@ -8,7 +8,7 @@
  * 
  * @author Yotam Harchol (yotam.harchol@bigswitch.com)
  */
-public class EthType implements OFValueType {
+public class EthType implements OFValueType<EthType> {
     static final int LENGTH = 2;
 
     private final int rawValue;
@@ -235,4 +235,14 @@
         return EthType.of(c.readUnsignedShort());
     }
 
+    @Override
+    public EthType applyMask(EthType mask) {
+        return EthType.of(this.rawValue & mask.rawValue);
+    }
+    
+    public int getValue() {
+        return rawValue;
+    }
+
+    
 }
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/ICMPv4Code.java b/java_gen/pre-written/src/main/java/org/openflow/types/ICMPv4Code.java
index 147b5f7..42cc5be 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/ICMPv4Code.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/ICMPv4Code.java
@@ -7,7 +7,7 @@
  * @author Yotam Harchol (yotam.harchol@bigswitch.com)
  *
  */
-public class ICMPv4Code implements OFValueType {
+public class ICMPv4Code implements OFValueType<ICMPv4Code> {
 
     final static int LENGTH = 1;
     final static short MAX_CODE = 0xFF;
@@ -41,4 +41,10 @@
         return ICMPv4Code.of(c.readUnsignedByte());
     }
 
+    @Override
+    public ICMPv4Code applyMask(ICMPv4Code mask) {
+        return ICMPv4Code.of((short)(this.code & mask.code));
+    }
+
+    
 }
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/ICMPv4Type.java b/java_gen/pre-written/src/main/java/org/openflow/types/ICMPv4Type.java
index 01d6e8f..b1bbdc0 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/ICMPv4Type.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/ICMPv4Type.java
@@ -2,7 +2,7 @@
 
 import org.jboss.netty.buffer.ChannelBuffer;
 
-public class ICMPv4Type implements OFValueType {
+public class ICMPv4Type implements OFValueType<ICMPv4Type> {
 
     final static int LENGTH = 1;
 
@@ -155,4 +155,10 @@
         return ICMPv4Type.of(c.readUnsignedByte());
     }
 
+    @Override
+    public ICMPv4Type applyMask(ICMPv4Type mask) {
+        return ICMPv4Type.of((short)(this.type & mask.type));
+    }
+
+    
 }
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/IPv4.java b/java_gen/pre-written/src/main/java/org/openflow/types/IPv4.java
index 78b8dd2..f89f683 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/IPv4.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/IPv4.java
@@ -9,7 +9,7 @@
  *
  * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
  */
-public class IPv4 implements OFValueType {
+public class IPv4 implements OFValueType<IPv4> {
     static final int LENGTH = 4;
     private final int rawValue;
 
@@ -122,5 +122,11 @@
     public static IPv4 read4Bytes(ChannelBuffer c) {
         return IPv4.of(c.readInt());
     }
+
+    @Override
+    public IPv4 applyMask(IPv4 mask) {
+        return IPv4.of(this.rawValue & mask.rawValue);
+    }
+
     
 }
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 afb89ed..c24c4fd 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 OFValueType<?> ofPossiblyMasked(final String string) {
         int slashPos;
         String ip = string;
         int maskBits = 0;
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/IPv6.java b/java_gen/pre-written/src/main/java/org/openflow/types/IPv6.java
index e3166fd..200a33d 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/IPv6.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/IPv6.java
@@ -11,7 +11,7 @@
  *
  * @author Andreas Wundsam <andreas.wundsam@teleteach.de>
  */
-public class IPv6 implements OFValueType {
+public class IPv6 implements OFValueType<IPv6> {
     static final int LENGTH = 16;
     private final long raw1;
     private final long raw2;
@@ -278,4 +278,9 @@
     public static IPv6 read16Bytes(ChannelBuffer c) throws OFParseError {
         return IPv6.of(c.readLong(), c.readLong());
     }
+
+    @Override
+    public IPv6 applyMask(IPv6 mask) {
+        return IPv6.of(this.raw1 & mask.raw1, this.raw2 & mask.raw2);
+    }
 }
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/IPv6FlowLabel.java b/java_gen/pre-written/src/main/java/org/openflow/types/IPv6FlowLabel.java
index 6d9bfb5..d49e4e2 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/IPv6FlowLabel.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/IPv6FlowLabel.java
@@ -3,7 +3,7 @@
 import org.jboss.netty.buffer.ChannelBuffer;
 import org.openflow.exceptions.OFParseError;
 
-public class IPv6FlowLabel implements OFValueType {
+public class IPv6FlowLabel implements OFValueType<IPv6FlowLabel> {
 
     static final int LENGTH = 4;
     
@@ -53,4 +53,12 @@
         return IPv6FlowLabel.of((int)(c.readUnsignedInt() & 0xFFFFFFFF));
     }
 
+    @Override
+    public IPv6FlowLabel applyMask(IPv6FlowLabel mask) {
+        return IPv6FlowLabel.of(this.label & mask.label);
+    }
+
+    public int getIPv6FlowLabelValue() {
+        return label;
+    }
 }
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 f809d67..72319e3 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 OFValueType<?> ofPossiblyMasked(final String string) {
         int slashPos;
         String ip = string;
         int maskBits = 0;
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/IpDscp.java b/java_gen/pre-written/src/main/java/org/openflow/types/IpDscp.java
index 033e574..44e6296 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/IpDscp.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/IpDscp.java
@@ -3,7 +3,7 @@
 import org.jboss.netty.buffer.ChannelBuffer;
 import org.openflow.exceptions.OFParseError;
 
-public enum IpDscp implements OFValueType {
+public enum IpDscp implements OFValueType<IpDscp> {
     DSCP_0((byte)0),
     DSCP_1((byte)1),
     DSCP_2((byte)2),
@@ -230,4 +230,12 @@
         return IpDscp.of((byte)(c.readUnsignedByte()));
     }
 
+    @Override
+    public IpDscp applyMask(IpDscp mask) {
+        return IpDscp.of((byte)(this.dscp & mask.dscp));
+    }
+
+    public byte getDscpValue() {
+        return dscp;
+    }
 }
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/IpEcn.java b/java_gen/pre-written/src/main/java/org/openflow/types/IpEcn.java
index b261d41..90600df 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/IpEcn.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/IpEcn.java
@@ -3,7 +3,7 @@
 import org.jboss.netty.buffer.ChannelBuffer;
 import org.openflow.exceptions.OFParseError;
 
-public enum IpEcn implements OFValueType {
+public enum IpEcn implements OFValueType<IpEcn> {
     ECN_00((byte)0),
     ECN_01((byte)1),
     ECN_10((byte)2),
@@ -50,4 +50,12 @@
         return IpEcn.of((byte)(c.readUnsignedByte()));
     }
 
+    @Override
+    public IpEcn applyMask(IpEcn mask) {
+        return IpEcn.of((byte)(this.ecn & mask.ecn));
+    }
+
+    public byte getEcnValue() {
+        return ecn;
+    }
 }
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/IpProtocol.java b/java_gen/pre-written/src/main/java/org/openflow/types/IpProtocol.java
index 436db1d..f40eded 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/IpProtocol.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/IpProtocol.java
@@ -7,7 +7,7 @@
  * 
  * @author Yotam Harchol (yotam.harchol@bigswitch.com)
  */
-public class IpProtocol implements OFValueType {
+public class IpProtocol implements OFValueType<IpProtocol> {
 
     static final short MAX_PROTO = 0xFF;
     static final int LENGTH = 1;
@@ -632,4 +632,14 @@
     public static IpProtocol readByte(ChannelBuffer c) {
         return IpProtocol.of(c.readUnsignedByte());
     }
+
+    @Override
+    public IpProtocol applyMask(IpProtocol mask) {
+        return IpProtocol.of((short)(this.proto & mask.proto));
+    }
+
+    public short getIpProtocolNumber() {
+        return proto;
+    }
+    
 }
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/MacAddress.java b/java_gen/pre-written/src/main/java/org/openflow/types/MacAddress.java
index a18dff3..cb8ce84 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/MacAddress.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/MacAddress.java
@@ -10,7 +10,7 @@
  * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
  */
 
-public class MacAddress implements OFValueType {
+public class MacAddress implements OFValueType<MacAddress> {
     static final int MacAddrLen = 6;
     private final long rawValue;
 
@@ -116,6 +116,11 @@
         long raw = c.readUnsignedInt() << 16 | c.readUnsignedShort();
         return MacAddress.of(raw);
     }
+
+    @Override
+    public MacAddress applyMask(MacAddress mask) {
+        return MacAddress.of(this.rawValue & mask.rawValue);
+    }
     
     
 
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/Masked.java b/java_gen/pre-written/src/main/java/org/openflow/types/Masked.java
index 011bae8..433ca9d 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/Masked.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/Masked.java
@@ -2,12 +2,12 @@
 
 
 
-public class Masked<T extends OFValueType> implements OFValueType {
+public class Masked<T extends OFValueType<T>> implements OFValueType<Masked<T>> {
     protected T value;
     protected T mask;
     
     protected Masked(T value, T mask) {
-        this.value = value;
+        this.value = value.applyMask(mask);
         this.mask = mask;
     }
     
@@ -18,6 +18,10 @@
     public T getMask() {
         return mask;
     }
+    
+    public static <T extends OFValueType<T>> Masked<T> of(T value, T mask) {
+        return new Masked<T>(value, mask);
+    }
 
     @Override
     public int getLength() {
@@ -48,5 +52,10 @@
         sb.append(value.toString()).append('/').append(mask.toString());
         return sb.toString();
     }
+
+    @Override
+    public Masked<T> applyMask(Masked<T> mask) {
+        return this;
+    }
     
 }
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/OFMeterBand.java b/java_gen/pre-written/src/main/java/org/openflow/types/OFMeterBand.java
deleted file mode 100644
index d15812b..0000000
--- a/java_gen/pre-written/src/main/java/org/openflow/types/OFMeterBand.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package org.openflow.types;
-
-public interface OFMeterBand {
-
-}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/OFPhysicalPort.java b/java_gen/pre-written/src/main/java/org/openflow/types/OFPhysicalPort.java
index d8f71a3..7755a4a 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/OFPhysicalPort.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/OFPhysicalPort.java
@@ -10,7 +10,7 @@
  * @author capveg
  */
 
-public class OFPhysicalPort implements OFValueType {
+public class OFPhysicalPort implements OFValueType<OFPhysicalPort> {
 
     static final int LENGTH = 4;
     
@@ -60,4 +60,12 @@
         return OFPhysicalPort.of((int)(c.readUnsignedInt() & 0xFFFFFFFF));
     }
 
+    @Override
+    public OFPhysicalPort applyMask(OFPhysicalPort mask) {
+        return OFPhysicalPort.of(this.port & mask.port);
+    }
+
+    public int getPortNumber() {
+        return port;
+    }
 }
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/OFPort.java b/java_gen/pre-written/src/main/java/org/openflow/types/OFPort.java
index 3272660..f6dc408 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/OFPort.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/OFPort.java
@@ -15,7 +15,7 @@
  * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
  */
 @Immutable
-public class OFPort implements OFValueType {
+public class OFPort implements OFValueType<OFPort> {
     static final int LENGTH = 4;
     
     // private int constants (OF1.1+) to avoid duplication in the code
@@ -520,7 +520,7 @@
     }
 
     public static OFPort read2Bytes(ChannelBuffer c) throws OFParseError {
-        return OFPort.of((c.readUnsignedShort() & 0x0FFFF));
+        return OFPort.ofShort(c.readShort());
     }
 
     public void write4Bytes(ChannelBuffer c) {
@@ -530,4 +530,9 @@
     public static OFPort read4Bytes(ChannelBuffer c) throws OFParseError {
         return OFPort.of((int)(c.readUnsignedInt() & 0xFFFFFFFF));
     }
+
+    @Override
+    public OFPort applyMask(OFPort mask) {
+        return OFPort.of(this.portNumber & mask.portNumber);
+    }
 }
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/OFValueType.java b/java_gen/pre-written/src/main/java/org/openflow/types/OFValueType.java
index 51c8b36..8e2f9ed 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/OFValueType.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/OFValueType.java
@@ -3,8 +3,10 @@
 
 
 
-public interface OFValueType {
+public interface OFValueType<T extends OFValueType<T>> {
 
     public int getLength();
+    
+    public T applyMask(T mask);
 
 }
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/TransportPort.java b/java_gen/pre-written/src/main/java/org/openflow/types/TransportPort.java
index cecb349..82dab41 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/TransportPort.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/TransportPort.java
@@ -8,7 +8,7 @@
  * 
  * @author Yotam Harchol (yotam.harchol@bigswitch.com)
  */
-public class TransportPort implements OFValueType {
+public class TransportPort implements OFValueType<TransportPort> {
     
     static final int LENGTH = 2;
     static final int MAX_PORT = 0xFFFF;
@@ -31,6 +31,10 @@
     public int getLength() {
         return LENGTH;
     }
+    
+    public int getPort() {
+        return port;
+    }
 
     @Override
     public boolean equals(Object obj) {
@@ -63,4 +67,9 @@
         return TransportPort.of((c.readUnsignedShort() & 0x0FFFF));
     }
 
+    @Override
+    public TransportPort applyMask(TransportPort mask) {
+        return TransportPort.of(this.port & mask.port);
+    }
+    
 }
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 c0cd475..a46ded3 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
@@ -32,6 +32,10 @@
         return new U64(raw);
     }
 
+    public static U64 parseHex(String hex) {
+        return new U64(new BigInteger(hex, 16).longValue());
+    }
+
     public long getValue() {
         return raw;
     }
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/VlanPcp.java b/java_gen/pre-written/src/main/java/org/openflow/types/VlanPcp.java
index 2f406c8..531f878 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/VlanPcp.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/VlanPcp.java
@@ -3,7 +3,7 @@
 import org.jboss.netty.buffer.ChannelBuffer;
 import org.openflow.exceptions.OFParseError;
 
-public class VlanPcp implements OFValueType {
+public class VlanPcp implements OFValueType<VlanPcp> {
     
     private static final byte VALIDATION_MASK = 0x07;
     static final int LENGTH = 1; 
@@ -57,5 +57,10 @@
     public static VlanPcp readByte(ChannelBuffer c) throws OFParseError {
         return VlanPcp.of((byte)(c.readUnsignedByte() & 0xFF));
     }
+
+    @Override
+    public VlanPcp applyMask(VlanPcp mask) {
+        return VlanPcp.of((byte)(this.pcp & mask.pcp));
+    }
     
 }
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 a2b38b2..ca2c3c2 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
@@ -3,7 +3,7 @@
 import org.jboss.netty.buffer.ChannelBuffer;
 import org.openflow.exceptions.OFParseError;
 
-public class VlanVid implements OFValueType {
+public class VlanVid implements OFValueType<VlanVid> {
     
     private static final short VALIDATION_MASK = 0x0FFF;
     final static int LENGTH = 2;
@@ -73,5 +73,10 @@
     public VlanVid read2Bytes(ChannelBuffer c) throws OFParseError {
         return VlanVid.of(c.readShort());
     }
+
+    @Override
+    public VlanVid applyMask(VlanVid mask) {
+        return VlanVid.of((short)(this.vid & mask.vid));
+    }
     
 }
diff --git a/java_gen/pre-written/src/test/java/Test.java b/java_gen/pre-written/src/test/java/Test.java
deleted file mode 100644
index e83700d..0000000
--- a/java_gen/pre-written/src/test/java/Test.java
+++ /dev/null
@@ -1,30 +0,0 @@
-import org.openflow.protocol.match.MatchBuilderVer10;
-import org.openflow.types.MacAddress;
-import org.openflow.types.OFPort;
-
-
-public class Test {
-
-    private static volatile OFPort port;
-    private static volatile MacAddress ethSrc;
-
-    /**
-     * @param args
-     */
-    public static void main(String[] args) {
-        MacAddress mac = MacAddress.of("01:02:03:04:05:06");
-
-        long start = System.currentTimeMillis();
-        for(int i=0; i < 10000000; i++) {
-            MatchBuilderVer10 m = new MatchBuilderVer10();
-            // m.set(MatchField.IN_PORT, OFPort.CONTROLLER);
-            m.setInputPort(OFPort.CONTROLLER);
-            port = m.getInputPort(); //m.get(MatchField.IN_PORT);
-            m.setDataLayerSource(mac);
-            ethSrc = m.getDataLayerSource(); //(MatchField.ETH_SRC);
-        }
-        long end = System.currentTimeMillis();
-        System.out.println("end-start: "+ (end-start));
-    }
-
-}
diff --git a/java_gen/templates/_imports.java b/java_gen/templates/_imports.java
index 7700546..bac7065 100644
--- a/java_gen/templates/_imports.java
+++ b/java_gen/templates/_imports.java
@@ -1,7 +1,9 @@
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import org.openflow.protocol.*;
 import org.openflow.protocol.action.*;
+import org.openflow.protocol.meterband.*;
 import org.openflow.protocol.instruction.*;
 import org.openflow.protocol.match.*;
 import org.openflow.protocol.oxm.*;
@@ -10,3 +12,5 @@
 import org.openflow.util.*;
 import org.openflow.exceptions.*;
 import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import com.google.common.collect.ImmutableList;
diff --git a/java_gen/templates/_singleton.java b/java_gen/templates/_singleton.java
new file mode 100644
index 0000000..8ea9f01
--- /dev/null
+++ b/java_gen/templates/_singleton.java
@@ -0,0 +1,10 @@
+
+    private ${msg.name}() {}
+
+    private final static class Holder {
+        private static final ${msg.name} INSTANCE = new ${msg.name}();
+    }
+
+    public static ${msg.name} getInstance() {
+        return Holder.INSTANCE;
+    }
diff --git a/java_gen/templates/const.java b/java_gen/templates/const.java
index 7870529..11c09ab 100644
--- a/java_gen/templates/const.java
+++ b/java_gen/templates/const.java
@@ -37,16 +37,7 @@
 
 public enum ${class_name} {
 //:: for i, entry in enumerate(enum.entries):
-//::     values = [ ("0x%x" % val) if val is not None else "-1" for val in entry.all_values(all_versions) ]
-     ${entry.name}(new int[] { ${ ", ".join( values) } } )${ ", " if i < len(enum.entries)-1 else ";" }
+     ${entry.name}${ ", " if i < len(enum.entries)-1 else ";" }
 //:: #endfor
 
-    private final int[] wireValues;
-    ${class_name}(int[] wireValues) {
-        this.wireValues = wireValues;
-    }
-
-    public int getWireValue(OFVersion version) {
-        return this.wireValues[version.getWireVersion()];
-    }
 }
diff --git a/java_gen/templates/const_serializer.java b/java_gen/templates/const_serializer.java
new file mode 100644
index 0000000..4e21070
--- /dev/null
+++ b/java_gen/templates/const_serializer.java
@@ -0,0 +1,85 @@
+//:: # Copyright 2013, Big Switch Networks, Inc.
+//:: #
+//:: # LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
+//:: # the following special exception:
+//:: #
+//:: # LOXI Exception
+//:: #
+//:: # As a special exception to the terms of the EPL, you may distribute libraries
+//:: # generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
+//:: # that copyright and licensing notices generated by LoxiGen are not altered or removed
+//:: # from the LoxiGen Libraries and the notice provided below is (i) included in
+//:: # the LoxiGen Libraries, if distributed in source code form and (ii) included in any
+//:: # documentation for the LoxiGen Libraries, if distributed in binary form.
+//:: #
+//:: # Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
+//:: #
+//:: # You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
+//:: # a copy of the EPL at:
+//:: #
+//:: # http::: #www.eclipse.org/legal/epl-v10.html
+//:: #
+//:: # Unless required by applicable law or agreed to in writing, software
+//:: # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+//:: # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+//:: # EPL for the specific language governing permissions and limitations
+//:: # under the EPL.
+//::
+//:: import itertools
+//:: import of_g
+//:: include('_copyright.java')
+
+//:: include('_autogen.java')
+
+package ${package};
+
+import org.openflow.types.*;
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.exceptions.OFParseError;
+import org.openflow.protocol.OFVersion;
+import ${enum.package}.${enum.name};
+
+public class ${class_name} {
+    //:: wire_type = enum.wire_type(version)
+    //:: int_wire_type = enum.wire_type(version).pub_type
+    //:: entries = sorted([ (entry, entry.value(version)) for entry in enum.entries if entry.has_value(version) ], lambda (_,va), (_2,vb): va.__cmp__(vb))
+
+    //:: for entry, _ in entries:
+    public final static ${int_wire_type} ${entry.name}_VAL = ${entry.format_value(version)};
+    //:: #endfor
+
+    public static ${enum.name} readFrom(ChannelBuffer bb) throws OFParseError {
+        try {
+            return ofWireValue(${wire_type.read_op(version)});
+        } catch (IllegalArgumentException e) {
+            throw new OFParseError(e);
+        }
+    }
+
+    public static void writeTo(ChannelBuffer bb, ${enum.name} e) {
+        ${wire_type.write_op(version=version, name="toWireValue(e)")};
+    }
+
+    public static ${enum.name} ofWireValue(${int_wire_type} val) {
+        switch(val) {
+        //:: for entry, _ in entries:
+            case ${entry.name}_VAL:
+                return ${enum.name}.${entry.name};
+        //:: #endfor
+            default:
+                throw new IllegalArgumentException("Illegal wire value for type ${enum.name} in version ${version}: " + val);
+        }
+    }
+
+    public static ${int_wire_type} toWireValue(${enum.name} e) {
+        switch(e) {
+        //:: for entry, _ in entries:
+            case ${entry.name}:
+                return ${entry.name}_VAL;
+        //:: #endfor
+            default:
+                throw new IllegalArgumentException("Illegal enum value for type ${enum.name} in version ${version}: " + e);
+        }
+    }
+
+}
diff --git a/java_gen/templates/custom/OFMatchV1Ver10.Builder.java b/java_gen/templates/custom/OFMatchV1Ver10.Builder.java
new file mode 100644
index 0000000..58afcd0
--- /dev/null
+++ b/java_gen/templates/custom/OFMatchV1Ver10.Builder.java
@@ -0,0 +1,77 @@
+
+    @Override
+    public <F extends OFValueType<F>> F get(MatchField<F> field)
+            throws UnsupportedOperationException {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
+
+    @Override
+    public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
+            throws UnsupportedOperationException {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
+
+    @Override
+    public boolean supports(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public boolean supportsMasked(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public boolean isExact(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public boolean isFullyWildcarded(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public boolean isPartiallyMasked(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public <F extends OFValueType<F>> MatchBuilder setExact(
+            MatchField<F> field, F value) {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
+
+    @Override
+    public <F extends OFValueType<F>> MatchBuilder setMasked(
+            MatchField<F> field, F value, F mask) {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
+
+    @Override
+    public <F extends OFValueType<F>> MatchBuilder setMasked(
+            MatchField<F> field, Masked<F> valueWithMask) {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
+
+    @Override
+    public <F extends OFValueType<F>> MatchBuilder wildcard(MatchField<F> field) {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
+
+    @Override
+    public Match getMatch() {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
diff --git a/java_gen/templates/custom/OFMatchV1Ver10.java b/java_gen/templates/custom/OFMatchV1Ver10.java
new file mode 100644
index 0000000..ec7bfcc
--- /dev/null
+++ b/java_gen/templates/custom/OFMatchV1Ver10.java
@@ -0,0 +1,44 @@
+
+    @Override
+    public <F extends OFValueType<F>> F get(MatchField<F> field)
+            throws UnsupportedOperationException {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
+
+    @Override
+    public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
+            throws UnsupportedOperationException {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
+
+    @Override
+    public boolean supports(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public boolean supportsMasked(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public boolean isExact(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public boolean isFullyWildcarded(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public boolean isPartiallyMasked(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
diff --git a/java_gen/templates/custom/OFMatchV2Ver11.Builder.java b/java_gen/templates/custom/OFMatchV2Ver11.Builder.java
new file mode 100644
index 0000000..58afcd0
--- /dev/null
+++ b/java_gen/templates/custom/OFMatchV2Ver11.Builder.java
@@ -0,0 +1,77 @@
+
+    @Override
+    public <F extends OFValueType<F>> F get(MatchField<F> field)
+            throws UnsupportedOperationException {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
+
+    @Override
+    public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
+            throws UnsupportedOperationException {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
+
+    @Override
+    public boolean supports(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public boolean supportsMasked(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public boolean isExact(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public boolean isFullyWildcarded(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public boolean isPartiallyMasked(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public <F extends OFValueType<F>> MatchBuilder setExact(
+            MatchField<F> field, F value) {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
+
+    @Override
+    public <F extends OFValueType<F>> MatchBuilder setMasked(
+            MatchField<F> field, F value, F mask) {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
+
+    @Override
+    public <F extends OFValueType<F>> MatchBuilder setMasked(
+            MatchField<F> field, Masked<F> valueWithMask) {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
+
+    @Override
+    public <F extends OFValueType<F>> MatchBuilder wildcard(MatchField<F> field) {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
+
+    @Override
+    public Match getMatch() {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
diff --git a/java_gen/templates/custom/OFMatchV2Ver11.java b/java_gen/templates/custom/OFMatchV2Ver11.java
new file mode 100644
index 0000000..ec7bfcc
--- /dev/null
+++ b/java_gen/templates/custom/OFMatchV2Ver11.java
@@ -0,0 +1,44 @@
+
+    @Override
+    public <F extends OFValueType<F>> F get(MatchField<F> field)
+            throws UnsupportedOperationException {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
+
+    @Override
+    public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
+            throws UnsupportedOperationException {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
+
+    @Override
+    public boolean supports(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public boolean supportsMasked(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public boolean isExact(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public boolean isFullyWildcarded(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public boolean isPartiallyMasked(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
diff --git a/java_gen/templates/custom/OFMatchV3Ver12.Builder.java b/java_gen/templates/custom/OFMatchV3Ver12.Builder.java
new file mode 100644
index 0000000..58afcd0
--- /dev/null
+++ b/java_gen/templates/custom/OFMatchV3Ver12.Builder.java
@@ -0,0 +1,77 @@
+
+    @Override
+    public <F extends OFValueType<F>> F get(MatchField<F> field)
+            throws UnsupportedOperationException {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
+
+    @Override
+    public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
+            throws UnsupportedOperationException {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
+
+    @Override
+    public boolean supports(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public boolean supportsMasked(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public boolean isExact(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public boolean isFullyWildcarded(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public boolean isPartiallyMasked(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public <F extends OFValueType<F>> MatchBuilder setExact(
+            MatchField<F> field, F value) {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
+
+    @Override
+    public <F extends OFValueType<F>> MatchBuilder setMasked(
+            MatchField<F> field, F value, F mask) {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
+
+    @Override
+    public <F extends OFValueType<F>> MatchBuilder setMasked(
+            MatchField<F> field, Masked<F> valueWithMask) {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
+
+    @Override
+    public <F extends OFValueType<F>> MatchBuilder wildcard(MatchField<F> field) {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
+
+    @Override
+    public Match getMatch() {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
diff --git a/java_gen/templates/custom/OFMatchV3Ver12.java b/java_gen/templates/custom/OFMatchV3Ver12.java
new file mode 100644
index 0000000..ec7bfcc
--- /dev/null
+++ b/java_gen/templates/custom/OFMatchV3Ver12.java
@@ -0,0 +1,44 @@
+
+    @Override
+    public <F extends OFValueType<F>> F get(MatchField<F> field)
+            throws UnsupportedOperationException {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
+
+    @Override
+    public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
+            throws UnsupportedOperationException {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
+
+    @Override
+    public boolean supports(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public boolean supportsMasked(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public boolean isExact(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public boolean isFullyWildcarded(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public boolean isPartiallyMasked(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
diff --git a/java_gen/templates/custom/OFMatchV3Ver13.Builder.java b/java_gen/templates/custom/OFMatchV3Ver13.Builder.java
new file mode 100644
index 0000000..58afcd0
--- /dev/null
+++ b/java_gen/templates/custom/OFMatchV3Ver13.Builder.java
@@ -0,0 +1,77 @@
+
+    @Override
+    public <F extends OFValueType<F>> F get(MatchField<F> field)
+            throws UnsupportedOperationException {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
+
+    @Override
+    public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
+            throws UnsupportedOperationException {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
+
+    @Override
+    public boolean supports(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public boolean supportsMasked(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public boolean isExact(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public boolean isFullyWildcarded(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public boolean isPartiallyMasked(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public <F extends OFValueType<F>> MatchBuilder setExact(
+            MatchField<F> field, F value) {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
+
+    @Override
+    public <F extends OFValueType<F>> MatchBuilder setMasked(
+            MatchField<F> field, F value, F mask) {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
+
+    @Override
+    public <F extends OFValueType<F>> MatchBuilder setMasked(
+            MatchField<F> field, Masked<F> valueWithMask) {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
+
+    @Override
+    public <F extends OFValueType<F>> MatchBuilder wildcard(MatchField<F> field) {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
+
+    @Override
+    public Match getMatch() {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
diff --git a/java_gen/templates/custom/OFMatchV3Ver13.java b/java_gen/templates/custom/OFMatchV3Ver13.java
new file mode 100644
index 0000000..ec7bfcc
--- /dev/null
+++ b/java_gen/templates/custom/OFMatchV3Ver13.java
@@ -0,0 +1,44 @@
+
+    @Override
+    public <F extends OFValueType<F>> F get(MatchField<F> field)
+            throws UnsupportedOperationException {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
+
+    @Override
+    public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
+            throws UnsupportedOperationException {
+        // FIXME yotam - please replace with real implementation
+        return null;
+    }
+
+    @Override
+    public boolean supports(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public boolean supportsMasked(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public boolean isExact(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public boolean isFullyWildcarded(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
+
+    @Override
+    public boolean isPartiallyMasked(MatchField<?> field) {
+        // FIXME yotam - please replace with real implementation
+        return false;
+    }
diff --git a/java_gen/templates/of_class.java b/java_gen/templates/of_class.java
index 772858a..05018d3 100644
--- a/java_gen/templates/of_class.java
+++ b/java_gen/templates/of_class.java
@@ -26,6 +26,7 @@
 //:: # under the EPL.
 //::
 //:: from loxi_ir import *
+//:: import os
 //:: import itertools
 //:: import of_g
 //:: include('_copyright.java')
@@ -64,12 +65,15 @@
     // Accessors for OF message fields
 //:: include("_field_accessors.java", msg=msg, generate_setters=False, builder=False)
 
+    //:: if os.path.exists("%s/custom/%s.java" % (template_dir, msg.name)):
+    //:: include("custom/%s.java" % msg.name, msg=msg)
+    //:: #endif
 
-    public ${msg.name}.Builder createBuilder() {
-        return new BuilderImplWithParent(this);
+    public ${msg.interface.name}.Builder createBuilder() {
+        return new BuilderWithParent(this);
     }
 
-    static class BuilderImplWithParent implements ${msg.interface.name}.Builder {
+    static class BuilderWithParent implements ${msg.interface.name}.Builder {
         final ${impl_class} parentMessage;
 
         // OF message fields
@@ -78,7 +82,7 @@
         private ${prop.java_type.public_type} ${prop.name};
 //:: #endfor
 
-        BuilderImplWithParent(${impl_class} parentMessage) {
+        BuilderWithParent(${impl_class} parentMessage) {
             this.parentMessage = parentMessage;
         }
 
@@ -92,9 +96,13 @@
                              for prop in msg.data_members])}
                     );
         }
+        //:: if os.path.exists("%s/custom/%s.Builder.java" % (template_dir, msg.name)):
+        //:: include("custom/%s.Builder.java" % msg.name, msg=msg)
+        //:: #endif
+
     }
 
-    static class BuilderImpl implements ${msg.interface.name}.Builder {
+    static class Builder implements ${msg.interface.name}.Builder {
         // OF message fields
 //:: for prop in msg.data_members:
         private boolean ${prop.name}Set;
@@ -111,6 +119,10 @@
                          for prop in msg.data_members])}
                 );
         }
+        //:: if os.path.exists("%s/custom/%s.Builder.java" % (template_dir, msg.name)):
+        //:: include("custom/%s.Builder.java" % msg.name, msg=msg)
+        //:: #endif
+
     }
 
     final static Reader READER = new Reader();
@@ -141,6 +153,11 @@
     // fixme: todo ${prop.name}
 //:: #endif
 //:: #endfor
+            //:: if msg.align:
+            // align message to ${msg.align} bytes
+            bb.skipBytes(((length + ${msg.align-1})/${msg.align} * ${msg.align} ) - length );
+            //:: #endif
+
             return new ${impl_class}(
                     ${",\n                      ".join(
                          [ prop.name for prop in msg.data_members])}
@@ -148,14 +165,14 @@
         }
     }
 
-    public int writeTo(ChannelBuffer bb) {
-        return WRITER.write(bb, this);
+    public void writeTo(ChannelBuffer bb) {
+        WRITER.write(bb, this);
     }
 
     final static Writer WRITER = new Writer();
     static class Writer implements OFMessageWriter<${impl_class}> {
         @Override
-        public int write(ChannelBuffer bb, ${impl_class} message) {
+        public void write(ChannelBuffer bb, ${impl_class} message) {
 //:: if not msg.is_fixed_length:
             int startIndex = bb.writerIndex();
 //:: #end
@@ -193,17 +210,77 @@
 //:: #endif
 //:: #endfor
 
-//:: if msg.is_fixed_length:
-            return LENGTH;
-//:: else:
+//:: if not msg.is_fixed_length:
             // update length field
             int length = bb.writerIndex() - startIndex;
             bb.setShort(startIndex + 2, length);
-            return length;
+            //:: if msg.align:
+            // align message to ${msg.align} bytes
+            bb.writeZero( ((length + ${msg.align-1})/${msg.align} * ${msg.align}) - length);
+            //:: #endif
 //:: #end
 
         }
     }
 
+    @Override
+    public String toString() {
+        StringBuilder b = new StringBuilder("${msg.name}(");
+        //:: for i, prop in enumerate(msg.data_members):
+        //:: if i > 0:
+        b.append(", ");
+        //:: #endif
+        b.append("${prop.name}=").append(${ "Arrays.toString(%s)" % prop.name if prop.java_type.is_array else prop.name });
+        //:: #endfor
+        b.append(")");
+        return b.toString();
+    }
+
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        ${msg.name} other = (${msg.name}) obj;
+
+        //:: for prop in msg.data_members:
+        //:: if prop.java_type.is_primitive:
+        if( ${prop.name} != other.${prop.name})
+            return false;
+        //:: elif prop.java_type.is_array:
+        if (!Arrays.equals(${prop.name}, other.${prop.name}))
+                return false;
+        //:: else:
+        if (${prop.name} == null) {
+            if (other.${prop.name} != null)
+                return false;
+        } else if (!${prop.name}.equals(other.${prop.name}))
+            return false;
+        //:: #endif
+        //:: #endfor
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+
+        //:: for prop in msg.data_members:
+        //:: if prop.java_type.is_primitive:
+        result = prime * result + ${prop.name};
+        //:: elif prop.java_type.is_array:
+        result = prime * result + Arrays.hashCode(${prop.name});
+        //:: else:
+        result = prime * result + ((${prop.name} == null) ? 0 : ${prop.name}.hashCode());
+        //:: #endif
+        //:: #endfor
+        return result;
+    }
+
 
 }
diff --git a/java_gen/templates/of_factories.java b/java_gen/templates/of_factories.java
new file mode 100644
index 0000000..cce134d
--- /dev/null
+++ b/java_gen/templates/of_factories.java
@@ -0,0 +1,49 @@
+//:: # Copyright 2013, Big Switch Networks, Inc.
+//:: #
+//:: # LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
+//:: # the following special exception:
+//:: #
+//:: # LOXI Exception
+//:: #
+//:: # As a special exception to the terms of the EPL, you may distribute libraries
+//:: # generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
+//:: # that copyright and licensing notices generated by LoxiGen are not altered or removed
+//:: # from the LoxiGen Libraries and the notice provided below is (i) included in
+//:: # the LoxiGen Libraries, if distributed in source code form and (ii) included in any
+//:: # documentation for the LoxiGen Libraries, if distributed in binary form.
+//:: #
+//:: # Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
+//:: #
+//:: # You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
+//:: # a copy of the EPL at:
+//:: #
+//:: # http::: #www.eclipse.org/legal/epl-v10.html
+//:: #
+//:: # Unless required by applicable law or agreed to in writing, software
+//:: # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+//:: # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+//:: # EPL for the specific language governing permissions and limitations
+//:: # under the EPL.
+//::
+//:: import itertools
+//:: import of_g
+//:: include('_copyright.java')
+
+//:: include('_autogen.java')
+
+package org.openflow.protocol;
+
+//:: include("_imports.java")
+
+public final class OFFactories {
+    public static OFFactory getFactory(OFVersion version) {
+        switch(version) {
+            //:: for v in versions:
+            case ${v.constant_version}:
+                return org.openflow.protocol.ver${v.of_version}.OFFactoryVer${v.of_version}.getInstance();
+            //:: #endfor
+            default:
+                throw new IllegalArgumentException("Unknown version: "+version);
+            }
+    }
+}
diff --git a/java_gen/templates/of_factory_class.java b/java_gen/templates/of_factory_class.java
new file mode 100644
index 0000000..8620787
--- /dev/null
+++ b/java_gen/templates/of_factory_class.java
@@ -0,0 +1,56 @@
+//:: # Copyright 2013, Big Switch Networks, Inc.
+//:: #
+//:: # LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
+//:: # the following special exception:
+//:: #
+//:: # LOXI Exception
+//:: #
+//:: # As a special exception to the terms of the EPL, you may distribute libraries
+//:: # generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
+//:: # that copyright and licensing notices generated by LoxiGen are not altered or removed
+//:: # from the LoxiGen Libraries and the notice provided below is (i) included in
+//:: # the LoxiGen Libraries, if distributed in source code form and (ii) included in any
+//:: # documentation for the LoxiGen Libraries, if distributed in binary form.
+//:: #
+//:: # Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
+//:: #
+//:: # You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
+//:: # a copy of the EPL at:
+//:: #
+//:: # http::: #www.eclipse.org/legal/epl-v10.html
+//:: #
+//:: # Unless required by applicable law or agreed to in writing, software
+//:: # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+//:: # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+//:: # EPL for the specific language governing permissions and limitations
+//:: # under the EPL.
+//::
+//:: import itertools
+//:: import of_g
+//:: include('_copyright.java')
+
+//:: include('_autogen.java')
+
+package ${factory.package};
+
+//:: include("_imports.java")
+
+public class ${factory.name} implements ${factory.interface.name} {
+//:: for i in factory.interface.members:
+    //:: if i.is_virtual:
+    //::    continue
+    //:: #endif
+
+//::   if i.has_version(factory.version) and model.generate_class(i.versioned_class(factory.version)):
+    public ${i.name}.Builder create${i.name[2:]}Builder() {
+        return new ${i.versioned_class(factory.version).name}.Builder();
+    }
+//:: else:
+    public ${i.name}.Builder create${i.name[2:]}Builder() throws UnsupportedOperationException {
+        throw new UnsupportedOperationException("${i.name} not supported in version ${factory.version}");
+    }
+//:: #endif
+//:: #endfor
+
+    //:: include("_singleton.java", msg=factory)
+}
diff --git a/java_gen/templates/of_factory_interface.java b/java_gen/templates/of_factory_interface.java
new file mode 100644
index 0000000..467504e
--- /dev/null
+++ b/java_gen/templates/of_factory_interface.java
@@ -0,0 +1,45 @@
+//:: # Copyright 2013, Big Switch Networks, Inc.
+//:: #
+//:: # LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
+//:: # the following special exception:
+//:: #
+//:: # LOXI Exception
+//:: #
+//:: # As a special exception to the terms of the EPL, you may distribute libraries
+//:: # generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
+//:: # that copyright and licensing notices generated by LoxiGen are not altered or removed
+//:: # from the LoxiGen Libraries and the notice provided below is (i) included in
+//:: # the LoxiGen Libraries, if distributed in source code form and (ii) included in any
+//:: # documentation for the LoxiGen Libraries, if distributed in binary form.
+//:: #
+//:: # Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
+//:: #
+//:: # You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
+//:: # a copy of the EPL at:
+//:: #
+//:: # http::: #www.eclipse.org/legal/epl-v10.html
+//:: #
+//:: # Unless required by applicable law or agreed to in writing, software
+//:: # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+//:: # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+//:: # EPL for the specific language governing permissions and limitations
+//:: # under the EPL.
+//::
+//:: import itertools
+//:: import of_g
+//:: include('_copyright.java')
+
+//:: include('_autogen.java')
+
+package org.openflow.protocol;
+
+//:: include("_imports.java")
+
+public interface ${factory.name} {
+//:: for i in factory.members:
+    //:: if i.is_virtual:
+    //::    continue
+    //:: #endif
+    ${i.name}.Builder create${i.name[2:]}Builder()${ "" if i.is_universal else " throws UnsupportedOperationException"};
+//:: #endfor
+}
diff --git a/java_gen/templates/of_interface.java b/java_gen/templates/of_interface.java
index af6493e..186b787 100644
--- a/java_gen/templates/of_interface.java
+++ b/java_gen/templates/of_interface.java
@@ -35,12 +35,12 @@
 
 //:: include("_imports.java", msg=msg)
 
-public interface ${msg.name} ${"extends %s" % msg.parent_interface if msg.parent_interface else ""} {
+public interface ${msg.name} extends OFObject${", %s" % msg.parent_interface if msg.parent_interface else ""}{
 //:: for prop in msg.members:
     ${prop.java_type.public_type} get${prop.title_name}()${ "" if prop.is_universal else " throws UnsupportedOperationException"};
 //:: #endfor
 
-    int writeTo(ChannelBuffer channelBuffer);
+    void writeTo(ChannelBuffer channelBuffer);
 
     Builder createBuilder();
     public interface Builder ${"extends %s.Builder" % msg.parent_interface if msg.parent_interface else ""} {
diff --git a/java_gen/templates/unit_test.java b/java_gen/templates/unit_test.java
new file mode 100644
index 0000000..1462465
--- /dev/null
+++ b/java_gen/templates/unit_test.java
@@ -0,0 +1,102 @@
+//:: # Copyright 2013, Big Switch Networks, Inc.
+//:: #
+//:: # LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
+//:: # the following special exception:
+//:: #
+//:: # LOXI Exception
+//:: #
+//:: # As a special exception to the terms of the EPL, you may distribute libraries
+//:: # generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
+//:: # that copyright and licensing notices generated by LoxiGen are not altered or removed
+//:: # from the LoxiGen Libraries and the notice provided below is (i) included in
+//:: # the LoxiGen Libraries, if distributed in source code form and (ii) included in any
+//:: # documentation for the LoxiGen Libraries, if distributed in binary form.
+//:: #
+//:: # Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
+//:: #
+//:: # You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
+//:: # a copy of the EPL at:
+//:: #
+//:: # http::: #www.eclipse.org/legal/epl-v10.html
+//:: #
+//:: # Unless required by applicable law or agreed to in writing, software
+//:: # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+//:: # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+//:: # EPL for the specific language governing permissions and limitations
+//:: # under the EPL.
+//::
+//:: from loxi_ir import *
+//:: import itertools
+//:: import of_g
+//:: include('_copyright.java')
+
+//:: include('_autogen.java')
+
+package ${test.package};
+
+//:: include("_imports.java", msg=msg)
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+public class ${test.name} {
+    //:: var_type = msg.interface.name
+    //:: var_name = msg.interface.variable_name
+    OFFactory factory;
+
+    final static byte[] ${msg.constant_name}_SERIALIZED =
+        new byte[] { ${", ".join("%s0x%x" % (("" if ord(c)<128 else "(byte) "),  ord(c)) for c in test_data["binary"] ) } };
+
+    @Before
+    public void setup() {
+        factory = OFFactories.getFactory(OFVersion.${version.constant_version});
+    }
+
+    //:: if "java" in test_data:
+    @Test
+    public void testWrite() {
+        ${var_type}.Builder builder = factory.create${var_type[2:]}Builder();
+        ${test_data["java"]};
+        ${var_type} ${var_name} = builder.getMessage();
+        ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
+        ${var_name}.writeTo(bb);
+        byte[] written = new byte[bb.readableBytes()];
+        bb.readBytes(written);
+
+        assertArrayEquals(${msg.constant_name}_SERIALIZED, written);
+    }
+
+    @Test
+    public void testRead() throws Exception {
+        ${var_type}.Builder builder = factory.create${var_type[2:]}Builder();
+        ${test_data["java"]};
+        ${var_type} ${var_name}Built = builder.getMessage();
+
+        ChannelBuffer input = ChannelBuffers.copiedBuffer(${msg.constant_name}_SERIALIZED);
+
+        // FIXME should invoke the overall reader once implemented
+        ${var_type} ${var_name}Read = ${msg.name}.READER.readFrom(input);
+
+        assertEquals(${var_name}Read, ${var_name}Built);
+   }
+   //:: else:
+   // FIXME: No java stanza in test_data for this class. Add for more comprehensive unit testing
+   //:: #endif
+
+   @Test
+   public void testReadWrite() throws Exception {
+       ChannelBuffer input = ChannelBuffers.copiedBuffer(${msg.constant_name}_SERIALIZED);
+
+       // FIXME should invoke the overall reader once implemented
+       ${var_type} ${var_name} = ${msg.name}.READER.readFrom(input);
+
+       // write message again
+       ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
+       ${var_name}.writeTo(bb);
+       byte[] written = new byte[bb.readableBytes()];
+       bb.readBytes(written);
+
+       assertArrayEquals(${msg.constant_name}_SERIALIZED, written);
+   }
+
+}
diff --git a/loxi_front_end/frontend.py b/loxi_front_end/frontend.py
index d25c2eb..bba941c 100644
--- a/loxi_front_end/frontend.py
+++ b/loxi_front_end/frontend.py
@@ -46,6 +46,8 @@
             return OFFieldLengthMember(name=m_ast[2], oftype=m_ast[1], field_name='actions')
         else:
             return OFDataMember(name=m_ast[2], oftype=m_ast[1])
+    else:
+        raise Exception("Dont know how to create member: %s" % m_ast[0])
 
 def create_ofinput(ast):
     """
@@ -60,11 +62,25 @@
 
     for decl_ast in ast:
         if decl_ast[0] == 'struct':
-            members = [create_member(m_ast) for m_ast in decl_ast[3]]
-            ofclass = OFClass(name=decl_ast[1], superclass=decl_ast[2], members=members)
+            # 0: "enum"
+            # 1: name
+            # 2: potentially list of [param_name, param_value]
+            # 3: super_class
+            # 4: list of [constant_name, constant_value]+
+            super_class = decl_ast[3]
+            members = [create_member(m_ast) for m_ast in decl_ast[4]]
+            ofclass = OFClass(name=decl_ast[1], members=members, super_class=super_class,
+                    params = { param: value for param, value in decl_ast[2] })
             ofinput.classes.append(ofclass)
         if decl_ast[0] == 'enum':
-            enum = OFEnum(name=decl_ast[1], values=[(x[0], x[1]) for x in decl_ast[2]])
+            # 0: "enum"
+            # 1: name
+            # 2: potentially list of [param_name, param_value]
+            # 3: list of [constant_name, constant_value]+
+            enum = OFEnum(name=decl_ast[1],
+                    entries=[OFEnumEntry(name=x[0], value=x[2], params={param:value for param, value in x[1] }) for x in decl_ast[3]],
+                    params = { param: value for param, value in decl_ast[2] }
+                    )
             ofinput.enums.append(enum)
         elif decl_ast[0] == 'metadata':
             if decl_ast[1] == 'version':
diff --git a/loxi_front_end/parser.py b/loxi_front_end/parser.py
index 7893008..d5920e8 100644
--- a/loxi_front_end/parser.py
+++ b/loxi_front_end/parser.py
@@ -53,17 +53,33 @@
 pad_member = P.Group(kw('pad') - s('(') - integer - s(')'))
 type_member = P.Group(tag('type') + any_type + identifier + s('==') + integer)
 data_member = P.Group(tag('data') + any_type - identifier)
+
+struct_param_name = kw("align")
+struct_param = P.Group(struct_param_name - s('=') - any_type)
+struct_param_list = P.Forward()
+struct_param_list << struct_param + P.Optional(s(',') - P.Optional(struct_param_list))
+
 struct_member = pad_member | type_member | data_member;
 parent = (s(':') - identifier) | tag(None)
-struct = kw('struct') - identifier - parent - s('{') + \
+struct = kw('struct') - identifier - P.Group(P.Optional(s('(') - struct_param_list - s(')'))) - parent - s('{') + \
          P.Group(P.ZeroOrMore(struct_member - s(';'))) + \
          s('}') - s(';')
 
 # Enums
-enum_member = P.Group(identifier + s('=') + integer)
+enum_param_name = kw("wire_type") | kw("bitmask") | kw("complete")
+enum_param = P.Group(enum_param_name  - s('=') - any_type)
+enum_param_list = P.Forward()
+enum_param_list << enum_param + P.Optional(s(',') + P.Optional(enum_param_list))
+
+enum_member_param_name = kw("virtual")
+enum_member_param = P.Group(enum_member_param_name  - s('=') - any_type)
+enum_member_param_list = P.Forward()
+enum_member_param_list << enum_member_param + P.Optional(s(',') + P.Optional(enum_member_param_list))
+
+enum_member = P.Group(identifier - P.Group(P.Optional(s('(') - enum_member_param_list - s(')'))) - s('=') + integer)
 enum_list = P.Forward()
 enum_list << enum_member + P.Optional(s(',') + P.Optional(enum_list))
-enum = kw('enum') - identifier - s('{') + \
+enum = kw('enum') - identifier - P.Group(P.Optional(s('(') - enum_param_list - s(')'))) - s('{') + \
          P.Group(P.Optional(enum_list)) + \
          s('}') - s(';')
 
diff --git a/loxi_ir.py b/loxi_ir.py
index 824524b..9e266eb 100644
--- a/loxi_ir.py
+++ b/loxi_ir.py
@@ -25,6 +25,7 @@
 # EPL for the specific language governing permissions and limitations
 # under the EPL.
 
+from generic_utils import find
 from collections import namedtuple
 
 # This module is intended to be imported like this: from loxi_ir import *
@@ -39,6 +40,7 @@
     'OFFieldLengthMember',
     'OFPadMember',
     'OFEnum',
+    'OFEnumEntry'
 ]
 
 """
@@ -71,8 +73,12 @@
 
 @param name
 @param members List of *Member objects
+@param super_class name of the super class
+@param params optional dictionary of parameters
 """
-OFClass = namedtuple('OFClass', ['name', 'superclass', 'members'])
+class OFClass(namedtuple('OFClass', ['name', 'members', 'superclass', 'params'])):
+    def member_by_name(self, name):
+        return find(self.members, lambda m: hasattr(m, "name") and m.name == name)
 
 """
 Normal field
@@ -131,6 +137,13 @@
 All values are Python ints.
 
 @param name
-@param values List of (name, value) tuples in input order
+@param entries List of OFEnumEntry objects in input order
+@params dict of optional params. Currently defined:
+       - wire_type: the low_level type of the enum values (uint8,...)
 """
-OFEnum = namedtuple('OFEnum', ['name', 'values'])
+class OFEnum(namedtuple('OFEnum', ['name', 'entries', 'params'])):
+    @property
+    def values(self):
+        return [(e.name, e.value) for e in self.entries]
+
+OFEnumEntry = namedtuple('OFEnumEntry', ['name', 'value', 'params'])
diff --git a/loxigen.py b/loxigen.py
index 9bddf4b..dcd547e 100755
--- a/loxigen.py
+++ b/loxigen.py
@@ -447,10 +447,10 @@
                 versions[version_name]['classes'][ofclass.name] = legacy_members
 
             for enum in ofinput.enums:
-                for name, value in enum.values:
+                for entry in enum.entries:
                     identifiers.add_identifier(
-                        translation.loxi_name(name),
-                        name, enum.name, value, wire_version,
+                        translation.loxi_name(entry.name),
+                        entry.name, enum.name, entry.value, wire_version,
                         of_g.identifiers, of_g.identifiers_by_group)
 
         for wire_version, ofinputs in ofinputs_by_version.items():
diff --git a/openflow_input/bsn_vport b/openflow_input/bsn_vport
index 4da4638..06198df 100644
--- a/openflow_input/bsn_vport
+++ b/openflow_input/bsn_vport
@@ -38,7 +38,7 @@
 // When the ingress or egress VID has this value, no outer tag should be used.
 // In this case, the corresponding TPID is ignored.
 
-enum ofp_bsn_vport_q_in_q_untagged {
+enum ofp_bsn_vport_q_in_q_untagged(wire_type=uint16_t, complete=False) {
     OF_BSN_VPORT_Q_IN_Q_UNTAGGED = 0xffff,
 };
 
diff --git a/openflow_input/standard-1.0 b/openflow_input/standard-1.0
index 64c60d5..6382759 100644
--- a/openflow_input/standard-1.0
+++ b/openflow_input/standard-1.0
@@ -61,7 +61,7 @@
     OFPQ_MIN_RATE_UNCFG = 0xffff,
 };
 
-enum ofp_type {
+enum ofp_type(wire_type=uint8_t) {
     OFPT_HELLO = 0,
     OFPT_ERROR = 1,
     OFPT_ECHO_REQUEST = 2,
@@ -86,7 +86,7 @@
     OFPT_QUEUE_GET_CONFIG_REPLY = 21,
 };
 
-enum ofp_port_config {
+enum ofp_port_config(wire_type=uint32_t, bitmask=True) {
     OFPPC_PORT_DOWN = 0x1,
     OFPPC_NO_STP = 0x2,
     OFPPC_NO_RECV = 0x4,
@@ -96,16 +96,19 @@
     OFPPC_NO_PACKET_IN = 0x40,
 };
 
-enum ofp_port_state {
+enum ofp_port_state(wire_type=uint32_t, bitmask=True) {
     OFPPS_STP_LISTEN = 0,
     OFPPS_LINK_DOWN = 1,
     OFPPS_STP_LEARN = 0x100,
     OFPPS_STP_FORWARD = 0x200,
     OFPPS_STP_BLOCK = 0x300,
-    OFPPS_STP_MASK = 0x300,
+    OFPPS_STP_MASK(virtual=True) = 0x300,
 };
 
-enum ofp_port {
+// FIXME: these constants are currently 32 bit due to implementation
+// details of loci, which is in violation of the OpenFlow spec.
+// Should recast to 32 bits and fix/glue the c backend
+enum ofp_port(wire_type=uint16_t, complete=False) {
     OFPP_MAX = 0xffffff00,
     OFPP_IN_PORT = 0xfffffff8,
     OFPP_TABLE = 0xfffffff9,
@@ -117,7 +120,7 @@
     OFPP_NONE = 0xffffffff,
 };
 
-enum ofp_port_features {
+enum ofp_port_features(wire_type=uint32_t, bitmask=True) {
     OFPPF_10MB_HD = 0x1,
     OFPPF_10MB_FD = 0x2,
     OFPPF_100MB_HD = 0x4,
@@ -132,12 +135,12 @@
     OFPPF_PAUSE_ASYM = 0x800,
 };
 
-enum ofp_queue_properties {
+enum ofp_queue_properties(wire_type=uint32_t) {
     OFPQT_NONE = 0,
     OFPQT_MIN_RATE = 1,
 };
 
-enum ofp_flow_wildcards {
+enum ofp_flow_wildcards(wire_type=uint32_t, bitmask=True) {
     OFPFW_IN_PORT = 0x1,
     OFPFW_DL_VLAN = 0x2,
     OFPFW_DL_SRC = 0x4,
@@ -159,7 +162,7 @@
     OFPFW_ALL = 0x3fffff,
 };
 
-enum ofp_action_type {
+enum ofp_action_type(wire_type=uint16_t) {
     OFPAT_OUTPUT = 0,
     OFPAT_SET_VLAN_VID = 1,
     OFPAT_SET_VLAN_PCP = 2,
@@ -175,7 +178,7 @@
     OFPAT_VENDOR = 0xffff,
 };
 
-enum ofp_capabilities {
+enum ofp_capabilities(wire_type=uint32_t, bitmask=True) {
     OFPC_FLOW_STATS = 0x1,
     OFPC_TABLE_STATS = 0x2,
     OFPC_PORT_STATS = 0x4,
@@ -186,14 +189,14 @@
     OFPC_ARP_MATCH_IP = 0x80,
 };
 
-enum ofp_config_flags {
+enum ofp_config_flags(wire_type=uint32_t, bitmask=True) {
     OFPC_FRAG_NORMAL = 0x0,
     OFPC_FRAG_DROP = 0x1,
     OFPC_FRAG_REASM = 0x2,
     OFPC_FRAG_MASK = 0x3,
 };
 
-enum ofp_flow_mod_command {
+enum ofp_flow_mod_command(wire_type=uint16_t) {
     OFPFC_ADD = 0,
     OFPFC_MODIFY = 1,
     OFPFC_MODIFY_STRICT = 2,
@@ -201,17 +204,17 @@
     OFPFC_DELETE_STRICT = 4,
 };
 
-enum ofp_flow_mod_flags {
+enum ofp_flow_mod_flags(wire_type=uint16_t, bitmask=True) {
     OFPFF_SEND_FLOW_REM = 0x1,
     OFPFF_CHECK_OVERLAP = 0x2,
     OFPFF_EMERG = 0x4,
 };
 
-enum ofp_stats_reply_flags {
+enum ofp_stats_reply_flags(wire_type=uint16_t, bitmask=True) {
     OFPSF_REPLY_MORE = 0x1,
 };
 
-enum ofp_stats_types {
+enum ofp_stats_types(wire_type=uint16_t) {
     OFPST_DESC = 0,
     OFPST_FLOW = 1,
     OFPST_AGGREGATE = 2,
@@ -221,24 +224,24 @@
     OFPST_VENDOR = 0xffff,
 };
 
-enum ofp_packet_in_reason {
+enum ofp_packet_in_reason(wire_type=uint8_t) {
     OFPR_NO_MATCH = 0,
     OFPR_ACTION = 1,
 };
 
-enum ofp_flow_removed_reason {
+enum ofp_flow_removed_reason(wire_type=uint8_t) {
     OFPRR_IDLE_TIMEOUT = 0,
     OFPRR_HARD_TIMEOUT = 1,
     OFPRR_DELETE = 2,
 };
 
-enum ofp_port_reason {
+enum ofp_port_reason(wire_type=uint8_t) {
     OFPPR_ADD = 0,
     OFPPR_DELETE = 1,
     OFPPR_MODIFY = 2,
 };
 
-enum ofp_error_type {
+enum ofp_error_type(wire_type=uint16_t) {
     OFPET_HELLO_FAILED = 0,
     OFPET_BAD_REQUEST = 1,
     OFPET_BAD_ACTION = 2,
@@ -247,12 +250,12 @@
     OFPET_QUEUE_OP_FAILED = 5,
 };
 
-enum ofp_hello_failed_code {
+enum ofp_hello_failed_code(wire_type=uint16_t) {
     OFPHFC_INCOMPATIBLE = 0,
     OFPHFC_EPERM = 1,
 };
 
-enum ofp_bad_request_code {
+enum ofp_bad_request_code(wire_type=uint16_t) {
     OFPBRC_BAD_VERSION = 0,
     OFPBRC_BAD_TYPE = 1,
     OFPBRC_BAD_STAT = 2,
@@ -264,7 +267,7 @@
     OFPBRC_BUFFER_UNKNOWN = 8,
 };
 
-enum ofp_bad_action_code {
+enum ofp_bad_action_code(wire_type=uint16_t) {
     OFPBAC_BAD_TYPE = 0,
     OFPBAC_BAD_LEN = 1,
     OFPBAC_BAD_VENDOR = 2,
@@ -276,7 +279,7 @@
     OFPBAC_BAD_QUEUE = 8,
 };
 
-enum ofp_flow_mod_failed_code {
+enum ofp_flow_mod_failed_code(wire_type=uint16_t) {
     OFPFMFC_ALL_TABLES_FULL = 0,
     OFPFMFC_OVERLAP = 1,
     OFPFMFC_EPERM = 2,
@@ -285,12 +288,12 @@
     OFPFMFC_UNSUPPORTED = 5,
 };
 
-enum ofp_port_mod_failed_code {
+enum ofp_port_mod_failed_code(wire_type=uint16_t) {
     OFPPMFC_BAD_PORT = 0,
     OFPPMFC_BAD_HW_ADDR = 1,
 };
 
-enum ofp_queue_op_failed_code {
+enum ofp_queue_op_failed_code(wire_type=uint16_t) {
     OFPQOFC_BAD_PORT = 0,
     OFPQOFC_BAD_QUEUE = 1,
     OFPQOFC_EPERM = 2,
diff --git a/openflow_input/standard-1.1 b/openflow_input/standard-1.1
index 4366af8..222071a 100644
--- a/openflow_input/standard-1.1
+++ b/openflow_input/standard-1.1
@@ -63,7 +63,7 @@
     OFPQ_MIN_RATE_UNCFG = 0xffff,
 };
 
-enum ofp_port {
+enum ofp_port(wire_type=uint32_t) {
     OFPP_MAX = 0xffffff00,
     OFPP_IN_PORT = 0xfffffff8,
     OFPP_TABLE = 0xfffffff9,
@@ -74,11 +74,11 @@
     OFPP_LOCAL = 0xfffffffe,
 };
 
-enum ofp_port_no {
+enum ofp_port_no(wire_type=uint32_t, complete=no) {
     OFPP_ANY = 0xffffffff,
 };
 
-enum ofp_type {
+enum ofp_type(wire_type=uint8_t) {
     OFPT_HELLO = 0,
     OFPT_ERROR = 1,
     OFPT_ECHO_REQUEST = 2,
@@ -105,22 +105,22 @@
     OFPT_QUEUE_GET_CONFIG_REPLY = 23,
 };
 
-enum ofp_config_flags {
+enum ofp_config_flags(wire_type=uint16_t, bitmask=True) {
     OFPC_FRAG_NORMAL = 0,
     OFPC_FRAG_DROP = 1,
     OFPC_FRAG_REASM = 2,
-    OFPC_FRAG_MASK = 3,
+    OFPC_FRAG_MASK(virtual=True) = 3,
     OFPC_INVALID_TTL_TO_CONTROLLER = 4,
 };
 
-enum ofp_table_config {
+enum ofp_table_config(wire_type=uint32_t, bitmask=True) {
     OFPTC_TABLE_MISS_CONTROLLER = 0,
     OFPTC_TABLE_MISS_CONTINUE = 1,
     OFPTC_TABLE_MISS_DROP = 2,
-    OFPTC_TABLE_MISS_MASK = 3,
+    OFPTC_TABLE_MISS_MASK(virtual=True) = 3,
 };
 
-enum ofp_capabilities {
+enum ofp_capabilities(wire_type=uint32_t, bitmask=True) {
     OFPC_FLOW_STATS = 0x1,
     OFPC_TABLE_STATS = 0x2,
     OFPC_PORT_STATS = 0x4,
@@ -130,20 +130,20 @@
     OFPC_ARP_MATCH_IP = 0x80,
 };
 
-enum ofp_port_config {
+enum ofp_port_config(wire_type=uint32_t, bitmask=True) {
     OFPPC_PORT_DOWN = 0x1,
     OFPPC_NO_RECV = 0x4,
     OFPPC_NO_FWD = 0x20,
     OFPPC_NO_PACKET_IN = 0x40,
 };
 
-enum ofp_port_state {
+enum ofp_port_state(wire_type=uint32_t, bitmask=True) {
     OFPPS_LINK_DOWN = 0x1,
     OFPPS_BLOCKED = 0x2,
     OFPPS_LIVE = 0x4,
 };
 
-enum ofp_port_features {
+enum ofp_port_features(wire_type=uint32_t, bitmask=True) {
     OFPPF_10MB_HD = 0x1,
     OFPPF_10MB_FD = 0x2,
     OFPPF_100MB_HD = 0x4,
@@ -162,18 +162,18 @@
     OFPPF_PAUSE_ASYM = 0x8000,
 };
 
-enum ofp_port_reason {
+enum ofp_port_reason(wire_type=uint8_t) {
     OFPPR_ADD = 0,
     OFPPR_DELETE = 1,
     OFPPR_MODIFY = 2,
 };
 
-enum ofp_packet_in_reason {
+enum ofp_packet_in_reason(wire_type=uint8_t) {
     OFPR_NO_MATCH = 0,
     OFPR_ACTION = 1,
 };
 
-enum ofp_action_type {
+enum ofp_action_type(wire_type=uint16_t) {
     OFPAT_OUTPUT = 0,
     OFPAT_SET_VLAN_VID = 1,
     OFPAT_SET_VLAN_PCP = 2,
@@ -202,7 +202,7 @@
     OFPAT_EXPERIMENTER = 0xffff,
 };
 
-enum ofp_flow_mod_command {
+enum ofp_flow_mod_command(wire_type=uint8_t) {
     OFPFC_ADD = 0,
     OFPFC_MODIFY = 1,
     OFPFC_MODIFY_STRICT = 2,
@@ -210,13 +210,13 @@
     OFPFC_DELETE_STRICT = 4,
 };
 
-enum ofp_group_mod_command {
+enum ofp_group_mod_command(wire_type=uint16_t) {
     OFPGC_ADD = 0,
     OFPGC_MODIFY = 1,
     OFPGC_DELETE = 2,
 };
 
-enum ofp_flow_wildcards {
+enum ofp_flow_wildcards(wire_type=uint32_t, bitmask=True) {
     OFPFW_IN_PORT = 0x1,
     OFPFW_DL_VLAN = 0x2,
     OFPFW_DL_VLAN_PCP = 0x4,
@@ -227,19 +227,19 @@
     OFPFW_TP_DST = 0x80,
     OFPFW_MPLS_LABEL = 0x100,
     OFPFW_MPLS_TC = 0x200,
-    OFPFW_ALL = 0x3ff,
+    OFPFW_ALL(virtual=True) = 0x3ff,
 };
 
-enum ofp_vlan_id {
+enum ofp_vlan_id(wire_type=uint16_t) {
     OFPVID_ANY = 0xfffe,
     OFPVID_NONE = 0xffff,
 };
 
-enum ofp_match_type {
+enum ofp_match_type(wire_type=uint16_t) {
     OFPMT_STANDARD = 0,
 };
 
-enum ofp_instruction_type {
+enum ofp_instruction_type(wire_type=uint16_t, bitmask=True) {
     OFPIT_GOTO_TABLE = 0x1,
     OFPIT_WRITE_METADATA = 0x2,
     OFPIT_WRITE_ACTIONS = 0x3,
@@ -248,32 +248,32 @@
     OFPIT_EXPERIMENTER = 0xffff,
 };
 
-enum ofp_flow_mod_flags {
+enum ofp_flow_mod_flags(wire_type=uint16_t, bitmask=True) {
     OFPFF_SEND_FLOW_REM = 0x1,
     OFPFF_CHECK_OVERLAP = 0x2,
 };
 
-enum ofp_group {
+enum ofp_group(wire_type=uint32_t, complete=False) {
     OFPG_MAX = 0xffffff00,
     OFPG_ALL = 0xfffffffc,
     OFPG_ANY = 0xffffffff,
 };
 
-enum ofp_group_type {
+enum ofp_group_type(wire_type=uint8_t) {
     OFPGT_ALL = 0,
     OFPGT_SELECT = 1,
     OFPGT_INDIRECT = 2,
     OFPGT_FF = 3,
 };
 
-enum ofp_flow_removed_reason {
+enum ofp_flow_removed_reason(wire_type=uint8_t) {
     OFPRR_IDLE_TIMEOUT = 0,
     OFPRR_HARD_TIMEOUT = 1,
     OFPRR_DELETE = 2,
     OFPRR_GROUP_DELETE = 3,
 };
 
-enum ofp_error_type {
+enum ofp_error_type(wire_type=uint16_t) {
     OFPET_HELLO_FAILED = 0,
     OFPET_BAD_REQUEST = 1,
     OFPET_BAD_ACTION = 2,
@@ -287,12 +287,12 @@
     OFPET_SWITCH_CONFIG_FAILED = 10,
 };
 
-enum ofp_hello_failed_code {
+enum ofp_hello_failed_code(wire_type=uint16_t) {
     OFPHFC_INCOMPATIBLE = 0,
     OFPHFC_EPERM = 1,
 };
 
-enum ofp_bad_request_code {
+enum ofp_bad_request_code(wire_type=uint16_t) {
     OFPBRC_BAD_VERSION = 0,
     OFPBRC_BAD_TYPE = 1,
     OFPBRC_BAD_STAT = 2,
@@ -305,7 +305,7 @@
     OFPBRC_BAD_TABLE_ID = 9,
 };
 
-enum ofp_bad_action_code {
+enum ofp_bad_action_code(wire_type=uint16_t) {
     OFPBAC_BAD_TYPE = 0,
     OFPBAC_BAD_LEN = 1,
     OFPBAC_BAD_EXPERIMENTER = 2,
@@ -321,7 +321,7 @@
     OFPBAC_BAD_TAG = 12,
 };
 
-enum ofp_bad_instruction_code {
+enum ofp_bad_instruction_code(wire_type=uint16_t) {
     OFPBIC_UNKNOWN_INST = 0,
     OFPBIC_UNSUP_INST = 1,
     OFPBIC_BAD_TABLE_ID = 2,
@@ -330,7 +330,7 @@
     OFPBIC_UNSUP_EXP_INST = 5,
 };
 
-enum ofp_bad_match_code {
+enum ofp_bad_match_code(wire_type=uint16_t) {
     OFPBMC_BAD_TYPE = 0,
     OFPBMC_BAD_LEN = 1,
     OFPBMC_BAD_TAG = 2,
@@ -341,7 +341,7 @@
     OFPBMC_BAD_VALUE = 7,
 };
 
-enum ofp_flow_mod_failed_code {
+enum ofp_flow_mod_failed_code(wire_type=uint16_t) {
     OFPFMFC_UNKNOWN = 0,
     OFPFMFC_TABLE_FULL = 1,
     OFPFMFC_BAD_TABLE_ID = 2,
@@ -351,7 +351,7 @@
     OFPFMFC_BAD_COMMAND = 6,
 };
 
-enum ofp_group_mod_failed_code {
+enum ofp_group_mod_failed_code(wire_type=uint16_t) {
     OFPGMFC_GROUP_EXISTS = 0,
     OFPGMFC_INVALID_GROUP = 1,
     OFPGMFC_WEIGHT_UNSUPPORTED = 2,
@@ -363,30 +363,30 @@
     OFPGMFC_UNKNOWN_GROUP = 8,
 };
 
-enum ofp_port_mod_failed_code {
+enum ofp_port_mod_failed_code(wire_type=uint16_t) {
     OFPPMFC_BAD_PORT = 0,
     OFPPMFC_BAD_HW_ADDR = 1,
     OFPPMFC_BAD_CONFIG = 2,
     OFPPMFC_BAD_ADVERTISE = 3,
 };
 
-enum ofp_table_mod_failed_code {
+enum ofp_table_mod_failed_code(wire_type=uint16_t) {
     OFPTMFC_BAD_TABLE = 0,
     OFPTMFC_BAD_CONFIG = 1,
 };
 
-enum ofp_queue_op_failed_code {
+enum ofp_queue_op_failed_code(wire_type=uint16_t) {
     OFPQOFC_BAD_PORT = 0,
     OFPQOFC_BAD_QUEUE = 1,
     OFPQOFC_EPERM = 2,
 };
 
-enum ofp_switch_config_failed_code {
+enum ofp_switch_config_failed_code(wire_type=uint16_t) {
     OFPSCFC_BAD_FLAGS = 0,
     OFPSCFC_BAD_LEN = 1,
 };
 
-enum ofp_stats_types {
+enum ofp_stats_types(wire_type=uint16_t) {
     OFPST_DESC = 0,
     OFPST_FLOW = 1,
     OFPST_AGGREGATE = 2,
@@ -398,11 +398,11 @@
     OFPST_EXPERIMENTER = 0xffff,
 };
 
-enum ofp_stats_reply_flags {
+enum ofp_stats_reply_flags(wire_type=uint16_t, bitmask=True) {
     OFPSF_REPLY_MORE = 0x1,
 };
 
-enum ofp_queue_properties {
+enum ofp_queue_properties(wire_type=uint16_t) {
     OFPQT_NONE = 0,
     OFPQT_MIN_RATE = 1,
 };
diff --git a/openflow_input/standard-1.2 b/openflow_input/standard-1.2
index b49c83f..6bcebdc 100644
--- a/openflow_input/standard-1.2
+++ b/openflow_input/standard-1.2
@@ -59,7 +59,7 @@
     OFPQ_MAX_RATE_UNCFG = 0xffff,
 };
 
-enum ofp_port {
+enum ofp_port(wire_type=uint32_t) {
     OFPP_MAX = 0xffffff00,
     OFPP_IN_PORT = 0xfffffff8,
     OFPP_TABLE = 0xfffffff9,
@@ -70,11 +70,11 @@
     OFPP_LOCAL = 0xfffffffe,
 };
 
-enum ofp_port_no {
+enum ofp_port_no(wire_type=uint32_t, complete=no) {
     OFPP_ANY = 0xffffffff,
 };
 
-enum ofp_type {
+enum ofp_type(wire_type=uint8_t) {
     OFPT_HELLO = 0,
     OFPT_ERROR = 1,
     OFPT_ECHO_REQUEST = 2,
@@ -103,7 +103,7 @@
     OFPT_ROLE_REPLY = 25,
 };
 
-enum ofp_config_flags {
+enum ofp_config_flags(wire_type=uint16_t, bitmask=True) {
     OFPC_FRAG_NORMAL = 0,
     OFPC_FRAG_DROP = 1,
     OFPC_FRAG_REASM = 2,
@@ -111,19 +111,19 @@
     OFPC_INVALID_TTL_TO_CONTROLLER = 4,
 };
 
-enum ofp_table_config {
+enum ofp_table_config(wire_type=uint32_t, bitmask=True) {
     OFPTC_TABLE_MISS_CONTROLLER = 0,
     OFPTC_TABLE_MISS_CONTINUE = 1,
     OFPTC_TABLE_MISS_DROP = 2,
     OFPTC_TABLE_MISS_MASK = 3,
 };
 
-enum ofp_table {
+enum ofp_table(wire_type=uint8_t, complete=False) {
     OFPTT_MAX = 0xfe,
     OFPTT_ALL = 0xff,
 };
 
-enum ofp_capabilities {
+enum ofp_capabilities(wire_type=uint32_t, bitmask=True) {
     OFPC_FLOW_STATS = 0x1,
     OFPC_TABLE_STATS = 0x2,
     OFPC_PORT_STATS = 0x4,
@@ -133,20 +133,20 @@
     OFPC_PORT_BLOCKED = 0x100,
 };
 
-enum ofp_port_config {
+enum ofp_port_config(wire_type=uint32_t, bitmask=True) {
     OFPPC_PORT_DOWN = 0x1,
     OFPPC_NO_RECV = 0x4,
     OFPPC_NO_FWD = 0x20,
     OFPPC_NO_PACKET_IN = 0x40,
 };
 
-enum ofp_port_state {
+enum ofp_port_state(wire_type=uint32_t, bitmask=True) {
     OFPPS_LINK_DOWN = 0x1,
     OFPPS_BLOCKED = 0x2,
     OFPPS_LIVE = 0x4,
 };
 
-enum ofp_port_features {
+enum ofp_port_features(wire_type=uint32_t, bitmask=True) {
     OFPPF_10MB_HD = 0x1,
     OFPPF_10MB_FD = 0x2,
     OFPPF_100MB_HD = 0x4,
@@ -165,30 +165,30 @@
     OFPPF_PAUSE_ASYM = 0x8000,
 };
 
-enum ofp_port_reason {
+enum ofp_port_reason(wire_type=uint8_t) {
     OFPPR_ADD = 0,
     OFPPR_DELETE = 1,
     OFPPR_MODIFY = 2,
 };
 
-enum ofp_match_type {
+enum ofp_match_type(wire_type=uint16_t) {
     OFPMT_STANDARD = 0,
     OFPMT_OXM = 1,
 };
 
-enum ofp_oxm_class {
+enum ofp_oxm_class(wire_type=uint16_t) {
     OFPXMC_NXM_0 = 0,
     OFPXMC_NXM_1 = 1,
     OFPXMC_OPENFLOW_BASIC = 0x8000,
     OFPXMC_EXPERIMENTER = 0xffff,
 };
 
-enum ofp_vlan_id {
+enum ofp_vlan_id(wire_type=uint16_t) {
     OFPVID_NONE = 0,
     OFPVID_PRESENT = 0x1000,
 };
 
-enum ofp_action_type {
+enum ofp_action_type(wire_type=uint16_t) {
     OFPAT_OUTPUT = 0,
     OFPAT_COPY_TTL_OUT = 0xb,
     OFPAT_COPY_TTL_IN = 0xc,
@@ -206,12 +206,12 @@
     OFPAT_EXPERIMENTER = 0xffff,
 };
 
-enum ofp_controller_max_len {
+enum ofp_controller_max_len(wire_type=uint16_t, complete=False) {
     OFPCML_MAX = 0xffe5,
     OFPCML_NO_BUFFER = 0xffff,
 };
 
-enum ofp_instruction_type {
+enum ofp_instruction_type(wire_type=uint16_t, bitmask=True) {
     OFPIT_GOTO_TABLE = 0x1,
     OFPIT_WRITE_METADATA = 0x2,
     OFPIT_WRITE_ACTIONS = 0x3,
@@ -220,7 +220,7 @@
     OFPIT_EXPERIMENTER = 0xffff,
 };
 
-enum ofp_flow_mod_command {
+enum ofp_flow_mod_command(wire_type=uint8_t) {
     OFPFC_ADD = 0,
     OFPFC_MODIFY = 1,
     OFPFC_MODIFY_STRICT = 2,
@@ -228,45 +228,45 @@
     OFPFC_DELETE_STRICT = 4,
 };
 
-enum ofp_flow_mod_flags {
+enum ofp_flow_mod_flags(wire_type=uint16_t, bitmask=True) {
     OFPFF_SEND_FLOW_REM = 0x1,
     OFPFF_CHECK_OVERLAP = 0x2,
     OFPFF_RESET_COUNTS = 0x4,
 };
 
-enum ofp_group {
+enum ofp_group(wire_type=uint32_t, complete=False) {
     OFPG_MAX = 0xffffff00,
     OFPG_ALL = 0xfffffffc,
     OFPG_ANY = 0xffffffff,
 };
 
-enum ofp_group_mod_command {
+enum ofp_group_mod_command(wire_type=uint16_t) {
     OFPGC_ADD = 0,
     OFPGC_MODIFY = 1,
     OFPGC_DELETE = 2,
 };
 
-enum ofp_group_type {
+enum ofp_group_type(wire_type=uint8_t) {
     OFPGT_ALL = 0,
     OFPGT_SELECT = 1,
     OFPGT_INDIRECT = 2,
     OFPGT_FF = 3,
 };
 
-enum ofp_packet_in_reason {
+enum ofp_packet_in_reason(wire_type=uint8_t) {
     OFPR_NO_MATCH = 0,
     OFPR_ACTION = 1,
     OFPR_INVALID_TTL = 2,
 };
 
-enum ofp_flow_removed_reason {
+enum ofp_flow_removed_reason(wire_type=uint8_t) {
     OFPRR_IDLE_TIMEOUT = 0,
     OFPRR_HARD_TIMEOUT = 1,
     OFPRR_DELETE = 2,
     OFPRR_GROUP_DELETE = 3,
 };
 
-enum ofp_error_type {
+enum ofp_error_type(wire_type=uint16_t) {
     OFPET_HELLO_FAILED = 0,
     OFPET_BAD_REQUEST = 1,
     OFPET_BAD_ACTION = 2,
@@ -282,12 +282,12 @@
     OFPET_EXPERIMENTER = 0xffff,
 };
 
-enum ofp_hello_failed_code {
+enum ofp_hello_failed_code(wire_type=uint16_t) {
     OFPHFC_INCOMPATIBLE = 0,
     OFPHFC_EPERM = 1,
 };
 
-enum ofp_bad_request_code {
+enum ofp_bad_request_code(wire_type=uint16_t) {
     OFPBRC_BAD_VERSION = 0,
     OFPBRC_BAD_TYPE = 1,
     OFPBRC_BAD_STAT = 2,
@@ -303,7 +303,7 @@
     OFPBRC_BAD_PACKET = 12,
 };
 
-enum ofp_bad_action_code {
+enum ofp_bad_action_code(wire_type=uint16_t) {
     OFPBAC_BAD_TYPE = 0,
     OFPBAC_BAD_LEN = 1,
     OFPBAC_BAD_EXPERIMENTER = 2,
@@ -322,7 +322,7 @@
     OFPBAC_BAD_SET_ARGUMENT = 15,
 };
 
-enum ofp_bad_instruction_code {
+enum ofp_bad_instruction_code(wire_type=uint16_t) {
     OFPBIC_UNKNOWN_INST = 0,
     OFPBIC_UNSUP_INST = 1,
     OFPBIC_BAD_TABLE_ID = 2,
@@ -334,7 +334,7 @@
     OFPBIC_EPERM = 8,
 };
 
-enum ofp_bad_match_code {
+enum ofp_bad_match_code(wire_type=uint16_t) {
     OFPBMC_BAD_TYPE = 0,
     OFPBMC_BAD_LEN = 1,
     OFPBMC_BAD_TAG = 2,
@@ -349,7 +349,7 @@
     OFPBMC_EPERM = 11,
 };
 
-enum ofp_flow_mod_failed_code {
+enum ofp_flow_mod_failed_code(wire_type=uint16_t) {
     OFPFMFC_UNKNOWN = 0,
     OFPFMFC_TABLE_FULL = 1,
     OFPFMFC_BAD_TABLE_ID = 2,
@@ -360,7 +360,7 @@
     OFPFMFC_BAD_FLAGS = 7,
 };
 
-enum ofp_group_mod_failed_code {
+enum ofp_group_mod_failed_code(wire_type=uint16_t) {
     OFPGMFC_GROUP_EXISTS = 0,
     OFPGMFC_INVALID_GROUP = 1,
     OFPGMFC_WEIGHT_UNSUPPORTED = 2,
@@ -378,7 +378,7 @@
     OFPGMFC_EPERM = 14,
 };
 
-enum ofp_port_mod_failed_code {
+enum ofp_port_mod_failed_code(wire_type=uint16_t) {
     OFPPMFC_BAD_PORT = 0,
     OFPPMFC_BAD_HW_ADDR = 1,
     OFPPMFC_BAD_CONFIG = 2,
@@ -386,31 +386,31 @@
     OFPPMFC_EPERM = 4,
 };
 
-enum ofp_table_mod_failed_code {
+enum ofp_table_mod_failed_code(wire_type=uint16_t) {
     OFPTMFC_BAD_TABLE = 0,
     OFPTMFC_BAD_CONFIG = 1,
     OFPTMFC_EPERM = 2,
 };
 
-enum ofp_queue_op_failed_code {
+enum ofp_queue_op_failed_code(wire_type=uint16_t) {
     OFPQOFC_BAD_PORT = 0,
     OFPQOFC_BAD_QUEUE = 1,
     OFPQOFC_EPERM = 2,
 };
 
-enum ofp_switch_config_failed_code {
+enum ofp_switch_config_failed_code(wire_type=uint16_t) {
     OFPSCFC_BAD_FLAGS = 0,
     OFPSCFC_BAD_LEN = 1,
     OFPSCFC_EPERM = 2,
 };
 
-enum ofp_role_request_failed_code {
+enum ofp_role_request_failed_code (wire_type=uint16_t){
     OFPRRFC_STALE = 0,
     OFPRRFC_UNSUP = 1,
     OFPRRFC_BAD_ROLE = 2,
 };
 
-enum ofp_stats_types {
+enum ofp_stats_types(wire_type=uint16_t) {
     OFPST_DESC = 0,
     OFPST_FLOW = 1,
     OFPST_AGGREGATE = 2,
@@ -423,24 +423,24 @@
     OFPST_EXPERIMENTER = 0xffff,
 };
 
-enum ofp_stats_reply_flags {
+enum ofp_stats_reply_flags(wire_type=uint16_t, bitmask=True) {
     OFPSF_REPLY_MORE = 0x1,
 };
 
-enum ofp_group_capabilities {
+enum ofp_group_capabilities(wire_type=uint32_t, bitmask=True) {
     OFPGFC_SELECT_WEIGHT = 0x1,
     OFPGFC_SELECT_LIVENESS = 0x2,
     OFPGFC_CHAINING = 0x4,
     OFPGFC_CHAINING_CHECKS = 0x8,
 };
 
-enum ofp_queue_properties {
+enum ofp_queue_properties(wire_type=uint16_t) {
     OFPQT_MIN_RATE = 0x1,
     OFPQT_MAX_RATE = 0x2,
     OFPQT_EXPERIMENTER = 0xffff,
 };
 
-enum ofp_controller_role {
+enum ofp_controller_role(wire_type=uint32_t) {
     OFPCR_ROLE_NOCHANGE = 0,
     OFPCR_ROLE_EQUAL = 1,
     OFPCR_ROLE_MASTER = 2,
@@ -599,7 +599,7 @@
     pad(4);
 };
 
-struct of_match_v3 {
+struct of_match_v3(align=8) {
     uint16_t type == 1;
     uint16_t length;
     list(of_oxm_t) oxm_list;
diff --git a/openflow_input/standard-1.3 b/openflow_input/standard-1.3
index ab32abe..0a56793 100644
--- a/openflow_input/standard-1.3
+++ b/openflow_input/standard-1.3
@@ -58,11 +58,11 @@
     OFPQ_MIN_RATE_UNCFG = 0xffff,
 };
 
-enum ofp_port_no {
+enum ofp_port_no(wire_type=uint32_t, complete=no) {
     OFPP_ANY = 0xffffffff,
 };
 
-enum ofp_port {
+enum ofp_port(wire_type=uint32_t) {
     OFPP_MAX = 0xffffff00,
     OFPP_IN_PORT = 0xfffffff8,
     OFPP_TABLE = 0xfffffff9,
@@ -73,7 +73,7 @@
     OFPP_LOCAL = 0xfffffffe,
 };
 
-enum ofp_type {
+enum ofp_type(wire_type=uint8_t) {
     OFPT_HELLO = 0,
     OFPT_ERROR = 1,
     OFPT_ECHO_REQUEST = 2,
@@ -106,23 +106,23 @@
     OFPT_METER_MOD = 29,
 };
 
-enum ofp_config_flags {
+enum ofp_config_flags(wire_type=uint16_t, bitmask=True) {
     OFPC_FRAG_NORMAL = 0,
     OFPC_FRAG_DROP = 1,
     OFPC_FRAG_REASM = 2,
     OFPC_FRAG_MASK = 3,
 };
 
-enum ofp_table_config {
+enum ofp_table_config(wire_type=uint32_t, bitmask=True) {
     OFPTC_DEPRECATED_MASK = 0x3,
 };
 
-enum ofp_table {
+enum ofp_table(wire_type=uint8_t, complete=False) {
     OFPTT_MAX = 0xfe,
     OFPTT_ALL = 0xff,
 };
 
-enum ofp_capabilities {
+enum ofp_capabilities(wire_type=uint32_t, bitmask=True) {
     OFPC_FLOW_STATS = 0x1,
     OFPC_TABLE_STATS = 0x2,
     OFPC_PORT_STATS = 0x4,
@@ -132,20 +132,20 @@
     OFPC_PORT_BLOCKED = 0x100,
 };
 
-enum ofp_port_config {
+enum ofp_port_config(wire_type=uint32_t, bitmask=True) {
     OFPPC_PORT_DOWN = 0x1,
     OFPPC_NO_RECV = 0x4,
     OFPPC_NO_FWD = 0x20,
     OFPPC_NO_PACKET_IN = 0x40,
 };
 
-enum ofp_port_state {
+enum ofp_port_state(wire_type=uint32_t, bitmask=True) {
     OFPPS_LINK_DOWN = 0x1,
     OFPPS_BLOCKED = 0x2,
     OFPPS_LIVE = 0x4,
 };
 
-enum ofp_port_features {
+enum ofp_port_features(wire_type=uint32_t, bitmask=True) {
     OFPPF_10MB_HD = 0x1,
     OFPPF_10MB_FD = 0x2,
     OFPPF_100MB_HD = 0x4,
@@ -164,30 +164,32 @@
     OFPPF_PAUSE_ASYM = 0x8000,
 };
 
-enum ofp_port_reason {
+enum ofp_port_reason(wire_type=uint8_t) {
     OFPPR_ADD = 0,
     OFPPR_DELETE = 1,
     OFPPR_MODIFY = 2,
 };
 
-enum ofp_match_type {
+enum ofp_match_type(wire_type=uint16_t) {
     OFPMT_STANDARD = 0,
     OFPMT_OXM = 1,
 };
 
-enum ofp_oxm_class {
+enum ofp_oxm_class(wire_type=uint16_t) {
     OFPXMC_NXM_0 = 0,
     OFPXMC_NXM_1 = 1,
     OFPXMC_OPENFLOW_BASIC = 0x8000,
     OFPXMC_EXPERIMENTER = 0xffff,
 };
 
-enum ofp_vlan_id {
+enum ofp_vlan_id(wire_type=uint16_t) {
     OFPVID_NONE = 0,
     OFPVID_PRESENT = 0x1000,
 };
 
-enum ofp_ipv6exthdr_flags {
+// FIXME: OF spec specified this as '9' bits, implicitly adding
+// to full byte
+enum ofp_ipv6exthdr_flags(wire_type=uint16_t, bitmask=True) {
     OFPIEH_NONEXT = 0x1,
     OFPIEH_ESP = 0x2,
     OFPIEH_AUTH = 0x4,
@@ -199,7 +201,7 @@
     OFPIEH_UNSEQ = 0x100,
 };
 
-enum ofp_action_type {
+enum ofp_action_type(wire_type=uint16_t) {
     OFPAT_OUTPUT = 0,
     OFPAT_COPY_TTL_OUT = 0xb,
     OFPAT_COPY_TTL_IN = 0xc,
@@ -219,12 +221,12 @@
     OFPAT_EXPERIMENTER = 0xffff,
 };
 
-enum ofp_controller_max_len {
+enum ofp_controller_max_len(wire_type=uint16_t, complete=False) {
     OFPCML_MAX = 0xffe5,
     OFPCML_NO_BUFFER = 0xffff,
 };
 
-enum ofp_instruction_type {
+enum ofp_instruction_type(wire_type=uint16_t, bitmask=True) {
     OFPIT_GOTO_TABLE = 0x1,
     OFPIT_WRITE_METADATA = 0x2,
     OFPIT_WRITE_ACTIONS = 0x3,
@@ -234,7 +236,7 @@
     OFPIT_EXPERIMENTER = 0xffff,
 };
 
-enum ofp_flow_mod_command {
+enum ofp_flow_mod_command(wire_type=uint8_t) {
     OFPFC_ADD = 0,
     OFPFC_MODIFY = 1,
     OFPFC_MODIFY_STRICT = 2,
@@ -242,7 +244,7 @@
     OFPFC_DELETE_STRICT = 4,
 };
 
-enum ofp_flow_mod_flags {
+enum ofp_flow_mod_flags(wire_type=uint16_t, bitmask=True) {
     OFPFF_SEND_FLOW_REM = 0x1,
     OFPFF_CHECK_OVERLAP = 0x2,
     OFPFF_RESET_COUNTS = 0x4,
@@ -250,65 +252,65 @@
     OFPFF_NO_BYT_COUNTS = 0x10,
 };
 
-enum ofp_group {
+enum ofp_group(wire_type=uint32_t, complete=False) {
     OFPG_MAX = 0xffffff00,
     OFPG_ALL = 0xfffffffc,
     OFPG_ANY = 0xffffffff,
 };
 
-enum ofp_group_mod_command {
+enum ofp_group_mod_command(wire_type=uint16_t) {
     OFPGC_ADD = 0,
     OFPGC_MODIFY = 1,
     OFPGC_DELETE = 2,
 };
 
-enum ofp_group_type {
+enum ofp_group_type(wire_type=uint8_t) {
     OFPGT_ALL = 0,
     OFPGT_SELECT = 1,
     OFPGT_INDIRECT = 2,
     OFPGT_FF = 3,
 };
 
-enum ofp_packet_in_reason {
+enum ofp_packet_in_reason(wire_type=uint8_t) {
     OFPR_NO_MATCH = 0,
     OFPR_ACTION = 1,
     OFPR_INVALID_TTL = 2,
 };
 
-enum ofp_flow_removed_reason {
+enum ofp_flow_removed_reason(wire_type=uint8_t) {
     OFPRR_IDLE_TIMEOUT = 0,
     OFPRR_HARD_TIMEOUT = 1,
     OFPRR_DELETE = 2,
     OFPRR_GROUP_DELETE = 3,
 };
 
-enum ofp_meter {
+enum ofp_meter(wire_type=uint32_t, complete=False) {
     OFPM_MAX = 0xffff0000,
     OFPM_SLOWPATH = 0xfffffffd,
     OFPM_CONTROLLER = 0xfffffffe,
     OFPM_ALL = 0xffffffff,
 };
 
-enum ofp_meter_band_type {
+enum ofp_meter_band_type(wire_type=uint16_t) {
     OFPMBT_DROP = 0x1,
     OFPMBT_DSCP_REMARK = 0x2,
     OFPMBT_EXPERIMENTER = 0xffff,
 };
 
-enum ofp_meter_mod_command {
+enum ofp_meter_mod_command(wire_type=uint16_t) {
     OFPMC_ADD = 0,
     OFPMC_MODIFY = 1,
     OFPMC_DELETE = 2,
 };
 
-enum ofp_meter_flags {
+enum ofp_meter_flags(wire_type=uint16_t, bitmask=True) {
     OFPMF_KBPS = 0x1,
     OFPMF_PKTPS = 0x2,
     OFPMF_BURST = 0x4,
     OFPMF_STATS = 0x8,
 };
 
-enum ofp_error_type {
+enum ofp_error_type(wire_type=uint16_t) {
     OFPET_HELLO_FAILED = 0,
     OFPET_BAD_REQUEST = 1,
     OFPET_BAD_ACTION = 2,
@@ -326,12 +328,12 @@
     OFPET_EXPERIMENTER = 0xffff,
 };
 
-enum ofp_hello_failed_code {
+enum ofp_hello_failed_code(wire_type=uint16_t) {
     OFPHFC_INCOMPATIBLE = 0,
     OFPHFC_EPERM = 1,
 };
 
-enum ofp_bad_request_code {
+enum ofp_bad_request_code(wire_type=uint16_t) {
     OFPBRC_BAD_VERSION = 0,
     OFPBRC_BAD_TYPE = 1,
     OFPBRC_BAD_MULTIPART = 2,
@@ -348,7 +350,7 @@
     OFPBRC_MULTIPART_BUFFER_OVERFLOW = 13,
 };
 
-enum ofp_bad_action_code {
+enum ofp_bad_action_code(wire_type=uint16_t) {
     OFPBAC_BAD_TYPE = 0,
     OFPBAC_BAD_LEN = 1,
     OFPBAC_BAD_EXPERIMENTER = 2,
@@ -367,7 +369,7 @@
     OFPBAC_BAD_SET_ARGUMENT = 15,
 };
 
-enum ofp_bad_instruction_code {
+enum ofp_bad_instruction_code(wire_type=uint16_t) {
     OFPBIC_UNKNOWN_INST = 0,
     OFPBIC_UNSUP_INST = 1,
     OFPBIC_BAD_TABLE_ID = 2,
@@ -379,7 +381,7 @@
     OFPBIC_EPERM = 8,
 };
 
-enum ofp_bad_match_code {
+enum ofp_bad_match_code(wire_type=uint16_t) {
     OFPBMC_BAD_TYPE = 0,
     OFPBMC_BAD_LEN = 1,
     OFPBMC_BAD_TAG = 2,
@@ -394,7 +396,7 @@
     OFPBMC_EPERM = 11,
 };
 
-enum ofp_flow_mod_failed_code {
+enum ofp_flow_mod_failed_code(wire_type=uint16_t) {
     OFPFMFC_UNKNOWN = 0,
     OFPFMFC_TABLE_FULL = 1,
     OFPFMFC_BAD_TABLE_ID = 2,
@@ -405,7 +407,7 @@
     OFPFMFC_BAD_FLAGS = 7,
 };
 
-enum ofp_group_mod_failed_code {
+enum ofp_group_mod_failed_code(wire_type=uint16_t) {
     OFPGMFC_GROUP_EXISTS = 0,
     OFPGMFC_INVALID_GROUP = 1,
     OFPGMFC_WEIGHT_UNSUPPORTED = 2,
@@ -423,7 +425,7 @@
     OFPGMFC_EPERM = 14,
 };
 
-enum ofp_port_mod_failed_code {
+enum ofp_port_mod_failed_code(wire_type=uint16_t) {
     OFPPMFC_BAD_PORT = 0,
     OFPPMFC_BAD_HW_ADDR = 1,
     OFPPMFC_BAD_CONFIG = 2,
@@ -431,31 +433,31 @@
     OFPPMFC_EPERM = 4,
 };
 
-enum ofp_table_mod_failed_code {
+enum ofp_table_mod_failed_code(wire_type=uint16_t) {
     OFPTMFC_BAD_TABLE = 0,
     OFPTMFC_BAD_CONFIG = 1,
     OFPTMFC_EPERM = 2,
 };
 
-enum ofp_queue_op_failed_code {
+enum ofp_queue_op_failed_code(wire_type=uint16_t) {
     OFPQOFC_BAD_PORT = 0,
     OFPQOFC_BAD_QUEUE = 1,
     OFPQOFC_EPERM = 2,
 };
 
-enum ofp_switch_config_failed_code {
+enum ofp_switch_config_failed_code(wire_type=uint16_t) {
     OFPSCFC_BAD_FLAGS = 0,
     OFPSCFC_BAD_LEN = 1,
     OFPSCFC_EPERM = 2,
 };
 
-enum ofp_role_request_failed_code {
+enum ofp_role_request_failed_code(wire_type=uint16_t){
     OFPRRFC_STALE = 0,
     OFPRRFC_UNSUP = 1,
     OFPRRFC_BAD_ROLE = 2,
 };
 
-enum ofp_meter_mod_failed_code {
+enum ofp_meter_mod_failed_code(wire_type=uint16_t) {
     OFPMMFC_UNKNOWN = 0,
     OFPMMFC_METER_EXISTS = 1,
     OFPMMFC_INVALID_METER = 2,
@@ -470,7 +472,7 @@
     OFPMMFC_OUT_OF_BANDS = 11,
 };
 
-enum ofp_table_features_failed_code {
+enum ofp_table_features_failed_code(wire_type=uint16_t) {
     OFPTFFC_BAD_TABLE = 0,
     OFPTFFC_BAD_METADATA = 1,
     OFPTFFC_BAD_TYPE = 2,
@@ -479,7 +481,7 @@
     OFPTFFC_EPERM = 5,
 };
 
-enum ofp_multipart_types {
+enum ofp_multipart_types(wire_type=uint16_t) {
     OFPMP_DESC = 0,
     OFPMP_FLOW = 1,
     OFPMP_AGGREGATE = 2,
@@ -497,15 +499,15 @@
     OFPMP_EXPERIMENTER = 0xffff,
 };
 
-enum ofp_multipart_request_flags {
+enum ofp_multipart_request_flags(wire_type=uint16_t, bitmask=True) {
     OFPMPF_REQ_MORE = 0x1,
 };
 
-enum ofp_multipart_reply_flags {
+enum ofp_multipart_reply_flags(wire_type=uint16_t, bitmask=True) {
     OFPMPF_REPLY_MORE = 0x1,
 };
 
-enum ofp_table_feature_prop_type {
+enum ofp_table_feature_prop_type(wire_type=uint16_t) {
     OFPTFPT_INSTRUCTIONS = 0,
     OFPTFPT_INSTRUCTIONS_MISS = 1,
     OFPTFPT_NEXT_TABLES = 2,
@@ -524,27 +526,27 @@
     OFPTFPT_EXPERIMENTER_MISS = 0xffff,
 };
 
-enum ofp_group_capabilities {
+enum ofp_group_capabilities(wire_type=uint32_t, bitmask=True) {
     OFPGFC_SELECT_WEIGHT = 0x1,
     OFPGFC_SELECT_LIVENESS = 0x2,
     OFPGFC_CHAINING = 0x4,
     OFPGFC_CHAINING_CHECKS = 0x8,
 };
 
-enum ofp_queue_properties {
+enum ofp_queue_properties(wire_type=uint16_t) {
     OFPQT_MIN_RATE = 0x1,
     OFPQT_MAX_RATE = 0x2,
     OFPQT_EXPERIMENTER = 0xffff,
 };
 
-enum ofp_controller_role {
+enum ofp_controller_role(wire_type=uint32_t) {
     OFPCR_ROLE_NOCHANGE = 0,
     OFPCR_ROLE_EQUAL = 1,
     OFPCR_ROLE_MASTER = 2,
     OFPCR_ROLE_SLAVE = 3,
 };
 
-enum ofp_hello_elem_type {
+enum ofp_hello_elem_type(wire_type=uint16_t) {
     OFPHET_VERSIONBITMAP = 1,
 };
 
@@ -723,7 +725,7 @@
 };
 
 // FIXME Does this need to be v4?
-struct of_match_v3 {
+struct of_match_v3(align=8) {
     uint16_t type == 1;
     uint16_t length;
     list(of_oxm_t) oxm_list;
diff --git a/test_data/__init__.py b/test_data/__init__.py
index f21770b..7a55c11 100644
--- a/test_data/__init__.py
+++ b/test_data/__init__.py
@@ -45,6 +45,9 @@
                 result.append(dirname + '/' + filename)
     return sorted(result)
 
+def exists(name):
+    return os.path.exists(os.path.join(_test_data_dir, name))
+
 def read(name):
     """
     Read, parse, and return a test data file
diff --git a/test_data/of10/hello.data b/test_data/of10/hello.data
index 3dc2b44..d29dff9 100644
--- a/test_data/of10/hello.data
+++ b/test_data/of10/hello.data
@@ -7,3 +7,5 @@
 -- c
 obj = of_hello_new(OF_VERSION_1_0);
 of_hello_xid_set(obj, 305419896);
+-- java
+builder.setXid(0x12345678)
diff --git a/test_data/of10/packet_in.data b/test_data/of10/packet_in.data
index 8168e3b..2cd98b0 100644
--- a/test_data/of10/packet_in.data
+++ b/test_data/of10/packet_in.data
@@ -27,3 +27,11 @@
 of_packet_in_reason_set(obj, 1);
 of_packet_in_total_len_set(obj, 9);
 of_packet_in_xid_set(obj, 305419896);
+-- java
+builder
+   .setXid(0x12345678)
+   .setBufferId(0xabcdef01)
+   .setTotalLen(9)
+   .setInPort(OFPort.LOCAL)
+   .setReason(OFPacketInReason.ACTION)
+   .setData(new byte[] { 0x61, 0x62, 0x63 } );
diff --git a/test_data/of13/flow_add.data b/test_data/of13/flow_add.data
index c66518f..d01c209 100644
--- a/test_data/of13/flow_add.data
+++ b/test_data/of13/flow_add.data
@@ -50,3 +50,23 @@
     instructions=[
         ofp.instruction.goto_table(table_id=4),
         ofp.instruction.goto_table(table_id=7)])
+-- java
+builder.setXid(0x12345678)
+    .setCookie(U64.parseHex("FEDCBA9876543210"))
+    .setCookieMask(U64.parseHex("FF00FF00FF00FF00"))
+    .setTableId((byte) 3)
+    .setIdleTimeout(5)
+    .setHardTimeout(10)
+    .setPriority(6000)
+    .setBufferId(50)
+    .setOutPort(OFPort.of(6))
+    .setOutGroup(8)
+    .setFlags(0)
+    .setMatch(factory.createMatchV3Builder().getMessage()) // FIXME: @yotam: replace once we have generic ofmatch
+    .setInstructions(
+        ImmutableList.<OFInstruction>of(
+            factory.createInstructionGotoTableBuilder().setTableId((byte) 4).getMessage(),
+            factory.createInstructionGotoTableBuilder().setTableId((byte) 7).getMessage()
+        )
+    );
+