Merge into master from pull request #79:
Fixes to java_gen (https://github.com/floodlight/loxigen/pull/79)
diff --git a/java_gen/java_model.py b/java_gen/java_model.py
index f30ab1b..f631483 100644
--- a/java_gen/java_model.py
+++ b/java_gen/java_model.py
@@ -140,7 +140,7 @@
 class JavaModel(object):
     # registry for enums that should not be generated
     # set(${java_enum_name})
-    enum_blacklist = set(("OFDefinitions", "OFPortNo",))
+    enum_blacklist = set(("OFDefinitions", "OFPortNo", "OFVlanId"))
     # registry for enum *entry* that should not be generated
     # map: ${java_enum_name} -> set(${java_entry_entry_name})
     enum_entry_blacklist = defaultdict(lambda: set(), OFFlowWildcards=set([ "NW_DST_BITS", "NW_SRC_BITS", "NW_SRC_SHIFT", "NW_DST_SHIFT" ]))
diff --git a/java_gen/java_type.py b/java_gen/java_type.py
index 82510d2..f50d29a 100644
--- a/java_gen/java_type.py
+++ b/java_gen/java_type.py
@@ -227,7 +227,8 @@
 # FIXME: This list needs to be pruned / cleaned up. Most of these are schematic.
 
 u8 =  JType('short', 'byte') \
-        .op(read='bb.readByte()', write='bb.writeByte($name)')
+        .op(read='U8.f(bb.readByte())', write='bb.writeByte(U8.t($name))', pub_type=True) \
+        .op(read='bb.readByte()', write='bb.writeByte($name)', pub_type=False)
 u8_list =  JType('List<U8>') \
         .op(read='ChannelUtils.readList(bb, $length, U8.READER)', write='ChannelUtils.writeList(bb, $name)')
 u16 = JType('int', 'short') \
@@ -323,9 +324,9 @@
             write="$name.write2Bytes(bb)",
             default="EthType.NONE")
 vlan_vid = JType("VlanVid")\
