Reorganized OFFactories
diff --git a/java_gen/templates/_imports.java b/java_gen/templates/_imports.java
index 5b86571..a4c564c 100644
--- a/java_gen/templates/_imports.java
+++ b/java_gen/templates/_imports.java
@@ -1,6 +1,7 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 import org.openflow.protocol.*;
 import org.openflow.protocol.action.*;
 import org.openflow.protocol.meterband.*;
diff --git a/java_gen/templates/of_factories.java b/java_gen/templates/of_factories.java
index cce134d..9225510 100644
--- a/java_gen/templates/of_factories.java
+++ b/java_gen/templates/of_factories.java
@@ -40,7 +40,7 @@
         switch(version) {
             //:: for v in versions:
             case ${v.constant_version}:
-                return org.openflow.protocol.ver${v.of_version}.OFFactoryVer${v.of_version}.getInstance();
+                return org.openflow.protocol.ver${v.of_version}.OFFactoryVer${v.of_version}.INSTANCE;
             //:: #endfor
             default:
                 throw new IllegalArgumentException("Unknown version: "+version);
diff --git a/java_gen/templates/of_factory_class.java b/java_gen/templates/of_factory_class.java
index fec0bcf..e83344b 100644
--- a/java_gen/templates/of_factory_class.java
+++ b/java_gen/templates/of_factory_class.java
@@ -36,25 +36,53 @@
 //:: include("_imports.java")
 
 public class ${factory.name} implements ${factory.interface.name} {
+    public final static ${factory.name} INSTANCE = new ${factory.name}();
+    private ${factory.name}() {}
+
+    //:: for name, clazz in factory.interface.sub_factories.items():
+    public ${clazz} ${name}() {
+        return ${clazz}Ver${factory.version.of_version}.INSTANCE;
+    }
+    //:: #endfor
+
 //:: for i in factory.interface.members:
     //:: if i.is_virtual:
     //::    continue
     //:: #endif
 
-//::   if i.has_version(factory.version) and model.generate_class(i.versioned_class(factory.version)):
-    public ${i.name}.Builder create${i.name[2:]}Builder() {
+    //:: if len(i.writeable_members) > 0:
+    public ${i.name}.Builder ${factory.interface.method_name(i, builder=True)}() {
+        //::   if i.has_version(factory.version) and model.generate_class(i.versioned_class(factory.version)):
         return new ${i.versioned_class(factory.version).name}.Builder();
-    }
-//:: else:
-    public ${i.name}.Builder create${i.name[2:]}Builder() throws UnsupportedOperationException {
+        //:: else:
         throw new UnsupportedOperationException("${i.name} not supported in version ${factory.version}");
+        //:: #endif
     }
-//:: #endif
+    //:: #endif
+    //:: if len(i.writeable_members) <= 2:
+    public ${i.name} ${factory.interface.method_name(i, builder=False)}(${", ".join("%s %s" % (p.java_type.public_type, p.name) for p in i.writeable_members)}) {
+        //::   if i.has_version(factory.version) and model.generate_class(i.versioned_class(factory.version)):
+        //:: if len(i.writeable_members) > 0:
+        return new ${i.versioned_class(factory.version).name}(
+                ${",\n                      ".join(
+                         [ prop.name for prop in i.versioned_class(factory.version).data_members])}
+                    );
+        //:: else:
+        return ${i.versioned_class(factory.version).name}.INSTANCE;
+        //:: #endif
+        //:: else:
+        throw new UnsupportedOperationException("${i.name} not supported in version ${factory.version}");
+        //:: #endif
+    }
+    //:: #endif
 //:: #endfor
 
-    public OFMessageReader<OFMessage> getMessageReader() {
-        return OFMessageVer${factory.version.of_version}.READER;
+    public OFMessageReader<${factory.base_class}> getReader() {
+//:: if factory.versioned_base_class:
+        return ${factory.versioned_base_class.name}.READER;
+//:: else:
+        throw new UnsupportedOperationException("Reader<${factory.base_class}> not supported in version ${factory.version}");
+//:: #endif
     }
 
-    //:: include("_singleton.java", msg=factory)
 }
diff --git a/java_gen/templates/of_factory_interface.java b/java_gen/templates/of_factory_interface.java
index 39432a8..fcb690f 100644
--- a/java_gen/templates/of_factory_interface.java
+++ b/java_gen/templates/of_factory_interface.java
@@ -31,17 +31,27 @@
 
 //:: include('_autogen.java')
 
-package org.openflow.protocol;
+package ${factory.package};
 
 //:: include("_imports.java")
 
 public interface ${factory.name} {
+    // Subfactories
+//:: for name, clazz in factory.sub_factories.items():
+    ${clazz} ${name}();
+//:: #endfor
+
 //:: for i in factory.members:
     //:: if i.is_virtual:
     //::    continue
     //:: #endif
-    ${i.name}.Builder create${i.name[2:]}Builder()${ "" if i.is_universal else " throws UnsupportedOperationException"};
+    //:: if len(i.writeable_members) > 0:
+    ${i.name}.Builder ${factory.method_name(i, builder=True)}()${ "" if i.is_universal else " throws UnsupportedOperationException"};
+    //:: #endif
+    //:: if len(i.writeable_members) <= 2:
+    ${i.name} ${factory.method_name(i, builder=False )}(${", ".join("%s %s" % (p.java_type.public_type, p.name) for p in i.writeable_members)});
+    //:: #endif
 //:: #endfor
 
-    OFMessageReader<OFMessage> getMessageReader();
+    OFMessageReader<${factory.base_class}> getReader();
 }
diff --git a/java_gen/templates/unit_test.java b/java_gen/templates/unit_test.java
index 45472f2..47dcc24 100644
--- a/java_gen/templates/unit_test.java
+++ b/java_gen/templates/unit_test.java
@@ -55,9 +55,9 @@
     //:: if "java" in test_data:
     @Test
     public void testWrite() {
-        ${var_type}.Builder builder = factory.create${var_type[2:]}Builder();
+        ${var_type}.Builder builder = factory.build${var_type[2:]}();
         ${test_data["java"]};
-        ${var_type} ${var_name} = builder.getMessage();
+        ${var_type} ${var_name} = builder.build();
         ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
         ${var_name}.writeTo(bb);
         byte[] written = new byte[bb.readableBytes()];
@@ -68,9 +68,9 @@
 
     @Test
     public void testRead() throws Exception {
-        ${var_type}.Builder builder = factory.create${var_type[2:]}Builder();
+        ${var_type}.Builder builder = factory.build${var_type[2:]}();
         ${test_data["java"]};
-        ${var_type} ${var_name}Built = builder.getMessage();
+        ${var_type} ${var_name}Built = builder.build();
 
         ChannelBuffer input = ChannelBuffers.copiedBuffer(${msg.constant_name}_SERIALIZED);