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.pyfile. 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
5from besser.utilities import sort_by_timestamp
6
7class PythonGenerator(GeneratorInterface):
8 """
9 PythonGenerator is a class that implements the GeneratorInterface and is responsible
10 for generating the Python domain model code based on the input B-UML model.
11
12 Args:
13 model (DomainModel): An instance of the DomainModel class representing the B-UML model.
14 output_dir (str, optional): The output directory where the generated code will be
15 saved. Defaults to None.
16 """
17 def __init__(self, model: DomainModel, output_dir: str = None):
18 super().__init__(model, output_dir)
19
20 def generate(self, *args):
21 """
22 Generates Python domain model code based on the provided B-UML model and saves it to
23 the specified output directory.
24 If the output directory was not specified, the code generated will be stored in the
25 <current directory>/output folder.
26
27 Returns:
28 None, but store the generated code as a file named classes.py
29 """
30 file_path = self.build_generation_path(file_name="classes.py")
31 templates_path = os.path.join(os.path.dirname(
32 os.path.abspath(__file__)), "templates")
33 env = Environment(loader=FileSystemLoader(templates_path))
34 template = env.get_template('python_classes_template.py.j2')
35 with open(file_path, mode="w", encoding='utf-8') as f:
36 generated_code = template.render(domain=self.model, sort_by_timestamp=sort_by_timestamp)
37 f.write(generated_code)
38 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.
Registering Your Generator in the Web Editor¶
To make your generator available in the BESSER Web Modeling Editor, register
it in besser/utilities/web_modeling_editor/backend/config/generators.py. Each entry uses the
GeneratorInfo NamedTuple:
from besser.utilities.web_modeling_editor.backend.config.generators import GeneratorInfo
SUPPORTED_GENERATORS["my_generator"] = GeneratorInfo(
generator_class=MyGenerator,
output_type="zip", # "file" for single-file output, "zip" for archives
file_extension=".zip", # extension of the generated artifact
category="web_framework", # logical grouping (object_oriented, web_framework, database, etc.)
requires_class_diagram=True, # True if the generator needs a ClassDiagram as input
)
Set requires_class_diagram=False for generators that consume other diagram types
(e.g., agent diagrams, quantum circuits, deployment models).
You should also add a filename mapping in get_filename_for_generator() in the same file so
the download response uses a meaningful name.