-        .op(read="VlanVid.read2Bytes(bb)",
-            write="$name.write2Bytes(bb)",
-            default="VlanVid.NONE")
+        .op(version=1, read="VlanVid.read2BytesOF10(bb)", write="$name.write2BytesOF10(bb)", default="VlanVid.NONE") \
+        .op(version=2, read="VlanVid.read2BytesOF10(bb)", write="$name.write2BytesOF10(bb)", default="VlanVid.NONE") \
+        .op(version=ANY, read="VlanVid.read2Bytes(bb)", write="$name.write2Bytes(bb)", default="VlanVid.NONE")
 vlan_pcp = JType("VlanPcp")\
         .op(read="VlanPcp.readByte(bb)",
             write="$name.writeByte(bb)",
@@ -549,6 +550,10 @@
         return JType("OFActionType", 'short') \
             .op(read='bb.readShort()', write='bb.writeShort($name)', pub_type=False)\
             .op(read="OFActionTypeSerializerVer$version.readFrom(bb)", write="OFActionTypeSerializerVer$version.writeTo(bb, $name)", pub_type=True)
+    elif field_name == "type" and re.match(r'of_instruction.*', obj_name):
+        return JType("OFInstructionType", 'short') \
+            .op(read='bb.readShort()', write='bb.writeShort($name)', pub_type=False)\
+            .op(read="OFInstructionTypeSerializerVer$version.readFrom(bb)", write="OFInstructionTypeSerializerVer$version.writeTo(bb, $name)", pub_type=True)
     elif field_name == "table_id" and c_type == "uint8_t":
         return table_id
     elif field_name == "version" and c_type == "uint8_t":
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/Metadata.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ClassId.java
similarity index 73%
rename from java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/Metadata.java
rename to java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ClassId.java
index 4764747..a6f2106 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/Metadata.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ClassId.java
@@ -5,23 +5,23 @@
 import com.google.common.primitives.UnsignedInts;
 
 @Immutable
-public class Metadata implements OFValueType<Metadata> {
+public class ClassId implements OFValueType<ClassId> {
     static final int LENGTH = 4;
 
     private final static int NONE_VAL = 0;
-    public final static Metadata NONE = new Metadata(NONE_VAL);
+    public final static ClassId NONE = new ClassId(NONE_VAL);
 
     private final int rawValue;
 
-    private Metadata(final int rawValue) {
+    private ClassId(final int rawValue) {
         this.rawValue = rawValue;
     }
 
-    public static Metadata of(final int raw) {
+    public static ClassId of(final int raw) {
         if(raw == NONE_VAL)
             return NONE;
 
-        return new Metadata(raw);
+        return new ClassId(raw);
     }
 
     public int getInt() {
@@ -39,8 +39,8 @@
     }
 
     @Override
-    public Metadata applyMask(Metadata mask) {
-        return Metadata.of(rawValue & mask.rawValue);    }
+    public ClassId applyMask(ClassId mask) {
+        return ClassId.of(rawValue & mask.rawValue);    }
 
     @Override
     public int hashCode() {
@@ -58,14 +58,14 @@
             return false;
         if (getClass() != obj.getClass())
             return false;
-        Metadata other = (Metadata) obj;
+        ClassId other = (ClassId) obj;
         if (rawValue != other.rawValue)
             return false;
         return true;
     }
 
     @Override
-    public int compareTo(Metadata o) {
+    public int compareTo(ClassId o) {
         return UnsignedInts.compare(rawValue, rawValue);
     }
 }
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVid.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVid.java
index d6f65d5..6bd7581 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVid.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVid.java
@@ -5,15 +5,45 @@
 
 import com.google.common.primitives.Shorts;
 
+/** Represents an OpenFlow Vlan VID, as specified by the OpenFlow 1.3 spec.
+ *
+ *  <b> Note: this is not just the 12-bit vlan tag. OpenFlow defines
+ *      the additional mask bits 0x1000 to represent the presence of a vlan
+ *      tag. This additional bit will be stripped when writing a OF1.0 value
+ *      tag.
+ *  </b>
+ *
+ *
+ * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+ *
+ */
 public class VlanVid implements OFValueType<VlanVid> {
 
-    private static final short VALIDATION_MASK = 0x0FFF;
+    private static final short VALIDATION_MASK = 0x1FFF;
+    private static final short PRESENT_VAL = 0x1000;
+    private static final short VLAN_MASK = 0x0FFF;
     private static final short NONE_VAL = 0x0000;
+    private static final short UNTAGGED_VAL_OF13 = (short) 0x0000;
+    private static final short UNTAGGED_VAL_OF10 = (short) 0xFFFF;
     final static int LENGTH = 2;
 
+    /** presence of a VLAN tag is idicated by the presence of bit 0x1000 */
+    public static final VlanVid PRESENT = new VlanVid(PRESENT_VAL);
+
+    /** this value means 'not set' in OF1.0 (e.g., in a match). not used elsewhere */
     public static final VlanVid NONE = new VlanVid(NONE_VAL);
+
+    /** for use with masking operations */
     public static final VlanVid NO_MASK = new VlanVid((short)0xFFFF);
-    public static final VlanVid FULL_MASK = VlanVid.of((short)0x0);
+    public static final VlanVid FULL_MASK = NONE;
+
+    /** an untagged packet is specified as 0000 in OF 1.0, but 0xFFFF in OF1.0. Special case that. */
+    public static final VlanVid UNTAGGED = new VlanVid(NONE_VAL) {
+        @Override
+        public void write2BytesOF10(ChannelBuffer c) {
+            c.writeShort(UNTAGGED_VAL_OF10);
+        }
+    };
 
     private final short vid;
 
@@ -21,14 +51,42 @@
         this.vid = vid;
     }
 
-    public static VlanVid of(short vid) {
-        if(vid == NONE_VAL)
-            return NONE;
+    public static VlanVid ofRawVid(short vid) {
+        if(vid == UNTAGGED_VAL_OF13)
+            return UNTAGGED;
+        else if(vid == PRESENT_VAL)
+            return PRESENT;
         else if ((vid & VALIDATION_MASK) != vid)
-            throw new IllegalArgumentException("Illegal VLAN VID value: " + vid);
+            throw new IllegalArgumentException(String.format("Illegal VLAN value: %x", vid));
         return new VlanVid(vid);
     }
 
+    public static VlanVid ofVlan(int vlan) {
+        if( (vlan & VLAN_MASK) != vlan)
+            throw new IllegalArgumentException(String.format("Illegal VLAN value: %x", vlan));
+        return ofRawVid( (short) (vlan | PRESENT_VAL));
+    }
+
+    public static VlanVid ofVlanOF10(short of10vlan) {
+        if(of10vlan == NONE_VAL) {
+            return NONE;
+        } else if(of10vlan == UNTAGGED_VAL_OF10) {
+            return UNTAGGED;
+        } else {
+            return ofVlan(of10vlan);
+        }
+    }
+
+    /** @return whether or not this VlanId has the present (0x1000) bit set */
+    public boolean isPresentBitSet() {
+       return (vid & PRESENT_VAL) != 0;
+    }
+
+    /** @return the actual VLAN tag this vid identifies */
+    public short getVlan() {
+        return (short) (vid & VLAN_MASK);
+    }
+
     @Override
     public boolean equals(Object obj) {
         if (!(obj instanceof VlanVid))
@@ -50,10 +108,11 @@
         return "0x" + Integer.toHexString(vid);
     }
 
-    public short getValue() {
+    public short getRawVid() {
         return vid;
     }
 
+
     @Override
     public int getLength() {
         return LENGTH;
@@ -79,13 +138,21 @@
         c.writeShort(this.vid);
     }
 
+    public void write2BytesOF10(ChannelBuffer c) {
+        c.writeShort(this.getVlan());
+    }
+
     public static VlanVid read2Bytes(ChannelBuffer c) throws OFParseError {
-        return VlanVid.of(c.readShort());
+        return VlanVid.ofRawVid(c.readShort());
+    }
+
+    public static VlanVid read2BytesOF10(ChannelBuffer c) throws OFParseError {
+        return VlanVid.ofVlanOF10(c.readShort());
     }
 
     @Override
     public VlanVid applyMask(VlanVid mask) {
-        return VlanVid.of((short)(this.vid & mask.vid));
+        return VlanVid.ofRawVid((short)(this.vid & mask.vid));
     }
 
     @Override
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVidWithMask.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVidWithMask.java
new file mode 100644
index 0000000..cb81d31
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVidWithMask.java
@@ -0,0 +1,11 @@
+package org.projectfloodlight.openflow.types;
+
+public class VlanVidWithMask extends Masked<VlanVid> {
+    private VlanVidWithMask(VlanVid value, VlanVid mask) {
+        super(value, mask);
+    }
+
+    /* a combination of Vlan Vid and mask that matches any tagged packet */
+    public final static VlanVidWithMask ANY_TAGGED = new VlanVidWithMask(VlanVid.PRESENT, VlanVid.PRESENT);
+
+}
diff --git a/java_gen/templates/of_class.java b/java_gen/templates/of_class.java
index aa68d04..8a8d09d 100644
--- a/java_gen/templates/of_class.java
+++ b/java_gen/templates/of_class.java
@@ -195,27 +195,30 @@
 //:: elif prop.is_pad:
             // pad: ${prop.length} bytes
             bb.skipBytes(${prop.length});
-//:: elif prop.is_fixed_value:
-            // fixed value property ${prop.name} == ${prop.value}
-            ${prop.java_type.priv_type} ${prop.name} = ${prop.java_type.read_op(version, pub_type=False)};
-            if(${prop.name} != ${prop.priv_value})
-                throw new OFParseError("Wrong ${prop.name}: Expected=${prop.enum_value}(${prop.value}), got="+${prop.name});
 //:: elif prop.is_length_value:
-            ${prop.java_type.public_type} ${prop.name} = ${prop.java_type.read_op(version, pub_type=False)};
+            ${prop.java_type.public_type} ${prop.name} = ${prop.java_type.read_op(version, pub_type=True)};
+            //:: if prop.is_fixed_value:
+            if(${prop.name} != ${prop.value})
+                throw new OFParseError("Wrong ${prop.name}: Expected=${prop.enum_value}(${prop.value}), got="+${prop.name});
+            //:: else:
             if(${prop.name} < MINIMUM_LENGTH)
                 throw new OFParseError("Wrong ${prop.name}: Expected to be >= " + MINIMUM_LENGTH + ", was: " + ${prop.name});
-//:: elif prop.is_field_length_value:
-//::        fields_with_length_member[prop.member.field_name] = prop.name
-            int ${prop.name} = ${prop.java_type.read_op(version, pub_type=False)};
-//:: else:
-    // fixme: todo ${prop.name}
-//:: #endif
-//:: if prop.is_length_value or prop.is_field_length_value:
+            //:: #endif
             if(bb.readableBytes() + (bb.readerIndex() - start) < ${prop.name}) {
                 // Buffer does not have all data yet
                 bb.readerIndex(start);
                 return null;
             }
+//:: elif prop.is_fixed_value:
+            // fixed value property ${prop.name} == ${prop.value}
+            ${prop.java_type.priv_type} ${prop.name} = ${prop.java_type.read_op(version, pub_type=False)};
+            if(${prop.name} != ${prop.priv_value})
+                throw new OFParseError("Wrong ${prop.name}: Expected=${prop.enum_value}(${prop.value}), got="+${prop.name});
+//:: elif prop.is_field_length_value:
+//::        fields_with_length_member[prop.member.field_name] = prop.name
+            ${prop.java_type.public_type} ${prop.name} = ${prop.java_type.read_op(version, pub_type=True)};
+//:: else:
+    // fixme: todo ${prop.name}
 //:: #endif
 //:: #endfor
             //:: if msg.align: