blob: f60341171b70f0b41e330bb15961e39469f8073d [file] [log] [blame]
Andreas Wundsam27303462013-07-16 12:52:35 -07001# Copyright 2013, Big Switch Networks, Inc.
2#
3# LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
4# the following special exception:
5#
6# LOXI Exception
7#
8# As a special exception to the terms of the EPL, you may distribute libraries
9# generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
10# that copyright and licensing notices generated by LoxiGen are not altered or removed
11# from the LoxiGen Libraries and the notice provided below is (i) included in
12# the LoxiGen Libraries, if distributed in source code form and (ii) included in any
13# documentation for the LoxiGen Libraries, if distributed in binary form.
14#
15# Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
16#
17# You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
18# a copy of the EPL at:
19#
20# http://www.eclipse.org/legal/epl-v10.html
21#
22# Unless required by applicable law or agreed to in writing, software
23# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
24# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
25# EPL for the specific language governing permissions and limitations
26# under the EPL.
27
Andreas Wundsam40e14f72013-05-06 14:49:08 -070028# Prototype of an Intermediate Object model for the java code generator
29# A lot of this stuff could/should probably be merged with the python utilities
30
Andreas Wundsam27303462013-07-16 12:52:35 -070031import collections
Andreas Wundsam5204de22013-07-30 11:34:45 -070032from collections import namedtuple, defaultdict, OrderedDict
Andreas Wundsam27303462013-07-16 12:52:35 -070033import logging
Andreas Wundsam40e14f72013-05-06 14:49:08 -070034import os
35import pdb
36import re
37
Andreas Wundsam5204de22013-07-30 11:34:45 -070038from generic_utils import find, memoize, OrderedSet, OrderedDefaultDict
Andreas Wundsam27303462013-07-16 12:52:35 -070039import of_g
40from loxi_ir import *
Andreas Wundsam40e14f72013-05-06 14:49:08 -070041import loxi_front_end.type_maps as type_maps
Andreas Wundsam5204de22013-07-30 11:34:45 -070042import loxi_utils.loxi_utils as loxi_utils
Andreas Wundsam40e14f72013-05-06 14:49:08 -070043import py_gen.util as py_utils
Andreas Wundsam5204de22013-07-30 11:34:45 -070044import test_data
Andreas Wundsam40e14f72013-05-06 14:49:08 -070045
Andreas Wundsam27303462013-07-16 12:52:35 -070046import java_gen.java_type as java_type
Andreas Wundsam40e14f72013-05-06 14:49:08 -070047
Andreas Wundsam27303462013-07-16 12:52:35 -070048class JavaModel(object):
Andreas Wundsam43526532013-08-01 22:03:50 -070049 enum_blacklist = set(("OFDefinitions",))
50 enum_entry_blacklist = defaultdict(lambda: set(), OFFlowWildcards=set([ "NW_DST_BITS", "NW_SRC_BITS", "NW_SRC_SHIFT", "NW_DST_SHIFT" ]))
51 write_blacklist = defaultdict(lambda: set(), OFOxm=set(('typeLen',)), OFAction=set(('type',)), OFInstruction=set(('type',)))
52 virtual_interfaces = set(['OFOxm', 'OFAction', 'OFInstruction' ])
Andreas Wundsam27303462013-07-16 12:52:35 -070053
54 @property
55 @memoize
56 def versions(self):
57 return OrderedSet( JavaOFVersion(raw_version) for raw_version in of_g.target_version_list )
58
59 @property
60 @memoize
61 def interfaces(self):
Andreas Wundsam5204de22013-07-30 11:34:45 -070062 version_map_per_class = collections.OrderedDict()
Andreas Wundsam27303462013-07-16 12:52:35 -070063
64 for raw_version, of_protocol in of_g.ir.items():
65 jversion = JavaOFVersion(of_protocol.wire_version)
66
67 for of_class in of_protocol.classes:
Andreas Wundsam5204de22013-07-30 11:34:45 -070068 if not of_class.name in version_map_per_class:
69 version_map_per_class[of_class.name] = collections.OrderedDict()
70
Andreas Wundsam27303462013-07-16 12:52:35 -070071 version_map_per_class[of_class.name][jversion] = of_class
72
73 interfaces = []
74 for class_name, version_map in version_map_per_class.items():
75 interfaces.append(JavaOFInterface(class_name, version_map))
76
77 return interfaces
78
79 @property
80 @memoize
81 def enums(self):
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -070082 name_version_enum_map = OrderedDefaultDict(lambda: OrderedDict())
Andreas Wundsam27303462013-07-16 12:52:35 -070083
84 for version in self.versions:
85 of_protocol = of_g.ir[version.int_version]
86 for enum in of_protocol.enums:
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -070087 name_version_enum_map[enum.name][version] = enum
Andreas Wundsam27303462013-07-16 12:52:35 -070088
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -070089 enums = [ JavaEnum(name, version_enum_map) for name, version_enum_map,
90 in name_version_enum_map.items() ]
Andreas Wundsam27303462013-07-16 12:52:35 -070091
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -070092 # inelegant - need java name here
93 enums = [ enum for enum in enums if enum.name not in self.enum_blacklist ]
Andreas Wundsam27303462013-07-16 12:52:35 -070094 return enums
95
96 @memoize
97 def enum_by_name(self, name):
98 try:
99 return find(self.enums, lambda e: e.name == name)
100 except KeyError:
101 raise KeyError("Could not find enum with name %s" % name)
102
Andreas Wundsam5204de22013-07-30 11:34:45 -0700103 @property
104 @memoize
105 def of_factory(self):
106 return OFFactory(
107 package="org.openflow.protocol",
108 name="OFFactory",
109 members=self.interfaces)
110
111 def generate_class(self, clazz):
112 if clazz.interface.is_virtual:
113 return False
114 if clazz.interface.name == "OFTableMod":
115 return False
Andreas Wundsam43526532013-08-01 22:03:50 -0700116 if clazz.interface.name.startswith("OFMatchV"):
117 return True
Andreas Wundsam5204de22013-07-30 11:34:45 -0700118 if loxi_utils.class_is_message(clazz.interface.c_name):
119 return True
120 if loxi_utils.class_is_oxm(clazz.interface.c_name):
121 return True
Andreas Wundsam43526532013-08-01 22:03:50 -0700122 if loxi_utils.class_is_action(clazz.interface.c_name):
123 return True
124 if loxi_utils.class_is_instruction(clazz.interface.c_name):
125 return True
Andreas Wundsam5204de22013-07-30 11:34:45 -0700126 else:
127 return False
128
129
130class OFFactory(namedtuple("OFFactory", ("package", "name", "members"))):
131 @property
132 def factory_classes(self):
133 return [ OFFactoryClass(
134 package="org.openflow.protocol.ver{}".format(version.of_version),
135 name="OFFactoryVer{}".format(version.of_version),
136 interface=self,
137 version=version
138 ) for version in model.versions ]
139
140
141OFGenericClass = namedtuple("OFGenericClass", ("package", "name"))
142OFFactoryClass = namedtuple("OFFactory", ("package", "name", "interface", "version"))
143
Andreas Wundsam27303462013-07-16 12:52:35 -0700144model = JavaModel()
145
146#######################################################################
147### OFVersion
148#######################################################################
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700149
150class JavaOFVersion(object):
151 """ Models a version of OpenFlow. contains methods to convert the internal
152 Loxi version to a java constant / a string """
153 def __init__(self, int_version):
154 self.int_version = int(int_version)
155
156 @property
157 def of_version(self):
158 return "1" + str(int(self.int_version) - 1)
159
160 @property
161 def constant_version(self):
162 return "OF_" + self.of_version
163
Andreas Wundsam27303462013-07-16 12:52:35 -0700164 def __repr__(self):
165 return "JavaOFVersion(%d)" % self.int_version
166
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700167 def __str__(self):
168 return of_g.param_version_names[self.int_version]
169
Andreas Wundsam27303462013-07-16 12:52:35 -0700170 def __hash__(self):
171 return hash(self.int_version)
172
173 def __eq__(self, other):
174 if other is None or type(self) != type(other):
175 return False
176 return (self.int_version,) == (other.int_version,)
177
178#######################################################################
179### Interface
180#######################################################################
181
182class JavaOFInterface(object):
183 """ Models an OpenFlow Message class for the purpose of the java class.
184 Version agnostic, in contrast to the loxi_ir python model.
185 """
186 def __init__(self, c_name, version_map):
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700187 self.c_name = c_name
Andreas Wundsam27303462013-07-16 12:52:35 -0700188 self.version_map = version_map
189 self.name = java_type.name_c_to_caps_camel(c_name)
Andreas Wundsam5204de22013-07-30 11:34:45 -0700190 self.variable_name = self.name[2].lower() + self.name[3:]
Andreas Wundsam27303462013-07-16 12:52:35 -0700191 self.constant_name = c_name.upper().replace("OF_", "")
192
193 pck_suffix, parent_interface = self.class_info()
194 self.package = "org.openflow.protocol.%s" % pck_suffix if pck_suffix else "org.openflow.protocol"
195 if self.name != parent_interface:
196 self.parent_interface = parent_interface
197 else:
198 self.parent_interface = None
199
200 def class_info(self):
Yotam Harchol161a5d52013-07-25 17:17:48 -0700201 if re.match(r'OFFlow(Add|Modify(Strict)?|Delete(Strict)?)$', self.name):
Andreas Wundsam27303462013-07-16 12:52:35 -0700202 return ("", "OFFlowMod")
Andreas Wundsam43526532013-08-01 22:03:50 -0700203 elif re.match(r'OFMatch.*', self.name):
204 return ("", "Match")
Andreas Wundsam5204de22013-07-30 11:34:45 -0700205 elif loxi_utils.class_is_message(self.c_name):
Andreas Wundsam27303462013-07-16 12:52:35 -0700206 return ("", "OFMessage")
Andreas Wundsam5204de22013-07-30 11:34:45 -0700207 elif loxi_utils.class_is_action(self.c_name):
Andreas Wundsam27303462013-07-16 12:52:35 -0700208 return ("action", "OFAction")
Andreas Wundsam5204de22013-07-30 11:34:45 -0700209 elif loxi_utils.class_is_oxm(self.c_name):
Andreas Wundsam27303462013-07-16 12:52:35 -0700210 return ("oxm", "OFOxm")
Andreas Wundsam5204de22013-07-30 11:34:45 -0700211 elif loxi_utils.class_is_instruction(self.c_name):
Andreas Wundsam27303462013-07-16 12:52:35 -0700212 return ("instruction", "OFInstruction")
Andreas Wundsam5204de22013-07-30 11:34:45 -0700213 elif loxi_utils.class_is_meter_band(self.c_name):
Andreas Wundsam27303462013-07-16 12:52:35 -0700214 return ("meterband", "OFMeterBand")
215 else:
216 return ("", None)
217
218 @property
219 @memoize
220 def members(self):
221 all_versions = []
222 member_map = collections.OrderedDict()
223
224 for (version, of_class) in self.version_map.items():
225 for of_member in of_class.members:
226 if isinstance(of_member, OFLengthMember) or \
227 isinstance(of_member, OFFieldLengthMember) or \
228 isinstance(of_member, OFPadMember):
229 continue
230 if of_member.name not in member_map:
231 member_map[of_member.name] = JavaMember.for_of_member(self, of_member)
232
233 return member_map.values()
234
235 @property
236 @memoize
237 def is_virtual(self):
238 return self.name in model.virtual_interfaces
239
240 @property
Andreas Wundsam5204de22013-07-30 11:34:45 -0700241 def is_universal(self):
242 return len(self.all_versions) == len(model.versions)
243
244 @property
Andreas Wundsam27303462013-07-16 12:52:35 -0700245 @memoize
246 def all_versions(self):
247 return self.version_map.keys()
248
Andreas Wundsam5204de22013-07-30 11:34:45 -0700249 def has_version(self, version):
250 return version in self.version_map
251
Andreas Wundsam27303462013-07-16 12:52:35 -0700252 def versioned_class(self, version):
253 return JavaOFClass(self, version, self.version_map[version])
254
255 @property
256 @memoize
257 def versioned_classes(self):
258 if self.is_virtual:
259 return []
260 else:
261 return [ self.versioned_class(version) for version in self.all_versions ]
262
263#######################################################################
264### (Versioned) Classes
265#######################################################################
266
267class JavaOFClass(object):
268 """ Models an OpenFlow Message class for the purpose of the java class.
Andreas Wundsamd40ddbf2013-07-25 15:40:47 -0700269 Version specific child of a JavaOFInterface
Andreas Wundsam27303462013-07-16 12:52:35 -0700270 """
271 def __init__(self, interface, version, ir_class):
272 self.interface = interface
273 self.ir_class = ir_class
274 self.c_name = self.ir_class.name
275 self.version = version
276 self.constant_name = self.c_name.upper().replace("OF_", "")
277 self.package = "org.openflow.protocol.ver%s" % version.of_version
Andreas Wundsame916d6f2013-07-30 11:33:58 -0700278 self.generated = False
279
280 @property
281 @memoize
282 def unit_test(self):
283 return JavaUnitTest(self)
Andreas Wundsam27303462013-07-16 12:52:35 -0700284
285 @property
286 def name(self):
287 return "%sVer%s" % (self.interface.name, self.version.of_version)
288
289 @property
Andreas Wundsam5204de22013-07-30 11:34:45 -0700290 def variable_name(self):
291 return self.name[3:]
292
293 @property
Andreas Wundsam27303462013-07-16 12:52:35 -0700294 def length(self):
295 if self.is_fixed_length:
296 return self.min_length
297 else:
298 raise Exception("No fixed length for class %s, version %s" % (self.name, self.version))
299
300 @property
301 def min_length(self):
302 id_tuple = (self.ir_class.name, self.version.int_version)
303 return of_g.base_length[id_tuple] if id_tuple in of_g.base_length else -1
304
305 @property
306 def is_fixed_length(self):
307 return (self.ir_class.name, self.version.int_version) in of_g.is_fixed_length
308
309 def all_properties(self):
310 return self.interface.members
311
312 def get_member(self, name):
313 for m in self.members:
314 if m.name == name:
315 return m
316
317 @property
318 @memoize
319 def data_members(self):
320 return [ prop for prop in self.members if prop.is_data ]
321
322 @property
323 @memoize
324 def fixed_value_members(self):
325 return [ prop for prop in self.members if prop.is_fixed_value ]
326
327 @property
328 @memoize
329 def public_members(self):
330 return [ prop for prop in self.members if prop.is_public ]
331
332 @property
333 @memoize
334 def members(self):
335 members = [ JavaMember.for_of_member(self, of_member) for of_member in self.ir_class.members ]
336 return members
337
338 def all_versions(self):
339 return [ JavaOFVersion(int_version)
340 for int_version in of_g.unified[self.c_name]
341 if int_version != 'union' and int_version != 'object_id' ]
342
343 def version_is_inherited(self, version):
344 return 'use_version' in of_g.unified[self.ir_class.name][version.int_version]
345
346 def inherited_from(self, version):
347 return JavaOFVersion(of_g.unified[self.ir_class.name][version.int_version]['use_version'])
348
349 @property
350 def is_virtual(self):
351 return type_maps.class_is_virtual(self.c_name)
352
353 @property
354 def is_extension(self):
355 return type_maps.message_is_extension(self.c_name, -1)
356
357#######################################################################
358### Member
359#######################################################################
360
361
362class JavaMember(object):
363 """ Models a property (member) of an openflow class. """
364 def __init__(self, msg, name, java_type, member):
365 self.msg = msg
366 self.name = name
367 self.java_type = java_type
368 self.member = member
369 self.c_name = self.member.name if(hasattr(self.member, "name")) else ""
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700370
371 @property
372 def title_name(self):
373 return self.name[0].upper() + self.name[1:]
374
375 @property
376 def constant_name(self):
377 return self.c_name.upper()
378
379 @property
380 def default_name(self):
Andreas Wundsam27303462013-07-16 12:52:35 -0700381 if self.is_fixed_value:
382 return self.constant_name
383 else:
384 return "DEFAULT_"+self.constant_name
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700385
386 @property
387 def default_value(self):
388 java_type = self.java_type.public_type;
389
Andreas Wundsam27303462013-07-16 12:52:35 -0700390 if self.is_fixed_value:
391 return self.enum_value
392 elif re.match(r'List.*', java_type):
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700393 return "Collections.emptyList()"
394 elif java_type == "boolean":
395 return "false";
396 elif java_type in ("byte", "char", "short", "int", "long"):
397 return "({0}) 0".format(java_type);
398 else:
399 return "null";
400
401 @property
Andreas Wundsam27303462013-07-16 12:52:35 -0700402 def enum_value(self):
403 if self.name == "version":
404 return "OFVersion.%s" % self.msg.version.constant_version
405
406 java_type = self.java_type.public_type;
407 try:
408 global model
409 enum = model.enum_by_name(java_type)
410 entry = enum.entry_by_version_value(self.msg.version, self.value)
411 return "%s.%s" % ( enum.name, entry.name)
412 except KeyError, e:
413 print e.message
414 return self.value
415
416 @property
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700417 def is_pad(self):
Andreas Wundsam27303462013-07-16 12:52:35 -0700418 return isinstance(self.member, OFPadMember)
419
420 def is_type_value(self, version=None):
421 if(version==None):
422 return any(self.is_type_value(version) for version in self.msg.all_versions)
423 try:
424 return self.c_name in get_type_values(self.msg.c_name, version.int_version)
425 except:
426 return False
427
428 @property
429 def is_field_length_value(self):
430 return isinstance(self.member, OFFieldLengthMember)
431
432 @property
433 def is_length_value(self):
434 return isinstance(self.member, OFLengthMember)
435
436 @property
437 def is_public(self):
438 return not (self.is_pad or self.is_length_value)
439
440 @property
441 def is_data(self):
442 return isinstance(self.member, OFDataMember) and self.name != "version"
443
444 @property
445 def is_fixed_value(self):
446 return hasattr(self.member, "value") or self.name == "version" \
447 or ( self.name == "length" and self.msg.is_fixed_length) \
448 or ( self.name == "len" and self.msg.is_fixed_length)
449
450 @property
451 def value(self):
452 if self.name == "version":
453 return self.msg.version.int_version
454 elif self.name == "length" or self.name == "len":
455 return self.msg.length
456 elif self.java_type.public_type in ("int", "short", "byte") and self.member.value > 100:
457 return "0x%x" % self.member.value
458 else:
459 return self.member.value
460
461 @property
462 def is_writeable(self):
463 return self.is_data and not self.name in model.write_blacklist[self.msg.name]
464
465 def get_type_value_info(self, version):
466 return get_type_values(msg.c_name, version.int_version)[self.c_name]
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700467
468 @property
469 def length(self):
Andreas Wundsam27303462013-07-16 12:52:35 -0700470 if hasattr(self.member, "length"):
471 return self.member.length
472 else:
Andreas Wundsam5204de22013-07-30 11:34:45 -0700473 count, base = loxi_utils.type_dec_to_count_base(self.member.type)
Andreas Wundsam27303462013-07-16 12:52:35 -0700474 return of_g.of_base_types[base]['bytes'] * count
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700475
476 @staticmethod
Andreas Wundsam27303462013-07-16 12:52:35 -0700477 def for_of_member(java_class, member):
478 if isinstance(member, OFPadMember):
479 return JavaMember(None, "", None, member)
480 else:
481 if member.name == 'len':
482 name = 'length'
483 else:
484 name = java_type.name_c_to_camel(member.name)
485 j_type = java_type.convert_to_jtype(java_class.c_name, member.name, member.oftype)
486 return JavaMember(java_class, name, j_type, member)
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700487
488 @property
489 def is_universal(self):
Andreas Wundsam27303462013-07-16 12:52:35 -0700490 if not self.msg.c_name in of_g.unified:
491 print("%s not self.unified" % self.msg.c_name)
492 return False
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700493 for version in of_g.unified[self.msg.c_name]:
494 if version == 'union' or version =='object_id':
495 continue
496 if 'use_version' in of_g.unified[self.msg.c_name][version]:
497 continue
498
Andreas Wundsam27303462013-07-16 12:52:35 -0700499 if not self.member.name in (f['name'] for f in of_g.unified[self.msg.c_name][version]['members']):
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700500 return False
501 return True
502
Andreas Wundsam27303462013-07-16 12:52:35 -0700503 def __hash__(self):
504 return hash(self.name)
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700505
Andreas Wundsam27303462013-07-16 12:52:35 -0700506 def __eq__(self, other):
507 if other is None or type(self) != type(other):
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700508 return False
Andreas Wundsam27303462013-07-16 12:52:35 -0700509 return (self.name,) == (other.name,)
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700510
Andreas Wundsame916d6f2013-07-30 11:33:58 -0700511
512#######################################################################
513### Unit Test
514#######################################################################
515
516class JavaUnitTest(object):
517 def __init__(self, java_class):
518 self.java_class = java_class
519 self.data_file_name = "of{version}/{name}.data".format(version=java_class.version.of_version,
520 name=java_class.c_name[3:])
521 @property
522 def package(self):
523 return self.java_class.package
524
525 @property
526 def name(self):
527 return self.java_class.name + "Test"
528
529 @property
530 def has_test_data(self):
531 return test_data.exists(self.data_file_name)
532
533 @property
534 @memoize
535 def test_data(self):
536 return test_data.read(self.data_file_name)
537
538
Andreas Wundsam27303462013-07-16 12:52:35 -0700539#######################################################################
540### Enums
541#######################################################################
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700542
Andreas Wundsam27303462013-07-16 12:52:35 -0700543class JavaEnum(object):
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -0700544 def __init__(self, c_name, version_enum_map):
Andreas Wundsam27303462013-07-16 12:52:35 -0700545 self.c_name = c_name
546 self.name = "OF" + java_type.name_c_to_caps_camel("_".join(c_name.split("_")[1:]))
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700547
Andreas Wundsam27303462013-07-16 12:52:35 -0700548 # Port_features has constants that start with digits
549 self.name_prefix = "PF_" if self.name == "OFPortFeatures" else ""
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700550
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -0700551 self.version_enums = version_enum_map
552
553 entry_name_version_value_map = OrderedDefaultDict(lambda: OrderedDict())
554 for version, ir_enum in version_enum_map.items():
555 for ir_entry in ir_enum.entries:
556 if "virtual" in ir_entry.params:
557 continue
558 entry_name_version_value_map[ir_entry.name][version] = ir_entry.value
559
Andreas Wundsam27303462013-07-16 12:52:35 -0700560 self.entries = [ JavaEnumEntry(self, name, version_value_map)
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -0700561 for (name, version_value_map) in entry_name_version_value_map.items() ]
Andreas Wundsam43526532013-08-01 22:03:50 -0700562
563 self.entries = [ e for e in self.entries if e.name not in model.enum_entry_blacklist[self.name] ]
Andreas Wundsam27303462013-07-16 12:52:35 -0700564 self.package = "org.openflow.protocol"
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700565
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -0700566 def wire_type(self, version):
567 ir_enum = self.version_enums[version]
568 if "wire_type" in ir_enum.params:
569 return java_type.convert_enum_wire_type_to_jtype(ir_enum.params["wire_type"])
570 else:
571 return java_type.u8
572
573 @property
574 def versions(self):
575 return self.version_enums.keys()
576
Andreas Wundsam27303462013-07-16 12:52:35 -0700577 @memoize
578 def entry_by_name(self, name):
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700579 try:
Andreas Wundsam27303462013-07-16 12:52:35 -0700580 return find(self.entries, lambda e: e.name == name)
581 except KeyError:
582 raise KeyError("Enum %s: no entry with name %s" % (self.name, name))
583
584 @memoize
585 def entry_by_c_name(self, name):
586 try:
587 return find(self.entries, lambda e: e.c_name == name)
588 except KeyError:
589 raise KeyError("Enum %s: no entry with c_name %s" % (self.name, name))
590
591 @memoize
592 def entry_by_version_value(self, version, value):
593 try:
594 return find(self.entries, lambda e: e.values[version] == value if version in e.values else False )
595 except KeyError:
596 raise KeyError("Enum %s: no entry with version %s, value %s" % (self.name, version, value))
597
598# values: Map JavaVersion->Value
599class JavaEnumEntry(object):
600 def __init__(self, enum, name, values):
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -0700601 self.enum = enum
Andreas Wundsam27303462013-07-16 12:52:35 -0700602 self.name = enum.name_prefix + "_".join(name.split("_")[1:]).upper()
603 self.values = values
604
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -0700605 def has_value(self, version):
606 return version in self.values
607
Andreas Wundsam27303462013-07-16 12:52:35 -0700608 def value(self, version):
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -0700609 return self.values[version]
610
611 def format_value(self, version):
612 res = self.enum.wire_type(version).format_value(self.values[version])
Andreas Wundsam27303462013-07-16 12:52:35 -0700613 return res
614
Andreas Wundsam27303462013-07-16 12:52:35 -0700615 def all_values(self, versions, not_present=None):
616 return [ self.values[version] if version in self.values else not_present for version in versions ]