PlantUML-compatible grammar for structural models

A B-UML model can also be generated from a class model built with PlantUML . All you need is to provide the textual model (PlantUML) and our T2M transformation will produce the B-UML based model.

Let’s see an example with the classic library model. The textual model written in PlantUML is shown below.

 1@startuml
 2class Library {
 3+ name: str
 4+ address: str
 5+ findBook(title: str): Book
 6}
 7
 8class Book {
 9+ title: str
10+ pages: int
11+ release: date
12}
13
14class Author {
15+ name: str
16+ email: str
17+ member: MemberType
18+ notify(sms: str = "hello")
19}
20
21enum MemberType {
22    CHILD
23    ADULT
24    SENIOR
25    STUDENT
26}
27
28Book "*" -- "1..*" Author: writtenBy
29Library "1" -- "*" Book: has
30@enduml

And the diagram produced by PlantUML is as follows.

Library model

Save the PlantUML textual model in a file, e.g. library.plantuml. (.txt extension is also allowed)

Then, load and process the model using our grammar and apply the transformation to obtain the B-UML based model.

# Import methods and classes
from besser.BUML.notations.structuralPlantUML import plantuml_to_buml
from besser.BUML.metamodel.structural import DomainModel

# PlantUML to B-UML model
library_buml: DomainModel = plantuml_to_buml(plantUML_model_path='library.plantuml')

Note

The plantUML_model_path parameter contains the path and name of the .plantuml model to be transformed

library_buml is the B-UML model containing the domain specification. You can look up the classes, attributes, relationships, etc. For example, you can print the class names as follows.

# Print class names
for cls in library_buml.get_classes():
    print(cls.name)

You should get output like this:

Library
Book
Author

Warning

Although the PlantUML notation allows the definition of unnamed associations, for the BESSER platform it is necessary that all associations have a unique name.

B-UML model source code

When you run this PlantUML to B-UML transformation, you could also generate a .py file with the python based code of your B-UML model definition. This code is reusable, allowing you to make quick updates to your model. For example, you could add more classes, properties, or update the name of the ends of an association.

To generate the py file, set the buml_file_path parameter with your desired file path in the plantuml_to_buml method.

# Import methods and classes
from besser.BUML.notations.structuralPlantUML import plantuml_to_buml
from besser.BUML.metamodel.structural import DomainModel

# PlantUML to B-UML model
library_buml: DomainModel = plantuml_to_buml(plantUML_model_path='library.plantuml',
                                             buml_file_path="buml/model.py")

After running this code, the file model.py with your B-UML model source code will be created in the buml folder, containing content similar to the following example:

 1# Generated B-UML Model
 2from besser.BUML.metamodel.structural import (
 3    Class, Property, Method, Parameter,
 4    BinaryAssociation, Generalization, DomainModel,
 5    Enumeration, EnumerationLiteral, Multiplicity,
 6    StringType, IntegerType, FloatType, BooleanType,
 7    TimeType, DateType, DateTimeType, TimeDeltaType
 8)
 9
10# Enumerations
11MemberType: Enumeration = Enumeration(
12    name="MemberType",
13    literals={
14            EnumerationLiteral(name="ADULT"),
15			EnumerationLiteral(name="SENIOR"),
16			EnumerationLiteral(name="STUDENT"),
17			EnumerationLiteral(name="CHILD")
18    }
19)
20
21# Classes
22Book = Class(name="Book")
23Author = Class(name="Author")
24Library = Class(name="Library")
25
26# Book class attributes and methods
27Book_release: Property = Property(name="release", type=DateType)
28Book_title: Property = Property(name="title", type=StringType)
29Book_pages: Property = Property(name="pages", type=IntegerType)
30Book.attributes={Book_release, Book_title, Book_pages}
31
32# Author class attributes and methods
33Author_email: Property = Property(name="email", type=StringType)
34Author_member: Property = Property(name="member", type=MemberType)
35Author_m_method: Method = Method(name="method", parameters={Parameter(name='sms', type=StringType, default_value='message')})
36Author.attributes={Author_email, Author_member}
37Author.methods={Author_m_method}
38
39# Library class attributes and methods
40Library_name: Property = Property(name="name", type=StringType)
41Library_address: Property = Property(name="address", type=StringType)
42Library_m_findBook: Method = Method(name="findBook", parameters={Parameter(name='title', type=StringType)}, type=Book)
43Library.attributes={Library_name, Library_address}
44Library.methods={Library_m_findBook}
45
46# Relationships
47Has: BinaryAssociation = BinaryAssociation(
48    name="Has",
49    ends={
50        Property(name="Book_end", type=Book, multiplicity=Multiplicity(0, "*")),
51        Property(name="Library_end", type=Library, multiplicity=Multiplicity(1, 1))
52    }
53)
54BookAuthor_Relation: BinaryAssociation = BinaryAssociation(
55    name="BookAuthor_Relation",
56    ends={
57        Property(name="writtenBy", type=Author, multiplicity=Multiplicity(1, "*")),
58        Property(name="Book_end", type=Book, multiplicity=Multiplicity(0, "*"))
59    }
60)
61
62# Domain Model
63domain_model = DomainModel(
64    name="Generated_Model",
65    types={Book, Author, Library, MemberType},
66    associations={Has, BookAuthor_Relation},
67    generalizations={}
68)