java_gen: adapt to of_g removal, new ir
diff --git a/java_gen/java_model.py b/java_gen/java_model.py
index 83c89b5..d124f5a 100644
--- a/java_gen/java_model.py
+++ b/java_gen/java_model.py
@@ -36,16 +36,17 @@
 import re
 
 from generic_utils import find, memoize, OrderedSet, OrderedDefaultDict
-import of_g
+from loxi_globals import OFVersions
+import loxi_globals
 from loxi_ir import *
-import loxi_front_end.type_maps as type_maps
 import loxi_utils.loxi_utils as loxi_utils
-import py_gen.util as py_utils
 import test_data
 
 import java_gen.java_type as java_type
 from java_gen.java_type import erase_type_annotation
 
+logger = logging.getLogger(__name__)
+
 class JavaModel(object):
     # registry for enums that should not be generated
     # set(${java_enum_name})
@@ -227,26 +228,12 @@
     @property
     @memoize
     def versions(self):
-        return OrderedSet( JavaOFVersion(raw_version) for raw_version in of_g.target_version_list )
+        return OrderedSet( JavaOFVersion(ir_version) for ir_version in OFVersions.target_versions)
 
     @property
     @memoize
     def interfaces(self):
-        version_map_per_class = collections.OrderedDict()
-
-        for raw_version, of_protocol in of_g.ir.items():
-            jversion = JavaOFVersion(of_protocol.wire_version)
-
-            for of_class in of_protocol.classes:
-                if not of_class.name in version_map_per_class:
-                    version_map_per_class[of_class.name] = collections.OrderedDict()
-
-                version_map_per_class[of_class.name][jversion] = of_class
-
-        interfaces = []
-        for class_name, version_map in version_map_per_class.items():
-            interfaces.append(JavaOFInterface(class_name, version_map))
-
+        interfaces = [ JavaOFInterface(ir_class) for ir_class in loxi_globals.unified.classes ]
         interfaces = [ i for i in interfaces if i.name not in self.interface_blacklist ]
 
         return interfaces
@@ -266,7 +253,8 @@
         name_version_enum_map = OrderedDefaultDict(lambda: OrderedDict())
 
         for version in self.versions:
-            of_protocol = of_g.ir[version.int_version]
+            logger.info("version: {}".format(version.ir_version))
+            of_protocol = loxi_globals.ir[version.ir_version]
             for enum in of_protocol.enums:
                 name_version_enum_map[enum.name][version] = enum
 
@@ -321,7 +309,7 @@
                         factory.members.append(i)
                         break
         return factories.values()
-    
+
     @memoize
     def factory_of(self, interface):
         for factory in self.of_factories:
@@ -355,8 +343,8 @@
     @property
     def factory_classes(self):
             return [ OFFactoryClass(
-                    package="org.projectfloodlight.openflow.protocol.ver{}".format(version.of_version),
-                    name="{}Ver{}".format(self.name, version.of_version),
+                    package="org.projectfloodlight.openflow.protocol.ver{}".format(version.dotless_version),
+                    name="{}Ver{}".format(self.name, version.dotless_version),
                     interface=self,
                     version=version
                     ) for version in model.versions ]
@@ -370,7 +358,7 @@
             return "build" + n[0].upper() + n[1:]
         else:
             return n
-    
+
     def of_version(self, version):
         for fc in self.factory_classes:
             if fc.version == version:
@@ -400,30 +388,32 @@
 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)
+    def __init__(self, ir_version):
+        assert isinstance(ir_version, OFVersion)
+        self.ir_version = ir_version
+        self.int_version = self.ir_version.wire_version
 
     @property
-    def of_version(self):
-        return "1" + str(int(self.int_version) - 1)
+    def dotless_version(self):
+        return self.ir_version.version.replace(".", "")
 
     @property
     def constant_version(self):
-        return "OF_" + self.of_version
+        return "OF_" + self.dotless_version
 
     def __repr__(self):
         return "JavaOFVersion(%d)" % self.int_version
 
     def __str__(self):
-        return of_g.param_version_names[self.int_version]
+        return self.ir_version.version
 
     def __hash__(self):
-        return hash(self.int_version)
+        return hash(self.ir_version)
 
     def __eq__(self, other):
         if other is None or type(self) != type(other):
             return False
-        return (self.int_version,) == (other.int_version,)
+        return (self.ir_version,) == (other.ir_version,)
 
 #######################################################################
 ### Interface
@@ -433,20 +423,21 @@
     """ Models an OpenFlow Message class for the purpose of the java class.
         Version agnostic, in contrast to the loxi_ir python model.
     """
-    def __init__(self, c_name, version_map):
+    def __init__(self, ir_class):
         """"
         @param c_name: loxi style name (e.g., of_flow_add)
         @param version_map map of { JavaOFVersion: OFClass (from loxi_ir) }
         """
-        self.c_name = c_name
-        self.version_map = version_map
+        self.ir_class = ir_class
+        self.c_name = ir_class.name
+        self.version_map = { JavaOFVersion(v): c for v,c in ir_class.version_classes.items() }
         # name: the Java Type name, e.g., OFFlowAdd
