Structural model¶
The structural metamodel enables the specification of a domain model using the typical concepts of a class diagram. Elements such as Classes, Properties, Associations, and Generalizations can be instantiated to define the static structure of a system or application. While this metamodel is rooted in the UML specification, certain modifications and additions have been implemented to provide additional modeling capabilities. For instance, the is_id attribute has been introduced in the Property class to specify whether a property serves as an identifier for the instances of that class, a common need in many code generation scenarios.
Note
This figure contains only the main classes, attributes, and methods of the B-UML language. For a detailed description please refer to the API documentation.
Available Data Types¶
BESSER provides a comprehensive set of primitive data types for modeling. The available types include StringType,
IntegerType, FloatType, BooleanType, DateType, TimeType, DateTimeType, TimeDeltaType
and AnyType. These types can be used to define properties and attributes in your structural models.
Method Implementations¶
A Method can declare how its behavior is implemented through implementation_type
(a MethodImplementationType):
NONE: signature only (plain UML).CODE: Python code stored incode.BAL: BESSER Action Language code stored incode.STATE_MACHINE: behavior defined by a state machine (state_machine).QUANTUM_CIRCUIT: behavior defined by a quantum circuit (quantum_circuit).NEURAL_NETWORK: behavior defined by a neural network (neural_network); calling the method runs the NN.
When a behavior model is passed and implementation_type is omitted, the type is detected
automatically:
from besser.BUML.metamodel.nn import NN
classifier = NN(name="ImageClassifier")
predict = Method(name="predict", parameters={Parameter(name="image", type=StringType)},
type=StringType, neural_network=classifier)
assert predict.implementation_type == MethodImplementationType.NEURAL_NETWORK
In the web modeling editor, choose the implementation type in the method’s popup, then pick the linked diagram from the project (the NN option lists the project’s NN diagrams). The Backend and Web App generators turn NN-implemented methods into endpoints that run the network.
Association Navigability¶
Each end of a BinaryAssociation is a Property whose is_navigable flag (True by
default) states whether the associated class can be reached through that end. Both ends navigable
gives a bidirectional association; one non-navigable end gives a one-way association. Two rules apply:
at least one end must be navigable;
in a composition, the non-composite (part) end must be navigable. The composite (whole) end may be non-navigable.
Creating an association that breaks either rule raises a ValueError. Ends changed afterwards
(e.g. end.is_navigable = False) are reported as errors by DomainModel.validate().
from besser.BUML.metamodel.structural import (
BinaryAssociation, Class, DomainModel, Multiplicity, Property,
)
order = Class(name="Order")
line = Class(name="OrderLine")
# Composition: Order (whole) owns its lines; the line -> order direction is not navigable
order_end = Property(name="order", type=order, multiplicity=Multiplicity(1, 1),
is_composite=True, is_navigable=False)
lines_end = Property(name="lines", type=line, multiplicity=Multiplicity(0, "*"))
order_lines = BinaryAssociation(name="Order_Lines", ends={order_end, lines_end})
model = DomainModel(name="Shop", types={order, line}, associations={order_lines})
assert model.validate(raise_exception=False)["success"]
lines_end.is_navigable = False # now no end is navigable, and the part end of the composition is not
for error in model.validate(raise_exception=False)["errors"]:
print(error)
# Association 'Order_Lines': at least one end must be navigable, but both 'lines' (OrderLine) and 'order' (Order) are non-navigable
# Association 'Order_Lines': the non-composite end 'lines' (OrderLine) of a composition must be navigable
In the web modeling editor, every plain association is drawn as an Association whose ends each carry a Navigable toggle; compositions and aggregations carry the same per-end toggle. Diagrams saved with the former Unidirectional association type are loaded as an Association whose source end is not navigable.
Validation¶
The structural metamodel performs validation at multiple levels:
Construction validation:
NamedElement.namesetters rejectNone, empty, or whitespace-only names and warn when the name is a Python keyword.Attribute shadowing:
DomainModel.validate()checks that subclass attributes do not shadow inherited attributes from parent classes. A warning is raised if a subclass defines an attribute with the same name as one already present in a superclass.Association navigability:
DomainModel.validate()reports binary associations with no navigable end, and compositions whose part end is not navigable (see Association Navigability).
result = domain_model.validate()
# result contains errors and warnings about the model structure
Supported notations¶
To create a structural model, you can use any of these notations: