Andreas Wundsam | 40e14f7 | 2013-05-06 14:49:08 -0700 | [diff] [blame] | 1 | # Prototype of an Intermediate Object model for the java code generator |
| 2 | # A lot of this stuff could/should probably be merged with the python utilities |
| 3 | |
| 4 | import of_g |
| 5 | import os |
| 6 | import pdb |
| 7 | import re |
| 8 | |
| 9 | import loxi_front_end.type_maps as type_maps |
| 10 | import loxi_utils.loxi_utils as utils |
| 11 | import py_gen.util as py_utils |
| 12 | |
| 13 | import java_gen.java_utils as java_utils |
| 14 | ignore_fields = ['version', 'xid', 'length', 'type' ] |
| 15 | |
| 16 | protected_fields = ['version', 'length'] |
| 17 | |
| 18 | class JavaOFVersion(object): |
| 19 | """ Models a version of OpenFlow. contains methods to convert the internal |
| 20 | Loxi version to a java constant / a string """ |
| 21 | def __init__(self, int_version): |
| 22 | self.int_version = int(int_version) |
| 23 | |
| 24 | @property |
| 25 | def of_version(self): |
| 26 | return "1" + str(int(self.int_version) - 1) |
| 27 | |
| 28 | @property |
| 29 | def constant_version(self): |
| 30 | return "OF_" + self.of_version |
| 31 | |
| 32 | def __str__(self): |
| 33 | return of_g.param_version_names[self.int_version] |
| 34 | |
| 35 | class JavaProperty(object): |
| 36 | """ Models a property (member) of an openflow class. """ |
| 37 | def __init__(self, msg, java_type, c_type, name, c_name): |
| 38 | self.msg = msg |
| 39 | self.java_type = java_type |
| 40 | self.c_type = c_type |
| 41 | self.name = name |
| 42 | self.c_name = c_name |
| 43 | |
| 44 | @property |
| 45 | def title_name(self): |
| 46 | return self.name[0].upper() + self.name[1:] |
| 47 | |
| 48 | @property |
| 49 | def constant_name(self): |
| 50 | return self.c_name.upper() |
| 51 | |
| 52 | @property |
| 53 | def default_name(self): |
| 54 | return "DEFAULT_"+self.constant_name |
| 55 | |
| 56 | @property |
| 57 | def default_value(self): |
| 58 | java_type = self.java_type.public_type; |
| 59 | |
| 60 | if re.match(r'List.*', java_type): |
| 61 | return "Collections.emptyList()" |
| 62 | elif java_type == "boolean": |
| 63 | return "false"; |
| 64 | elif java_type in ("byte", "char", "short", "int", "long"): |
| 65 | return "({0}) 0".format(java_type); |
| 66 | else: |
| 67 | return "null"; |
| 68 | |
| 69 | @property |
| 70 | def is_pad(self): |
| 71 | return self.c_name.startswith("pad") |
| 72 | |
| 73 | @property |
| 74 | def length(self): |
| 75 | count, base = utils.type_dec_to_count_base(self.c_type) |
| 76 | return of_g.of_base_types[base]['bytes'] * count |
| 77 | |
| 78 | @staticmethod |
| 79 | def for_field(msg, field, c_name=None): |
| 80 | if not c_name: |
| 81 | c_name = field['name'] |
| 82 | |
| 83 | name = java_utils.name_c_to_camel(c_name) |
| 84 | java_type = java_utils.convert_to_jtype(msg.c_name, c_name, field['m_type']) |
| 85 | c_type = field['m_type'] |
| 86 | return JavaProperty(msg, java_type, c_type, name, c_name) |
| 87 | |
| 88 | @property |
| 89 | def is_universal(self): |
| 90 | for version in of_g.unified[self.msg.c_name]: |
| 91 | if version == 'union' or version =='object_id': |
| 92 | continue |
| 93 | if 'use_version' in of_g.unified[self.msg.c_name][version]: |
| 94 | continue |
| 95 | |
| 96 | if not self.c_name in (f['name'] for f in of_g.unified[self.msg.c_name][version]['members']): |
| 97 | return False |
| 98 | return True |
| 99 | |
| 100 | class JavaOFMessage(object): |
| 101 | """ Models an OpenFlow Message class """ |
| 102 | def __init__(self, c_name): |
| 103 | self.c_name = c_name |
| 104 | self.interface_name = java_utils.name_c_to_caps_camel(c_name) |
| 105 | self.builder_name = self.interface_name + "Builder" |
| 106 | self.constant_name = c_name.upper().replace("OF_", "") |
| 107 | |
| 108 | def min_length(self, version): |
| 109 | return of_g.base_length[(self.c_name, version.int_version)] if (self.c_name, version.int_version) in of_g.base_length else -1 |
| 110 | |
| 111 | def is_fixed_length(self, version): |
| 112 | return (self.c_name, version.int_version) in of_g.is_fixed_length |
| 113 | |
| 114 | def class_name_for_version(self, version): |
| 115 | return self.interface_name + "Ver"+version.of_version |
| 116 | |
| 117 | |
| 118 | def all_properties(self, skip_pads=True): |
| 119 | if 'union' in of_g.unified[self.c_name]: |
| 120 | props = [] |
| 121 | fields = of_g.unified[self.c_name]['union'] |
| 122 | for field_name in sorted( fields.keys(), key=lambda k: fields[k]['memid']): |
| 123 | if field_name in ignore_fields: |
| 124 | continue |
| 125 | if skip_pads and field_name.startswith("pad"): |
| 126 | continue |
| 127 | |
| 128 | java_property = JavaProperty.for_field(self, fields[field_name], c_name=field_name) |
| 129 | props.append(java_property) |
| 130 | return props |
| 131 | else: |
| 132 | return [] |
| 133 | |
| 134 | def all_versions(self): |
| 135 | return [ JavaOFVersion(int_version) |
| 136 | for int_version in of_g.unified[self.c_name] |
| 137 | if int_version != 'union' and int_version != 'object_id' ] |
| 138 | |
| 139 | def property_in_version(self, prop, version): |
| 140 | if self.version_is_inherited(version): |
| 141 | version = self.inherited_from(version) |
| 142 | |
| 143 | if 'members' not in of_g.unified[self.c_name][version.int_version]: |
| 144 | return False |
| 145 | return prop.c_name in (member['name'] for member in of_g.unified[self.c_name][version.int_version]['members']) |
| 146 | |
| 147 | def properties_for_version(self, version, skip_pads=True): |
| 148 | props = [] |
| 149 | if self.version_is_inherited(version): |
| 150 | version = self.inherited_from(version) |
| 151 | |
| 152 | for field in of_g.unified[self.c_name][version.int_version]['members']: |
| 153 | if field['name'] in ignore_fields: |
| 154 | continue |
| 155 | if skip_pads and field['name'].startswith("pad"): |
| 156 | continue |
| 157 | |
| 158 | java_property = JavaProperty.for_field(self, field, c_name=field['name']) |
| 159 | props.append(java_property) |
| 160 | return props |
| 161 | |
| 162 | def version_is_inherited(self, version): |
| 163 | return 'use_version' in of_g.unified[self.c_name][version.int_version] |
| 164 | |
| 165 | def inherited_from(self, version): |
| 166 | return JavaOFVersion(of_g.unified[self.c_name][version.int_version]['use_version']) |
| 167 | |
| 168 | @property |
| 169 | def is_virtual(self): |
| 170 | return type_maps.class_is_virtual(self.c_name) |
| 171 | |
| 172 | @property |
| 173 | def is_extension(self): |
| 174 | return type_maps.message_is_extension(self.c_name, -1) |
| 175 | |
| 176 | def wire_type(self, version): |
| 177 | try: |
| 178 | return py_utils.primary_wire_type(self.c_name, version.int_version) |
| 179 | except ValueError, e: |
| 180 | return -1 |