blob: c01ba68afaae0554793ebce40ff7a19e36bdb33d [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
28"""
29@brief Main Java Generation module
30"""
31
Andreas Wundsam76db0062013-11-15 13:34:41 -080032import logging
Andreas Wundsam27303462013-07-16 12:52:35 -070033import pdb
34import os
35import shutil
36
Andreas Wundsam76db0062013-11-15 13:34:41 -080037import loxi_globals
Andreas Wundsam27303462013-07-16 12:52:35 -070038from loxi_ir import *
39import lang_java
Andreas Wundsame916d6f2013-07-30 11:33:58 -070040import test_data
Andreas Wundsam70aa5492013-10-23 15:26:53 -070041from collections import namedtuple
Yotam Harchol466b3212013-08-15 12:14:46 -070042from import_cleaner import ImportCleaner
Andreas Wundsam27303462013-07-16 12:52:35 -070043
Andreas Wundsam5420b952013-11-15 13:41:01 -080044import template_utils
Andreas Wundsam27303462013-07-16 12:52:35 -070045import loxi_utils.loxi_utils as loxi_utils
46
47import java_gen.java_model as java_model
48
Andreas Wundsam76db0062013-11-15 13:34:41 -080049logger = logging.getLogger(__name__)
50
51def gen_all_java(install_dir):
52 basedir= '%s/openflowj' % install_dir
53 logger.info("Outputting to %s" % basedir)
Andreas Wundsam27303462013-07-16 12:52:35 -070054 if os.path.exists(basedir):
55 shutil.rmtree(basedir)
56 os.makedirs(basedir)
57 copy_prewrite_tree(basedir)
Andreas Wundsam70aa5492013-10-23 15:26:53 -070058 gen = JavaGenerator(basedir, JavaGeneratorOptions(instrument=True))
Andreas Wundsam27303462013-07-16 12:52:35 -070059 gen.create_of_interfaces()
60 gen.create_of_classes()
61 gen.create_of_const_enums()
Andreas Wundsam5204de22013-07-30 11:34:45 -070062 gen.create_of_factories()
Andreas Wundsam27303462013-07-16 12:52:35 -070063
Andreas Wundsam70aa5492013-10-23 15:26:53 -070064JavaGeneratorOptions = namedtuple("JavaGeneratorOptions", ("instrument",))
Andreas Wundsam27303462013-07-16 12:52:35 -070065
66class JavaGenerator(object):
67 templates_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'templates')
68
Andreas Wundsam70aa5492013-10-23 15:26:53 -070069 def __init__(self, basedir, gen_opts):
Andreas Wundsam27303462013-07-16 12:52:35 -070070 self.basedir = basedir
71 self.java_model = java_model.model
Andreas Wundsam70aa5492013-10-23 15:26:53 -070072 self.gen_opts = gen_opts
Andreas Wundsam27303462013-07-16 12:52:35 -070073
Andreas Wundsame916d6f2013-07-30 11:33:58 -070074 def render_class(self, clazz, template, src_dir=None, **context):
75 if not src_dir:
76 src_dir = "src/main/java/"
77
Andreas Wundsam27303462013-07-16 12:52:35 -070078 context['class_name'] = clazz.name
79 context['package'] = clazz.package
Andreas Wundsamd10e1c52013-08-01 22:02:49 -070080 context['template_dir'] = self.templates_dir
Andreas Wundsam70aa5492013-10-23 15:26:53 -070081 context['genopts']= self.gen_opts
Andreas Wundsam27303462013-07-16 12:52:35 -070082
Andreas Wundsame916d6f2013-07-30 11:33:58 -070083 filename = os.path.join(self.basedir, src_dir, "%s/%s.java" % (clazz.package.replace(".", "/"), clazz.name))
Andreas Wundsam27303462013-07-16 12:52:35 -070084 dirname = os.path.dirname(filename)
85 if not os.path.exists(dirname):
86 os.makedirs(dirname)
87 prefix = '//::(?=[ \t]|$)'
Andreas Wundsamc8912c12013-11-15 13:44:48 -080088 logger.debug("rendering filename: %s" % filename)
Andreas Wundsam27303462013-07-16 12:52:35 -070089 with open(filename, "w") as f:
Andreas Wundsam5420b952013-11-15 13:41:01 -080090 template_utils.render_template(f, template, [self.templates_dir], context, prefix=prefix)
Andreas Wundsam70aa5492013-10-23 15:26:53 -070091
Yotam Harchol466b3212013-08-15 12:14:46 -070092 try:
93 cleaner = ImportCleaner(filename)
94 cleaner.find_used_imports()
95 cleaner.rewrite_file(filename)
96 except:
Andreas Wundsamc8912c12013-11-15 13:44:48 -080097 logger.info('Cannot clean imports from file %s' % filename)
Andreas Wundsam27303462013-07-16 12:52:35 -070098
99 def create_of_const_enums(self):
100 for enum in self.java_model.enums:
101 if enum.name in ["OFPort"]:
102 continue
103 self.render_class(clazz=enum,
104 template='const.java', enum=enum, all_versions=self.java_model.versions)
105
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -0700106 for version in enum.versions:
Andreas Wundsamc8912c12013-11-15 13:44:48 -0800107 clazz = java_model.OFGenericClass(package="org.projectfloodlight.openflow.protocol.ver{}".format(version.dotless_version), name="{}SerializerVer{}".format(enum.name, version.dotless_version))
Andreas Wundsam7cfeac32013-09-17 13:53:48 -0700108
109 if enum.is_bitmask:
110 self.render_class(clazz=clazz, template="const_set_serializer.java", enum=enum, version=version)
111 else:
112 self.render_class(clazz=clazz, template="const_serializer.java", enum=enum, version=version)
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -0700113
Andreas Wundsam27303462013-07-16 12:52:35 -0700114 def create_of_interfaces(self):
115 """ Create the base interfaces for of classes"""
116 for interface in self.java_model.interfaces:
117 #if not utils.class_is_message(interface.c_name):
118 # continue
119 self.render_class(clazz=interface,
120 template="of_interface.java", msg=interface)
121
122 def create_of_classes(self):
123 """ Create the OF classes with implementations for each of the interfaces and versions """
124 for interface in self.java_model.interfaces:
Andreas Wundsam27303462013-07-16 12:52:35 -0700125 for java_class in interface.versioned_classes:
Andreas Wundsam001b1822013-08-02 22:25:55 -0700126 if self.java_model.generate_class(java_class):
127 if not java_class.is_virtual:
128 self.render_class(clazz=java_class,
129 template='of_class.java', version=java_class.version, msg=java_class,
130 impl_class=java_class.name)
Andreas Wundsam27303462013-07-16 12:52:35 -0700131
Andreas Wundsam001b1822013-08-02 22:25:55 -0700132 self.create_unit_test(java_class.unit_test)
133 else:
134 disc = java_class.discriminator
135 if disc:
136 self.render_class(clazz=java_class,
137 template='of_virtual_class.java', version=java_class.version, msg=java_class,
138 impl_class=java_class.name, model=self.java_model)
139 else:
Andreas Wundsamc8912c12013-11-15 13:44:48 -0800140 logger.warn("Class %s virtual but no discriminator" % java_class.name)
Andreas Wundsam001b1822013-08-02 22:25:55 -0700141 else:
Andreas Wundsamc8912c12013-11-15 13:44:48 -0800142 logger.info("Class %s ignored by generate_class" % java_class.name)
Andreas Wundsame916d6f2013-07-30 11:33:58 -0700143
Yotam Harchol466b3212013-08-15 12:14:46 -0700144 def create_unit_test(self, unit_tests):
145 if unit_tests.has_test_data:
146 for i in range(unit_tests.length):
147 unit_test = unit_tests.get_test_unit(i)
148 if unit_test.has_test_data:
149 self.render_class(clazz=unit_test,
150 template='unit_test.java', src_dir="src/test/java",
151 version=unit_test.java_class.version,
152 test=unit_test, msg=unit_test.java_class,
153 test_data=unit_test.test_data)
Andreas Wundsame916d6f2013-07-30 11:33:58 -0700154
155 def create_of_factories(self):
Andreas Wundsame0d52be2013-08-22 07:52:13 -0700156 for factory in self.java_model.of_factories:
157 self.render_class(clazz=factory, template="of_factory_interface.java", factory=factory)
158 for factory_class in factory.factory_classes:
159 self.render_class(clazz=factory_class, template="of_factory_class.java", factory=factory_class, model=self.java_model)
Yotam Harchol791e4882013-09-05 16:32:56 -0700160 self.render_class(clazz=java_model.OFGenericClass(package="org.projectfloodlight.openflow.protocol", name="OFFactories"), template="of_factories.java", versions=self.java_model.versions)
Andreas Wundsame916d6f2013-07-30 11:33:58 -0700161
Andreas Wundsam27303462013-07-16 12:52:35 -0700162def copy_prewrite_tree(basedir):
163 """ Recursively copy the directory structure from ./java_gen/pre-write
164 into $basedir"""
Andreas Wundsamc8912c12013-11-15 13:44:48 -0800165 logger.info("Copying pre-written files into %s" % basedir)