blob: 6f5cfaa15662b87e26726a8268b664087a706277 [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 Wundsam5204de22013-07-30 11:34:45 -070049 enum_blacklist = set(("OFDefinitions","OFFlowWildcards"))
50 write_blacklist = defaultdict(lambda: set(), OFOxm=set(('typeLen',)), OFAction=set(('type',)))
51 virtual_interfaces = set(['OFOxm', 'OFAction' ])
Andreas Wundsam27303462013-07-16 12:52:35 -070052
53 @property
54 @memoize
55 def versions(self):
56 return OrderedSet( JavaOFVersion(raw_version) for raw_version in of_g.target_version_list )
57
58 @property
59 @memoize
60 def interfaces(self):
Andreas Wundsam5204de22013-07-30 11:34:45 -070061 version_map_per_class = collections.OrderedDict()
Andreas Wundsam27303462013-07-16 12:52:35 -070062
63 for raw_version, of_protocol in of_g.ir.items():
64 jversion = JavaOFVersion(of_protocol.wire_version)
65
66 for of_class in of_protocol.classes:
Andreas Wundsam5204de22013-07-30 11:34:45 -070067 if not of_class.name in version_map_per_class:
68 version_map_per_class[of_class.name] = collections.OrderedDict()
69
Andreas Wundsam27303462013-07-16 12:52:35 -070070 version_map_per_class[of_class.name][jversion] = of_class
71
72 interfaces = []
73 for class_name, version_map in version_map_per_class.items():
74 interfaces.append(JavaOFInterface(class_name, version_map))
75
76 return interfaces
77
78 @property
79 @memoize
80 def enums(self):
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -070081 name_version_enum_map = OrderedDefaultDict(lambda: OrderedDict())
Andreas Wundsam27303462013-07-16 12:52:35 -070082
83 for version in self.versions:
84 of_protocol = of_g.ir[version.int_version]
85 for enum in of_protocol.enums:
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -070086 name_version_enum_map[enum.name][version] = enum
Andreas Wundsam27303462013-07-16 12:52:35 -070087
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -070088 enums = [ JavaEnum(name, version_enum_map) for name, version_enum_map,
89 in name_version_enum_map.items() ]
Andreas Wundsam27303462013-07-16 12:52:35 -070090
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -070091 # inelegant - need java name here
92 enums = [ enum for enum in enums if enum.name not in self.enum_blacklist ]
Andreas Wundsam27303462013-07-16 12:52:35 -070093 return enums
94
95 @memoize
96 def enum_by_name(self, name):
97 try:
98 return find(self.enums, lambda e: e.name == name)
99 except KeyError:
100 raise KeyError("Could not find enum with name %s" % name)
101
Andreas Wundsam5204de22013-07-30 11:34:45 -0700102 @property
103 @memoize
104 def of_factory(self):
105 return OFFactory(
106 package="org.openflow.protocol",
107 name="OFFactory",
108 members=self.interfaces)
109
110 def generate_class(self, clazz):
111 if clazz.interface.is_virtual:
112 return False
113 if clazz.interface.name == "OFTableMod":
114 return False
115 if loxi_utils.class_is_message(clazz.interface.c_name):
116 return True
117 if loxi_utils.class_is_oxm(clazz.interface.c_name):
118 return True
119 else:
120 return False
121
122
123class OFFactory(namedtuple("OFFactory", ("package", "name", "members"))):
124 @property
125 def factory_classes(self):
126 return [ OFFactoryClass(
127 package="org.openflow.protocol.ver{}".format(version.of_version),
128 name="OFFactoryVer{}".format(version.of_version),
129 interface=self,
130 version=version
131 ) for version in model.versions ]
132
133
134OFGenericClass = namedtuple("OFGenericClass", ("package", "name"))
135OFFactoryClass = namedtuple("OFFactory", ("package", "name", "interface", "version"))
136
Andreas Wundsam27303462013-07-16 12:52:35 -0700137model = JavaModel()
138
139#######################################################################
140### OFVersion
141#######################################################################
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700142
143class JavaOFVersion(object):
144 """ Models a version of OpenFlow. contains methods to convert the internal
145 Loxi version to a java constant / a string """
146 def __init__(self, int_version):
147 self.int_version = int(int_version)
148
149 @property
150 def of_version(self):
151 return "1" + str(int(self.int_version) - 1)
152
153 @property
154 def constant_version(self):
155 return "OF_" + self.of_version
156
Andreas Wundsam27303462013-07-16 12:52:35 -0700157 def __repr__(self):
158 return "JavaOFVersion(%d)" % self.int_version
159
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700160 def __str__(self):
161 return of_g.param_version_names[self.int_version]
162
Andreas Wundsam27303462013-07-16 12:52:35 -0700163 def __hash__(self):
164 return hash(self.int_version)
165
166 def __eq__(self, other):
167 if other is None or type(self) != type(other):
168 return False
169 return (self.int_version,) == (other.int_version,)
170
171#######################################################################
172### Interface
173#######################################################################
174
175class JavaOFInterface(object):
176 """ Models an OpenFlow Message class for the purpose of the java class.
177 Version agnostic, in contrast to the loxi_ir python model.
178 """
179 def __init__(self, c_name, version_map):
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700180 self.c_name = c_name
Andreas Wundsam27303462013-07-16 12:52:35 -0700181 self.version_map = version_map
182 self.name = java_type.name_c_to_caps_camel(c_name)
Andreas Wundsam5204de22013-07-30 11:34:45 -0700183 self.variable_name = self.name[2].lower() + self.name[3:]
Andreas Wundsam27303462013-07-16 12:52:35 -0700184 self.constant_name = c_name.upper().replace("OF_", "")
185
186 pck_suffix, parent_interface = self.class_info()
187 self.package = "org.openflow.protocol.%s" % pck_suffix if pck_suffix else "org.openflow.protocol"
188 if self.name != parent_interface:
189 self.parent_interface = parent_interface
190 else:
191 self.parent_interface = None
192
193 def class_info(self):
Yotam Harchol161a5d52013-07-25 17:17:48 -0700194 if re.match(r'OFFlow(Add|Modify(Strict)?|Delete(Strict)?)$', self.name):
Andreas Wundsam27303462013-07-16 12:52:35 -0700195 return ("", "OFFlowMod")
Andreas Wundsam5204de22013-07-30 11:34:45 -0700196 elif loxi_utils.class_is_message(self.c_name):
Andreas Wundsam27303462013-07-16 12:52:35 -0700197 return ("", "OFMessage")
Andreas Wundsam5204de22013-07-30 11:34:45 -0700198 elif loxi_utils.class_is_action(self.c_name):
Andreas Wundsam27303462013-07-16 12:52:35 -0700199 return ("action", "OFAction")
Andreas Wundsam5204de22013-07-30 11:34:45 -0700200 elif loxi_utils.class_is_oxm(self.c_name):
Andreas Wundsam27303462013-07-16 12:52:35 -0700201 return ("oxm", "OFOxm")
Andreas Wundsam5204de22013-07-30 11:34:45 -0700202 elif loxi_utils.class_is_instruction(self.c_name):
Andreas Wundsam27303462013-07-16 12:52:35 -0700203 return ("instruction", "OFInstruction")
Andreas Wundsam5204de22013-07-30 11:34:45 -0700204 elif loxi_utils.class_is_meter_band(self.c_name):
Andreas Wundsam27303462013-07-16 12:52:35 -0700205 return ("meterband", "OFMeterBand")
206 else:
207 return ("", None)
208
209 @property
210 @memoize
211 def members(self):
212 all_versions = []
213 member_map = collections.OrderedDict()
214
215 for (version, of_class) in self.version_map.items():
216 for of_member in of_class.members:
217 if isinstance(of_member, OFLengthMember) or \
218 isinstance(of_member, OFFieldLengthMember) or \
219 isinstance(of_member, OFPadMember):
220 continue
221 if of_member.name not in member_map:
222 member_map[of_member.name] = JavaMember.for_of_member(self, of_member)
223
224 return member_map.values()
225
226 @property
227 @memoize
228 def is_virtual(self):
229 return self.name in model.virtual_interfaces
230
231 @property
Andreas Wundsam5204de22013-07-30 11:34:45 -0700232 def is_universal(self):
233 return len(self.all_versions) == len(model.versions)
234
235 @property
Andreas Wundsam27303462013-07-16 12:52:35 -0700236 @memoize
237 def all_versions(self):
238 return self.version_map.keys()
239
Andreas Wundsam5204de22013-07-30 11:34:45 -0700240 def has_version(self, version):
241 return version in self.version_map
242
Andreas Wundsam27303462013-07-16 12:52:35 -0700243 def versioned_class(self, version):
244 return JavaOFClass(self, version, self.version_map[version])
245
246 @property
247 @memoize
248 def versioned_classes(self):
249 if self.is_virtual:
250 return []
251 else:
252 return [ self.versioned_class(version) for version in self.all_versions ]
253
254#######################################################################
255### (Versioned) Classes
256#######################################################################
257
258class JavaOFClass(object):
259 """ Models an OpenFlow Message class for the purpose of the java class.
Andreas Wundsamd40ddbf2013-07-25 15:40:47 -0700260 Version specific child of a JavaOFInterface
Andreas Wundsam27303462013-07-16 12:52:35 -0700261 """
262 def __init__(self, interface, version, ir_class):
263 self.interface = interface
264 self.ir_class = ir_class
265 self.c_name = self.ir_class.name
266 self.version = version
267 self.constant_name = self.c_name.upper().replace("OF_", "")
268 self.package = "org.openflow.protocol.ver%s" % version.of_version
Andreas Wundsame916d6f2013-07-30 11:33:58 -0700269 self.generated = False
270
271 @property
272 @memoize
273 def unit_test(self):
274 return JavaUnitTest(self)
Andreas Wundsam27303462013-07-16 12:52:35 -0700275
276 @property
277 def name(self):
278 return "%sVer%s" % (self.interface.name, self.version.of_version)
279
280 @property
Andreas Wundsam5204de22013-07-30 11:34:45 -0700281 def variable_name(self):
282 return self.name[3:]
283
284 @property
Andreas Wundsam27303462013-07-16 12:52:35 -0700285 def length(self):
286 if self.is_fixed_length:
287 return self.min_length
288 else:
289 raise Exception("No fixed length for class %s, version %s" % (self.name, self.version))
290
291 @property
292 def min_length(self):
293 id_tuple = (self.ir_class.name, self.version.int_version)
294 return of_g.base_length[id_tuple] if id_tuple in of_g.base_length else -1
295
296 @property
297 def is_fixed_length(self):
298 return (self.ir_class.name, self.version.int_version) in of_g.is_fixed_length
299
300 def all_properties(self):
301 return self.interface.members
302
303 def get_member(self, name):
304 for m in self.members:
305 if m.name == name:
306 return m
307
308 @property
309 @memoize
310 def data_members(self):
311 return [ prop for prop in self.members if prop.is_data ]
312
313 @property
314 @memoize
315 def fixed_value_members(self):
316 return [ prop for prop in self.members if prop.is_fixed_value ]
317
318 @property
319 @memoize
320 def public_members(self):
321 return [ prop for prop in self.members if prop.is_public ]
322
323 @property
324 @memoize
325 def members(self):
326 members = [ JavaMember.for_of_member(self, of_member) for of_member in self.ir_class.members ]
327 return members
328
329 def all_versions(self):
330 return [ JavaOFVersion(int_version)
331 for int_version in of_g.unified[self.c_name]
332 if int_version != 'union' and int_version != 'object_id' ]
333
334 def version_is_inherited(self, version):
335 return 'use_version' in of_g.unified[self.ir_class.name][version.int_version]
336
337 def inherited_from(self, version):
338 return JavaOFVersion(of_g.unified[self.ir_class.name][version.int_version]['use_version'])
339
340 @property
341 def is_virtual(self):
342 return type_maps.class_is_virtual(self.c_name)
343
344 @property
345 def is_extension(self):
346 return type_maps.message_is_extension(self.c_name, -1)
347
348#######################################################################
349### Member
350#######################################################################
351
352
353class JavaMember(object):
354 """ Models a property (member) of an openflow class. """
355 def __init__(self, msg, name, java_type, member):
356 self.msg = msg
357 self.name = name
358 self.java_type = java_type
359 self.member = member
360 self.c_name = self.member.name if(hasattr(self.member, "name")) else ""
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700361
362 @property
363 def title_name(self):
364 return self.name[0].upper() + self.name[1:]
365
366 @property
367 def constant_name(self):
368 return self.c_name.upper()
369
370 @property
371 def default_name(self):
Andreas Wundsam27303462013-07-16 12:52:35 -0700372 if self.is_fixed_value:
373 return self.constant_name
374 else:
375 return "DEFAULT_"+self.constant_name
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700376
377 @property
378 def default_value(self):
379 java_type = self.java_type.public_type;
380
Andreas Wundsam27303462013-07-16 12:52:35 -0700381 if self.is_fixed_value:
382 return self.enum_value
383 elif re.match(r'List.*', java_type):
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700384 return "Collections.emptyList()"
385 elif java_type == "boolean":
386 return "false";
387 elif java_type in ("byte", "char", "short", "int", "long"):
388 return "({0}) 0".format(java_type);
389 else:
390 return "null";
391
392 @property
Andreas Wundsam27303462013-07-16 12:52:35 -0700393 def enum_value(self):
394 if self.name == "version":
395 return "OFVersion.%s" % self.msg.version.constant_version
396
397 java_type = self.java_type.public_type;
398 try:
399 global model
400 enum = model.enum_by_name(java_type)
401 entry = enum.entry_by_version_value(self.msg.version, self.value)
402 return "%s.%s" % ( enum.name, entry.name)
403 except KeyError, e:
404 print e.message
405 return self.value
406
407 @property
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700408 def is_pad(self):
Andreas Wundsam27303462013-07-16 12:52:35 -0700409 return isinstance(self.member, OFPadMember)
410
411 def is_type_value(self, version=None):
412 if(version==None):
413 return any(self.is_type_value(version) for version in self.msg.all_versions)
414 try:
415 return self.c_name in get_type_values(self.msg.c_name, version.int_version)
416 except:
417 return False
418
419 @property
420 def is_field_length_value(self):
421 return isinstance(self.member, OFFieldLengthMember)
422
423 @property
424 def is_length_value(self):
425 return isinstance(self.member, OFLengthMember)
426
427 @property
428 def is_public(self):
429 return not (self.is_pad or self.is_length_value)
430
431 @property
432 def is_data(self):
433 return isinstance(self.member, OFDataMember) and self.name != "version"
434
435 @property
436 def is_fixed_value(self):
437 return hasattr(self.member, "value") or self.name == "version" \
438 or ( self.name == "length" and self.msg.is_fixed_length) \
439 or ( self.name == "len" and self.msg.is_fixed_length)
440
441 @property
442 def value(self):
443 if self.name == "version":
444 return self.msg.version.int_version
445 elif self.name == "length" or self.name == "len":
446 return self.msg.length
447 elif self.java_type.public_type in ("int", "short", "byte") and self.member.value > 100:
448 return "0x%x" % self.member.value
449 else:
450 return self.member.value
451
452 @property
453 def is_writeable(self):
454 return self.is_data and not self.name in model.write_blacklist[self.msg.name]
455
456 def get_type_value_info(self, version):
457 return get_type_values(msg.c_name, version.int_version)[self.c_name]
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700458
459 @property
460 def length(self):
Andreas Wundsam27303462013-07-16 12:52:35 -0700461 if hasattr(self.member, "length"):
462 return self.member.length
463 else:
Andreas Wundsam5204de22013-07-30 11:34:45 -0700464 count, base = loxi_utils.type_dec_to_count_base(self.member.type)
Andreas Wundsam27303462013-07-16 12:52:35 -0700465 return of_g.of_base_types[base]['bytes'] * count
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700466
467 @staticmethod
Andreas Wundsam27303462013-07-16 12:52:35 -0700468 def for_of_member(java_class, member):
469 if isinstance(member, OFPadMember):
470 return JavaMember(None, "", None, member)
471 else:
472 if member.name == 'len':
473 name = 'length'
474 else:
475 name = java_type.name_c_to_camel(member.name)
476 j_type = java_type.convert_to_jtype(java_class.c_name, member.name, member.oftype)
477 return JavaMember(java_class, name, j_type, member)
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700478
479 @property
480 def is_universal(self):
Andreas Wundsam27303462013-07-16 12:52:35 -0700481 if not self.msg.c_name in of_g.unified:
482 print("%s not self.unified" % self.msg.c_name)
483 return False
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700484 for version in of_g.unified[self.msg.c_name]:
485 if version == 'union' or version =='object_id':
486 continue
487 if 'use_version' in of_g.unified[self.msg.c_name][version]:
488 continue
489
Andreas Wundsam27303462013-07-16 12:52:35 -0700490 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 -0700491 return False
492 return True
493
Andreas Wundsam27303462013-07-16 12:52:35 -0700494 def __hash__(self):
495 return hash(self.name)
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700496
Andreas Wundsam27303462013-07-16 12:52:35 -0700497 def __eq__(self, other):
498 if other is None or type(self) != type(other):
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700499 return False
Andreas Wundsam27303462013-07-16 12:52:35 -0700500 return (self.name,) == (other.name,)
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700501
Andreas Wundsame916d6f2013-07-30 11:33:58 -0700502
503#######################################################################
504### Unit Test
505#######################################################################
506
507class JavaUnitTest(object):
508 def __init__(self, java_class):
509 self.java_class = java_class
510 self.data_file_name = "of{version}/{name}.data".format(version=java_class.version.of_version,
511 name=java_class.c_name[3:])
512 @property
513 def package(self):
514 return self.java_class.package
515
516 @property
517 def name(self):
518 return self.java_class.name + "Test"
519
520 @property
521 def has_test_data(self):
522 return test_data.exists(self.data_file_name)
523
524 @property
525 @memoize
526 def test_data(self):
527 return test_data.read(self.data_file_name)
528
529
Andreas Wundsam27303462013-07-16 12:52:35 -0700530#######################################################################
531### Enums
532#######################################################################
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700533
Andreas Wundsam27303462013-07-16 12:52:35 -0700534class JavaEnum(object):
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -0700535 def __init__(self, c_name, version_enum_map):
Andreas Wundsam27303462013-07-16 12:52:35 -0700536 self.c_name = c_name
537 self.name = "OF" + java_type.name_c_to_caps_camel("_".join(c_name.split("_")[1:]))
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700538
Andreas Wundsam27303462013-07-16 12:52:35 -0700539 # Port_features has constants that start with digits
540 self.name_prefix = "PF_" if self.name == "OFPortFeatures" else ""
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700541
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -0700542 self.version_enums = version_enum_map
543
544 entry_name_version_value_map = OrderedDefaultDict(lambda: OrderedDict())
545 for version, ir_enum in version_enum_map.items():
546 for ir_entry in ir_enum.entries:
547 if "virtual" in ir_entry.params:
548 continue
549 entry_name_version_value_map[ir_entry.name][version] = ir_entry.value
550
Andreas Wundsam27303462013-07-16 12:52:35 -0700551 self.entries = [ JavaEnumEntry(self, name, version_value_map)
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -0700552 for (name, version_value_map) in entry_name_version_value_map.items() ]
Andreas Wundsam27303462013-07-16 12:52:35 -0700553 self.package = "org.openflow.protocol"
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700554
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -0700555 def wire_type(self, version):
556 ir_enum = self.version_enums[version]
557 if "wire_type" in ir_enum.params:
558 return java_type.convert_enum_wire_type_to_jtype(ir_enum.params["wire_type"])
559 else:
560 return java_type.u8
561
562 @property
563 def versions(self):
564 return self.version_enums.keys()
565
Andreas Wundsam27303462013-07-16 12:52:35 -0700566 @memoize
567 def entry_by_name(self, name):
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700568 try:
Andreas Wundsam27303462013-07-16 12:52:35 -0700569 return find(self.entries, lambda e: e.name == name)
570 except KeyError:
571 raise KeyError("Enum %s: no entry with name %s" % (self.name, name))
572
573 @memoize
574 def entry_by_c_name(self, name):
575 try:
576 return find(self.entries, lambda e: e.c_name == name)
577 except KeyError:
578 raise KeyError("Enum %s: no entry with c_name %s" % (self.name, name))
579
580 @memoize
581 def entry_by_version_value(self, version, value):
582 try:
583 return find(self.entries, lambda e: e.values[version] == value if version in e.values else False )
584 except KeyError:
585 raise KeyError("Enum %s: no entry with version %s, value %s" % (self.name, version, value))
586
587# values: Map JavaVersion->Value
588class JavaEnumEntry(object):
589 def __init__(self, enum, name, values):
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -0700590 self.enum = enum
Andreas Wundsam27303462013-07-16 12:52:35 -0700591 self.name = enum.name_prefix + "_".join(name.split("_")[1:]).upper()
592 self.values = values
593
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -0700594 def has_value(self, version):
595 return version in self.values
596
Andreas Wundsam27303462013-07-16 12:52:35 -0700597 def value(self, version):
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -0700598 return self.values[version]
599
600 def format_value(self, version):
601 res = self.enum.wire_type(version).format_value(self.values[version])
Andreas Wundsam27303462013-07-16 12:52:35 -0700602 return res
603
Andreas Wundsam27303462013-07-16 12:52:35 -0700604 def all_values(self, versions, not_present=None):
605 return [ self.values[version] if version in self.values else not_present for version in versions ]