Merge into master from pull request #336:
java_gen: generate getStableValue() for 'stable' enums (https://github.com/floodlight/loxigen/pull/336)
diff --git a/java_gen/java_model.py b/java_gen/java_model.py
index 8726632..fc64f80 100644
--- a/java_gen/java_model.py
+++ b/java_gen/java_model.py
@@ -184,14 +184,25 @@
     @memoize
     def enums(self):
         name_version_enum_map = OrderedDefaultDict(lambda: OrderedDict())
+        name_stable_map = {}
 
         for version in self.versions:
-            logger.info("version: {}".format(version.ir_version))
+            logger.debug("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
+                stable = (enum.params.get('stable') == 'True')
 
-        enums = [ JavaEnum(name, version_enum_map) for name, version_enum_map,
+                logger.debug("Enum: %s stable: %s", enum.name, stable)
+
+                if not enum.name in name_stable_map:
+                    name_stable_map[enum.name] = stable
+                else:
+                    if name_stable_map[enum.name] != stable:
+                        raise Exception("Inconsistent enum stability (should be caught " +\
+                            " by IR)")
+
+        enums = [ JavaEnum(name, name_stable_map[name], version_enum_map) for name, version_enum_map,
                         in name_version_enum_map.items() ]
 
         # inelegant - need java name here
@@ -1041,8 +1052,9 @@
 #######################################################################
 
 class JavaEnum(object):
-    def __init__(self, c_name, version_enum_map):
+    def __init__(self, c_name, stable, version_enum_map):
         self.c_name = c_name
+        self.stable = stable
 
         self.name   = "OF" + java_type.name_c_to_caps_camel("_".join(c_name.split("_")[1:]))
 
@@ -1062,7 +1074,23 @@
         self.entries = [ e for e in self.entries if e.name not in model.enum_entry_blacklist[self.name] ]
         self.package = "org.projectfloodlight.openflow.protocol"
 
-        self.metadata = model.enum_metadata_map[self.name]
+        static_metadata = model.enum_metadata_map[self.name]
+        if self.stable:
+            # need this to look up wire_type, which does not matter
+            any_version = version_enum_map.keys()[0]
+            # if this is a 'stable' enum, i.e., its value won't change, add
+            # a "Metadata" (virtual) field "StableValue" to it that returns
+            # its wirevalue.
+            stable_value = JavaModel.OFEnumPropertyMetadata("StableValue",
+                    self.wire_type(any_version),
+                    value = lambda entry: entry.stable_value)
+
+            self.metadata = JavaModel.OFEnumMetadata(
+                              properties=static_metadata.properties + (stable_value, ),
+                              to_string=static_metadata.to_string
+                            )
+        else:
+            self.metadata = static_metadata
 
     def wire_type(self, version):
         ir_enum = self.version_enums[version]
@@ -1113,7 +1141,7 @@
 
     @property
     def constructor_params(self):
-        return [ m.value(self) for m in self.enum.metadata.properties ]
+        return [ (m.type, m.value(self)) for m in self.enum.metadata.properties ]
 
     def has_value(self, version):
         return version in self.values
@@ -1129,6 +1157,13 @@
         return [ self.values[version] if version in self.values else not_present for version in versions ]
 
     @property
+    def stable_value(self):
+        if self.enum.stable:
+            return self.values.values()[0]
+        else:
+            raise Exception("Enum {} not stable".format(self.enum.name))
+
+    @property
     @memoize
     def masked_enum_group(self):
         group = find(lambda g: self.name in g.members, model.masked_enum_groups[self.enum.name])
diff --git a/java_gen/java_type.py b/java_gen/java_type.py
index e0f0680..427de95 100644
--- a/java_gen/java_type.py
+++ b/java_gen/java_type.py
@@ -53,9 +53,12 @@
         signed-craziness
     """
     signed, bits, cast_needed = java_primitives_info[t]
+    if t == 'boolean':
+        return "true" if bool(value) and value not in("False", "false") else "false"
+
     max = (1 << bits)-1
     if value > max:
-        raise Exception("Value %d to large for type %s" % (value, t))
+        raise Exception("Value %s to large for type %s" % (value, t))
 
     if signed:
         max_pos = (1 << (bits-1)) - 1
diff --git a/java_gen/templates/const.java b/java_gen/templates/const.java
index a7786f4..1828bac 100644
--- a/java_gen/templates/const.java
+++ b/java_gen/templates/const.java
@@ -37,7 +37,7 @@
 public enum ${class_name} {
 //:: for i, entry in enumerate(enum.entries):
 //::    if enum.metadata.properties:
-//::        params = "({})".format(", ".join(entry.constructor_params))
+//::        params = "({})".format(", ".join(type.format_value(value) for (type, value) in entry.constructor_params))
 //::    else:
 //::        params = ""
 //::    #endif