{"id":8936,"date":"2024-05-27T18:00:20","date_gmt":"2024-05-27T18:00:20","guid":{"rendered":"https:\/\/modeling-languages.com\/?p=8936"},"modified":"2024-05-27T18:00:20","modified_gmt":"2024-05-27T18:00:20","slug":"ocl-interpreter","status":"publish","type":"post","link":"https:\/\/modeling-languages.com\/ocl-interpreter\/","title":{"rendered":"A new Object Constraint Language Interpreter in town"},"content":{"rendered":"
Object Constraint Language<\/a> (OCL) is a formal language that is widely used in the modelling community to complement the (UML<\/a>) models with textual constraints that precisely define additional business rules for the system.\u00a0<\/p>\r\n Despite the benefits of using OCL to create precise software specifications, writing the OCL rules themselves is a challenging task<\/strong> that may lead to a number of verification (are the OCL expressions correct?) and validation (are they the correct OCL expressions?) challenges. Formal methods techniques, such as smart bounded verification<\/a>, are typically used for the verification part. But for the validation part, we need to be able to “execute” or “evaluate” the OCL expressions over different valid and invalid scenarios<\/strong> to make sure the expressions forbid the invalid ones and allow the valid ones.\u00a0<\/p>\r\n Unfortunately, our search for an OCL interpreter able to run OCL expressions that was suitable to be integrated in the low-code low-modeling BESSER<\/a> platform came up empty. Not really a surprise, as OCL is probably the only language that has less and less tool support every year.<\/a> And the few OCL tools that exist (shoutout to USE<\/a> and Eclipse OCL)<\/a> are Java-based and by now you should already know that BESSER is Python-based.\u00a0<\/p>\r\n So, at the risk of reinventing the wheel, we decided to go ahead and add full OCL support to our modeling BESSER components<\/strong>, including a brand new OCL interpreter to evaluate OCL constraints on scenarios conforming to BESSER models.\u00a0<\/p>\r\n OCL is widely used in modelling domain and a rich set of tools support OCL interpretation such as eclipse modeling framework. Unfortunately, the available tool sets are only available in java language and to the best of our knowledge, there is no OCL interpreter available in python \ud83d\ude41<\/p>\r\n The first-ever open source OCL interpreter in python<\/strong> language. The beta version is available on GitHub<\/a> and it is ready to use. We have also provided two example BESSER<\/a> models and sample constraints in the models’ folder.<\/p>\r\n Remember that in the core BESSER platform<\/a> we already provided the OCL metamodel and parser so you were already able to annotate your B-UML models with OCL constraints<\/strong>. Or better said, with B-OCL constraints as we don’t claim to have fully compliant support with the OCL standard but a more pragmatic approach for now.\u00a0<\/p>\r\n The B-OCL interpreter adds to that the capability to actually execute those constraints and evaluate them on top of an object model, where each object is an instance of a B-UML class. The figure below shows the workflow for our B-OCL interpreter<\/p>\r\n <\/a><\/p>\r\n\r\n Let’s now see each step in more detail.<\/p>\r\n In the first step, we need a domain model. Let’s take an example of a simple team-player domain model containing a team and player class as shown in the figure below<\/p>\r\n <\/a><\/p>\r\n The corresponding B-UML code for defining the classes and association in the diagram is shown below (just keep in mind you don’t need to write this code by hand, BESSER has importers to automatically generate the model description from different sources!):<\/p>\r\n Now, let’s define some OCL constraints, starting with a simple one that the age should be greater than 10.<\/p>\r\n And the corresponding B-UML code is:<\/p>\r\n Similarly, let’s have a constraint where less than three players can play center:<\/p>\r\n And the corresponding B-UML code is:<\/p>\r\n Let’s combine all this into a domain model with the code:<\/p>\r\n In the second step, we need to define an object model for these constraints to be validated on. Now, let’s create the objects for our team-player domain model as shown in the figure below:<\/p>\r\nIntroducing the\u00a0BESSER Object Constraint Language (B-OCL) Interpreter<\/h2>\r\n
How to define and evaluate OCL constraints<\/h2>\r\n
First Step: Defining a domain Model<\/h3>\r\n
\r\n
# Primitive DataTypes
t_int: PrimitiveDataType = PrimitiveDataType(\"int\")
t_str: PrimitiveDataType = PrimitiveDataType(\"str\")
t_date: PrimitiveDataType = PrimitiveDataType(\"date\")
# Team attributes definition
team_name: Property = Property(name=\"name\", type=t_str)
team_city: Property = Property(name=\"city\", type=t_str)
team_division: Property = Property(name=\"division\", type=t_str)
# Team class definition
team: Class = Class (name=\"team\", attributes={team_name,team_city,team_division})
# Player attributes definition
name: Property = Property(name=\"name\", type=t_str)
age: Property = Property(name=\"age\", type=t_int)
position: Property = Property(name=\"position\", type=t_str)
jerseyNumber: Property = Property(name=\"jerseyNumber\", type=t_int)
# Player class definition
player: Class = Class (name=\"player\", attributes={name, age, position,jerseyNumber})
# team-player association definition
hasteam: Property = Property(name=\"many\",type=team, multiplicity=Multiplicity(1, 1))
many: Property = Property(name=\"has\", type=player, multiplicity=Multiplicity(0, \"*\"))
team_player_association: BinaryAssociation = BinaryAssociation(name=\"team_player_asso\", ends={hasteam, many})
<\/pre>\r\n<\/blockquote>\r\n<\/div>\r\n\r\n
\r\ncontext player inv inv1: self.age > 10<\/code><\/p>\r\n<\/blockquote>\r\n
\r\n
\r\nconstraintPlayerAge: Constraint = Constraint(name = \"playerAge\", context=player, expression=\"context player inv inv1: self.age > 10\", language=\"OCL\")\r\n <\/code><\/p>\r\n<\/blockquote>\r\n
\r\ncontext team inv inv2: self.many -> collect(p:player| p.position = 'center')->size()<3\r\n <\/code><\/p>\r\n
\r\nconstraintTeamCenter: Constraint = Constraint(name = \"teamCenter\", context=team, expression=\"context team inv inv2: self.many -> collect(p:player| p.position = 'center')->size()<3\", language=\"OCL\")\r\n <\/code><\/p>\r\n
\r\nteam_player_model : DomainModel = DomainModel(name=\"Team-Player model\", types={team, player}, associations={team_player_association}, constraints={constraintPlayerAge, constraintTeamCenter})\r\n <\/code><\/p>\r\n
Second Step: Defining an object Model<\/h3>\r\n