Various improvements for the of classes
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/match/Match.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/Match.java
index 8f17845..cdb34e5 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/protocol/match/Match.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/Match.java
@@ -32,20 +32,20 @@
  * On prerequisites:<br>
  * From the OF1.1 spec, page 28, the OF1.0 spec failed to explicitly specify this, but it
  * is the behavior of OF1.0 switches:
- * "Protocol-specific fields within ofp_match will be ignored within a single table when 
- * the corresponding protocol is not specified in the match. The MPLS match fields will 
- * be ignored unless the Ethertype is specified as MPLS. Likewise, the IP header and 
- * transport header fields will be ignored unless the Ethertype is specified as either 
- * IPv4 or ARP. The tp_src and tp_dst fields will be ignored unless the network protocol 
- * specified is as TCP, UDP or SCTP. Fields that are ignored donÕt need to be wildcarded 
+ * "Protocol-specific fields within ofp_match will be ignored within a single table when
+ * the corresponding protocol is not specified in the match. The MPLS match fields will
+ * be ignored unless the Ethertype is specified as MPLS. Likewise, the IP header and
+ * transport header fields will be ignored unless the Ethertype is specified as either
+ * IPv4 or ARP. The tp_src and tp_dst fields will be ignored unless the network protocol
+ * specified is as TCP, UDP or SCTP. Fields that are ignored don�t need to be wildcarded
  * and should be set to 0."
  * <br><br>
- * This interface uses generics to assure type safety in users code. However, implementing classes may have to suppress 
+ * This interface uses generics to assure type safety in users code. However, implementing classes may have to suppress
  * 'unchecked cast' warnings while making sure they correctly cast base on their implementation details.
- * 
+ *
  * @author Yotam Harchol (yotam.harchol@bigswitch.com)
  */
