java_gen: work in progress commit of java generator
diff --git a/java_gen/.gitignore b/java_gen/.gitignore
new file mode 100644
index 0000000..84c1d8e
--- /dev/null
+++ b/java_gen/.gitignore
@@ -0,0 +1,2 @@
+*.class
+bin/
diff --git a/java_gen/__init__.py b/java_gen/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/java_gen/__init__.py
diff --git a/java_gen/java_code_gen.py b/java_gen/java_code_gen.py
new file mode 100644
index 0000000..91c89a7
--- /dev/null
+++ b/java_gen/java_code_gen.py
@@ -0,0 +1,68 @@
+import of_g
+import pdb
+import os
+
+import lang_java
+
+import loxi_utils.loxi_utils as loxi_utils
+
+import java_gen.msgs as msgs
+import java_gen.java_utils as java_utils
+
+def gen_all_java(out, name):
+    """ Generate all of the java files
+
+    @param out is an open file handle to a file called README
+    @param name should be 'README' and is ignored for the java
+        driver
+    """
+    messages = list()
+    actions = list()
+    instructions = list()
+    matches = list()
+    stat_types = list()
+    queue_prop = list()
+    lists = list()
+    for cls in of_g.unified:
+        print "! Classifying %s" % cls
+        if cls in [ 'of_stats_reply', 'of_flow_mod', 'of_stats_request' ] :
+            continue # doesn't work?!
+        if loxi_utils.class_is_stats_message(cls):
+            stat_types.append(cls)
+        elif loxi_utils.class_is_message(cls):
+            messages.append(cls)
+        elif loxi_utils.class_is_action(cls):
+            actions.append(cls)
+        elif loxi_utils.class_is_instruction(cls):
+            instructions.append(cls)
+        elif loxi_utils.class_is_oxm(cls):
+            matches.append(cls)
+        elif loxi_utils.class_is_queue_prop(cls):
+            queue_prop.append(cls)
+        elif loxi_utils.class_is_list(cls):
+            lists.append(cls)
+        else:
+            print "Skipping Unknown class object %s" % str(cls)
+    print "Parsed "
+    print "  Messages: %d" % len(messages)
+    print "  Actions: %d" % len(actions)
+    print "  Instructions: %d" % len(instructions)
+    print "  OXM matches: %d" % len(matches)
+    print "  Stat types: %d" % len(stat_types)
+    print "  Queue properties: %d" % len(queue_prop)
+    print "  Lists: %d" % len(lists)
+    target_dir='loxi_output/openflowj'
+    basedir="%s/%s/" % (
+            target_dir,
+            lang_java.file_to_subdir_map['base_java'])
+    srcdir = "%s/src/main/java/org/openflow/protocol" % basedir
+    print "Outputting to %s" % basedir
+    if not os.path.exists(basedir):
+        os.makedirs(basedir)
+    java_utils.copy_prewrite_tree(basedir)
+    msgs.create_message_interfaces(messages,srcdir)
+    msgs.create_message_by_version(messages,srcdir)
+    msgs.create_of_type_enum(messages,srcdir)
+    with open('README.java-lang') as readme_src:
+        out.writelines(readme_src.readlines())
+    out.close()
diff --git a/java_gen/java_model.py b/java_gen/java_model.py
new file mode 100644
index 0000000..062a64d
--- /dev/null
+++ b/java_gen/java_model.py
@@ -0,0 +1,180 @@
+# Prototype of an Intermediate Object model for the java code generator
+# A lot of this stuff could/should probably be merged with the python utilities
+
+import of_g
+import os
+import pdb
+import re
+
+import loxi_front_end.type_maps as type_maps
+import loxi_utils.loxi_utils as utils
+import py_gen.util as py_utils
+
+import java_gen.java_utils as java_utils
+ignore_fields = ['version', 'xid', 'length', 'type' ]
+
+protected_fields = ['version', 'length']
+
+class JavaOFVersion(object):
+    """ Models a version of OpenFlow. contains methods to convert the internal
+        Loxi version to a java constant / a string """
+    def __init__(self, int_version):
+        self.int_version = int(int_version)
+
+    @property
+    def of_version(self):
+        return "1" + str(int(self.int_version) - 1)
+
+    @property
+    def constant_version(self):
+        return "OF_" + self.of_version
+
+    def __str__(self):
+        return of_g.param_version_names[self.int_version]
+
+class JavaProperty(object):
+    """ Models a property (member) of an openflow class. """
+    def __init__(self, msg, java_type, c_type, name, c_name):
+        self.msg = msg
+        self.java_type = java_type
+        self.c_type = c_type
+        self.name = name
+        self.c_name = c_name
+
+    @property
+    def title_name(self):
+        return self.name[0].upper() + self.name[1:]
+
+    @property
+    def constant_name(self):
+        return self.c_name.upper()
+
+    @property
+    def default_name(self):
+        return "DEFAULT_"+self.constant_name
+
+    @property
+    def default_value(self):
+        java_type = self.java_type.public_type;
+
+        if re.match(r'List.*', java_type):
+            return "Collections.emptyList()"
+        elif java_type == "boolean":
+            return "false";
+        elif java_type in ("byte", "char", "short", "int", "long"):
+            return "({0}) 0".format(java_type);
+        else:
+            return "null";
+
+    @property
+    def is_pad(self):
+        return self.c_name.startswith("pad")
+
+    @property
+    def length(self):
+        count, base = utils.type_dec_to_count_base(self.c_type)
+        return of_g.of_base_types[base]['bytes'] * count
+
+    @staticmethod
+    def for_field(msg, field, c_name=None):
+        if not c_name:
+            c_name = field['name']
+
+        name = java_utils.name_c_to_camel(c_name)
+        java_type = java_utils.convert_to_jtype(msg.c_name, c_name, field['m_type'])
+        c_type = field['m_type']
+        return JavaProperty(msg, java_type, c_type, name, c_name)
+
+    @property
+    def is_universal(self):
+        for version in of_g.unified[self.msg.c_name]:
+            if version == 'union' or version =='object_id':
+                continue
+            if 'use_version' in of_g.unified[self.msg.c_name][version]:
+                continue
+
+            if not self.c_name in (f['name'] for f in of_g.unified[self.msg.c_name][version]['members']):
+                return False
+        return True
+
+class JavaOFMessage(object):
+    """ Models an OpenFlow Message class """
+    def __init__(self, c_name):
+        self.c_name = c_name
+        self.interface_name = java_utils.name_c_to_caps_camel(c_name)
+        self.builder_name = self.interface_name + "Builder"
+        self.constant_name = c_name.upper().replace("OF_", "")
+
+    def min_length(self, version):
+        return of_g.base_length[(self.c_name, version.int_version)] if (self.c_name, version.int_version) in of_g.base_length else -1
+
+    def is_fixed_length(self, version):
+        return (self.c_name, version.int_version) in of_g.is_fixed_length
+
+    def class_name_for_version(self, version):
+        return self.interface_name + "Ver"+version.of_version
+
+
+    def all_properties(self, skip_pads=True):
+        if 'union' in of_g.unified[self.c_name]:
+            props = []
+            fields = of_g.unified[self.c_name]['union']
+            for field_name in sorted( fields.keys(), key=lambda k: fields[k]['memid']):
+                if field_name in ignore_fields:
+                    continue
+                if skip_pads and field_name.startswith("pad"):
+                    continue
+
+                java_property = JavaProperty.for_field(self, fields[field_name], c_name=field_name)
+                props.append(java_property)
+            return props
+        else:
+            return []
+
+    def all_versions(self):
+        return [ JavaOFVersion(int_version)
+                 for int_version in of_g.unified[self.c_name]
+                 if int_version != 'union' and int_version != 'object_id' ]
+
+    def property_in_version(self, prop, version):
+        if self.version_is_inherited(version):
+            version = self.inherited_from(version)
+
+        if 'members' not in of_g.unified[self.c_name][version.int_version]:
+            return False
+        return prop.c_name in (member['name'] for member in of_g.unified[self.c_name][version.int_version]['members'])
+
+    def properties_for_version(self, version, skip_pads=True):
+        props = []
+        if self.version_is_inherited(version):
+            version = self.inherited_from(version)
+
+        for field in of_g.unified[self.c_name][version.int_version]['members']:
+            if field['name'] in ignore_fields:
+                continue
+            if skip_pads and field['name'].startswith("pad"):
+                continue
+
+            java_property = JavaProperty.for_field(self, field, c_name=field['name'])
+            props.append(java_property)
+        return props
+
+    def version_is_inherited(self, version):
+        return 'use_version' in of_g.unified[self.c_name][version.int_version]
+
+    def inherited_from(self, version):
+        return JavaOFVersion(of_g.unified[self.c_name][version.int_version]['use_version'])
+
+    @property
+    def is_virtual(self):
+        return type_maps.class_is_virtual(self.c_name)
+
+    @property
+    def is_extension(self):
+        return type_maps.message_is_extension(self.c_name, -1)
+
+    def wire_type(self, version):
+        try:
+            return py_utils.primary_wire_type(self.c_name, version.int_version)
+        except ValueError, e:
+            return -1
diff --git a/java_gen/java_utils.py b/java_gen/java_utils.py
new file mode 100644
index 0000000..c55b275
--- /dev/null
+++ b/java_gen/java_utils.py
@@ -0,0 +1,215 @@
+import os
+import errno
+import re
+import subprocess
+import time
+
+def name_c_to_camel(name):
+    """ 'of_stats_reply' -> 'ofStatsReply' """
+    tokens = name.split('_')
+    for i in range(1, len(tokens)):
+            tokens[i] = tokens[i].title()
+    return "".join(tokens)
+
+def name_c_to_caps_camel(name):
+    """ 'of_stats_reply' to 'OFStatsReply' """
+    camel = name_c_to_camel(name.title())
+    if camel.startswith('Of'):
+        return camel.replace('Of','OF',1)
+    else:
+        return camel
+
+
+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):
+        self.pub_type = pub_type    # the type we expose externally, e.g. 'U8'
+        if priv_type is None:
+            priv_type = pub_type
+        self.priv_type = priv_type  # the internal storage type
+        self.size = size            # bytes on the wire; None == variable length or hard to calc
+        if read_op is None:
+            read_op = 'ChannelUtils.read%s(this, "$name", bb)' % self.pub_type
+        if write_op is None:
+            write_op = 'ChannelUtils.write($name)'
+        self._read_op = read_op
+        self.write_op = write_op
+
+    @property
+    def public_type(self):
+        """ return the public type """
+        return self.pub_type
+
+    def priv(self):
+        """ return the public type """
+        return self.priv_type
+
+    def has_priv(self):
+        """ Is the private type different from the public one?"""
+        return self.pub_type != self.priv_type
+
+    def read_op(self, version=None):
+        if callable(self._read_op):
+            return self._read_op(version)
+        else:
+            return self._read_op
+
+hello_elem_list = JType("List<OFHelloElement>",
+        read_op = 'ChannelUtils.readHelloElementList(bb)',
+        write_op = 'ChannelUtils.writeHelloElementList(bb)'
+        )
+
+u8 =  JType('byte',  size=1, read_op='bb.readByte()',
+        write_op='bb.writeByte($name)')
+u16 = JType('int', 'int', size=2, read_op='U16.f(bb.readShort())',
+        write_op='bb.writeShort(U16.t($name))')
+u32 = JType('int', 'int',   size=4, read_op='bb.readInt()',
+        write_op='bb.writeInt($name)')
+u64 = JType('U64', 'U64', size=8, read_op='U64.of(bb.readLong())',
+        write_op='bb.writeLong($name.getLong())')
+of_port= JType('OFPort',size=None,
+        read_op=lambda(version): 'OFPort.ofShort(bb.readShort())' if version.int_version < 2 else 'OFPort.ofInt(bb.readInt())',
+        write_op='$name.writeTo(bb)')
+one_byte_array = JType('byte[]', size=1,
+        read_op = 'ChannelUtils.readBytes(bb, 1)',
+        write_op = 'ChannelUtils.writeBytes(bb, $name)')
+two_byte_array = JType('byte[]', size=2,
+        read_op = 'ChannelUtils.readBytes(bb, 2)',
+        write_op = 'ChannelUtils.writeBytes(bb, $name)')
+three_byte_array = JType('byte[]', size=3,
+        read_op = 'ChannelUtils.readBytes(bb, 3)',
+        write_op = 'ChannelUtils.writeBytes(bb, $name)')
+four_byte_array = JType('byte[]', size=4,
+        read_op = 'ChannelUtils.readBytes(bb, 4)',
+        write_op = 'ChannelUtils.writeBytes(bb, $name)')
+five_byte_array = JType('byte[]', size=5,
+        read_op = 'ChannelUtils.readBytes(bb, 5)',
+        write_op = 'ChannelUtils.writeBytes(bb, $name)')
+six_byte_array = JType('byte[]', size=6,
+        read_op = 'ChannelUtils.readBytes(bb, 6)',
+        write_op = 'ChannelUtils.writeBytes(bb, $name)')
+seven_byte_array = JType('byte[]', size=7,
+        read_op = 'ChannelUtils.readBytes(bb, 7)',
+        write_op = 'ChannelUtils.writeBytes(bb, $name)')
+actions_list = JType('List<OFAction>', size='ChannelUtils.calcListSize($name)',
+        read_op = 'ChannelUtils.readActionsList(bb, length - MINIMUM_LENGTH)',
+        write_op = 'ChannelUtils.writeList(this, $name)')
+instructions_list = JType('List<OFInstruction>', size='ChannelUtils.calcListSize($name)',
+        read_op = 'ChannelUtils.readInstructionsList(bb, length - MINIMUM_LENGTH)',
+        write_op = 'ChannelUtils.writeList(this, $name)')
+buckets_list = JType('List<OFBucket>', size='ChannelUtils.calcListSize($name)',
+        read_op = 'ChannelUtils.readBucketList(bb, length - MINIMUM_LENGTH)',
+        write_op = 'ChannelUtils.writeList(this, $name)')
+port_desc_list = JType('List<OFPhysicalPort>', size='ChannelUtils.calcListSize($name)',
+        read_op = 'ChannelUtils.readPhysicalPortList(bb, length - MINIMUM_LENGTH)',
+        write_op = 'ChannelUtils.writeList(this, $name)')
+port_desc = JType('OFPhysicalPort', size='$name.getLength()',
+        read_op = 'ChannelUtils.readPhysicalPort(bb)',
+        write_op = 'ChannelUtils.write(this, $name)')
+packet_queue_list = JType('List<OFPacketQueue>', size='ChannelUtils.calcListSize($name)',
+        read_op = 'ChannelUtils.readPacketQueueList(bb, length - MINIMUM_LENGTH)',
+        write_op = 'ChannelUtils.writeList(this, $name)')
+octets = JType('byte[]', size="length - MINIMUM_LENGTH",
+        read_op = 'ChannelUtils.readBytes(bb, length - MINIMUM_LENGTH)',
+        write_op = 'ChannelUtils.writeBytes(bb, this.$name)')
+of_match = JType('Match', size="$name.getLength()",
+        read_op = 'ChannelUtils.readOFMatch(bb)',
+        write_op = 'ChannelUtils.writeOFMatch(this, $name)')
+flow_mod_cmd = JType('OFFlowModCmd', size="$name.getLength()",
+        read_op = 'ChannelUtils.readOFFlowModCmd(bb)',
+        write_op = 'ChannelUtils.writeOFFlowModCmd(this, $name)')
+mac_addr = JType('MacAddress', 'byte[]', size=6,
+        read_op = 'MacAddress.readFrom(bb)',
+        write_op = 'ChannelUtils.writeBytes(bb, $name)')
+bsn_interface_list = JType("List<OFBsnInterface>",
+        read_op = 'ChannelUtils.readBsnInterfaceList(bb)',
+        write_op = 'ChannelUtils.writeBsnInterfaceList(bb)'
+        )
+meter_band_list = JType("List<OFMeterBand>",
+        read_op = 'ChannelUtils.readMeterBandList(bb)',
+        write_op = 'ChannelUtils.writeMeterBandList(bb, $name)'
+        )
+
+
+
+
+
+default_mtype_to_jtype_convert_map = {
+        'uint8_t' : u8,
+        'uint16_t' : u16,
+        'uint32_t' : u32,
+        'uint64_t' : u64,
+        'uint8_t[1]' : one_byte_array,
+        'uint8_t[2]' : two_byte_array,
+        'uint8_t[3]' : three_byte_array,
+        'uint8_t[4]' : four_byte_array,
+        'uint8_t[5]' : five_byte_array,
+        'uint8_t[6]' : six_byte_array,
+        'uint8_t[7]' : seven_byte_array,
+        'of_port_no_t' : of_port,
+        'of_list_action_t' : actions_list,
+        'of_list_instruction_t' : instructions_list,
+        'of_list_bucket_t': buckets_list,
+        'of_list_port_desc_t' : port_desc_list,
+        'of_list_packet_queue_t' : packet_queue_list,
+        'of_octets_t' : octets,
+        'of_match_t': of_match,
+        'of_fm_cmd_t': flow_mod_cmd,
+        'of_mac_addr_t': mac_addr,
+        'of_port_desc_t': port_desc,
+        'of_list_bsn_interface_t': bsn_interface_list,
+        'of_list_hello_elem_t': hello_elem_list,
+        'of_list_meter_band_t': meter_band_list
+        }
+
+## This is where we drop in special case handling for certain types
+exceptions = {
+        'OFPacketIn': {
+            'data' : octets
+            },
+        }
+
+
+def convert_to_jtype(obj_name, field_name, c_type):
+    """ Convert from a C type ("uint_32") to a java type ("U32")
+    and return a JType object with the size, internal type, and marshalling functions"""
+    if obj_name in exceptions and field_name in exceptions[obj_name]:
+        return exceptions[obj_name][field_name]
+    elif c_type in default_mtype_to_jtype_convert_map:
+        return default_mtype_to_jtype_convert_map[c_type]
+    else:
+        print "WARN: Couldn't find java type conversion for '%s' in %s:%s" % (c_type, obj_name, field_name)
+        jtype = name_c_to_caps_camel(c_type)      # not sure... try to fake it
+        return JType(jtype)
+
+
+def mkdir_p(path):
+    """ Emulates `mkdir -p` """
+    try:
+        os.makedirs(path)
+    except OSError as exc: # Python >2.5
+        if exc.errno == errno.EEXIST:
+            pass
+        else: raise
+
+def copy_file_with_boiler_plate(src_name, dst_name, with_boiler=True):
+    with open("java_gen/pre-written/%s" % src_name, "r") as src:
+        with open(dst_name, "w") as dst:
+            if with_boiler:
+                print_boiler_plate(os.path.basename(dst_name), dst)
+            dst.writelines(src.readlines())
+
+def frob(s, **kwargs):
+    """ Step through string s and for each key in kwargs,
+         replace $key with kwargs[key] in s.
+    """
+    for k,v in kwargs.iteritems():
+        s = s.replace('$%s' % k, v)
+    return s
+
+def copy_prewrite_tree(basedir):
+    """ Recursively copy the directory structure from ./java_gen/pre-write
+       into $basedir"""
+    print "Copying pre-written files into %s" % basedir
+#    subprocess.call("cd java_gen/pre-written && tar cpf - . | ( cd ../../%s && tar xvpf - )" % basedir,
+#            shell=True)
diff --git a/java_gen/msgs.py b/java_gen/msgs.py
new file mode 100644
index 0000000..3cdef2c
--- /dev/null
+++ b/java_gen/msgs.py
@@ -0,0 +1,55 @@
+import of_g
+import os
+import pdb
+import re
+
+import loxi_front_end.type_maps as type_maps
+import loxi_utils.loxi_utils as utils
+import py_gen.util as py_utils
+
+import java_gen.java_utils as java_utils
+from java_gen.java_model import *
+ignore_fields = ['version', 'xid', 'length', 'type' ]
+
+protected_fields = ['version', 'length']
+
+
+templates_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'templates')
+
+def render_template(out, name, **context):
+    prefix = '//::(?=[ \t]|$)'
+    utils.render_template(out, name, [templates_dir], context, prefix=prefix)
+
+def create_message_interfaces(message_names, basedir):
+    """ Create the base interfaces for OFMessages"""
+    for msg_name in message_names:
+        msg = JavaOFMessage(msg_name)
+
+        filename = os.path.join(basedir, "%s.java" % msg.interface_name)
+        dirname = os.path.dirname(filename)
+        if not os.path.exists(dirname):
+            os.makedirs(dirname)
+
+        with open(filename, "w") as f:
+            render_template(f, "message_interface.java", msg=msg)
+
+def create_of_type_enum(message_names, basedir):
+    all_versions = [ JavaOFVersion(v) for v in of_g.target_version_list ]
+    messages =  sorted(filter(lambda msg: not msg.is_virtual and not msg.is_extension, [ JavaOFMessage(msg_name) for msg_name in message_names ]), key=lambda msg: msg.wire_type(all_versions[-1]))
+    filename = os.path.join(basedir, "../types/OFType.java")
+    dirname = os.path.dirname(filename)
+    if not os.path.exists(dirname):
+        os.makedirs(dirname)
+    with open(filename, "w") as f:
+        render_template(f, "of_type.java", all_messages=messages, all_versions = all_versions)
+
+def create_message_by_version(message_names, basedir):
+    """ Create the OF Messages for each version that implement the above interfaces"""
+    for msg_name in message_names:
+        msg = JavaOFMessage(msg_name)
+
+        for version in msg.all_versions():
+            filename = os.path.join(basedir, "%s.java" % msg.class_name_for_version(version))
+            with open(filename, "w") as f:
+                   render_template(f, "message_class.java", msg=msg, version=version,
+                            impl_class=msg.class_name_for_version(version))
diff --git a/java_gen/pre-written/lib/.gitignore b/java_gen/pre-written/lib/.gitignore
new file mode 100644
index 0000000..b4cb1f8
--- /dev/null
+++ b/java_gen/pre-written/lib/.gitignore
@@ -0,0 +1 @@
+netty-3.2.6.Final.jar
diff --git a/java_gen/pre-written/src/main/java/org/openflow/annotations/Immutable.java b/java_gen/pre-written/src/main/java/org/openflow/annotations/Immutable.java
new file mode 100644
index 0000000..1d432c7
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/annotations/Immutable.java
@@ -0,0 +1,13 @@
+package org.openflow.annotations;
+
+/**
+ * This annotation marks a class that is considered externally immutable. I.e.,
+ * the externally visible state of the class will not change after its
+ * construction. Such a class can be freely shared between threads and does not
+ * require defensive copying (don't call clone).
+ *
+ * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+ */
+public @interface Immutable {
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/exceptions/NonExistantMessage.java b/java_gen/pre-written/src/main/java/org/openflow/exceptions/NonExistantMessage.java
new file mode 100644
index 0000000..2d82ba2
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/exceptions/NonExistantMessage.java
@@ -0,0 +1,30 @@
+package org.openflow.exceptions;
+
+/**
+ * Error: someone asked to create an OFMessage with wireformat type and version,
+ * but that doesn't exist
+ *
+ * @author capveg
+ */
+public class NonExistantMessage extends Exception {
+
+    private static final long serialVersionUID = 1L;
+    byte type;
+    byte version;
+
+    /**
+     * Error: someone asked to create an OFMessage with wireformat type and
+     * version, but that doesn't exist
+     *
+     * @param type
+     *            the wire format
+     * @param version
+     *            the OpenFlow wireformat version number, e.g. 1 == v1.1, 2 =
+     *            v1.2, etc.
+     */
+    public NonExistantMessage(final byte type, final byte version) {
+        this.type = type;
+        this.version = version;
+    }
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/exceptions/OFParseError.java b/java_gen/pre-written/src/main/java/org/openflow/exceptions/OFParseError.java
new file mode 100644
index 0000000..76afc79
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/exceptions/OFParseError.java
@@ -0,0 +1,22 @@
+package org.openflow.exceptions;
+
+public class OFParseError extends Exception {
+    private static final long serialVersionUID = 1L;
+
+    public OFParseError() {
+        super();
+    }
+
+    public OFParseError(final String message, final Throwable cause) {
+        super(message, cause);
+    }
+
+    public OFParseError(final String message) {
+        super(message);
+    }
+
+    public OFParseError(final Throwable cause) {
+        super(cause);
+    }
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/exceptions/OFShortRead.java b/java_gen/pre-written/src/main/java/org/openflow/exceptions/OFShortRead.java
new file mode 100644
index 0000000..3007803
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/exceptions/OFShortRead.java
@@ -0,0 +1,6 @@
+package org.openflow.exceptions;
+
+public class OFShortRead extends Exception {
+    private static final long serialVersionUID = 1L;
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/exceptions/OFShortWrite.java b/java_gen/pre-written/src/main/java/org/openflow/exceptions/OFShortWrite.java
new file mode 100644
index 0000000..fb0ddea
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/exceptions/OFShortWrite.java
@@ -0,0 +1,7 @@
+package org.openflow.exceptions;
+
+public class OFShortWrite extends Exception {
+
+    private static final long serialVersionUID = 1L;
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/exceptions/OFUnsupported.java b/java_gen/pre-written/src/main/java/org/openflow/exceptions/OFUnsupported.java
new file mode 100644
index 0000000..14e96db
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/exceptions/OFUnsupported.java
@@ -0,0 +1,7 @@
+package org.openflow.exceptions;
+
+public class OFUnsupported extends Exception {
+
+    private static final long serialVersionUID = 1L;
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/OFAbstractMessage.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFAbstractMessage.java
new file mode 100644
index 0000000..bc2218f
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFAbstractMessage.java
@@ -0,0 +1,83 @@
+/* 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.
+ */
+package org.openflow.protocol;
+
+/**
+ * The base interface for all OpenFlow message objects
+ */
+
+import org.openflow.types.OFType;
+
+abstract public class OFAbstractMessage implements OFObject {
+    private final OFVersion version;
+    private final OFType type;
+    private int xid;
+
+    public static int MINIMUM_SIZE = 8;
+
+    public OFAbstractMessage(final OFVersion version, final OFType type) {
+        this.version = version;
+        this.type = type;
+    }
+
+    /**
+     * Return the wire format version of this message, e.g., 0x01
+     */
+    OFVersion getVersion() {
+        return version;
+    }
+
+    /**
+     * @return the transction ID for this message
+     */
+    int getXid() {
+        return xid;
+    }
+
+    /**
+     * @param newXid
+     *            Set this transaction ID for this message
+     */
+    void setXid(final int xid) {
+        this.xid = xid;
+    }
+
+    /**
+     * The type that is returned here is agnostic to the underlying wire format
+     *
+     * @return the type of OpenFlow message.
+     */
+    OFType getType() {
+        return type;
+    }
+
+    @Override
+    public int getLength() {
+        return MINIMUM_SIZE;
+    }
+}
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
new file mode 100644
index 0000000..4f31741
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFMessage.java
@@ -0,0 +1,13 @@
+package org.openflow.protocol;
+
+import org.openflow.types.OFType;
+
+public interface OFMessage {
+    int getXid();
+
+    boolean isXidSet();
+
+    OFType getType();
+
+    OFVersion getVersion();
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/OFMessageReader.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFMessageReader.java
new file mode 100644
index 0000000..24c3314
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFMessageReader.java
@@ -0,0 +1,8 @@
+package org.openflow.protocol;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.exceptions.OFParseError;
+
+public interface OFMessageReader<T extends OFMessage> {
+    T readFrom(ChannelBuffer bb) 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
new file mode 100644
index 0000000..21a4607
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFObject.java
@@ -0,0 +1,35 @@
+package org.openflow.protocol;
+
+/**
+ *  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.
+ */
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.exceptions.OFParseError;
+import org.openflow.exceptions.OFShortWrite;
+
+public interface OFObject {
+    /**
+     * Return a number equal or greater than zero (and currently in OF less than
+     * 65536)
+     *
+     * @return the number of bytes this object will represent on the wire
+     */
+    public int getLength();
+
+    /**
+     * Automatically calculate any lengths and write an openflow object into the
+     * byte buffer.
+     *
+     * @param bb
+     *            A valid byte buffer with sufficient capacity to hold this
+     *            object/
+     */
+    public void writeTo(ChannelBuffer bb) throws OFParseError, OFShortWrite;
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/OFObjectFactory.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFObjectFactory.java
new file mode 100644
index 0000000..86cafb1
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFObjectFactory.java
@@ -0,0 +1,7 @@
+package org.openflow.protocol;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFObjectFactory<T extends OFObject> {
+    T read(ChannelBuffer buffer);
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/OFVersion.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFVersion.java
new file mode 100644
index 0000000..afc0393
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFVersion.java
@@ -0,0 +1,16 @@
+package org.openflow.protocol;
+
+public enum OFVersion {
+    OF_10(1), OF_11(2), OF_12(3), OF_13(4);
+
+    private final int wireVersion;
+
+    OFVersion(final int wireVersion) {
+        this.wireVersion = wireVersion;
+    }
+
+    public int getWireVersion() {
+        return wireVersion;
+    }
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/actions/OFAction.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/actions/OFAction.java
new file mode 100644
index 0000000..f01f8fe
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/actions/OFAction.java
@@ -0,0 +1,7 @@
+package org.openflow.protocol.actions;
+
+import org.openflow.protocol.OFObject;
+
+public interface OFAction extends OFObject {
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/instructions/OFInstruction.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/instructions/OFInstruction.java
new file mode 100644
index 0000000..8af305c
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/instructions/OFInstruction.java
@@ -0,0 +1,7 @@
+package org.openflow.protocol.instructions;
+
+import org.openflow.protocol.OFObject;
+
+public interface OFInstruction extends OFObject {
+
+}
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
new file mode 100644
index 0000000..5c1e7b5
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/Match.java
@@ -0,0 +1,21 @@
+package org.openflow.protocol.match;
+
+import org.openflow.protocol.OFObject;
+
+public interface Match extends OFObject {
+    public <F> F get(MatchField<F, ?> match);
+
+    public <M> M getMasked(MatchField<?, M> match);
+
+    public boolean supports(MatchField<?, ?> field);
+
+    public boolean supportsMasked(MatchField<?, ?> field);
+
+    public boolean isExact(MatchField<?, ?> field);
+
+    public boolean isFullyWildcarded(MatchField<?, ?> field);
+
+    public boolean isPartiallyMasked(MatchField<?, ?> field);
+
+    public MatchBuilder getBuilder();
+}
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
new file mode 100644
index 0000000..7a5e57c
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchBuilder.java
@@ -0,0 +1,9 @@
+package org.openflow.protocol.match;
+
+public interface MatchBuilder extends Match {
+    public <F> MatchBuilder set(MatchField<F, ?> match, F value);
+
+    public <M> void setMasked(MatchField<?, M> match, M value);
+
+    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
new file mode 100644
index 0000000..19ced8f
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchBuilderVer10.java
@@ -0,0 +1,177 @@
+package org.openflow.protocol.match;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.exceptions.OFParseError;
+import org.openflow.exceptions.OFShortWrite;
+import org.openflow.protocol.types.IpDscp;
+import org.openflow.types.EthType;
+import org.openflow.types.IPv4;
+import org.openflow.types.IpProtocol;
+import org.openflow.types.MacAddress;
+import org.openflow.types.OFPort;
+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> 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> 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 <M> M getMasked(final MatchField<?, M> match) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @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) throws OFParseError, OFShortWrite {
+        // 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
new file mode 100644
index 0000000..b6e8317
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchField.java
@@ -0,0 +1,106 @@
+package org.openflow.protocol.match;
+
+import org.openflow.types.EthType;
+import org.openflow.types.IPv4;
+import org.openflow.types.IPv4WithMask;
+import org.openflow.types.IPv6;
+import org.openflow.types.IPv6WithMask;
+import org.openflow.types.IpProtocol;
+import org.openflow.types.MacAddress;
+import org.openflow.types.MacAddressWithMask;
+import org.openflow.types.OFPort;
+import org.openflow.types.U16;
+import org.openflow.types.U8;
+import org.openflow.types.VlanPcp;
+import org.openflow.types.VlanVid;
+import org.openflow.types.VlanVidWithMask.VlanVidWithMask;
+
+public class MatchField<F, M> {
+    private final String name;
+    public final int id;
+
+    public MatchField(final String name) {
+        this.name = name;
+        this.id = -1;
+    }
+
+    public MatchField(final String name, final int id) {
+        this.name = name;
+        this.id = id;
+    }
+
+    public final static MatchField<OFPort, NoMatch> IN_PORT =
+            new MatchField<OFPort, NoMatch>("in_port", 0);
+    public final static MatchField<OFPort, NoMatch> IN_PHY_PORT =
+            new MatchField<OFPort, NoMatch>("in_phy_port");
+    public final static MatchField<OFPort, NoMatch> METADATA =
+            new MatchField<OFPort, NoMatch>("metadata");
+
+    public final static MatchField<MacAddress, MacAddressWithMask> ETH_DST =
+            new MatchField<MacAddress, MacAddressWithMask>("eth_dst");
+    public final static MatchField<MacAddress, MacAddressWithMask> ETH_SRC =
+            new MatchField<MacAddress, MacAddressWithMask>("eth_src", 1);
+
+    public final static MatchField<EthType, NoMatch> ETH_TYPE =
+            new MatchField<EthType, NoMatch>("eth_type");
+    public final static MatchField<VlanVid, VlanVidWithMask> VLAN_VID =
+            new MatchField<VlanVid, VlanVidWithMask>("vlan_vid");
+    public final static MatchField<VlanPcp, NoMatch> VLAN_PCP =
+            new MatchField<VlanPcp, NoMatch>("vlan_pcp");
+
+    public final static MatchField<NoMatch, NoMatch> IP_DSCP =
+            new MatchField<NoMatch, NoMatch>("ip_dscp");
+    public final static MatchField<NoMatch, NoMatch> IP_ECN =
+            new MatchField<NoMatch, NoMatch>("ip_dscp");
+    public final static MatchField<IpProtocol, NoMatch> IP_PROTO =
+            new MatchField<IpProtocol, NoMatch>("ip_proto");
+
+    public final static MatchField<IPv4, IPv4WithMask> IPV4_SRC =
+            new MatchField<IPv4, IPv4WithMask>("ipv4_src");
+    public final static MatchField<IPv4, IPv4WithMask> IPV4_DST =
+            new MatchField<IPv4, IPv4WithMask>("ipv4_dst");
+
+    public final static MatchField<U16, NoMatch> TCP_SRC = new MatchField<U16, NoMatch>(
+            "tcp_src");
+    public final static MatchField<U16, NoMatch> TCP_DST = new MatchField<U16, NoMatch>(
+            "tcp_dst");
+
+    public final static MatchField<U16, NoMatch> UDP_SRC = new MatchField<U16, NoMatch>(
+            "udp_src");
+    public final static MatchField<U16, NoMatch> UDP_DST = new MatchField<U16, NoMatch>(
+            "udp_dst");
+
+    public final static MatchField<U16, NoMatch> SCTP_SRC = new MatchField<U16, NoMatch>(
+            "sctp_src");
+    public final static MatchField<U16, NoMatch> SCTP_DST = new MatchField<U16, NoMatch>(
+            "sctp_dst");
+
+    public final static MatchField<U8, NoMatch> ICMPV4_TYPE = new MatchField<U8, NoMatch>(
+            "icmpv4_src");
+    public final static MatchField<U8, NoMatch> ICMPV4_CODE = new MatchField<U8, NoMatch>(
+            "icmpv4_dst");
+
+    public final static MatchField<U16, NoMatch> ARP_OP = new MatchField<U16, NoMatch>(
+            "arp_op");
+    public final static MatchField<IPv4, IPv4WithMask> ARP_SPA =
+            new MatchField<IPv4, IPv4WithMask>("arp_spa");
+    public final static MatchField<IPv4, IPv4WithMask> ARP_TPA =
+            new MatchField<IPv4, IPv4WithMask>("arp_tpa");
+    public final static MatchField<MacAddress, MacAddressWithMask> ARP_SHA =
+            new MatchField<MacAddress, MacAddressWithMask>("arp_sha");
+    public final static MatchField<MacAddress, MacAddressWithMask> ARP_THA =
+            new MatchField<MacAddress, MacAddressWithMask>("arp_tha");
+
+    public final static MatchField<IPv6, IPv6WithMask> IPV6_SRC =
+            new MatchField<IPv6, IPv6WithMask>("ipv6_src");
+    public final static MatchField<IPv6, IPv6WithMask> IPV6_DST =
+            new MatchField<IPv6, IPv6WithMask>("ipv6_dst");
+
+    public final static MatchField<U8, IPv6WithMask> IPV6_FLABEL =
+            new MatchField<U8, IPv6WithMask>("ipv6_flabel");
+
+    public String getName() {
+        return name;
+    }
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/match/NoMatch.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/NoMatch.java
new file mode 100644
index 0000000..b314a59
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/NoMatch.java
@@ -0,0 +1,5 @@
+package org.openflow.protocol.match;
+
+public class NoMatch {
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/types/IpDscp.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/types/IpDscp.java
new file mode 100644
index 0000000..dcc242a
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/types/IpDscp.java
@@ -0,0 +1,5 @@
+package org.openflow.protocol.types;
+
+public class IpDscp {
+
+}
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
new file mode 100644
index 0000000..d319e57
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/EthType.java
@@ -0,0 +1,5 @@
+package org.openflow.types;
+
+public class EthType {
+
+}
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
new file mode 100644
index 0000000..b4eb8cf
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/IPv4.java
@@ -0,0 +1,129 @@
+package org.openflow.types;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.exceptions.OFParseError;
+import org.openflow.exceptions.OFShortRead;
+import org.openflow.exceptions.OFShortWrite;
+import org.openflow.protocol.OFObject;
+
+/**
+ * Wrapper around an IPv4 address
+ *
+ * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+ */
+public class IPv4 implements OFObject {
+    static final int LENGTH = 4;
+    private final int rawValue;
+
+    private IPv4(final int rawValue) {
+        this.rawValue = rawValue;
+    }
+
+    public static IPv4 of(final byte[] address) {
+        if (address.length != LENGTH) {
+            throw new IllegalArgumentException(
+                    "Invalid byte array length for IPv4 address: " + address);
+        }
+
+        int raw =
+                (address[0] & 0xFF) << 24 | (address[1] & 0xFF) << 16
+                        | (address[2] & 0xFF) << 8 | (address[3] & 0xFF) << 0;
+        return IPv4.of(raw);
+    }
+
+    public static IPv4 of(final int raw) {
+        return new IPv4(raw);
+    }
+
+    public static IPv4 of(final String string) {
+        int start = 0;
+        int shift = 24;
+
+        int raw = 0;
+        while (shift >= 0) {
+            int end = string.indexOf('.', start);
+            if (end == start || !((shift > 0) ^ (end < 0)))
+                throw new IllegalArgumentException("IP Address not well formed: " + string);
+
+            String substr =
+                    end > 0 ? string.substring(start, end) : string.substring(start);
+            int val = Integer.parseInt(substr);
+            if (val < 0 || val > 255)
+                throw new IllegalArgumentException("IP Address not well formed: " + string);
+
+            raw |= val << shift;
+
+            shift -= 8;
+            start = end + 1;
+        }
+        return IPv4.of(raw);
+    }
+
+    public int getInt() {
+        return rawValue;
+    }
+
+    volatile byte[] bytesCache = null;
+
+    public byte[] getBytes() {
+        if (bytesCache == null) {
+            synchronized (this) {
+                if (bytesCache == null) {
+                    bytesCache =
+                            new byte[] { (byte) ((rawValue >>> 24) & 0xFF),
+                                    (byte) ((rawValue >>> 16) & 0xFF),
+                                    (byte) ((rawValue >>> 8) & 0xFF),
+                                    (byte) ((rawValue >>> 0) & 0xFF) };
+                }
+            }
+        }
+        return bytesCache;
+    }
+
+    @Override
+    public int getLength() {
+        return LENGTH;
+    }
+
+    public static IPv4 readFrom(final ChannelBuffer bb) throws OFParseError, OFShortRead {
+        return IPv4.of(bb.readInt());
+    }
+
+    @Override
+    public void writeTo(final ChannelBuffer bb) throws OFParseError, OFShortWrite {
+        bb.writeInt(rawValue);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder res = new StringBuilder();
+        res.append((rawValue >> 24) & 0xFF).append('.');
+        res.append((rawValue >> 16) & 0xFF).append('.');
+        res.append((rawValue >> 8) & 0xFF).append('.');
+        res.append((rawValue >> 0) & 0xFF);
+        return res.toString();
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + rawValue;
+        return result;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        IPv4 other = (IPv4) obj;
+        if (rawValue != other.rawValue)
+            return false;
+        return true;
+    }
+
+}
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
new file mode 100644
index 0000000..ec777c0
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/IPv4WithMask.java
@@ -0,0 +1,5 @@
+package org.openflow.types;
+
+public class IPv4WithMask {
+
+}
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
new file mode 100644
index 0000000..5f51665
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/IPv6.java
@@ -0,0 +1,286 @@
+package org.openflow.types;
+
+import java.util.regex.Pattern;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.exceptions.OFParseError;
+import org.openflow.exceptions.OFShortRead;
+import org.openflow.exceptions.OFShortWrite;
+import org.openflow.protocol.OFObject;
+
+/**
+ * IPv6 address object. Instance controlled, immutable. Internal representation:
+ * two 64 bit longs (not that you'd have to know).
+ *
+ * @author Andreas Wundsam <andreas.wundsam@teleteach.de>
+ */
+public class IPv6 implements OFObject {
+    static final int LENGTH = 16;
+    private final long raw1;
+    private final long raw2;
+
+    private IPv6(final long raw1, final long raw2) {
+        this.raw1 = raw1;
+        this.raw2 = raw2;
+    }
+
+    public static IPv6 of(final byte[] address) {
+        if (address.length != LENGTH) {
+            throw new IllegalArgumentException(
+                    "Invalid byte array length for IPv6 address: " + address);
+        }
+
+        long raw1 =
+                (address[0] & 0xFFL) << 56 | (address[1] & 0xFFL) << 48
+                        | (address[2] & 0xFFL) << 40 | (address[3] & 0xFFL) << 32
+                        | (address[4] & 0xFFL) << 24 | (address[5] & 0xFFL) << 16
+                        | (address[6] & 0xFFL) << 8 | (address[7]);
+
+        long raw2 =
+                (address[8] & 0xFFL) << 56 | (address[9] & 0xFFL) << 48
+                        | (address[10] & 0xFFL) << 40 | (address[11] & 0xFFL) << 32
+                        | (address[12] & 0xFFL) << 24 | (address[13] & 0xFFL) << 16
+                        | (address[14] & 0xFFL) << 8 | (address[15]);
+
+        return IPv6.of(raw1, raw2);
+    }
+
+    private static class IPv6Builder {
+        private long raw1, raw2;
+
+        public void setUnsignedShortWord(final int i, final int value) {
+            int shift = 48 - (i % 4) * 16;
+
+            if (value < 0 || value > 0xFFFF)
+                throw new IllegalArgumentException("16 bit word must be in [0, 0xFFFF]");
+
+            if (i >= 0 && i < 4)
+                raw1 = raw1 & ~(0xFFFFL << shift) | (value & 0xFFFFL) << shift;
+            else if (i >= 4 && i < 8)
+                raw2 = raw2 & ~(0xFFFFL << shift) | (value & 0xFFFFL) << shift;
+            else
+                throw new IllegalArgumentException("16 bit word index must be in [0,7]");
+        }
+
+        public IPv6 getIPv6() {
+            return IPv6.of(raw1, raw2);
+        }
+    }
+
+    private final static Pattern colonPattern = Pattern.compile(":");
+
+    public static IPv6 of(final String string) {
+        IPv6Builder builder = new IPv6Builder();
+        String[] parts = colonPattern.split(string, -1);
+
+        int leftWord = 0;
+        int leftIndex = 0;
+
+        boolean hitZeroCompression = false;
+
+        for (leftIndex = 0; leftIndex < parts.length; leftIndex++) {
+            String part = parts[leftIndex];
+            if (part.length() == 0) {
+                // hit empty group of zero compression
+                hitZeroCompression = true;
+                break;
+            }
+            builder.setUnsignedShortWord(leftWord++, Integer.parseInt(part, 16));
+        }
+
+        if (hitZeroCompression) {
+            if (leftIndex == 0) {
+                // if colon is at the start, two columns must be at the start,
+                // move to the second empty group
+                leftIndex = 1;
+                if (parts.length < 2 || parts[1].length() > 0)
+                    throw new IllegalArgumentException("Malformed IPv6 address: " + string);
+            }
+
+            int rightWord = 7;
+            int rightIndex;
+            for (rightIndex = parts.length - 1; rightIndex > leftIndex; rightIndex--) {
+                String part = parts[rightIndex];
+                if (part.length() == 0)
+                    break;
+                builder.setUnsignedShortWord(rightWord--, Integer.parseInt(part, 16));
+            }
+            if (rightIndex == parts.length - 1) {
+                // if colon is at the end, two columns must be at the end, move
+                // to the second empty group
+                if (rightIndex < 1 || parts[rightIndex - 1].length() > 0)
+                    throw new IllegalArgumentException("Malformed IPv6 address: " + string);
+                rightIndex--;
+            }
+            if (leftIndex != rightIndex)
+                throw new IllegalArgumentException("Malformed IPv6 address: " + string);
+        } else {
+            if (leftIndex != 8) {
+                throw new IllegalArgumentException("Malformed IPv6 address: " + string);
+            }
+        }
+        return builder.getIPv6();
+    }
+
+    public static IPv6 of(final long raw1, final long raw2) {
+        return new IPv6(raw1, raw2);
+    }
+
+    volatile byte[] bytesCache = null;
+
+    public byte[] getBytes() {
+        if (bytesCache == null) {
+            synchronized (this) {
+                if (bytesCache == null) {
+                    bytesCache =
+                            new byte[] { (byte) ((raw1 >> 56) & 0xFF),
+                                    (byte) ((raw1 >> 48) & 0xFF),
+                                    (byte) ((raw1 >> 40) & 0xFF),
+                                    (byte) ((raw1 >> 32) & 0xFF),
+                                    (byte) ((raw1 >> 24) & 0xFF),
+                                    (byte) ((raw1 >> 16) & 0xFF),
+                                    (byte) ((raw1 >> 8) & 0xFF),
+                                    (byte) ((raw1 >> 0) & 0xFF),
+
+                                    (byte) ((raw2 >> 56) & 0xFF),
+                                    (byte) ((raw2 >> 48) & 0xFF),
+                                    (byte) ((raw2 >> 40) & 0xFF),
+                                    (byte) ((raw2 >> 32) & 0xFF),
+                                    (byte) ((raw2 >> 24) & 0xFF),
+                                    (byte) ((raw2 >> 16) & 0xFF),
+                                    (byte) ((raw2 >> 8) & 0xFF),
+                                    (byte) ((raw2 >> 0) & 0xFF) };
+                }
+            }
+        }
+        return bytesCache;
+    }
+
+    @Override
+    public int getLength() {
+        return LENGTH;
+    }
+
+    public static IPv6 readFrom(final ChannelBuffer bb) throws OFParseError, OFShortRead {
+        return IPv6.of(bb.readLong(), bb.readLong());
+    }
+
+    @Override
+    public void writeTo(final ChannelBuffer bb) throws OFParseError, OFShortWrite {
+        bb.writeLong(raw1);
+        bb.writeLong(raw2);
+    }
+
+    @Override
+    public String toString() {
+        return toString(true, false);
+    }
+
+    public int getUnsignedShortWord(final int i) {
+        if (i >= 0 && i < 4)
+            return (int) ((raw1 >>> (48 - i * 16)) & 0xFFFF);
+        else if (i >= 4 && i < 8)
+            return (int) ((raw2 >>> (48 - (i - 4) * 16)) & 0xFFFF);
+        else
+            throw new IllegalArgumentException("16 bit word index must be in [0,7]");
+    }
+
+    /** get the index of the first word where to apply IPv6 zero compression */
+    public int getZeroCompressStart() {
+        int start = Integer.MAX_VALUE;
+        int maxLength = -1;
+
+        int candidateStart = -1;
+
+        for (int i = 0; i < 8; i++) {
+            if (candidateStart >= 0) {
+                // in a zero octect
+                if (getUnsignedShortWord(i) != 0) {
+                    // end of this candidate word
+                    int candidateLength = i - candidateStart;
+                    if (candidateLength >= maxLength) {
+                        start = candidateStart;
+                        maxLength = candidateLength;
+                    }
+                    candidateStart = -1;
+                }
+            } else {
+                // not in a zero octect
+                if (getUnsignedShortWord(i) == 0) {
+                    candidateStart = i;
+                }
+            }
+        }
+
+        if (candidateStart >= 0) {
+            int candidateLength = 8 - candidateStart;
+            if (candidateLength >= maxLength) {
+                start = candidateStart;
+                maxLength = candidateLength;
+            }
+        }
+
+        return start;
+    }
+
+    public String toString(final boolean zeroCompression, final boolean leadingZeros) {
+        StringBuilder res = new StringBuilder();
+
+        int compressionStart = zeroCompression ? getZeroCompressStart() : Integer.MAX_VALUE;
+        boolean inCompression = false;
+        boolean colonNeeded = false;
+
+        for (int i = 0; i < 8; i++) {
+            int word = getUnsignedShortWord(i);
+
+            if (word == 0) {
+                if (inCompression)
+                    continue;
+                else if (i == compressionStart) {
+                    res.append(':').append(':');
+                    inCompression = true;
+                    colonNeeded = false;
+                    continue;
+                }
+            } else {
+                inCompression = false;
+            }
+
+            if (colonNeeded) {
+                res.append(':');
+                colonNeeded = false;
+            }
+
+            res.append(leadingZeros ? String.format("%04x", word) : Integer.toString(word,
+                    16));
+            colonNeeded = true;
+        }
+        return res.toString();
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + (int) (raw1 ^ (raw1 >>> 32));
+        result = prime * result + (int) (raw2 ^ (raw2 >>> 32));
+        return result;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        IPv6 other = (IPv6) obj;
+        if (raw1 != other.raw1)
+            return false;
+        if (raw2 != other.raw2)
+            return false;
+        return true;
+    }
+
+}
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
new file mode 100644
index 0000000..0fb3281
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/IPv6WithMask.java
@@ -0,0 +1,5 @@
+package org.openflow.types;
+
+public class IPv6WithMask {
+
+}
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
new file mode 100644
index 0000000..a295cb2
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/IpProtocol.java
@@ -0,0 +1,5 @@
+package org.openflow.types;
+
+public class IpProtocol {
+
+}
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
new file mode 100644
index 0000000..4ce19ab
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/MacAddress.java
@@ -0,0 +1,123 @@
+package org.openflow.types;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.exceptions.OFParseError;
+import org.openflow.exceptions.OFShortWrite;
+import org.openflow.protocol.OFObject;
+import org.openflow.util.HexString;
+
+/**
+ * Wrapper around a 6 byte mac address.
+ *
+ * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+ */
+
+public class MacAddress implements OFObject {
+    static final int MacAddrLen = 6;
+    private final long rawValue;
+
+    private MacAddress(final long rawValue) {
+        this.rawValue = rawValue;
+    }
+
+    public static MacAddress of(final byte[] address) {
+        long raw =
+                (address[0] & 0xFFL) << 40 | (address[1] & 0xFFL) << 32
+                        | (address[2] & 0xFFL) << 24 | (address[3] & 0xFFL) << 16
+                        | (address[4] & 0xFFL) << 8 | (address[5] & 0xFFL);
+        return MacAddress.of(raw);
+    }
+
+    public static MacAddress of(final long raw) {
+        return new MacAddress(raw);
+    }
+
+    public static MacAddress of(final String string) {
+        int index = 0;
+        int shift = 40;
+
+        long raw = 0;
+        if (string.length() != 6 * 2 + 5)
+            throw new IllegalArgumentException("Mac address not well formed: " + string);
+
+        while (shift >= 0) {
+            raw |=
+                    ((long) (Character.digit(string.charAt(index++), 16) << 4 | Character
+                            .digit(string.charAt(index++), 16))) << shift;
+
+            if (shift == 0)
+                break;
+            if (string.charAt(index++) != ':')
+                throw new IllegalArgumentException("Mac address not well formed: " + string);
+            shift -= 8;
+        }
+        return MacAddress.of(raw);
+    }
+
+    volatile byte[] bytesCache = null;
+
+    public byte[] getBytes() {
+        if (bytesCache == null) {
+            synchronized (this) {
+                if (bytesCache == null) {
+                    bytesCache =
+                            new byte[] { (byte) ((rawValue >> 40) & 0xFF),
+                                    (byte) ((rawValue >> 32) & 0xFF),
+                                    (byte) ((rawValue >> 24) & 0xFF),
+                                    (byte) ((rawValue >> 16) & 0xFF),
+                                    (byte) ((rawValue >> 8) & 0xFF),
+                                    (byte) ((rawValue >> 0) & 0xFF) };
+                }
+            }
+        }
+        return bytesCache;
+    }
+
+    @Override
+    public int getLength() {
+        return MacAddrLen;
+    }
+
+    public static MacAddress readFrom(final ChannelBuffer bb) throws OFParseError {
+        long raw = bb.readUnsignedInt() << 16 | bb.readUnsignedShort();
+        return MacAddress.of(raw);
+    }
+
+    @Override
+    public void writeTo(final ChannelBuffer bb) throws OFParseError, OFShortWrite {
+        bb.writeInt((int) (rawValue >> 16));
+        bb.writeShort((int) rawValue & 0xFFFF);
+    }
+
+    @Override
+    public String toString() {
+        return HexString.toHexString(rawValue, 6);
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + (int) (rawValue ^ (rawValue >>> 32));
+        return result;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        MacAddress other = (MacAddress) obj;
+        if (rawValue != other.rawValue)
+            return false;
+        return true;
+    }
+
+    public long getLong() {
+        return rawValue;
+    }
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/MacAddressWithMask.java b/java_gen/pre-written/src/main/java/org/openflow/types/MacAddressWithMask.java
new file mode 100644
index 0000000..ffa5fa7
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/MacAddressWithMask.java
@@ -0,0 +1,5 @@
+package org.openflow.types;
+
+public class MacAddressWithMask {
+
+}
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
new file mode 100644
index 0000000..98a8e0b
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/Masked.java
@@ -0,0 +1,5 @@
+package org.openflow.types;
+
+public class Masked<T> {
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/OFBsnInterface.java b/java_gen/pre-written/src/main/java/org/openflow/types/OFBsnInterface.java
new file mode 100644
index 0000000..d0afb56
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/OFBsnInterface.java
@@ -0,0 +1,5 @@
+package org.openflow.types;
+
+public interface OFBsnInterface {
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/OFBucket.java b/java_gen/pre-written/src/main/java/org/openflow/types/OFBucket.java
new file mode 100644
index 0000000..47b403b
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/OFBucket.java
@@ -0,0 +1,22 @@
+package org.openflow.types;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.exceptions.OFParseError;
+import org.openflow.exceptions.OFShortWrite;
+import org.openflow.protocol.OFObject;
+
+public class OFBucket implements OFObject {
+
+    @Override
+    public int getLength() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public void writeTo(final ChannelBuffer bb) throws OFParseError, OFShortWrite {
+        // TODO Auto-generated method stub
+
+    }
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/OFFlowModCmd.java b/java_gen/pre-written/src/main/java/org/openflow/types/OFFlowModCmd.java
new file mode 100644
index 0000000..6ca2c04
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/OFFlowModCmd.java
@@ -0,0 +1,11 @@
+package org.openflow.types;
+
+/**
+ * Version agnostic view of commands to an OFFlowMod
+ *
+ * @author capveg
+ */
+
+public enum OFFlowModCmd {
+    ADD, MODIFY, MODIFY_STRICT, DELETE, DELETE_STRICT
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/OFHelloElement.java b/java_gen/pre-written/src/main/java/org/openflow/types/OFHelloElement.java
new file mode 100644
index 0000000..288e1b6
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/OFHelloElement.java
@@ -0,0 +1,5 @@
+package org.openflow.types;
+
+public interface OFHelloElement {
+
+}
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
new file mode 100644
index 0000000..d15812b
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/OFMeterBand.java
@@ -0,0 +1,5 @@
+package org.openflow.types;
+
+public interface OFMeterBand {
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/OFPacketQueue.java b/java_gen/pre-written/src/main/java/org/openflow/types/OFPacketQueue.java
new file mode 100644
index 0000000..d74906f
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/OFPacketQueue.java
@@ -0,0 +1,22 @@
+package org.openflow.types;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.exceptions.OFParseError;
+import org.openflow.exceptions.OFShortWrite;
+import org.openflow.protocol.OFObject;
+
+public class OFPacketQueue implements OFObject {
+
+    @Override
+    public int getLength() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public void writeTo(final ChannelBuffer bb) throws OFParseError, OFShortWrite {
+        // TODO Auto-generated method stub
+
+    }
+
+}
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
new file mode 100644
index 0000000..0853fea
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/OFPhysicalPort.java
@@ -0,0 +1,12 @@
+package org.openflow.types;
+
+/**
+ * A wrapper around the OpenFlow physical port description. The interfaces to
+ * this object are version agnostic.
+ *
+ * @author capveg
+ */
+
+public class OFPhysicalPort {
+
+}
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
new file mode 100644
index 0000000..4156f1f
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/OFPort.java
@@ -0,0 +1,491 @@
+package org.openflow.types;
+
+import org.openflow.annotations.Immutable;
+
+/**
+ * Abstraction of an logical / OpenFlow switch port (ofp_port_no) in OpenFlow.
+ * Immutable. Note: Switch port numbers were changed in OpenFlow 1.1 from uint16
+ * to uint32. This class uses a 32 bit representation internally. Port numbers
+ * are converted from/to uint16 when constructed / getPortNumberasShort is
+ * called. If this port is not representable in OpenFlow 1.0, an
+ * IllegalStateException is raised.
+ *
+ * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+ */
+@Immutable
+public class OFPort {
+    // private int constants (OF1.1+) to avoid duplication in the code
+    // should not have to use these outside this class
+    private static final int OFPP_ANY_INT = 0xFFffFFff;
+    private static final int OFPP_LOCAL_INT = 0xFFffFFfe;
+    private static final int OFPP_CONTROLLER_INT = 0xFFffFFfd;
+    private static final int OFPP_ALL_INT = 0xFFffFFfc;
+    private static final int OFPP_FLOOD_INT = 0xFFffFFfb;
+    private static final int OFPP_NORMAL_INT = 0xFFffFFfa;
+    private static final int OFPP_TABLE_INT = 0xFFffFFf9;
+    private static final int OFPP_MAX_INT = 0xFFffFF00;
+    private static final int OFPP_IN_PORT_INT = 0xFFffFFf8;
+
+    // private short constants (OF1.0) to avoid duplication in the code
+    // should not have to use these outside this class
+    private static final short OFPP_ANY_SHORT = (short) 0xFFff;
+    private static final short OFPP_LOCAL_SHORT = (short) 0xFFfe;
+    private static final short OFPP_CONTROLLER_SHORT = (short) 0xFFfd;
+    private static final short OFPP_ALL_SHORT = (short) 0xFFfc;
+    private static final short OFPP_FLOOD_SHORT = (short) 0xFFfb;
+    private static final short OFPP_NORMAL_SHORT = (short) 0xFFfa;
+    private static final short OFPP_TABLE_SHORT = (short) 0xFFf9;
+    private static final short OFPP_IN_PORT_SHORT = (short) 0xFFf8;
+    private static final short OFPP_MAX_SHORT = (short) 0xFF00;
+    private static final int OFPP_MAX_SHORT_UNSIGNED = 0xFF00;
+
+    // ////////////// public constants - use to access well known OpenFlow ports
+
+    /** Maximum number of physical and logical switch ports. */
+    public final static OFPort MAX = new NamedPort(OFPP_MAX_INT, "max");
+
+    /**
+     * Send the packet out the input port. This reserved port must be explicitly
+     * used in order to send back out of the input port.
+     */
+    public final static OFPort IN_PORT = new NamedPort(OFPP_IN_PORT_INT, "in_port");
+
+    /**
+     * Submit the packet to the first flow table NB: This destination port can
+     * only be used in packet-out messages.
+     */
+    public final static OFPort TABLE = new NamedPort(OFPP_TABLE_INT, "table");
+
+    /** Process with normal L2/L3 switching. */
+    public final static OFPort NORMAL = new NamedPort(OFPP_NORMAL_INT, "normal");
+
+    /**
+     * All physical ports in VLAN, except input port and those blocked or link
+     * down
+     */
+    public final static OFPort FLOOD = new NamedPort(OFPP_FLOOD_INT, "flood");
+
+    /** All physical ports except input port */
+    public final static OFPort ALL = new NamedPort(OFPP_ALL_INT, "all");
+
+    /** Send to controller */
+    public final static OFPort CONTROLLER =
+            new NamedPort(OFPP_CONTROLLER_INT, "controller");
+
+    /** local openflow "port" */
+    public final static OFPort LOCAL = new NamedPort(OFPP_LOCAL_INT, "local");
+
+    /**
+     * Wildcard port used only for flow mod (delete) and flow stats requests.
+     * Selects all flows regardless of output port (including flows with no
+     * output port). NOTE: OpenFlow 1.0 calls this 'NONE'
+     */
+    public final static OFPort ANY = new NamedPort(OFPP_ANY_INT, "any");
+
+    /** cache of frequently used ports */
+    private static class PrecachedPort {
+        private final static OFPort p1 = new OFPort(1);
+        private final static OFPort p2 = new OFPort(2);
+        private final static OFPort p3 = new OFPort(3);
+        private final static OFPort p4 = new OFPort(4);
+        private final static OFPort p5 = new OFPort(5);
+        private final static OFPort p6 = new OFPort(6);
+        private final static OFPort p7 = new OFPort(7);
+        private final static OFPort p8 = new OFPort(8);
+        private final static OFPort p9 = new OFPort(9);
+        private final static OFPort p10 = new OFPort(10);
+        private final static OFPort p11 = new OFPort(11);
+        private final static OFPort p12 = new OFPort(12);
+        private final static OFPort p13 = new OFPort(13);
+        private final static OFPort p14 = new OFPort(14);
+        private final static OFPort p15 = new OFPort(15);
+        private final static OFPort p16 = new OFPort(16);
+        private final static OFPort p17 = new OFPort(17);
+        private final static OFPort p18 = new OFPort(18);
+        private final static OFPort p19 = new OFPort(19);
+        private final static OFPort p20 = new OFPort(20);
+        private final static OFPort p21 = new OFPort(21);
+        private final static OFPort p22 = new OFPort(22);
+        private final static OFPort p23 = new OFPort(23);
+        private final static OFPort p24 = new OFPort(24);
+        private final static OFPort p25 = new OFPort(25);
+        private final static OFPort p26 = new OFPort(26);
+        private final static OFPort p27 = new OFPort(27);
+        private final static OFPort p28 = new OFPort(28);
+        private final static OFPort p29 = new OFPort(29);
+        private final static OFPort p31 = new OFPort(31);
+        private final static OFPort p32 = new OFPort(32);
+        private final static OFPort p33 = new OFPort(33);
+        private final static OFPort p34 = new OFPort(34);
+        private final static OFPort p35 = new OFPort(35);
+        private final static OFPort p36 = new OFPort(36);
+        private final static OFPort p37 = new OFPort(37);
+        private final static OFPort p38 = new OFPort(38);
+        private final static OFPort p39 = new OFPort(39);
+        private final static OFPort p40 = new OFPort(40);
+        private final static OFPort p41 = new OFPort(41);
+        private final static OFPort p42 = new OFPort(42);
+        private final static OFPort p43 = new OFPort(43);
+        private final static OFPort p44 = new OFPort(44);
+        private final static OFPort p45 = new OFPort(45);
+        private final static OFPort p46 = new OFPort(46);
+        private final static OFPort p47 = new OFPort(47);
+        private final static OFPort p48 = new OFPort(48);
+    }
+
+    /** raw openflow port number as a signed 32 bit integer */
+    private final int portNumber;
+
+    /** private constructor. use of*-Factory methods instead */
+    private OFPort(final int portNumber) {
+        this.portNumber = portNumber;
+    }
+
+    /**
+     * get an OFPort object corresponding to a raw 32-bit integer port number.
+     * NOTE: The port object may either be newly allocated or cached. Do not
+     * rely on either behavior.
+     *
+     * @param portNumber
+     * @return a corresponding OFPort
+     */
+    public static OFPort ofInt(final int portNumber) {
+        switch (portNumber) {
+            case 1:
+                return PrecachedPort.p1;
+            case 2:
+                return PrecachedPort.p2;
+            case 3:
+                return PrecachedPort.p3;
+            case 4:
+                return PrecachedPort.p4;
+            case 5:
+                return PrecachedPort.p5;
+            case 6:
+                return PrecachedPort.p6;
+            case 7:
+                return PrecachedPort.p7;
+            case 8:
+                return PrecachedPort.p8;
+            case 9:
+                return PrecachedPort.p9;
+            case 10:
+                return PrecachedPort.p10;
+            case 11:
+                return PrecachedPort.p11;
+            case 12:
+                return PrecachedPort.p12;
+            case 13:
+                return PrecachedPort.p13;
+            case 14:
+                return PrecachedPort.p14;
+            case 15:
+                return PrecachedPort.p15;
+            case 16:
+                return PrecachedPort.p16;
+            case 17:
+                return PrecachedPort.p17;
+            case 18:
+                return PrecachedPort.p18;
+            case 19:
+                return PrecachedPort.p19;
+            case 20:
+                return PrecachedPort.p20;
+            case 21:
+                return PrecachedPort.p21;
+            case 22:
+                return PrecachedPort.p22;
+            case 23:
+                return PrecachedPort.p23;
+            case 24:
+                return PrecachedPort.p24;
+            case 25:
+                return PrecachedPort.p25;
+            case 26:
+                return PrecachedPort.p26;
+            case 27:
+                return PrecachedPort.p27;
+            case 28:
+                return PrecachedPort.p28;
+            case 29:
+                return PrecachedPort.p29;
+            case 31:
+                return PrecachedPort.p31;
+            case 32:
+                return PrecachedPort.p32;
+            case 33:
+                return PrecachedPort.p33;
+            case 34:
+                return PrecachedPort.p34;
+            case 35:
+                return PrecachedPort.p35;
+            case 36:
+                return PrecachedPort.p36;
+            case 37:
+                return PrecachedPort.p37;
+            case 38:
+                return PrecachedPort.p38;
+            case 39:
+                return PrecachedPort.p39;
+            case 40:
+                return PrecachedPort.p40;
+            case 41:
+                return PrecachedPort.p41;
+            case 42:
+                return PrecachedPort.p42;
+            case 43:
+                return PrecachedPort.p43;
+            case 44:
+                return PrecachedPort.p44;
+            case 45:
+                return PrecachedPort.p45;
+            case 46:
+                return PrecachedPort.p46;
+            case 47:
+                return PrecachedPort.p47;
+            case 48:
+                return PrecachedPort.p48;
+            case OFPP_MAX_INT:
+                return MAX;
+            case OFPP_IN_PORT_INT:
+                return IN_PORT;
+            case OFPP_TABLE_INT:
+                return TABLE;
+            case OFPP_NORMAL_INT:
+                return NORMAL;
+            case OFPP_FLOOD_INT:
+                return FLOOD;
+            case OFPP_ALL_INT:
+                return ALL;
+            case OFPP_CONTROLLER_INT:
+                return CONTROLLER;
+            case OFPP_LOCAL_INT:
+                return LOCAL;
+            case OFPP_ANY_INT:
+                return ANY;
+            default:
+                // note: This means effectively : portNumber > OFPP_MAX_SHORT
+                // accounting for
+                // signedness of both portNumber and OFPP_MAX_INT(which is
+                // -256).
+                // Any unsigned integer value > OFPP_MAX_INT will be ]-256:0[
+                // when read signed
+                if (portNumber < 0 && portNumber > OFPP_MAX_INT)
+                    throw new IllegalArgumentException("Unknown special port number: "
+                            + portNumber);
+                return new OFPort(portNumber);
+        }
+    }
+
+    /** convenience function: delegates to ofInt */
+    public static OFPort of(final int portNumber) {
+        return ofInt(portNumber);
+    }
+
+    /**
+     * get an OFPort object corresponding to a raw signed 16-bit integer port
+     * number (OF1.0). Note that the port returned will have the corresponding
+     * 32-bit integer value allocated as its port number. NOTE: The port object
+     * may either be newly allocated or cached. Do not rely on either behavior.
+     *
+     * @param portNumber
+     * @return a corresponding OFPort
+     */
+    public static OFPort ofShort(final short portNumber) {
+        switch (portNumber) {
+            case 1:
+                return PrecachedPort.p1;
+            case 2:
+                return PrecachedPort.p2;
+            case 3:
+                return PrecachedPort.p3;
+            case 4:
+                return PrecachedPort.p4;
+            case 5:
+                return PrecachedPort.p5;
+            case 6:
+                return PrecachedPort.p6;
+            case 7:
+                return PrecachedPort.p7;
+            case 8:
+                return PrecachedPort.p8;
+            case 9:
+                return PrecachedPort.p9;
+            case 10:
+                return PrecachedPort.p10;
+            case 11:
+                return PrecachedPort.p11;
+            case 12:
+                return PrecachedPort.p12;
+            case 13:
+                return PrecachedPort.p13;
+            case 14:
+                return PrecachedPort.p14;
+            case 15:
+                return PrecachedPort.p15;
+            case 16:
+                return PrecachedPort.p16;
+            case 17:
+                return PrecachedPort.p17;
+            case 18:
+                return PrecachedPort.p18;
+            case 19:
+                return PrecachedPort.p19;
+            case 20:
+                return PrecachedPort.p20;
+            case 21:
+                return PrecachedPort.p21;
+            case 22:
+                return PrecachedPort.p22;
+            case 23:
+                return PrecachedPort.p23;
+            case 24:
+                return PrecachedPort.p24;
+            case 25:
+                return PrecachedPort.p25;
+            case 26:
+                return PrecachedPort.p26;
+            case 27:
+                return PrecachedPort.p27;
+            case 28:
+                return PrecachedPort.p28;
+            case 29:
+                return PrecachedPort.p29;
+            case 31:
+                return PrecachedPort.p31;
+            case 32:
+                return PrecachedPort.p32;
+            case 33:
+                return PrecachedPort.p33;
+            case 34:
+                return PrecachedPort.p34;
+            case 35:
+                return PrecachedPort.p35;
+            case 36:
+                return PrecachedPort.p36;
+            case 37:
+                return PrecachedPort.p37;
+            case 38:
+                return PrecachedPort.p38;
+            case 39:
+                return PrecachedPort.p39;
+            case 40:
+                return PrecachedPort.p40;
+            case 41:
+                return PrecachedPort.p41;
+            case 42:
+                return PrecachedPort.p42;
+            case 43:
+                return PrecachedPort.p43;
+            case 44:
+                return PrecachedPort.p44;
+            case 45:
+                return PrecachedPort.p45;
+            case 46:
+                return PrecachedPort.p46;
+            case 47:
+                return PrecachedPort.p47;
+            case 48:
+                return PrecachedPort.p48;
+            case OFPP_MAX_SHORT:
+                return MAX;
+            case OFPP_IN_PORT_SHORT:
+                return IN_PORT;
+            case OFPP_TABLE_SHORT:
+                return TABLE;
+            case OFPP_NORMAL_SHORT:
+                return NORMAL;
+            case OFPP_FLOOD_SHORT:
+                return FLOOD;
+            case OFPP_ALL_SHORT:
+                return ALL;
+            case OFPP_CONTROLLER_SHORT:
+                return CONTROLLER;
+            case OFPP_LOCAL_SHORT:
+                return LOCAL;
+            case OFPP_ANY_SHORT:
+                return ANY;
+            default:
+                // note: This means effectively : portNumber > OFPP_MAX_SHORT
+                // accounting for
+                // signedness of both portNumber and OFPP_MAX_SHORT (which is
+                // -256).
+                // Any unsigned integer value > OFPP_MAX_SHORT will be ]-256:0[
+                // when read signed
+                if (portNumber < 0 && portNumber > OFPP_MAX_SHORT)
+                    throw new IllegalArgumentException("Unknown special port number: "
+                            + portNumber);
+                return new OFPort(portNumber);
+        }
+    }
+
+    /** return the port number as a int32 */
+    public int getPortNumber() {
+        return portNumber;
+    }
+
+    /**
+     * return the port number as int16. Special ports as defined by the OpenFlow
+     * spec will be converted to their OpenFlow 1.0 equivalent. port numbers >=
+     * FF00 will cause a IllegalArgumentException to be thrown
+     *
+     * @throws IllegalArgumentException
+     *             if a regular port number exceeds the maximum value in OF1.0
+     **/
+    public short getShortPortNumber() {
+
+        switch (portNumber) {
+            case OFPP_MAX_INT:
+                return OFPP_MAX_SHORT;
+            case OFPP_IN_PORT_INT:
+                return OFPP_IN_PORT_SHORT;
+            case OFPP_TABLE_INT:
+                return OFPP_TABLE_SHORT;
+            case OFPP_NORMAL_INT:
+                return OFPP_NORMAL_SHORT;
+            case OFPP_FLOOD_INT:
+                return OFPP_FLOOD_SHORT;
+            case OFPP_ALL_INT:
+                return OFPP_ALL_SHORT;
+            case OFPP_CONTROLLER_INT:
+                return OFPP_CONTROLLER_SHORT;
+            case OFPP_LOCAL_INT:
+                return OFPP_LOCAL_SHORT;
+            case OFPP_ANY_INT:
+                return OFPP_ANY_SHORT;
+
+            default:
+                if (portNumber >= OFPP_MAX_SHORT_UNSIGNED || portNumber < 0)
+                    throw new IllegalArgumentException("32bit Port number "
+                            + U32.f(portNumber)
+                            + " cannot be represented as uint16 (OF1.0)");
+
+                return (short) portNumber;
+        }
+    }
+
+    @Override
+    public String toString() {
+        return Long.toString(U32.f(portNumber));
+    }
+
+    /** Extension of OFPort for named ports */
+    static class NamedPort extends OFPort {
+        private final String name;
+
+        NamedPort(final int portNo, final String name) {
+            super(portNo);
+            this.name = name;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        @Override
+        public String toString() {
+            return name;
+        }
+    }
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/U16.java b/java_gen/pre-written/src/main/java/org/openflow/types/U16.java
new file mode 100644
index 0000000..5884adc
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/U16.java
@@ -0,0 +1,28 @@
+/**
+ *    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+ *    University
+ *
+ *    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.types;
+
+public class U16 {
+    public static int f(final short i) {
+        return i & 0xffff;
+    }
+
+    public static short t(final int l) {
+        return (short) l;
+    }
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/U32.java b/java_gen/pre-written/src/main/java/org/openflow/types/U32.java
new file mode 100644
index 0000000..003f35d
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/U32.java
@@ -0,0 +1,28 @@
+/**
+ *    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+ *    University
+ *
+ *    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.types;
+
+public class U32 {
+    public static long f(final int i) {
+        return i & 0xffffffffL;
+    }
+
+    public static int t(final long l) {
+        return (int) l;
+    }
+}
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
new file mode 100644
index 0000000..211c3ea
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/U64.java
@@ -0,0 +1,57 @@
+/**
+ *    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+ *    University
+ *
+ *    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.types;
+
+import java.math.BigInteger;
+
+public class U64 {
+    private final static BigInteger TWO_POWER_64 = BigInteger.valueOf(Long.MAX_VALUE).add(
+            BigInteger.valueOf(1));
+
+    private final long raw;
+
+    private U64(final long raw) {
+        this.raw = raw;
+    }
+
+    public static U64 of(final long raw) {
+        return new U64(raw);
+    }
+
+    public long getValue() {
+        return raw;
+    }
+
+    public BigInteger getBigInteger() {
+        return raw >= 0 ? BigInteger.valueOf(raw) : TWO_POWER_64.add(BigInteger
+                .valueOf(raw));
+    }
+
+    @Override
+    public String toString() {
+        return getBigInteger().toString();
+    }
+
+    public static BigInteger f(final long i) {
+        return new BigInteger(Long.toBinaryString(i), 2);
+    }
+
+    public static long t(final BigInteger l) {
+        return l.longValue();
+    }
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/U8.java b/java_gen/pre-written/src/main/java/org/openflow/types/U8.java
new file mode 100644
index 0000000..1cdf0e5
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/U8.java
@@ -0,0 +1,34 @@
+/**
+ *    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+ *    University
+ *
+ *    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.types;
+
+public class U8 {
+    byte data;
+
+    public static short f(final byte i) {
+        return (short) (i & 0xff);
+    }
+
+    public static byte t(final short l) {
+        return (byte) l;
+    }
+
+    public byte getValue() {
+        return data;
+    }
+}
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
new file mode 100644
index 0000000..bda2dc1
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/VlanPcp.java
@@ -0,0 +1,5 @@
+package org.openflow.types;
+
+public class VlanPcp {
+
+}
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
new file mode 100644
index 0000000..0f9eaf7
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/VlanVid.java
@@ -0,0 +1,5 @@
+package org.openflow.types;
+
+public class VlanVid {
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/VlanVidWithMask/VlanVidWithMask.java b/java_gen/pre-written/src/main/java/org/openflow/types/VlanVidWithMask/VlanVidWithMask.java
new file mode 100644
index 0000000..610b11c
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/VlanVidWithMask/VlanVidWithMask.java
@@ -0,0 +1,5 @@
+package org.openflow.types.VlanVidWithMask;
+
+public class VlanVidWithMask {
+
+}
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/util/ChannelUtils.java
new file mode 100644
index 0000000..e8eeebd
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/util/ChannelUtils.java
@@ -0,0 +1,93 @@
+package org.openflow.util;
+
+import java.util.List;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.protocol.actions.OFAction;
+import org.openflow.protocol.instructions.OFInstruction;
+import org.openflow.protocol.match.Match;
+import org.openflow.types.OFBsnInterface;
+import org.openflow.types.OFBucket;
+import org.openflow.types.OFFlowModCmd;
+import org.openflow.types.OFHelloElement;
+import org.openflow.types.OFMeterBand;
+import org.openflow.types.OFPacketQueue;
+import org.openflow.types.OFPhysicalPort;
+
+/**
+ * Collection of helper functions for reading and writing into ChannelBuffers
+ *
+ * @author capveg
+ */
+
+public class ChannelUtils {
+
+    static public byte[] readBytes(final ChannelBuffer bb, final int length) {
+        byte byteArray[] = new byte[length];
+        bb.readBytes(byteArray);
+        return 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) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    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 OFFlowModCmd readOFFlowModCmd(final ChannelBuffer bb) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    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) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public static OFPhysicalPort readPhysicalPort(final ChannelBuffer bb) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    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) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public static List<OFBucket> readBucketList(final ChannelBuffer bb, final int i) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public static List<OFMeterBand> readMeterBandList(final ChannelBuffer bb) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/util/HexString.java b/java_gen/pre-written/src/main/java/org/openflow/util/HexString.java
new file mode 100644
index 0000000..8d17132
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/util/HexString.java
@@ -0,0 +1,98 @@
+/**
+ *    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+ *    University
+ *
+ *    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.util;
+
+import java.math.BigInteger;
+
+import org.openflow.types.U8;
+
+public class HexString {
+    /**
+     * Convert a string of bytes to a ':' separated hex string
+     *
+     * @param bytes
+     * @return "0f:ca:fe:de:ad:be:ef"
+     */
+    public static String toHexString(final byte[] bytes) {
+        int i;
+        String ret = "";
+        String tmp;
+        for (i = 0; i < bytes.length; i++) {
+            if (i > 0)
+                ret += ":";
+            tmp = Integer.toHexString(U8.f(bytes[i]));
+            if (tmp.length() == 1)
+                ret += "0";
+            ret += tmp;
+        }
+        return ret;
+    }
+
+    public static String toHexString(final long val, final int padTo) {
+        char arr[] = Long.toHexString(val).toCharArray();
+        String ret = "";
+        // prepend the right number of leading zeros
+        int i = 0;
+        for (; i < (padTo * 2 - arr.length); i++) {
+            ret += "0";
+            if ((i % 2) == 1)
+                ret += ":";
+        }
+        for (int j = 0; j < arr.length; j++) {
+            ret += arr[j];
+            if ((((i + j) % 2) == 1) && (j < (arr.length - 1)))
+                ret += ":";
+        }
+        return ret;
+    }
+
+    public static String toHexString(final long val) {
+        return toHexString(val, 8);
+    }
+
+    /**
+     * Convert a string of hex values into a string of bytes
+     *
+     * @param values
+     *            "0f:ca:fe:de:ad:be:ef"
+     * @return [15, 5 ,2, 5, 17]
+     * @throws NumberFormatException
+     *             If the string can not be parsed
+     */
+    public static byte[] fromHexString(final String values) throws NumberFormatException {
+        String[] octets = values.split(":");
+        byte[] ret = new byte[octets.length];
+
+        for (int i = 0; i < octets.length; i++) {
+            if (octets[i].length() > 2)
+                throw new NumberFormatException("Invalid octet length");
+            ret[i] = Integer.valueOf(octets[i], 16).byteValue();
+        }
+        return ret;
+    }
+
+    public static long toLong(final String values) throws NumberFormatException {
+        // Long.parseLong() can't handle HexStrings with MSB set. Sigh.
+        BigInteger bi = new BigInteger(values.replaceAll(":", ""), 16);
+        if (bi.bitLength() > 64)
+            throw new NumberFormatException("Input string too big to fit in long: "
+                    + values);
+        return bi.longValue();
+    }
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/util/LRULinkedHashMap.java b/java_gen/pre-written/src/main/java/org/openflow/util/LRULinkedHashMap.java
new file mode 100644
index 0000000..216319d
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/util/LRULinkedHashMap.java
@@ -0,0 +1,42 @@
+/**
+ *    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+ *    University
+ *
+ *    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.util;
+
+import java.util.LinkedHashMap;
+
+public class LRULinkedHashMap<K, V> extends LinkedHashMap<K, V> {
+    private static final long serialVersionUID = -2964986094089626647L;
+    protected int maximumCapacity;
+
+    public LRULinkedHashMap(final int initialCapacity, final int maximumCapacity) {
+        super(initialCapacity, 0.75f, true);
+        this.maximumCapacity = maximumCapacity;
+    }
+
+    public LRULinkedHashMap(final int maximumCapacity) {
+        super(16, 0.75f, true);
+        this.maximumCapacity = maximumCapacity;
+    }
+
+    @Override
+    protected boolean removeEldestEntry(final java.util.Map.Entry<K, V> eldest) {
+        if (this.size() > maximumCapacity)
+            return true;
+        return false;
+    }
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/util/StringByteSerializer.java b/java_gen/pre-written/src/main/java/org/openflow/util/StringByteSerializer.java
new file mode 100644
index 0000000..72c1224
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/util/StringByteSerializer.java
@@ -0,0 +1,58 @@
+/**
+ *    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+ *    University
+ *
+ *    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.util;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.util.Arrays;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public class StringByteSerializer {
+    public static String readFrom(final ChannelBuffer data, final int length) {
+        byte[] stringBytes = new byte[length];
+        data.readBytes(stringBytes);
+        // find the first index of 0
+        int index = 0;
+        for (byte b : stringBytes) {
+            if (0 == b)
+                break;
+            ++index;
+        }
+        return new String(Arrays.copyOf(stringBytes, index), Charset.forName("ascii"));
+    }
+
+    public static void writeTo(final ChannelBuffer data, final int length,
+            final String value) {
+        try {
+            byte[] name = value.getBytes("ASCII");
+            if (name.length < length) {
+                data.writeBytes(name);
+                for (int i = name.length; i < length; ++i) {
+                    data.writeByte((byte) 0);
+                }
+            } else {
+                data.writeBytes(name, 0, length - 1);
+                data.writeByte((byte) 0);
+            }
+        } catch (UnsupportedEncodingException e) {
+            throw new RuntimeException(e);
+        }
+
+    }
+}
diff --git a/java_gen/pre-written/src/test/java/Test.java b/java_gen/pre-written/src/test/java/Test.java
new file mode 100644
index 0000000..e83700d
--- /dev/null
+++ b/java_gen/pre-written/src/test/java/Test.java
@@ -0,0 +1,30 @@
+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/pre-written/src/test/java/org/openflow/types/IPv4Test.java b/java_gen/pre-written/src/test/java/org/openflow/types/IPv4Test.java
new file mode 100644
index 0000000..b19233c
--- /dev/null
+++ b/java_gen/pre-written/src/test/java/org/openflow/types/IPv4Test.java
@@ -0,0 +1,89 @@
+package org.openflow.types;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.junit.Test;
+import org.openflow.exceptions.OFParseError;
+import org.openflow.exceptions.OFShortRead;
+
+public class IPv4Test {
+    byte[][] testAddresses = new byte[][] {
+            {0x01, 0x02, 0x03, 0x04 },
+            {127, 0, 0, 1},
+            {(byte) 192, (byte) 168, 0, 100 },
+            {(byte) 255, (byte) 255, (byte) 255, (byte) 255 }
+    };
+
+    String[] testStrings = {
+            "1.2.3.4",
+            "127.0.0.1",
+            "192.168.0.100",
+            "255.255.255.255"
+    };
+
+    int[] testInts = {
+            0x01020304,
+            0x7f000001,
+            (192 << 24) | (168 << 16) | 100,
+            0xffffffff
+    };
+
+    String[] invalidIPs = {
+            "",
+            ".",
+            "1.2..3.4",
+            "1.2.3.4.",
+            "257.11.225.1",
+            "-1.2.3.4",
+            "1.2.3.4.5",
+            "1.x.3.4",
+            "1.2x.3.4"
+    };
+
+
+    @Test
+    public void testOfString() {
+        for(int i=0; i < testAddresses.length; i++ ) {
+            IPv4 ip = IPv4.of(testStrings[i]);
+            assertEquals(testInts[i], ip.getInt());
+            assertArrayEquals(testAddresses[i], ip.getBytes());
+            assertEquals(testStrings[i], ip.toString());
+        }
+    }
+
+    @Test
+    public void testOfByteArray() {
+        for(int i=0; i < testAddresses.length; i++ ) {
+            IPv4 ip = IPv4.of(testAddresses[i]);
+            assertEquals(testInts[i], ip.getInt());
+            assertArrayEquals(testAddresses[i], ip.getBytes());
+            assertEquals(testStrings[i], ip.toString());
+        }
+    }
+
+    @Test
+    public void testReadFrom() throws OFParseError, OFShortRead {
+        for(int i=0; i < testAddresses.length; i++ ) {
+            IPv4 ip = IPv4.readFrom(ChannelBuffers.copiedBuffer(testAddresses[i]));
+            assertEquals(testInts[i], ip.getInt());
+            assertArrayEquals(testAddresses[i], ip.getBytes());
+            assertEquals(testStrings[i], ip.toString());
+        }
+    }
+
+
+    @Test
+    public void testInvalidIPs() throws OFParseError, OFShortRead {
+        for(String invalid : invalidIPs) {
+            try {
+                IPv4.of(invalid);
+                fail("Invalid IP "+invalid+ " should have raised IllegalArgumentException");
+            } catch(IllegalArgumentException e) {
+                // ok
+            }
+        }
+    }
+}
diff --git a/java_gen/pre-written/src/test/java/org/openflow/types/IPv6Test.java b/java_gen/pre-written/src/test/java/org/openflow/types/IPv6Test.java
new file mode 100644
index 0000000..e3d5c81
--- /dev/null
+++ b/java_gen/pre-written/src/test/java/org/openflow/types/IPv6Test.java
@@ -0,0 +1,88 @@
+package org.openflow.types;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.junit.Test;
+import org.openflow.exceptions.OFParseError;
+import org.openflow.exceptions.OFShortRead;
+
+public class IPv6Test {
+
+    String[] testStrings = {
+            "::",
+            "::1",
+            "ffe0::",
+            "1:2:3:4:5:6:7:8"
+    };
+
+    @Test
+    public void testOfString() throws UnknownHostException {
+        for(int i=0; i < testStrings.length; i++ ) {
+            IPv6 ip = IPv6.of(testStrings[i]);
+            InetAddress inetAddress = InetAddress.getByName(testStrings[i]);
+
+            assertArrayEquals(ip.getBytes(), inetAddress.getAddress());
+            assertEquals(testStrings[i], ip.toString());
+        }
+    }
+
+    @Test
+    public void testOfByteArray() throws UnknownHostException {
+        for(int i=0; i < testStrings.length; i++ ) {
+            byte[] bytes = Inet6Address.getByName(testStrings[i]).getAddress();
+            IPv6 ip = IPv6.of(bytes);
+            assertEquals(testStrings[i], ip.toString());
+            assertArrayEquals(bytes, ip.getBytes());
+        }
+    }
+
+    @Test
+    public void testReadFrom() throws OFParseError, OFShortRead, UnknownHostException {
+        for(int i=0; i < testStrings.length; i++ ) {
+            byte[] bytes = Inet6Address.getByName(testStrings[i]).getAddress();
+            IPv6 ip = IPv6.readFrom(ChannelBuffers.copiedBuffer(bytes));
+            assertEquals(testStrings[i], ip.toString());
+            assertArrayEquals(bytes, ip.getBytes());
+        }
+    }
+
+    String[] invalidIPs = {
+            "",
+            ":",
+            "1:2:3:4:5:6:7:8:9",
+            "1:2:3:4:5:6:7:8:",
+            "1:2:3:4:5:6:7:8g",
+            "1:2:3:",
+            "12345::",
+            "1::3::8",
+            "::3::"
+    };
+
+    @Test
+    public void testInvalidIPs() throws OFParseError, OFShortRead {
+        for(String invalid : invalidIPs) {
+            try {
+                IPv6.of(invalid);
+                fail("Invalid IP "+invalid+ " should have raised IllegalArgumentException");
+            } catch(IllegalArgumentException e) {
+                // ok
+            }
+        }
+    }
+
+    @Test
+    public void testZeroCompression() throws OFParseError, OFShortRead {
+        assertEquals("::", IPv6.of("::").toString(true, false));
+        assertEquals("0:0:0:0:0:0:0:0", IPv6.of("::").toString(false, false));
+        assertEquals("0000:0000:0000:0000:0000:0000:0000:0000", IPv6.of("::").toString(false, true));
+        assertEquals("1::4:5:6:0:8", IPv6.of("1:0:0:4:5:6:0:8").toString(true, false));
+        assertEquals("1:0:0:4::8", IPv6.of("1:0:0:4:0:0:0:8").toString(true, false));
+    }
+}
diff --git a/java_gen/pre-written/src/test/java/org/openflow/types/MacAddressTest.java b/java_gen/pre-written/src/test/java/org/openflow/types/MacAddressTest.java
new file mode 100644
index 0000000..af86d9b
--- /dev/null
+++ b/java_gen/pre-written/src/test/java/org/openflow/types/MacAddressTest.java
@@ -0,0 +1,86 @@
+package org.openflow.types;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.util.Arrays;
+
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.junit.Test;
+import org.openflow.exceptions.OFParseError;
+import org.openflow.exceptions.OFShortRead;
+
+public class MacAddressTest {
+    byte[][] testAddresses = new byte[][] {
+            {0x01, 0x02, 0x03, 0x04, 0x05, 0x06 },
+            {(byte) 0x80, 0x0, 0x0, 0x0, 0x0, 0x01},
+            {(byte) 255, (byte) 255, (byte) 255, (byte) 255, (byte) 255, (byte) 255 }
+    };
+
+    String[] testStrings = {
+            "01:02:03:04:05:06",
+            "80:00:00:00:00:01",
+            "ff:ff:ff:ff:ff:ff"
+    };
+
+    long[] testInts = {
+            0x00010203040506L,
+            0x00800000000001L,
+            0x00ffffffffffffL
+    };
+
+    String[] invalidMacs = {
+            "",
+            "1.2.3.4",
+            "00:ff:ef:12:12:ff:",
+            "00:fff:ef:12:12:ff",
+            "01:02:03:04:05;06",
+            "0:1:2:3:4:5:6",
+            "01:02:03:04"
+    };
+
+
+    @Test
+    public void testOfString() {
+        for(int i=0; i < testAddresses.length; i++ ) {
+            MacAddress ip = MacAddress.of(testStrings[i]);
+            assertEquals(testInts[i], ip.getLong());
+            assertArrayEquals(testAddresses[i], ip.getBytes());
+            assertEquals(testStrings[i], ip.toString());
+        }
+    }
+
+    @Test
+    public void testOfByteArray() {
+        for(int i=0; i < testAddresses.length; i++ ) {
+            MacAddress ip = MacAddress.of(testAddresses[i]);
+            assertEquals("error checking long representation of "+Arrays.toString(testAddresses[i]) + "(should be "+Long.toHexString(testInts[i]) +")", testInts[i],  ip.getLong());
+            assertArrayEquals(testAddresses[i], ip.getBytes());
+            assertEquals(testStrings[i], ip.toString());
+        }
+    }
+
+    @Test
+    public void testReadFrom() throws OFParseError, OFShortRead {
+        for(int i=0; i < testAddresses.length; i++ ) {
+            MacAddress ip = MacAddress.readFrom(ChannelBuffers.copiedBuffer(testAddresses[i]));
+            assertEquals(testInts[i], ip.getLong());
+            assertArrayEquals(testAddresses[i], ip.getBytes());
+            assertEquals(testStrings[i], ip.toString());
+        }
+    }
+
+
+    @Test
+    public void testInvalidMacss() throws OFParseError, OFShortRead {
+        for(String invalid : invalidMacs) {
+            try {
+                MacAddress.of(invalid);
+                fail("Invalid IP "+invalid+ " should have raised IllegalArgumentException");
+            } catch(IllegalArgumentException e) {
+                // ok
+            }
+        }
+    }
+}
diff --git a/java_gen/templates/_autogen.java b/java_gen/templates/_autogen.java
new file mode 100644
index 0000000..e1ee006
--- /dev/null
+++ b/java_gen/templates/_autogen.java
@@ -0,0 +1,30 @@
+//:: # 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 inspect, os
+// Automatically generated by LOXI from template #{os.path.basename(inspect.stack()[3][1])}
+// Do not modify
diff --git a/java_gen/templates/_copyright.java b/java_gen/templates/_copyright.java
new file mode 100644
index 0000000..bf9ed02
--- /dev/null
+++ b/java_gen/templates/_copyright.java
@@ -0,0 +1,30 @@
+//:: # 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.
+//::
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
diff --git a/java_gen/templates/message_class.java b/java_gen/templates/message_class.java
new file mode 100644
index 0000000..2b4801c
--- /dev/null
+++ b/java_gen/templates/message_class.java
@@ -0,0 +1,258 @@
+//:: # 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;
+import java.util.Collections;
+import java.util.List;
+import org.openflow.protocol.actions.OFAction;
+import org.openflow.protocol.instructions.OFInstruction;
+import org.openflow.protocol.match.*;
+import org.openflow.types.*;
+import org.openflow.types.*;
+import org.openflow.util.*;
+import org.openflow.exceptions.*;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+class ${impl_class} implements ${msg.interface_name} {
+//:: if msg.is_fixed_length(version):
+    private static final int LENGTH = ${msg.min_length(version) };
+//:: else:
+    private static final int MINIMUM_LENGTH = ${msg.min_length(version) };
+//:: #endif
+
+//:: for prop in msg.properties_for_version(version):
+    private final static ${prop.java_type.public_type} ${prop.default_name} = ${prop.default_value};
+//:: #end
+    private boolean xidSet;
+    private final int xid;
+
+    // OF message fields
+//:: for prop in msg.properties_for_version(version):
+    private final ${prop.java_type.public_type} ${prop.name};
+//:: #endfor
+
+    // Constructor
+    ${impl_class}(${
+        ", ".join(["int xid" ] + [ "%s %s" %(prop.java_type.public_type, prop.name) for prop in msg.properties_for_version(version) ])}) {
+        this.xidSet = true;
+        this.xid = xid;
+//:: for prop in msg.properties_for_version(version):
+        this.${prop.name} = ${prop.name};
+//:: #endfor
+    }
+
+    ${impl_class}(${
+        ", ".join("%s %s" %(prop.java_type.public_type, prop.name) for prop in msg.properties_for_version(version)) }) {
+        this.xidSet = false;
+        this.xid = 0;
+//:: for prop in msg.properties_for_version(version):
+        this.${prop.name} = ${prop.name};
+//:: #endfor
+    }
+
+    @Override
+    public int getXid() {
+        return xid;
+    }
+
+    @Override
+    public boolean isXidSet() {
+        return xidSet;
+    }
+
+    @Override
+    public OFType getType() {
+        return OFType.${msg.constant_name};
+    }
+
+    @Override
+    public OFVersion getVersion() {
+        return OFVersion.${version.constant_version};
+    }
+
+    // Accessors for OF message fields
+//:: for prop in msg.all_properties():
+    @Override
+    public ${prop.java_type.public_type} get${prop.title_name}()${ "" if msg.property_in_version(prop, version) else "throws UnsupportedOperationException"} {
+//:: if msg.property_in_version(prop, version):
+        return ${prop.name};
+//:: else:
+        throw new UnsupportedOperationException("Property ${prop.name} not supported in version #{version}");
+//:: #endif
+    }
+//:: #endfor
+
+    public ${msg.interface_name}.Builder createBuilder() {
+        return new BuilderImplWithParent(this);
+    }
+
+    static class BuilderImplWithParent implements ${msg.interface_name}.Builder {
+        final ${impl_class} parentMessage;
+        private boolean xidSet;
+        private int xid;
+
+        // OF message fields
+//:: for prop in msg.properties_for_version(version):
+        private boolean ${prop.name}Set;
+        private ${prop.java_type.public_type} ${prop.name};
+//:: #endfor
+
+        BuilderImplWithParent(${impl_class} parentMessage) {
+            this.parentMessage = parentMessage;
+        }
+
+//:: for prop in msg.all_properties():
+        @Override
+        public ${prop.java_type.public_type} get${prop.title_name}()${ "" if msg.property_in_version(prop, version) else " throws UnsupportedOperationException"} {
+//:: if msg.property_in_version(prop, version):
+            return ${prop.name};
+//:: else:
+            throw new UnsupportedOperationException("Property ${prop.name} not supported in version #{version}");
+//:: #endif
+        }
+        @Override
+        public ${msg.interface_name}.Builder set${prop.title_name}(${prop.java_type.public_type} ${prop.name})${ "" if msg.property_in_version(prop, version) else " throws UnsupportedOperationException"} {
+//:: if msg.property_in_version(prop, version):
+            this.${prop.name} = ${prop.name};
+            this.${prop.name}Set = true;
+            return this;
+//:: else:
+        throw new UnsupportedOperationException("Property ${prop.name} not supported in version #{version}");
+//:: #endif
+        }
+//:: #endfor
+        @Override
+        public ${msg.interface_name} getMessage() {
+            if(this.xidSet) {
+                return new ${impl_class}(
+                    ${",\n                      ".join(
+                         [ "xid" ] +
+                         [ "this.{0}Set ? this.{0} : parentMessage.{0}".format(prop.name)
+                             for prop in msg.properties_for_version(version)])}
+                    );
+            } else {
+                return new ${impl_class}(
+                    ${",\n                      ".join(
+                         [ "this.{0}Set ? this.{0} : parentMessage.{0}".format(prop.name)
+                             for prop in msg.properties_for_version(version)])}
+                    );
+            }
+        }
+    }
+
+    static class BuilderImpl implements ${msg.interface_name}.Builder {
+        private boolean xidSet;
+        private int xid;
+
+        // OF message fields
+//:: for prop in msg.properties_for_version(version):
+        private boolean ${prop.name}Set;
+        private ${prop.java_type.public_type} ${prop.name};
+//:: #endfor
+
+//:: for prop in msg.all_properties():
+        @Override
+        public ${prop.java_type.public_type} get${prop.title_name}()${ "" if msg.property_in_version(prop, version) else " throws UnsupportedOperationException"} {
+//:: if msg.property_in_version(prop, version):
+            return ${prop.name};
+//:: else:
+            throw new UnsupportedOperationException("Property ${prop.name} not supported in version #{version}");
+//:: #endif
+        }
+        @Override
+        public ${msg.interface_name}.Builder set${prop.title_name}(${prop.java_type.public_type} ${prop.name})${ "" if msg.property_in_version(prop, version) else " throws UnsupportedOperationException"} {
+//:: if msg.property_in_version(prop, version):
+            this.${prop.name} = ${prop.name};
+            this.${prop.name}Set = true;
+            return this;
+//:: else:
+        throw new UnsupportedOperationException("Property ${prop.name} not supported in version #{version}");
+//:: #endif
+        }
+//:: #endfor
+        @Override
+        public ${msg.interface_name} getMessage() {
+            if(this.xidSet) {
+                return new ${impl_class}(
+                    ${",\n                      ".join(
+                         [ "xid" ] +
+                         [ "this.{0}Set ? this.{0} : {1}.{2}".format(prop.name, impl_class, prop.default_name)
+                             for prop in msg.properties_for_version(version)])}
+                    );
+            } else {
+                return new ${impl_class}(
+                    ${",\n                      ".join(
+                         [ "this.{0}Set ? this.{0} : {1}.{2}".format(prop.name, impl_class, prop.default_name)
+                             for prop in msg.properties_for_version(version)])}
+                    );
+            }
+        }
+    }
+
+    final static Reader READER = new Reader();
+    static class Reader implements OFMessageReader<${msg.interface_name}> {
+        @Override
+        public ${msg.interface_name} readFrom(ChannelBuffer bb) throws OFParseError {
+            byte version = bb.readByte();
+            if (version != (byte) ${version.int_version})
+                throw new OFParseError("Wrong version: Expected=${version.int_version}, got="+version);
+
+            byte type = bb.readByte();
+            if(type != ${msg.wire_type(version)})
+                throw new OFParseError("Wrong message type: Expected=${msg.constant_name}, got="+type);
+
+            int length = bb.readUnsignedShort();
+//:: if msg.is_fixed_length(version):
+            if(length != LENGTH)
+                throw new OFParseError("Wrong message length: Expected="+LENGTH +", got="+length);
+//:: else:
+            if(length < MINIMUM_LENGTH)
+                throw new OFParseError("Insufficient message length: minimum length="+MINIMUM_LENGTH +", got="+length);
+//:: #endif
+            int xid = bb.readInt();
+//:: for prop in msg.properties_for_version(version, skip_pads=False):
+//:: if prop.is_pad:
+            // pad: ${prop.length} bytes
+            bb.skipBytes(${prop.length});
+//:: else:
+            ${prop.java_type.public_type} ${prop.name} = ${prop.java_type.read_op(version)};
+//:: #endif
+//:: #endfor
+                return new ${impl_class}(
+                    ${",\n                      ".join(
+                         [ "xid" ] + [ prop.name for prop in msg.properties_for_version(version)])}
+                    );
+        }
+    }
+
+}
diff --git a/java_gen/templates/message_interface.java b/java_gen/templates/message_interface.java
new file mode 100644
index 0000000..904be95
--- /dev/null
+++ b/java_gen/templates/message_interface.java
@@ -0,0 +1,63 @@
+//:: # 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;
+import java.util.List;
+import org.openflow.protocol.match.*;
+import org.openflow.protocol.actions.OFAction;
+import org.openflow.protocol.instructions.OFInstruction;
+import org.openflow.types.*;
+import org.openflow.util.*;
+import org.openflow.exceptions.OFUnsupported;
+
+public interface ${msg.interface_name} extends OFMessage {
+    int getXid();
+    boolean isXidSet();
+    OFType getType();
+    OFVersion getVersion();
+
+//:: for prop in msg.all_properties():
+    ${prop.java_type.public_type} get${prop.title_name}()${ "" if prop.is_universal else "throws UnsupportedOperationException"};
+//:: #endfor
+
+    Builder createBuilder();
+
+    public interface Builder {
+        ${msg.interface_name} getMessage();
+//:: for prop in msg.all_properties():
+        ${prop.java_type.public_type} get${prop.title_name}()${ "" if prop.is_universal else "throws UnsupportedOperationException"};
+        Builder set${prop.title_name}(${prop.java_type.public_type} ${prop.name})${ "" if prop.is_universal else " throws UnsupportedOperationException"};
+//:: #endfor
+
+    }
+}
diff --git a/java_gen/templates/of_type.java b/java_gen/templates/of_type.java
new file mode 100644
index 0000000..951a648
--- /dev/null
+++ b/java_gen/templates/of_type.java
@@ -0,0 +1,51 @@
+//:: # 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.types;
+
+import org.openflow.protocol.OFVersion;
+
+public enum OFType {
+//:: for i, msg in enumerate(all_messages):
+     ${msg.constant_name}(new byte[] { ${ ", ".join( [str(msg.wire_type(version)) for version in all_versions ]) } } )${ ", " if i < len(all_messages)-1 else ";" }
+//:: #endfor
+
+    byte[] wireTypes;
+    OFType(byte[] wireTypes) {
+        this.wireTypes = wireTypes;
+    }
+
+    public byte getWireType(OFVersion version) {
+        return this.wireTypes[version.getWireVersion()];
+    }
+}
diff --git a/java_gen/test.sh b/java_gen/test.sh
new file mode 100755
index 0000000..7b71ffd
--- /dev/null
+++ b/java_gen/test.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+rm -rf target_code/
+cd ..
+./loxigen.py -ljava #&& ( cd target_code/Modules/openflowj/ && ant  )
diff --git a/lang_java.py b/lang_java.py
new file mode 100644
index 0000000..db23c82
--- /dev/null
+++ b/lang_java.py
@@ -0,0 +1,76 @@
+# 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.
+
+"""
+@brief Java language specific LOXI generating configuration
+
+This language specific file defines:
+
+target_files:  List of internal references to files to generate
+file_gen_map: The map from above file references to generator functions
+file_to_name_map: The map from internal references to external file names
+file_to_subdir_map: The map from internal references to external subdirectories
+
+HOWEVER, since java files are all a function of their class name, we don't
+know in advance what the names of the files/classes will be, so we just
+define a single directory and generate everything in there.
+    @fixme talk to DanT to see if there isn't something that makes more sense
+
+"""
+
+import java_gen.java_code_gen as java_code_gen
+
+
+targets = {
+    'base_java': java_code_gen.gen_all_java
+}
+
+##
+# The list of files to produce.  These are the keywords used to index
+# the arrays below giving the external file names, the subdirectory locations
+# and the generating functions.
+
+target_files =  ["base_java" ]
+# Internal file name references to actual file names
+file_to_name_map = dict(
+    # LOCI source
+    base_java="README.openflowj", # not really used by java generator
+)
+
+##
+# The map from the internal file identifier to the function name
+# that generates the content of the file
+
+file_gen_map = dict(
+    base_java=java_code_gen.gen_all_java,
+)
+
+
+# Map from file references to target sub-directories
+file_to_subdir_map = dict(
+    base_java="openflowj/",
+)