blob: a894179fa3b9b2bb8084350f8a1421eec110de8b [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
Andreas Wundsam758c9cc2013-08-01 22:16:06 -0700357 @property
358 def align(self):
359 return int(self.ir_class.params['align']) if 'align' in self.ir_class.params else 0
360
Andreas Wundsam27303462013-07-16 12:52:35 -0700361#######################################################################
362### Member
363#######################################################################
364
365
366class JavaMember(object):
367 """ Models a property (member) of an openflow class. """
368 def __init__(self, msg, name, java_type, member):
369 self.msg = msg
370 self.name = name
371 self.java_type = java_type
372 self.member = member
373 self.c_name = self.member.name if(hasattr(self.member, "name")) else ""
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700374
375 @property
376 def title_name(self):
377 return self.name[0].upper() + self.name[1:]
378
379 @property
380 def constant_name(self):
381 return self.c_name.upper()
382
383 @property
384 def default_name(self):
Andreas Wundsam27303462013-07-16 12:52:35 -0700385 if self.is_fixed_value:
386 return self.constant_name
387 else:
388 return "DEFAULT_"+self.constant_name
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700389
390 @property
391 def default_value(self):
392 java_type = self.java_type.public_type;
393
Andreas Wundsam27303462013-07-16 12:52:35 -0700394 if self.is_fixed_value:
395 return self.enum_value
396 elif re.match(r'List.*', java_type):
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700397 return "Collections.emptyList()"
398 elif java_type == "boolean":
399 return "false";
400 elif java_type in ("byte", "char", "short", "int", "long"):
401 return "({0}) 0".format(java_type);
402 else:
403 return "null";
404
405 @property
Andreas Wundsam27303462013-07-16 12:52:35 -0700406 def enum_value(self):
407 if self.name == "version":
408 return "OFVersion.%s" % self.msg.version.constant_version
409
410 java_type = self.java_type.public_type;
411 try:
412 global model
413 enum = model.enum_by_name(java_type)
414 entry = enum.entry_by_version_value(self.msg.version, self.value)
415 return "%s.%s" % ( enum.name, entry.name)
416 except KeyError, e:
417 print e.message
418 return self.value
419
420 @property
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700421 def is_pad(self):
Andreas Wundsam27303462013-07-16 12:52:35 -0700422 return isinstance(self.member, OFPadMember)
423
424 def is_type_value(self, version=None):
425 if(version==None):
426 return any(self.is_type_value(version) for version in self.msg.all_versions)
427 try:
428 return self.c_name in get_type_values(self.msg.c_name, version.int_version)
429 except:
430 return False
431
432 @property
433 def is_field_length_value(self):
434 return isinstance(self.member, OFFieldLengthMember)
435
436 @property
437 def is_length_value(self):
438 return isinstance(self.member, OFLengthMember)
439
440 @property
441 def is_public(self):
442 return not (self.is_pad or self.is_length_value)
443
444 @property
445 def is_data(self):
446 return isinstance(self.member, OFDataMember) and self.name != "version"
447
448 @property
449 def is_fixed_value(self):
450 return hasattr(self.member, "value") or self.name == "version" \
451 or ( self.name == "length" and self.msg.is_fixed_length) \
452 or ( self.name == "len" and self.msg.is_fixed_length)
453
454 @property
455 def value(self):
456 if self.name == "version":
457 return self.msg.version.int_version
458 elif self.name == "length" or self.name == "len":
459 return self.msg.length
460 elif self.java_type.public_type in ("int", "short", "byte") and self.member.value > 100:
461 return "0x%x" % self.member.value
462 else:
463 return self.member.value
464
465 @property
466 def is_writeable(self):
467 return self.is_data and not self.name in model.write_blacklist[self.msg.name]
468
469 def get_type_value_info(self, version):
470 return get_type_values(msg.c_name, version.int_version)[self.c_name]
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700471
472 @property
473 def length(self):
Andreas Wundsam27303462013-07-16 12:52:35 -0700474 if hasattr(self.member, "length"):
475 return self.member.length
476 else:
Andreas Wundsam5204de22013-07-30 11:34:45 -0700477 count, base = loxi_utils.type_dec_to_count_base(self.member.type)
Andreas Wundsam27303462013-07-16 12:52:35 -0700478 return of_g.of_base_types[base]['bytes'] * count
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700479
480 @staticmethod
Andreas Wundsam27303462013-07-16 12:52:35 -0700481 def for_of_member(java_class, member):
482 if isinstance(member, OFPadMember):
483 return JavaMember(None, "", None, member)
484 else:
485 if member.name == 'len':
486 name = 'length'
487 else:
488 name = java_type.name_c_to_camel(member.name)
489 j_type = java_type.convert_to_jtype(java_class.c_name, member.name, member.oftype)
490 return JavaMember(java_class, name, j_type, member)
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700491
492 @property
493 def is_universal(self):
Andreas Wundsam27303462013-07-16 12:52:35 -0700494 if not self.msg.c_name in of_g.unified:
495 print("%s not self.unified" % self.msg.c_name)
496 return False
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700497 for version in of_g.unified[self.msg.c_name]:
498 if version == 'union' or version =='object_id':
499 continue
500 if 'use_version' in of_g.unified[self.msg.c_name][version]:
501 continue
502
Andreas Wundsam27303462013-07-16 12:52:35 -0700503 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 -0700504 return False
505 return True
506
Andreas Wundsam27303462013-07-16 12:52:35 -0700507 def __hash__(self):
508 return hash(self.name)
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700509
Andreas Wundsam27303462013-07-16 12:52:35 -0700510 def __eq__(self, other):
511 if other is None or type(self) != type(other):
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700512 return False
Andreas Wundsam27303462013-07-16 12:52:35 -0700513 return (self.name,) == (other.name,)
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700514
Andreas Wundsame916d6f2013-07-30 11:33:58 -0700515
516#######################################################################
517### Unit Test
518#######################################################################
519
520class JavaUnitTest(object):
521 def __init__(self, java_class):
522 self.java_class = java_class
523 self.data_file_name = "of{version}/{name}.data".format(version=java_class.version.of_version,
524 name=java_class.c_name[3:])
525 @property
526 def package(self):
527 return self.java_class.package
528
529 @property
530 def name(self):
531 return self.java_class.name + "Test"
532
533 @property
534 def has_test_data(self):
535 return test_data.exists(self.data_file_name)
536
537 @property
538 @memoize
539 def test_data(self):
540 return test_data.read(self.data_file_name)
541
542
Andreas Wundsam27303462013-07-16 12:52:35 -0700543#######################################################################
544### Enums
545#######################################################################
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700546
Andreas Wundsam27303462013-07-16 12:52:35 -0700547class JavaEnum(object):
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -0700548 def __init__(self, c_name, version_enum_map):
Andreas Wundsam27303462013-07-16 12:52:35 -0700549 self.c_name = c_name
550 self.name = "OF" + java_type.name_c_to_caps_camel("_".join(c_name.split("_")[1:]))
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700551
Andreas Wundsam27303462013-07-16 12:52:35 -0700552 # Port_features has constants that start with digits
553 self.name_prefix = "PF_" if self.name == "OFPortFeatures" else ""
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700554
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -0700555 self.version_enums = version_enum_map
556
557 entry_name_version_value_map = OrderedDefaultDict(lambda: OrderedDict())
558 for version, ir_enum in version_enum_map.items():
559 for ir_entry in ir_enum.entries:
560 if "virtual" in ir_entry.params:
561 continue
562 entry_name_version_value_map[ir_entry.name][version] = ir_entry.value
563
Andreas Wundsam27303462013-07-16 12:52:35 -0700564 self.entries = [ JavaEnumEntry(self, name, version_value_map)
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -0700565 for (name, version_value_map) in entry_name_version_value_map.items() ]
Andreas Wundsam43526532013-08-01 22:03:50 -0700566
567 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 -0700568 self.package = "org.openflow.protocol"
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700569
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -0700570 def wire_type(self, version):
571 ir_enum = self.version_enums[version]
572 if "wire_type" in ir_enum.params:
573 return java_type.convert_enum_wire_type_to_jtype(ir_enum.params["wire_type"])
574 else:
575 return java_type.u8
576
577 @property
578 def versions(self):
579 return self.version_enums.keys()
580
Andreas Wundsam27303462013-07-16 12:52:35 -0700581 @memoize
582 def entry_by_name(self, name):
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700583 try:
Andreas Wundsam27303462013-07-16 12:52:35 -0700584 return find(self.entries, lambda e: e.name == name)
585 except KeyError:
586 raise KeyError("Enum %s: no entry with name %s" % (self.name, name))
587
588 @memoize
589 def entry_by_c_name(self, name):
590 try:
591 return find(self.entries, lambda e: e.c_name == name)
592 except KeyError:
593 raise KeyError("Enum %s: no entry with c_name %s" % (self.name, name))
594
595 @memoize
596 def entry_by_version_value(self, version, value):
597 try:
598 return find(self.entries, lambda e: e.values[version] == value if version in e.values else False )
599 except KeyError:
600 raise KeyError("Enum %s: no entry with version %s, value %s" % (self.name, version, value))
601
602# values: Map JavaVersion->Value
603class JavaEnumEntry(object):
604 def __init__(self, enum, name, values):
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -0700605 self.enum = enum
Andreas Wundsam27303462013-07-16 12:52:35 -0700606 self.name = enum.name_prefix + "_".join(name.split("_")[1:]).upper()
607 self.values = values
608
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -0700609 def has_value(self, version):
610 return version in self.values
611
Andreas Wundsam27303462013-07-16 12:52:35 -0700612 def value(self, version):
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -0700613 return self.values[version]
614
615 def format_value(self, version):
616 res = self.enum.wire_type(version).format_value(self.values[version])
Andreas Wundsam27303462013-07-16 12:52:35 -0700617 return res
618
Andreas Wundsam27303462013-07-16 12:52:35 -0700619 def all_values(self, versions, not_present=None):
620 return [ self.values[version] if version in self.values else not_present for version in versions ]