-public interface Match extends OFObject {    
+public interface Match extends OFObject {
 
     /**
      * Returns a value for the given field if:
@@ -55,7 +55,7 @@
      * <li>Prerequisites are ok
      * </ul>
      * If one of the above conditions does not hold, returns null. Value is returned masked if partially wildcarded.
-     * 
+     *
      * @param field Match field to retrieve
      * @return Value of match field (may be masked), or <code>null</code> if field is one of the conditions above does not hold.
      * @throws UnsupportedOperationException If field is not supported.
@@ -66,7 +66,7 @@
      * Returns the masked value for the given field from this match, along with the mask itself.
      * Prerequisite: field is partially masked.
      * If prerequisite is not met, a <code>null</code> is returned.
-     * 
+     *
      * @param field Match field to retrieve.
      * @return Masked value of match field or null if no mask is set.
      * @throws UnsupportedOperationException If field is not supported.
@@ -75,7 +75,7 @@
 
     /**
      * Returns true if and only if this match object supports the given match field.
-     * 
+     *
      * @param field Match field
      * @return true if field is supported, false otherwise.
      */
@@ -84,7 +84,7 @@
     /**
      * Returns true if and only if this match object supports partially bitmasking of the given field.
      * (note: not all possible values of this bitmask have to be acceptable)
-     * 
+     *
      * @param field Match field.
      * @return true if field can be partially masked, false otherwise.
      * @throws UnsupportedOperationException If field is not supported.
@@ -94,7 +94,7 @@
     /**
      * Returns true if and only if this field is currently specified in the match with an exact value and
      * no mask. I.e., the specified match will only select packets that match the exact value of getValue(field).
-     * 
+     *
      * @param field Match field.
      * @return true if field has a specific exact value, false if not.
      * @throws UnsupportedOperationException If field is not supported.
@@ -102,10 +102,10 @@
     public boolean isExact(MatchField<?> field) throws UnsupportedOperationException;
 
     /**
-     * True if and only if this field is currently logically unspecified in the match, i.e, the 
-     * value returned by getValue(f) has no impact on whether a packet will be selected 
+     * True if and only if this field is currently logically unspecified in the match, i.e, the
+     * value returned by getValue(f) has no impact on whether a packet will be selected
      * by the match or not.
-     * 
+     *
      * @param field Match field.
      * @return true if field is fully wildcarded, false if not.
      * @throws UnsupportedOperationException If field is not supported.
@@ -113,16 +113,16 @@
     public boolean isFullyWildcarded(MatchField<?> field) throws UnsupportedOperationException;
 
     /**
-     * True if and only if this field is currently partially specified in the match, i.e, the 
+     * True if and only if this field is currently partially specified in the match, i.e, the
      * match will only select packets that match (p.value & getMask(field)) == getValue(field),
      * and getMask(field) != 0.
-     * 
+     *
      * @param field Match field.
      * @return true if field is partially masked, false if not.
      * @throws UnsupportedOperationException If field is not supported.
      */
     public boolean isPartiallyMasked(MatchField<?> field) throws UnsupportedOperationException;
-    
+
     /**
      * Returns a builder to build new instances of this type of match object.
      * @return Match builder
@@ -135,17 +135,17 @@
      * corresponds to. The builder uses the same notation of wildcards and masks, and can also throw
      * <code>UnsupportedOperationException</code> if it is asked to create some matching that is not supported in
      * the version it represents.
-     * 
+     *
      * While used, MatchBuilder may not be consistent in terms of field prerequisites. However, user must
      * solve these before using the generated Match object as these prerequisites should be enforced in the
-     * getters. 
-     * 
+     * getters.
+     *
      * @author Yotam Harchol (yotam.harchol@bigswitch.com)
      */
     interface Builder extends Match {
         /**
          * Sets a specific exact value for a field.
-         * 
+         *
          * @param field Match field to set.
          * @param value Value of match field.
          * @return the Builder instance used.
@@ -155,7 +155,7 @@
 
         /**
          * Sets a masked value for a field.
-         * 
+         *
          * @param field Match field to set.
          * @param value Value of field.
          * @param mask Mask value.
@@ -166,7 +166,7 @@
 
         /**
          * Sets a masked value for a field.
-         * 
+         *
          * @param field Match field to set.
          * @param valueWithMask Compound Masked object contains the value and the mask.
          * @return the Builder instance used.
@@ -176,7 +176,7 @@
 
         /**
          * Unsets any value given for the field and wildcards it so that it matches any value.
-         * 
+         *
          * @param field Match field to unset.
          * @return the Builder instance used.
          * @throws UnsupportedOperationException If field is not supported.
@@ -185,9 +185,9 @@
 
         /**
          * Returns the match created by this builder.
-         * 
+         *
          * @return a Match object.
          */
-        public Match getMatch();
+        public Match build();
     }
 }
\ No newline at end of file
diff --git a/java_gen/templates/_field_accessors.java b/java_gen/templates/_field_accessors.java
index e8afe47..b64b29b 100644
--- a/java_gen/templates/_field_accessors.java
+++ b/java_gen/templates/_field_accessors.java
@@ -1,6 +1,6 @@
 //:: for prop in msg.interface.members:
     @Override
-    public ${prop.java_type.public_type} get${prop.title_name}()${ "" if prop in msg.members else "throws UnsupportedOperationException"} {
+    public ${prop.java_type.public_type} ${prop.getter_name}()${ "" if prop in msg.members else "throws UnsupportedOperationException"} {
 //:: if prop in msg.members:
 //::    version_prop = msg.get_member(prop.name)
 //::    if version_prop.is_fixed_value:
@@ -20,7 +20,7 @@
 
 //:: if generate_setters and prop.is_writeable:
     @Override
-    public ${msg.interface.name}.Builder set${prop.title_name}(${prop.java_type.public_type} ${prop.name})${ "" if prop in msg.members else " throws UnsupportedOperationException"} {
+    public ${msg.interface.name}.Builder ${prop.setter_name}(${prop.java_type.public_type} ${prop.name})${ "" if prop in msg.members else " throws UnsupportedOperationException"} {
 //:: if prop in msg.members:
         this.${prop.name} = ${prop.name};
         this.${prop.name}Set = true;
diff --git a/java_gen/templates/of_class.java b/java_gen/templates/of_class.java
index 43d9893..bcaf961 100644
--- a/java_gen/templates/of_class.java
+++ b/java_gen/templates/of_class.java
@@ -37,7 +37,7 @@
 
 //:: include("_imports.java", msg=msg)
 
-class ${impl_class} implements ${msg.interface.name} {
+class ${impl_class} implements ${msg.interface.inherited_declaration()} {
     // version: ${version}
     private final static byte WIRE_VERSION = ${version.int_version};
 //:: if msg.is_fixed_length:
@@ -55,20 +55,29 @@
     private final ${prop.java_type.public_type} ${prop.name};
 //:: #endfor
 
+    //:: if msg.data_members:
+    // package private constructor - used by readers, builders, and factory
     ${impl_class}(${
         ", ".join("%s %s" %(prop.java_type.public_type, prop.name) for prop in msg.data_members) }) {
 //:: for prop in msg.data_members:
         this.${prop.name} = ${prop.name};
 //:: #endfor
     }
+    //:: else:
+    final static ${impl_class} INSTANCE = new ${impl_class}();
+    // private empty constructor - use shared instance!
+    private ${impl_class}() {
+    }
+    //:: #endif
 
     // Accessors for OF message fields
-//:: include("_field_accessors.java", msg=msg, generate_setters=False, builder=False)
+    //:: include("_field_accessors.java", msg=msg, generate_setters=False, builder=False)
 
     //:: if os.path.exists("%s/custom/%s.java" % (template_dir, msg.name)):
     //:: include("custom/%s.java" % msg.name, msg=msg)
     //:: #endif
 
+    //:: if msg.data_members:
     public ${msg.interface.name}.Builder createBuilder() {
         return new BuilderWithParent(this);
     }
@@ -89,7 +98,7 @@
 //:: include("_field_accessors.java", msg=msg, generate_setters=True, builder=True)
 
         @Override
-        public ${msg.interface.name} getMessage() {
+        public ${msg.interface.name} build() {
                 return new ${impl_class}(
                     ${",\n                      ".join(
                          [ "this.{0}Set ? this.{0} : parentMessage.{0}".format(prop.name)
@@ -112,7 +121,7 @@
 //:: include("_field_accessors.java", msg=msg, generate_setters=True, builder=True)
 //
         @Override
-        public ${msg.interface.name} getMessage() {
+        public ${msg.interface.name} build() {
             return new ${impl_class}(
                 ${",\n                      ".join(
                      [ "this.{0}Set ? this.{0} : {1}.{2}".format(prop.name, impl_class, prop.default_name)
@@ -124,6 +133,13 @@
         //:: #endif
 
     }
+    //:: else:
+    // no data members - do not support builder
+    public ${msg.interface.name}.Builder createBuilder() {
+        throw new UnsupportedOperationException("${impl_class} has no mutable properties -- builder unneeded");
+    }
+    //:: #endif
+
 
     final static Reader READER = new Reader();
     static class Reader implements OFMessageReader<${msg.interface.name}> {
@@ -132,7 +148,9 @@
             int start = bb.readerIndex();
 //:: fields_with_length_member = {}
 //:: for prop in msg.members:
-//:: if prop.is_data:
+//:: if prop.is_virtual:
+//::    continue
+//:: elif prop.is_data:
             ${prop.java_type.public_type} ${prop.name} = ${prop.java_type.read_op(version, pub_type=True,
                     length=fields_with_length_member[prop.c_name] if prop.c_name in fields_with_length_member else None)};
 //:: elif prop.is_pad:
@@ -159,10 +177,14 @@
             bb.skipBytes(((length + ${msg.align-1})/${msg.align} * ${msg.align} ) - length );
             //:: #endif
 
+            //:: if msg.data_members:
             return new ${impl_class}(
                     ${",\n                      ".join(
                          [ prop.name for prop in msg.data_members])}
                     );
+            //:: else:
+            return INSTANCE;
+            //:: #endif
         }
     }
 
@@ -180,7 +202,9 @@
 //:: if prop.c_name in fields_with_length_member:
             int ${prop.name}StartIndex = bb.writerIndex();
 //:: #endif
-//:: if prop.is_data:
+//:: if prop.is_virtual:
+//::    continue
+//:: elif prop.is_data:
             ${prop.java_type.write_op(version, "message." + prop.name, pub_type=True)};
 //:: elif prop.is_pad:
             // pad: ${prop.length} bytes