1. Removed type serializers, added (write|read)[0-9]*Byte[s]?(ChannelBuffer) method to value types instead.
2. Updated Masked fields for IPv4, IPv6 with specific string methods.
3. Added value types for other fields from the spec
4. Updated unit tests accordingly
5. Changed java_type.py to support multiple read/write operations per type, per OF version.
diff --git a/java_gen/java_type.py b/java_gen/java_type.py
index e88458a..8580f37 100644
--- a/java_gen/java_type.py
+++ b/java_gen/java_type.py
@@ -21,6 +21,19 @@
         return camel
 
 
+ANY = 0xFFFFFFFFFFFFFFFF
+
+
+class VersionOp:
+    def __init__(self, version=ANY, read=None, write=None):
+        self.version = version
+        self.read = read
+        self.write = write
+        
+    def __str__(self):
+        return "[Version: %d, Read: '%s', Write: '%s']" % (self.version, self.read, self.write)
+
+
 class JType(object):
     """ Wrapper class to hold C to Java type conversion information """
     def __init__(self, pub_type, priv_type=None, size=None, read_op=None, write_op=None):
@@ -29,12 +42,17 @@
             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(bb)' % self.pub_type
-        if write_op is None:
-            write_op = 'ChannelUtils.write%s(bb, $name)'  % self.pub_type
-        self._read_op = read_op
-        self._write_op = write_op
+        self.ops = {}
+#        if read_op is None:
+#            read_op = 'ChannelUtils.read%s(bb)' % self.pub_type
+#        if write_op is None:
+#            write_op = 'ChannelUtils.write%s(bb, $name)'  % self.pub_type
+#        self._read_op = read_op
+#        self._write_op = write_op
+
+    def op(self, version=ANY, read=None, write=None):
+        self.ops[version] = VersionOp(version, read, write)
+        return self
 
     @property
     def public_type(self):
@@ -53,105 +71,111 @@
         if length is None:
             length = "length - bb.readerIndex()";
 
-        if callable(self._read_op):
-            return self._read_op(version)
+        ver = ANY if version is None else version.int_version
+        _read_op = None
+        if ver in self.ops:
+            _read_op = self.ops[ver].read or self.ops[ANY].read 
+        elif ANY in self.ops:
+            _read_op = self.ops[ANY].read
+        if _read_op is None:
+            _read_op = 'ChannelUtils.read%s(bb)' % self.pub_type
+        if callable(_read_op):
+            return _read_op(version)
         else:
-            return self._read_op.replace("$length", str(length)).replace("$version", version.of_version)
+            return _read_op.replace("$length", str(length)).replace("$version", version.of_version)
 
     def write_op(self, version=None, name=None):
-        if callable(self._write_op):
-            return self._write_op(version, name)
+        ver = ANY if version is None else version.int_version
+        _write_op = None
+        if ver in self.ops:
+            _write_op = self.ops[ver].write or self.ops[ANY].write
+        elif ANY in self.ops:
+            _write_op = self.ops[ANY].write
+        if _write_op is None:
+            _write_op = 'ChannelUtils.write%s(bb, $name)' % self.pub_type
+        if callable(_write_op):
+            return _write_op(version, name)
         else:
-            return self._write_op.replace("$name", str(name)).replace("$version", version.of_version)
+            return _write_op.replace("$name", str(name)).replace("$version", version.of_version)
 
-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)')
-u8_list =  JType('List<U8>',  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)')
-u32_list = JType('List<U32>', '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.getValue())')
-of_port= JType('OFPort',size=None,
-        read_op = "OFPort.SERIALIZER_V$version.readFrom(bb)",
-        write_op = "OFPort.SERIALIZER_V$version.writeTo($name, 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)',
-        write_op = 'ChannelUtils.writeActionsList(bb, $name);')
-instructions_list = JType('List<OFInstruction>', size='ChannelUtils.calcListSize($name)',
-        read_op = 'ChannelUtils.readInstructionsList(bb, $length)',
-        write_op = 'ChannelUtils.writeList(bb, $name)')
-buckets_list = JType('List<OFBucket>', size='ChannelUtils.calcListSize($name)',
-        read_op = 'ChannelUtils.readBucketList(bb, $length)',
-        write_op = 'ChannelUtils.writeList(bb, $name)')
-port_desc_list = JType('List<OFPhysicalPort>', size='ChannelUtils.calcListSize($name)',
-        read_op = 'ChannelUtils.readPhysicalPortList(bb, $length)',
-        write_op = 'ChannelUtils.writeList(bb, $name)')
-port_desc = JType('OFPortDesc', size='$name.getLength()',
-        read_op = 'null; // TODO OFPortDescVer$version.READER.read(bb)',
-        write_op = '$name.writeTo(bb)')
-packet_queue_list = JType('List<OFPacketQueue>', size='ChannelUtils.calcListSize($name)',
-        read_op = 'ChannelUtils.readPacketQueueList(bb, $length)',
-        write_op = 'ChannelUtils.writeList(bb, $name)')
-octets = JType('byte[]', size="$length",
-        read_op = 'ChannelUtils.readBytes(bb, $length)',
-        write_op = 'bb.writeBytes($name)')
-of_match = JType('Match', size="$name.getLength()",
-        read_op = 'ChannelUtils.readOFMatch(bb)',
-        write_op = 'ChannelUtils.writeOFMatch(bb, $name)')
-flow_mod_cmd = JType('OFFlowModCommand', 'short', size="$name.getLength()",
-        read_op = lambda v: "bb.readShort()" if v.int_version == 1 else "bb.readByte()",
-        write_op = lambda v, name: "bb.writeShort(%s)" % name if v.int_version == 1 else "bb.writeByte(%s)" % name)
-mac_addr = JType('MacAddress', 'byte[]', size=6,
-        read_op = "MacAddress.SERIALIZER_V$version.readFrom(bb)",
-        write_op = "MacAddress.SERIALIZER_V$version.writeTo($name, bb)")
-port_name = JType('String', size=16,
-        read_op = 'ChannelUtils.readFixedLengthString(bb, 16)',
-        write_op = 'ChannelUtils.writeFixedLengthString(bb, $name, 16)')
-desc_str = JType('String', size=256,
-        read_op = 'ChannelUtils.readFixedLengthString(bb, 256)',
-        write_op = 'ChannelUtils.writeFixedLengthString(bb, $name, 256)')
-serial_num = JType('String', size=32,
-        read_op = 'ChannelUtils.readFixedLengthString(bb, 32)',
-        write_op = 'ChannelUtils.writeFixedLengthString(bb, $name, 32)')
-table_name = JType('String', size=32,
-        read_op = 'ChannelUtils.readFixedLengthString(bb, 32)',
-        write_op = 'ChannelUtils.writeFixedLengthString(bb, $name, 32)')
-ipv4 = JType("IPv4",
-        read_op = "IPv4.SERIALIZER_V$version.readFrom(bb)",
-        write_op = "IPv4.SERIALIZER_V$version.writeTo($name, bb)")
-ipv6 = JType("IPv6",
-        read_op = "IPv6.SERIALIZER_V$version.readFrom(bb)",
-        write_op = "IPv6.SERIALIZER_V$version.writeTo($name, bb)")
+hello_elem_list = JType("List<OFHelloElement>") \
+        .op(read='ChannelUtils.readHelloElementList(bb)', write='ChannelUtils.writeHelloElementList(bb)')
+u8 =  JType('byte',  size=1) \
+        .op(read='bb.readByte()', write='bb.writeByte($name)')
+u8_list =  JType('List<U8>',  size=1) \
+        .op(read='bb.readByte()', write='bb.writeByte($name)')
+u16 = JType('int', 'int', size=2) \
+        .op(read='U16.f(bb.readShort())', write='bb.writeShort(U16.t($name))')
+u32 = JType('int', 'int', size=4) \
+        .op(read='bb.readInt()', write='bb.writeInt($name)')
+u32_list = JType('List<U32>', 'int[]', size=4) \
+        .op(read='bb.readInt()', write='bb.writeInt($name)')
+u64 = JType('U64', 'U64', size=8) \
+        .op(read='U64.of(bb.readLong())', write='bb.writeLong($name.getValue())')
+of_port = JType("OFPort") \
+         .op(version=1, read="OFPort.read2Bytes(bb)", write="$name.write2Bytes(bb)") \
+         .op(version=ANY, read="OFPort.read4Bytes(bb)", write="$name.write4Bytes(bb)")
+one_byte_array = JType('byte[]', size=1) \
+        .op(read='ChannelUtils.readBytes(bb, 1)', write='ChannelUtils.writeBytes(bb, $name)')
+two_byte_array = JType('byte[]', size=2) \
+        .op(read='ChannelUtils.readBytes(bb, 2)', write='ChannelUtils.writeBytes(bb, $name)')
+three_byte_array = JType('byte[]', size=3) \
+        .op(read='ChannelUtils.readBytes(bb, 3)', write='ChannelUtils.writeBytes(bb, $name)')
+four_byte_array = JType('byte[]', size=4) \
+        .op(read='ChannelUtils.readBytes(bb, 4)', write='ChannelUtils.writeBytes(bb, $name)')
+five_byte_array = JType('byte[]', size=5) \
+        .op(read='ChannelUtils.readBytes(bb, 5)', write='ChannelUtils.writeBytes(bb, $name)')
+six_byte_array = JType('byte[]', size=6) \
+        .op(read='ChannelUtils.readBytes(bb, 6)', write='ChannelUtils.writeBytes(bb, $name)')
+seven_byte_array = JType('byte[]', size=7) \
+        .op(read='ChannelUtils.readBytes(bb, 7)', write='ChannelUtils.writeBytes(bb, $name)')
+actions_list = JType('List<OFAction>', size='ChannelUtils.calcListSize($name)') \
+        .op(read='ChannelUtils.readActionsList(bb, $length)', write='ChannelUtils.writeActionsList(bb, $name);')
+instructions_list = JType('List<OFInstruction>', size='ChannelUtils.calcListSize($name)') \
+        .op(read='ChannelUtils.readInstructionsList(bb, $length)', \
+            write='ChannelUtils.writeList(bb, $name)')
+buckets_list = JType('List<OFBucket>', size='ChannelUtils.calcListSize($name)') \
+        .op(read='ChannelUtils.readBucketList(bb, $length)', \
+            write='ChannelUtils.writeList(bb, $name)')
+port_desc_list = JType('List<OFPhysicalPort>', size='ChannelUtils.calcListSize($name)') \
+        .op(read='ChannelUtils.readPhysicalPortList(bb, $length)', \
+            write='ChannelUtils.writeList(bb, $name)')
+port_desc = JType('OFPortDesc', size='$name.getLength()') \
+        .op(read='null; // TODO OFPortDescVer$version.READER.read(bb)', \
+            write='$name.writeTo(bb)')
+packet_queue_list = JType('List<OFPacketQueue>', size='ChannelUtils.calcListSize($name)') \
+        .op(read='ChannelUtils.readPacketQueueList(bb, $length)', \
+            write='ChannelUtils.writeList(bb, $name)')
+octets = JType('byte[]', size="$length") \
+        .op(read='ChannelUtils.readBytes(bb, $length)', \
+            write='bb.writeBytes($name)')
+of_match = JType('Match', size="$name.getLength()") \
+        .op(read='ChannelUtils.readOFMatch(bb)', \
+            write='ChannelUtils.writeOFMatch(bb, $name)')
+flow_mod_cmd = JType('OFFlowModCommand', 'short', size="$name.getLength()") \
+        .op(version=1, read="bb.readShort()", write="bb.writeShort($name)") \
+        .op(version=ANY, read="bb.readByte()", write="bb.writeByte($name)")
+mac_addr = JType('MacAddress', 'byte[]', size=6) \
+        .op(read="MacAddress.read6Bytes(bb)", \
+            write="$name.write6Bytes(bb)")
+port_name = JType('String', size=16) \
+        .op(read='ChannelUtils.readFixedLengthString(bb, 16)', \
+            write='ChannelUtils.writeFixedLengthString(bb, $name, 16)')
+desc_str = JType('String', size=256) \
+        .op(read='ChannelUtils.readFixedLengthString(bb, 256)', \
+            write='ChannelUtils.writeFixedLengthString(bb, $name, 256)')
+serial_num = JType('String', size=32) \
+        .op(read='ChannelUtils.readFixedLengthString(bb, 32)', \
+            write='ChannelUtils.writeFixedLengthString(bb, $name, 32)')
+table_name = JType('String', size=32) \
+        .op(read='ChannelUtils.readFixedLengthString(bb, 32)', \
+            write='ChannelUtils.writeFixedLengthString(bb, $name, 32)')
+ipv4 = JType("IPv4") \
+        .op(read="IPv4.read4Bytes(bb)", \
+            write="$name.write4Bytes(bb)")
+ipv6 = JType("IPv6") \
+        .op(read="IPv6.read16Bytes(bb)", \
+            write="$name.write16Bytes(bb)")
 
 default_mtype_to_jtype_convert_map = {
         'uint8_t' : u8,
@@ -201,10 +225,9 @@
         raise Exception("Not a recgonized standard list type declaration: %s" % c_type)
     base_name = m.group(1)
     java_base_name = name_c_to_caps_camel(base_name)
-    return JType("List<OF%s>" % java_base_name,
-        read_op = 'ChannelUtils.read%sList(bb)' % java_base_name,
-        write_op = 'ChannelUtils.write%sList(bb, $name)' % java_base_name
-        )
+    return JType("List<OF%s>" % java_base_name) \
+        .op(read='ChannelUtils.read%sList(bb)' % java_base_name, \
+            write='ChannelUtils.write%sList(bb, $name)' % java_base_name)
 
 def convert_to_jtype(obj_name, field_name, c_type):
     """ Convert from a C type ("uint_32") to a java type ("U32")
@@ -212,14 +235,14 @@
     if obj_name in exceptions and field_name in exceptions[obj_name]:
         return exceptions[obj_name][field_name]
     elif field_name == "type" and c_type == "uint8_t":
-        return JType("OFType", 'byte', size=1, read_op='bb.readByte()',
-        write_op='bb.writeByte($name)')
+        return JType("OFType", 'byte', size=1) \
+            .op(read='bb.readByte()', write='bb.writeByte($name)')
     elif field_name == "type" and re.match(r'of_action.*', obj_name):
-        return JType("OFActionType", 'short', size=2, read_op='bb.readShort()',
-        write_op='bb.writeShort($name)')
+        return JType("OFActionType", 'short', size=2) \
+            .op(read='bb.readShort()', write='bb.writeShort($name)')
     elif field_name == "version" and c_type == "uint8_t":
-        return JType("OFVersion", 'byte', size=1, read_op='bb.readByte()',
-        write_op='bb.writeByte($name)')
+        return JType("OFVersion", 'byte', size=1) \
+            .op(read='bb.readByte()', write='bb.writeByte($name)')
     elif c_type in default_mtype_to_jtype_convert_map:
         return default_mtype_to_jtype_convert_map[c_type]
     elif re.match(r'list\(of_([a-zA-Z_]+)_t\)', c_type):