-        self.name = java_type.name_c_to_caps_camel(c_name) if c_name != "of_header" else "OFMessage"
+        self.name = java_type.name_c_to_caps_camel(self.c_name) if self.c_name != "of_header" else "OFMessage"
         # variable_name name to use for variables of this type. i.e., flowAdd
         self.variable_name = self.name[2].lower() + self.name[3:]
         self.title_name = self.variable_name[0].upper() + self.variable_name[1:]
         # name for use in constants: FLOW_ADD
-        self.constant_name = c_name.upper().replace("OF_", "")
+        self.constant_name = self.c_name.upper().replace("OF_", "")
 
         pck_suffix, parent_interface, self.type_annotation = self.class_info()
         self.package = "org.projectfloodlight.openflow.protocol.%s" % pck_suffix if pck_suffix else "org.projectfloodlight.openflow.protocol"
@@ -510,30 +501,32 @@
         # inheritance information from the versioned lox_ir classes.
         if re.match(r'OFStatsRequest$', self.name):
             return ("", "OFMessage", "T extends OFStatsReply")
-        elif re.match(r'OF.+StatsRequest$', self.name):
+        elif self.ir_class.is_subclassof('of_stats_request'):
             return ("", "OFStatsRequest<{}>".format(re.sub(r'Request$', 'Reply', self.name)), None)
-        elif re.match(r'OF.+StatsReply$', self.name):
+        elif self.ir_class.is_subclassof('of_stats_reply'):
             return ("", "OFStatsReply", None)
-        elif re.match(r'OF.+ErrorMsg$', self.name):
+        elif self.ir_class.is_subclassof('of_error_msg'):
             return ("", "OFErrorMsg", None)
-        elif re.match(r'OFFlow(Add|Modify(Strict)?|Delete(Strict)?)$', self.name):
+        elif self.ir_class.is_subclassof('of_flow_mod'):
             return ("", "OFFlowMod", None)
-        elif loxi_utils.class_is_message(self.c_name) and re.match(r'OFBsn.+$', self.name) and self.name != "OFBsnHeader":
+        elif self.ir_class.is_subclassof('of_group_mod'):
+            return ("", "OFGroupMod", None)
+        elif self.ir_class.is_subclassof('of_bsn_header'):
             return ("", "OFBsnHeader", None)
-        elif loxi_utils.class_is_message(self.c_name) and re.match(r'OFNicira.+$', self.name) and self.name != "OFNiciraHeader":
+        elif self.ir_class.is_subclassof('of_nicira_header'):
             return ("", "OFNiciraHeader", None)
-        elif self.name == "OFBsnHeader" or self.name =="OFNiciraHeader":
+        elif self.ir_class.is_subclassof('of_experimenter'):
             return ("", "OFExperimenter", None)
         elif re.match(r'OFMatch.*', self.name):
             return ("", "Match", None)
-        elif loxi_utils.class_is_message(self.c_name):
+        elif self.ir_class.is_message:
             return ("", "OFMessage", None)
-        elif loxi_utils.class_is_action(self.c_name):
-            if re.match(r'OFActionBsn.+', self.name):
+        elif self.ir_class.is_action:
+            if self.ir_class.is_subclassof('of_action_bsn'):
                 return ("action", "OFActionBsn", None)
-            elif re.match(r'OFActionNicira.+', self.name):
+            elif self.ir_class.is_subclassof('of_action_nicira'):
                 return ("action", "OFActionNicira", None)
-            elif self.name == "OFActionBsn" or self.name == "OFActionNicira":
+            elif self.ir_class.is_subclassof('of_action_experimenter'):
                 return ("action", "OFActionExperimenter", None)
             else:
                 return ("action", "OFAction", None)
@@ -560,6 +553,7 @@
             return ("", None, None)
 
     @property
+
     @memoize
     def writeable_members(self):
         return [ m for m in self.members if m.is_writeable ]
@@ -582,14 +576,30 @@
         all_versions = []
         member_map = collections.OrderedDict()
 
+        member_version_map = {}
         for (version, of_class) in self.version_map.items():
             for of_member in of_class.members:
                 if isinstance(of_member, OFLengthMember) or \
                    isinstance(of_member, OFFieldLengthMember) or \
                    isinstance(of_member, OFPadMember):
                     continue
+                java_member = JavaMember.for_of_member(self, of_member)
                 if of_member.name not in member_map:
-                    member_map[of_member.name] = JavaMember.for_of_member(self, of_member)
+                    member_map[of_member.name] = java_member
+                    member_version_map[of_member.name] = version
+                else:
+                    existing = member_map[of_member.name]
+
+                    if existing.java_type.public_type != java_member.java_type.public_type:
+                        raise Exception(
+                             "Error constructing interface {}: type signatures do not match up between versions.\n"
+                             " Member Name: {}\n"
+                             " Existing: Version={}, Java={}, IR={}\n"
+                             " New:      Version={}, Java={}, IR={}"
+                               .format(self.name, existing.name,
+                                   member_version_map[of_member.name], existing.java_type.public_type, existing.member.oftype,
+                                   version, java_member.java_type.public_type, java_member.member.oftype)
+                        )
 
         return tuple(m for m in member_map.values() if m.name not in model.read_blacklist[self.name])
 
