Build Your Own Generator#
At BESSER, you can also build your own code generator. Code generators consist of M2T model-to-text transformations to automatically generate software artifacts from an input model (could be any type of model).
BESSER provides an interface (abstract class) called GeneratorInterface
that you can inherit to build your code
generator. This way, we standardize the use of BESSER code generators, improve maintainability, and usability (you can
check the code of
the GeneratorInterface in the repository).
As an example, let’s look at our Python class code generator below. Notice how this generator inherits from the
GeneratorInterface
class and defines two methods:
- Constructor method
__init__()
this method contains the parameters
model
(indicating the B-UML model) andoutput_dir
(the directory where the generated code will be stored) which is optional.
- Constructor method
generate()
methodto generate the
classes.py
file. The M2T transformation (lines 30 to 34) is performed using Jinja, a templating engine for generating template-based documents. However, you could use the tool of your choice for these transformations.
1import os
2from jinja2 import Environment, FileSystemLoader
3from besser.BUML.metamodel.structural import DomainModel
4from besser.generators import GeneratorInterface
5
6class PythonGenerator(GeneratorInterface):
7 """
8 PythonGenerator is a class that implements the GeneratorInterface and is responsible for generating
9 the Python domain model code based on the input B-UML model.
10
11 Args:
12 model (DomainModel): An instance of the DomainModel class representing the B-UML model.
13 output_dir (str, optional): The output directory where the generated code will be saved. Defaults to None.
14 """
15 def __init__(self, model: DomainModel, output_dir: str = None):
16 super().__init__(model, output_dir)
17
18 def generate(self):
19 """
20 Generates Python domain model code based on the provided B-UML model and saves it to the specified output directory.
21 If the output directory was not specified, the code generated will be stored in the <current directory>/output
22 folder.
23
24 Returns:
25 None, but store the generated code as a file named classes.py
26 """
27 file_path = self.build_generation_path(file_name="classes.py")
28 templates_path = os.path.join(os.path.dirname(
29 os.path.abspath(__file__)), "templates")
30 env = Environment(loader=FileSystemLoader(templates_path))
31 template = env.get_template('python_classes_template.py.j2')
32 with open(file_path, mode="w") as f:
33 generated_code = template.render(classes=self.model.classes_sorted_by_inheritance())
34 f.write(generated_code)
35 print("Code generated in the location: " + file_path)
Remember that in BESSER, B-UML models have a set of methods to facilitate their traversal. For example, for structural models,
the class.attributes
method gets the list of attributes of the class, class.all_attributes
gets the list of attributes
including the inherited ones (if the class inherits from another one), model.classes_sorted_by_inheritance()
gets the classes
of the model sorted according to the inheritance hierarchy, and so on. You can consult the API documentation for
more information.