@@ -604,7 +614,7 @@
                     JavaVirtualMember(self, "masked", java_type.boolean),
                     JavaVirtualMember(self, "canonical", java_type.make_oxm_jtype("T"))
                    ]
-        elif self.parent_interface and self.parent_interface.startswith("OFOxm"):
+        elif self.ir_class.is_subclassof("of_oxm"):
             field_type = java_type.make_match_field_jtype(model.oxm_map[self.name].type_name) \
                 if self.name in model.oxm_map \
                 else java_type.make_match_field_jtype()
@@ -616,7 +626,8 @@
                             custom_template=lambda builder: "OFOxm{}_getCanonical.java".format(".Builder" if builder else "")),
                    ]
             if not find(lambda x: x.name == "mask", self.ir_model_members):
-                virtual_members.append(JavaVirtualMember(self, "mask", find(lambda x: x.name == "value", self.ir_model_members).java_type))
+                virtual_members.append(
+                        JavaVirtualMember(self, "mask", find(lambda x: x.name == "value", self.ir_model_members).java_type))
 
         if not find(lambda m: m.name == "version", self.ir_model_members):
             virtual_members.append(JavaVirtualMember(self, "version", java_type.of_version))
@@ -670,7 +681,7 @@
         self.c_name = self.ir_class.name
         self.version = version
         self.constant_name = self.c_name.upper().replace("OF_", "")
-        self.package = "org.projectfloodlight.openflow.protocol.ver%s" % version.of_version
+        self.package = "org.projectfloodlight.openflow.protocol.ver%s" % version.dotless_version
         self.generated = False
 
     @property
@@ -680,7 +691,7 @@
 
     @property
     def name(self):
-        return "%sVer%s" % (self.interface.name, self.version.of_version)
+        return "%sVer%s" % (self.interface.name, self.version.dotless_version)
 
     @property
     def variable_name(self):
@@ -696,23 +707,16 @@
     @property
     def min_length(self):
         """ @return the minimum wire length of an instance of this class in bytes """
-        id_tuple = (self.ir_class.name, self.version.int_version)
-        return of_g.base_length[id_tuple] if id_tuple in of_g.base_length else -1
+        return self.ir_class.base_length
 
     @property
     def is_fixed_length(self):
         """ true iff this class serializes to a fixed length on the wire """
-        return (self.ir_class.name, self.version.int_version) in of_g.is_fixed_length and \
-                not self.is_virtual
+        return self.ir_class.is_fixed_length and not self.is_virtual
 
     def all_properties(self):
         return self.interface.members
 
-    def get_member(self, name):
-        for m in self.members:
-            if m.name == name:
-                return m
-
     @property
     @memoize
     def data_members(self):
@@ -802,7 +806,8 @@
     @property
     @memoize
     def subclasses(self):
-        return [ c for c in model.all_classes if c.version == self.version and c.ir_class.superclass == self.c_name ]
+        return [ c for c in model.all_classes if c.version == self.version and c.ir_class.superclass
+                   and c.ir_class.superclass.name == self.c_name ]
 
 #######################################################################
 ### Member
@@ -957,16 +962,8 @@
 
     @property
     def is_universal(self):
-        if not self.msg.c_name in of_g.unified:
-            print("%s not self.unified" % self.msg.c_name)
-            return False
-        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.member.name in (f['name'] for f in of_g.unified[self.msg.c_name][version]['members']):
+        for version, ir_class in self.msg.ir_class.version_classes.items():
+            if not ir_class.member_by_name(self.member.name):
                 return False
         return True
 
@@ -1022,9 +1019,9 @@
 class JavaUnitTestSet(object):
     def __init__(self, java_class):
         self.java_class = java_class
-        first_data_file_name = "of{version}/{name}.data".format(version=java_class.version.of_version,
+        first_data_file_name = "of{version}/{name}.data".format(version=java_class.version.dotless_version,
                                                      name=java_class.c_name[3:])
-        glob_file_name = "of{version}/{name}__*.data".format(version=java_class.version.of_version,
+        glob_file_name = "of{version}/{name}__*.data".format(version=java_class.version.dotless_version,
                                                      name=java_class.c_name[3:])
         test_class_name = self.java_class.name + "Test"
         self.test_units = []
@@ -1062,7 +1059,7 @@
     def __init__(self, java_class, file_name=None, test_class_name=None):
         self.java_class = java_class
         if file_name is None:
-            self.data_file_name = "of{version}/{name}.data".format(version=java_class.version.of_version,
+            self.data_file_name = "of{version}/{name}.data".format(version=java_class.version.dotless_version,
                                                          name=java_class.c_name[3:])
         else:
             self.data_file_name = file_name