Projet de Génie logiciel et des systèmes Rapport

Projet de Génie logiciel et des systèmes
Rapport
Département Informatique et Mathématiques Appliquées
INP-ENSEEIHT
Guillaume Kempf - 2INA - Promotion 2015
Enseignants en charge de l’unité d’enseignement :
Dr. Xavier Cregut et Dr. Marc Pantel
24 novembre 2013
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
Table des matières
Introduction
3
Partie I - Chaîne de vérification de modèle de processus
1.1 Méta-modélisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.1.1 Modèle du processus via SimplePDL sans ressources . . . . . . . . .
1.1.2 Modèle du processus via SimplePDL avec ressources simples . . . . .
1.1.3 Modèle du réseau de Petri - PetriNet . . . . . . . . . . . . . . . . . .
1.2 Principe de conversion d’un SimplePDL en un PetriNet . . . . . . . . . . .
1.3 Définition des contraintes OCL (SimplePDL et PetriNet) . . . . . . . . . . .
1.3.1 Contraintes OCL pour SimplePDL . . . . . . . . . . . . . . . . . . .
1.3.2 Contraintes OCL pour PetriNet . . . . . . . . . . . . . . . . . . . . .
1.3.3 Exemple de fichier xmi attestant des contraintes OCL . . . . . . . .
1.4 Transformation de modèles à textes . . . . . . . . . . . . . . . . . . . . . . .
1.4.1 Génération d’un fichier .dot à partir d’un PetriNet - PetriNet2dot . .
1.4.2 Génération d’un fichier .net à partir d’un PetriNet - PetriNet2Tina .
1.5 Définition de syntaxes concrètes textuelles via Text . . . . . . . . . . . . . .
1.5.1 Définition des syntaxes concrètes textuelles pour SimplePDL . . . .
1.5.2 Définition des syntaxes concrètes textuelles pour PetriNet . . . . . .
1.6 Définition de syntaxes concrètes graphiques . . . . . . . . . . . . . . . . . .
1.7 Utilisation de l’infrastructure fournie par EMF pour manipuler les modèles .
1.7.1 Génération du code Java pour SimplePDL et PetriNet . . . . . . . .
1.7.2 Utilisation du code Java/EMF pour manipuler les modèles . . . . . .
1.7.3 Exemple de conversion de modèles sans ressources . . . . . . . . . .
1.7.4 Exemple de conversion de modèles avec ressources . . . . . . . . . .
1.8 Définition de transformation de modèle à modèle (M2M) avec ATL . . . . .
1.8.1 Utilisation d’ATL pour convertir SimplePDL en PetriNet . . . . . .
1.8.2 Exemple de conversion d’un SimplePDL en PetriNet via ATL . . . .
1.9 Synthèse de la transformation . . . . . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
4
4
4
5
7
8
10
10
10
11
11
11
12
12
13
13
14
15
15
16
17
18
21
21
22
22
Partie II - Ressources alternatives
2.1 Modèle du processus SimplePDL avec les ressources alternatives
2.1.1 Mise à jour du Méta-modèle . . . . . . . . . . . . . . . .
2.1.2 Mise à jour de l’équivalence WorkDefinition - PetriNet .
2.2 Ressources alternatives, transformation SimplePDL - PetriNet .
2.2.1 Ressources alternatives, première possibilité . . . . . . .
2.2.2 Ressources alternatives, deuxième possibilité . . . . . . .
2.3 Utilisation d’ATL pour convertir SimplePDL en PetriNet . . . .
Manipulation de modèles en ATL . . . . . . . . . . . . . . . . .
Raffinage du fichier SimplePDL2PetriNet.atl . . . . . . . . . . .
Choix d’implantation . . . . . . . . . . . . . . . . . . . . . . . .
2.4 Contraintes LTL - Linear Temporal Logic . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
24
24
24
25
26
26
27
29
29
29
29
29
Projet I
1
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
2.4.1 Génération et interprétation des contraintes LTL à l’aide
2.4.2 Résultats des contraintes LTL . . . . . . . . . . . . . . .
Notre exemple file-rouge . . . . . . . . . . . . . . . . . . . . . .
2.5.1 Conversion des modèles . . . . . . . . . . . . . . . . . .
2.5.2 Réalisations des tests selon les contraintes LTL . . . . .
Synthèse de la transformation . . . . . . . . . . . . . . . . . . .
2.5
2.6
d’Acceleo
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
30
30
31
31
32
35
Conclusion
36
ANNEXES
38
Partie
1.1
1.2
1.3
1.4
1.5
1.6
1.7
1.8
I - Chaîne de vérification de modèle
SimplePDL2PetriNet.java . . . . . . . .
PetriNet2dot.mtl . . . . . . . . . . . . .
PetriNet2Tina.mtl . . . . . . . . . . . .
PDL1.xtext . . . . . . . . . . . . . . . .
PDL2.xtext . . . . . . . . . . . . . . . .
Perti1.xtext . . . . . . . . . . . . . . . .
Perti2.xtext . . . . . . . . . . . . . . . .
SimplePDL2PetriNet.atl . . . . . . . . .
.
.
.
.
.
.
.
.
38
38
46
46
47
48
49
50
50
Partie II - Ressources alternatives
1.9 SimplePDL2PetriNet.atl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.10 SimplePDLfinish.mtl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.11 validationPetri.mtl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
55
55
60
60
Projet I
2
de
. .
. .
. .
. .
. .
. .
. .
. .
processus
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
Introduction
L’objet de ce rapport est de développer et d’analyser la transformation de méta-modèles réalisée lors du projet de Génie du Logiciel et des Systèmes. Ce projet consiste à produire une chaîne
de vérification de modèle de processus SimplePDL. Il est nécessaire de pouvoir vérifier la cohérence d’un tel modèle de processus, en particulier de savoir si le processus décrit peut se terminer
ou non. Pour s’en assurer, nous utilisons les outils de model-checking définis sur les réseaux de
Petri au travers de la boîte à outil Tina. Le projet repose principalement sur la traduction d’un
modèle de processus SimplePDL en un réseau de Petri.
Le projet est séparé en deux parties. La première consiste pour l’essentiel à définir la chaîne
de vérification de modèle de processus sur une version simplifiée des modèles de processus. Ce
travail à été en partie fait lors des Travaux Pratiques et finalisé pour le BE. Les principales étapes
sont les suivantes :
1. Définition des méta-modèles avec Ecore,
2. Définition de la sémantique statique avec OCL,
3. Utilisation de l’infrastructure fournie par EMF pour manipuler les modèles,
4. Définition de transformation modèle à texte (M2T) avec Acceleo, par exemple pour engendrer la syntaxe attendue par Tina à partir d’un modèle de réseau de Petri ou engendrer les
propriétés LTL à partir d’un modèle de processus,
5. Définition de syntaxes concrètes textuelles avec Xtext,
6. Définition de syntaxes concrètes graphiques avec Obeo Designer,
7. Définition de transformation de modèle à modèle (M2M) avec ATL.
Le compte-rendu des séances de Travaux Pratiques est joint à ce rapport.
La deuxième partie du rapport est axée sur l’ajout de ressources : pour réaliser une activité,
celle-ci doit disposer d’un certain nombre de ressources. Une extension du modèle de processus
est également proposée en considérant des ressources alternatives. Plusieurs configurations de
ressources pourront permettre de réaliser une activité. Par exemple, rédiger les tests peut nécessiter soit un testeur et deux machines, soit un analyste et un générateur de test et une machine.
Si l’un de ces deux ensembles de ressources est disponible, il est utilisé par l’activité qui peut
alors commencer.
Dans ce rapport, je vous présente les résultats que j’ai atteints à l’issu de mon travail personnel
au cours des deux mois consacrés à ce projet, ainsi que les directions et les choix pris pour y
arriver. Enfin, vous trouverez en annexe les sources du projet, celles-ci fonctionnent de manière
optimale sur eclipse-indigo.
Projet I
3
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
Partie I - Chaîne de vérification de
modèle de processus
1.1
Méta-modélisation
1.1.1
Modèle du processus via SimplePDL sans ressources
Nous nous intéressons à des modèles de processus composés d’activités et de dépendances
entre ces activités. Le modèle de procédé utilisé est inspiré de SPEM 1, norme de l’OMG. Nous
donnons entre parenthèses le vocabulaire utilisé par cette norme. Dans un premier temps, nous
nous intéressons à des processus simples composés seulement d’activités (WorkDefinition) et de
dépendances (WorkSequence). La figure 1 donne un exemple de processus qui comprend quatre
activités : Conception, Rédaction-Doc, Développement et RédactionTests. Les activités sont représentées par des ovales. Les arcs entre activités représentent les dépendances. Une étiquette
permet de préciser la nature de la dépendance sous la forme « étatToAction » qui précise l’état
qui doit être atteint par l’activité source pour réaliser l’action sur l’activité cible. Par exemple,
on ne peut commencer RédactionTests que si Conception est commencée. On ne peut commencer Développement que si Conception est terminée. On ne peut terminer RédactionTests que si
Développement est terminé.
Figure 1.1 – Exemple de modèle de procédé - SimplePDL
Pour développer ce modèle et l’utiliser pour le projet, il est nécessaire de le modéliser sous forme
de diagramme UML. Nous utiliserons les méta-modèles EMOF (OMG) ou Ecore (Eclipse) pour
modéliser et permettre la définition du méta-modèle SimplePDL. Un extrait d’Ecore est donné
à la figure 2. La figure 3 donne le méta-modèle du langage SimplePDL, un langage très simplifié
de description des procédés de développement. Ce méta-modèle est conforme à EMOF/Ecore.
Il a été dessiné en utilisant les conventions traditionnellement utilisées qui sont empruntées au
diagramme de classe UML.
Projet I
4
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
Figure 1.2 – Version très simplifiée du méta-modèle Ecore
Figure 1.3 – Méta-modèle simplifié de SimplePDL conforme à EMOF/Ecore - Sans les ressources
1.1.2
Modèle du processus via SimplePDL avec ressources simples
Pour réaliser une activité, des ressources peuvent être nécessaires. Une ressource peut correspondre à un acteur humain, un outil ou tout autre élément jouant un rôle dans le déroulement
de l’activité. Ici, nous nous intéressons simplement aux types de ressources nécessaires et au
nombre d’occurrences d’un type de ressource. Par exemple, il peut y avoir deux développeurs,
deux concepteurs, trois machines, un bloc-note, etc. Un type de ressource sera seulement caractérisé par son nom et la quantité d’occurrences de celle-ci. Pour pouvoir être réalisée, une
activité peut nécessiter plusieurs ressources (éventuellement aucune). Par exemple, l’activité RedactionTest nécessite un développeur (une occurrence de la ressource de type Développeur) et
deux machines (deux occurrences de la ressource Machine). Les occurrences de ressources nécessaires à la réalisation d’une activité sont prises au moment de son démarrage et rendues à la
fin de son exécution. Bien entendu, une même occurrence de ressource ne peut pas être utilisée
simultanément par plusieurs activités. Les types de ressource et leur nombre d’occurrences sont
définis en même temps que le procédé lui-même. Voici une affectation possible de ressources pour
le processus décrit à la figure 4. Une ligne correspond à un type de ressource. Elle indique la
quantité totale de la ressource ainsi que le nombre d’occurrences de cette ressource nécessaire à
la réalisation d’une activité.
Projet I
5
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
Figure 1.4 – Exemple de répartition des ressources
Afin de prendre en compte les ressources, j’ai été amené à modifier le digramme UML de
SimplePDL. Ma démarche fut de regrouper les ressources à l’aide d’une classe abstraite Ressources
qui hérite de la classe ProcessElement pour pouvoir être ajouté à un Process via le lien de
contenance tout en ayant un lien direct avec ProcessElement, ce lien d’héritage sera utile lors de
la conversion de modèle par ATL. Une Ressources a un nom symbolisant sont type de ressource et
un nombre de jetons disponibles ou nécessaires. J’ai ensuite distingué deux ressources possibles :
les ressources disponibles à l’aide de la classe RessourcesDisponibles et les ressources nécessaires
via la classe RessourcesRequieses. Toutes deux héritent de Ressources. Les ressources disponibles
sont directement rattachées au Process, tandis que les ressources requises sont possédées par les
WorkDefinition (matérialisé par un besoin en ressource) et utilisent des ressources disponibles.
Figure 1.5 – Méta-modèle de SimplePDL conforme à EMOF/Ecore - Avec les ressources
Projet I
6
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
1.1.3
Modèle du réseau de Petri - PetriNet
Rappel : Réseaux de Petri
Le rappel donné ici est extrait de http://fr.wikipedia.org/wiki/R%C3%A9seau_de_Petrir
Définition Un réseau de Petri est un tuple (S, T, F, M0 , W) où :
– S définit une ou plusieurs places.
– T définit une ou plusieurs transitions.
– F définit un ou plusieurs arcs (flèches).
– Un arc ne peut pas être connecté entre 2 places ou 2 transitions ; plus formellement : F ⊆
(S × T) ∪ (T × S).
– M0 : S → N appelé marquage initial (ou parfois place initiale), où, pour chaque place s 2
∈ S, il y a n ∈ N jetons.
– W : F → N+ appelé ensemble d’arcs primaires , assignés à chaque arc f ∈ F un entier
positif n ∈ N+ qui indique combien de jetons sont consommés depuis une place vers une
transition, ou sinon, combien de jetons sont produis par une transition et arrivent pour
chaque place. De nombreuses définitions formelles existent. Cette définition concerne un
réseau place-transition (ou P-T).
Représentation Un réseau de Petri se représente par un graphe orienté composé d’arcs reliant des places et des transitions. Deux places ne peuvent pas être reliées entre elles, ni deux
transitions. Les places peuvent contenir des jetons. La distribution des jetons dans les places
est appelée le marquage du réseau de Petri. Le marquage d’un réseau de Petri caractéristique
l’état de ce réseau à une étape de son exécution. Les entrées d’une transition sont les places
desquelles part une flèche pointant vers cette transition, et les sorties d’une transition sont les
places pointées par une flèche ayant pour origine cette transition. La figure 7 propose quelques
exemples de réseaux de Petri.
Figure 1.6 – Exemples de réseaux de Petri
Dynamique d’exécution Un réseau de Petri évolue lorsqu’on exécute 2 une transition : des
jetons sont pris dans les places en entrée de cette transition et envoyés dans les places en sortie
de cette transition. Le nombre de jetons pris dans les places d’entrée et mis dans les places de
sortie est celui indiqué par l’arc correspondant. Une transition ne peut être exécutée que si elle est
exécutable, c’est-à-dire qu’il y a dans chaque place d’entrée un nombre de jetons au moins égal au
nombre de jetons indiqué sur l’arc. L’exécution d’une transition est une opération indivisible qui
est déterminée par la présence du jeton sur la place d’entrée. Une exécution possible d’un réseau
de Petri est une séquence de marquage correspond aux états du réseau au fur et à mesure de
son exécution. Le passage d’un état à l’état suivant se fait par l’exécution d’une seule transition.
L’exécution d’un réseau de Petri n’est pas déterministe, car il peut y avoir plusieurs possibilités
d’évolution à un instant donné. Si chaque transition dans un réseau de Petri a exactement une
entrée et une sortie alors ce réseau est un automate fini.
Projet I
7
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
Modélisation du Réseaux Petri Pour modéliser le Réseaux Petri, j’ai considéré 5 classes.
La première est la classe ReseauPetri dont le seul rôle est de contenir l’ensemble des éléments du
réseau. Un PetriNet étant composé d’arcs, de places et de transitions, j’ai décidé de regrouper
les places et les transitions en créant la classe abstraite Lieu de laquelle vont hériter les classes
Place et Transition dans un souci d’économie de code et de gain en modularité. Enfin, la classe
Arc permettra d’être reliée à différents lieu en définissant un prédécesseur et un successeur. Enfin
l’énumération TypeArc permet de qualifier un arc de type Normal ou ReadArc.
Figure 1.7 – Diagramme UML de ResreauPetri
Ma démarche fut de créer un modèle épuré, fonctionnel et facile à comprendre. Certaines
contraintes ne sont pas respectées par ce modèle. Par exemple, un arc pourrait relier deux places
entre elles alors que cela est impossible. Pour pallier à ces éventualités, je me suis reposé sur les
contraintes OCL développées plus tard dans ce rapport.
1.2
Principe de conversion d’un SimplePDL en un PetriNet
L’objet du projet étant la conversion d’un SimplePDL en PetriNet, il est nécessaire de trouver
une équivalence entre une workDefinition et un Réseau de Petri. Dans un premier temps nous
allons considérer qu’une workDefinition est équivalent à quatre places, deux transitions et 5 arcs
comme explosé dans à l’aide de la figure 6.
Projet I
8
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
Figure 1.8 – Equivalence WorkDefinition - PetriNet
Concernant la conversion des WorkSequence, nous utiliserons un Arc reliant les places started
ou finished aux transitions starts ou finishes selon la nature de la liaison.
Figure 1.9 – Equivalence WorkSequence - PetriNet
Projet I
9
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
1.3
Définition des contraintes OCL (SimplePDL et PetriNet)
Dans cette section sera développée la définition des contraintes OCL (Object Constraint Language) pour capturer les contraintes qui n’ont pu l’être par les méta-modèles. OCL permet avant
tout d’appréhender la vérification statique d’un méta-modèle par la création d’une sémantique
statique sous forme de DSML (Directory Service Markup Language). Les contraintes se réalisent
à l’aide d’invariants agissant principalement sur les attributs des classes.
1.3.1
Contraintes OCL pour SimplePDL
Ci-dessous la liste des contraintes OCL affectées au méta-modèle SimplePDL :
class Process – une WorkDefinition ne peuvent pas avoir le même nom
invariant ActivitesMemeNom1:
self.processElements->select(a : ProcessElement |
a.oclIsTypeOf(WorkDefinition))->forAll(WD1 : ProcessElement,
WD2 : ProcessElement | WD1 <> WD2 implies WD1.name <> WD2.name);
– un Process ne peut porter le nom "process"
invariant nameForbidden: name <> ’Process’;
class WorkDefinition – Une WorkDefinition doit avoir un nom
invariant NomAuMoinsUnCaractere: self.name <> ’’;
– deux WorkDefinition ne peuvent pas avoir le même nom (redondance avec la contrainte
ActivitesMemeNom1)
invariant ActivitesMemeNom2:
WorkDefinition.allInstances()->forAll(WD1 : WorkDefinition,
WD2 : WorkDefinition | WD1 <> WD2 implies WD1.name <> WD2.name);
class WorkSequence – Les WorkDefinition à relier doivent être dans le même Process (Contrôle
de chaque prédécesseur)
invariant previousWDinSameProcess: self.process =
self.predecessor.process;
– Impossibilité de relier une WorkDefinition à elle-même
invariant SequenceNonReflective: self.predecessor <> self.successor;
– Les WorkDefinition à relier doivent être dans le même Process (Contrôle de chaque
successeur) - redondance avec previousWDinSameProcess
invariant nextWDinSameProcess: self.process = self.successor.process;
class Ressources – Les ressources doivent avoir un nombre de jeton non négatif ou nul
invariant ressourceInitialeNonNagativeNulle: self.ressourceNombre > 0;
1.3.2
Contraintes OCL pour PetriNet
Ci-dessous la liste des contraintes OCL affectées au méta-modèle PetriNet :
class ReseauPetri – un ReseauPetri doit avoir un nom
invariant NomAuMoinsUnCaractere: self.Name <> ’’;
class Arc – Un Arc doit transmettre un nombre positif de jetons
invariant ArcValeurPositive: self.Valeur > 0;
– Un Arc ne peut pas relier une place à une place ou une transition à une transition (évite
également de relier un lieu à lui même)
Projet I
10
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
invariant NePeutRelierPlacePlaceOuTransitionTransition:
(self.Predecessor.oclIsTypeOf(Place) implies
self.Successor.oclIsTypeOf(Transition)) and
(self.Predecessor.oclIsTypeOf(Transition) implies
self.Successor.oclIsTypeOf(Place));
class Lieu – Un Lieu doit avoir un nom
invariant NomAuMoinsUnCaractere: self.Name <> ’’;
class Place – Une place ne peut pas avoir un nombre de jetons négatif.
invariant NbJetonNonNegatifOunul: self.NbJeton >= 0;
1.3.3
Exemple de fichier xmi attestant des contraintes OCL
Voici la liste des fichiers xmi joint avec le rapport, permettant d’attester de la pertinence des
contraintes OCL.
Pour les contraintes relatives au SimplePDL :
– KODependanceReflective.xmi
– KONomAuMoinsUnCaractere.xmi
– KONomEstProcess.xmi
– KOProcessDeuxActivitesMemeNom.xmi
– KOressourceInitialeNonNagativeNulle.xmi
– OKProcessMangerDormirTravailler.xmi
– pdl-sujet.xmi
– pdl-sujet2.xmi
Pour les contraintes relatives au PetriNet :
– KOArcValeurPositive.xmi
– KONbJetonNonNegatifOunul.xmi
– KONomAuMoinsUnCaractere.xmi
– KOPetriNetErreurRelierPlacePlace.xmi
– OKQuatreSaisons.xmi
– pdl-sujetViaSimplePDL2PetriNet.xmi
– PertiNet_From_SimplePDL.xmi
– PertiNet_From_SimplePDL2.xmi
– pnexemplesujet.xmi
1.4
Transformation de modèles à textes
Cette section aborde le principe de la transformation modèle à texte (M2T) avec Acceleo, par
exemple pour engendrer la syntaxe attendue par Tina à partir d’un modèle de réseau de Petri
ou engendrer les propriétés LTL à partir d’un modèle de processus. Jusqu’à présent, nous étions
en mesure de saisir ou de modifier un modèle en utilisant un éditeur réflexif arborescent. Nous
allons maintenant nous intéresser à la transformation d’un modèle en sa représentation textuelle.
L’outil Acceleo a été développé par la société Obeo.
1.4.1
Génération d’un fichier .dot à partir d’un PetriNet - PetriNet2dot
Nous allons utiliser Acceleo afin de convertir un PetriNet en texte .dot pour le visualiser via
NetDraw. Le principe d’Acceleo est de s’appuyer sur des templates des fichiers à engendrer. Un
exemple correspondant à la syntaxe dot est exposé ci-dessous :
Projet I
11
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
digraph ExempleProcessus {
Conception->RedactionDoc
Conception->RedactionDoc
Conception->Developpement
Conception->RedactionTests
Developpement->RedactionTests
}
Le template qui correspond à la génération de la syntaxe dot est fourni en annexe : PetriNet2dot.mtl.
Une fois le fichier .dot obtenu, on obtient le graphe correspondant en PDF en faisant :
dot ficher.dot -Tpdf -o fichier.pdf dans le terminal (sous unix).
1.4.2
Génération d’un fichier .net à partir d’un PetriNet - PetriNet2Tina
Application aux réseaux de Petri Nous allons utiliser Acceleo, cette fois pour convertir
un PetriNet en texte .net afin de le visualiser via NetDraw. L’objectif est d’engendrer la syntaxe
textuelle utilisée par les outils Tina, en particulier nd (Net- Draw). La figure 10(a) illustre les
principaux concepts présents des réseaux de Petri temporels que nous considérons. Le fichier
textuel de ce réseau est donné au listing 10(b) au format Tina.
Figure 1.10 – Correspondance PetriNet - .net
Le template qui correspond à la génération de la syntaxe net est fourni en annexe : PetriNet2Tina.mtl.
Une fois le fichier .net obtenu, il est possible de visualiser le réseau en faisant :
nd fichier.net dans le terminal (sous unix), puis edit > draw.
1.5
Définition de syntaxes concrètes textuelles via Text
Nous avons vu comment définir la syntaxe abstraite d’un DSML. Le principe est d’utiliser
Ecore (ou un autre langage de méta-modélisation) pour décrire le méta-modèle et OCL (ou un
autre langage de contrainte) pour exprimer les propriétés liées à la sémantique statique qui n’ont
pas pu être capturées par le méta-modèle.
La syntaxe abstraite ne peut pas être manipulée directement. Le projet EMF d’Eclipse permet
Projet I
12
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
d’engendrer un éditeur arborescent et les classes Java qui permettront de manipuler un modèle
conforme à un méta-modèle. Cependant, ce ne sont pas des outils très pratiques lorsque l’on veut
saisir un modèle. Aussi, il est souhaitable d’associer à une syntaxe abstraite une ou plusieurs
syntaxes concrètes pour faciliter la construction et la modification des modèles. Ces syntaxes
concrètes peuvent être textuelles (l’objet de cette section) ou graphiques (très brièvement abordées à la partie suivante).
Pour la définition des syntaxes concrètes textuelles, nous allons utiliser l’outil xText de openArchitectureWare(oAW). xText fait partie du projet TMF (Textual Modeling Framework). Il
permet non seulement de définir une syntaxe textuelle pour un DSL mais aussi de disposer, au
travers d’Eclipse, d’un environnement de développement pour ce langage, avec en particulier un
éditeur syntaxique (coloration, complétion, outline, détection et visualisation des erreurs, etc).
xText s’appuie sur un générateur d’analyseurs descendants récursifs (LL(k)). L’idée est de décrire
à la fois la syntaxe concrète du langage et comment le modèle EMF est construit en mémoire au
fur et à mesure de l’analyse syntaxique.
1.5.1
Définition des syntaxes concrètes textuelles pour SimplePDL
Deux syntaxes ont été définies pour SimplePDL : la syntaxe PDL1 et la syntaxe PDL2. Cidessous une syntaxe engendrée par PDL1.
process dvp {
wd a
wd b
wd c
ws s2s from a to b
ws f2f from b to c
}
L’ensemble du code PDL1.xtext et PDL2.xtext est disponible en annexe.
1.5.2
Définition des syntaxes concrètes textuelles pour PetriNet
J’ai également défini deux syntaxes pour PetriNet : la syntaxe Petri1 et la syntaxe Petri2.
Petri1 ne permet pas d’engendrer une syntaxe texutelle conveable mais génère un diagramme
UML proche du modèle Réseau Pétri :
Projet I
13
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
Figure 1.11 – diagramme UML généré par pERTI1.xtext
Ci-dessous une syntaxe gérée par Petri2.
tr Conception_starts Conception_ready -> Conception_started Conception_running
tr Conception_finishes Conception_running -> Conception_finished
tr RedactionDoc_starts RedactionDoc_ready -> RedactionDoc_started RedactionDoc_running
tr RedactionDoc_finishes RedactionDoc_running Conception_finished?1 Conception_finished?1
-> RedactionDoc_finished
tr Developpement_starts Developpement_ready -> Developpement_started Developpement_running
tr Developpement_finishes Developpement_running Conception_finished?1 -> Developpement_finished
tr RedactionTest_starts RedactionTest_ready -> RedactionTest_started RedactionTest_running
tr RedactionTest_finishes RedactionTest_running Conception_finished?1 Developpement_finished?1
-> RedactionTest_finished
pl Conception_ready (1)
pl RedactionDoc_ready (1)
pl Developpement_ready (1)
pl RedactionTest_ready (1)
net ifip
L’ensemble du code pERT1.xtext et pERTI2.xtext est disponible en annexe.
1.6
Définition de syntaxes concrètes graphiques
À l’instar d’une syntaxe concrète textuelle, une syntaxe concrète graphique fournit un moyen
de visualiser et/ou éditer plus agréablement et efficacement un modèle. Il est possible d’utiliser
l’outil ObeoDesigner également développé par la société Obeo et basé sur le projet GMF (Eclipse
Graphical Modeling Framework). Il permet de définir une syntaxe graphique pour un langage
de modélisation décrit en Ecore et d’engendrer un éditeur graphique intégré à Eclipse. L’éditeur
graphique Ecore utilisé pour visualiser et éditer les modèles Ecore a été développé avec GMF.
Obeo Designer est un logiciel nécessitant une licence pour fonctionner. L’INP-ENSEEIHT dispose
de licences académiques pour utiliser cet outil.
Projet I
14
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
Cette partie ne fut pas demandée et ne devait pas être traitée pour le projet. J’ai cependant
expérimenté une première prise en main sans poursuivre très loin faute de temps. La syntaxe
abstraite du DSML (Directory Service Markup Language) doit être définie par un modèle Ecore
(le méta-modèle) éventuellement complété par des contraintes (exprimées en OCL par exemple).
J’ai considéré le méta-modèle de SimplePDL. J’ai ensuite défini une syntaxe concrète graphique
souhaitée pour ce méta-modèle. Il est possible de créer graphiquement le Process, les WorkDefinition, les WorkSequence reliant les WorkDefinition. Je n’ai pas pris en compte les ressources
ici.
Figure 1.12 – Un SimplePDL créé avec mon éditeur graphique
1.7
Utilisation de l’infrastructure fournie par EMF pour manipuler les modèles
Le projet Eclipse Modeling Framework (EMF) est un framework de modélisation, une infrastructure de génération de code et des applications basées sur des modèles de données structurées.
Partant d’une spécification décrite généralement sous la forme d’un modèle en XMI, EMF fournit des outils permettant de produire des classes Java représentant le modèle avec un ensemble
de classes pour adapter les éléments du modèle afin de pouvoir les visualiser, les éditer avec un
système de commandes et les manipuler dans un éditeur.
EMF nous sera très utile dans la génération du code Java à partir de nos méta-modèles.
1.7.1
Génération du code Java pour SimplePDL et PetriNet
Après avoir saisi les méta-modèles sous la forme d’un fichier Ecore, il nous est possible de
générer automatiquement le code java associé aux modèles SimplePDL et PetriNet. De manière
plus large, je me suis intéressé à l’utilisation de ces méta-modèles afin de générer de l’outillage
et ainsi pouvoir manipuler des modèles instances de ces méta-modèles.
Projet I
15
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
Configuration la génération du code Java. Dans EMF, la génération de code Java est
configurée à l’aide d’un modèle appelé genmodel. Il est possible de créer ces modèles à partir des
fichiers SimplePDL.Ecore et PetriNet.Ecore. Après avoir généré les fichiers SimplePDL.genmodel
et PetriNet.genmodel nous sommes en mesure de Configurer la génération du code Java. En
sélectionnant l’action Generate Model nous générons la structure de données Java correspondant
au méta-modèles Ecore. De la même manière que précédemment, nous effectuons les actions
de génération : Generate Edit Code et Generate Editor Code. Ces actions nous permettent de
générer un éditeur arborescent pour les modèles conformes aux méta-modèles SimplePDL et
PetriNet.
Suite à cette manipulation, je dispose de trois nouveaux dossiers : Projet, Projet.edit et Projet.editor. Chaque dossier regroupe une partie associée au SimplePDL et une autre associée au
PetriNet.
Ainsi à l’intérieur de la partie Projet/src/PetriNet, j’obtiens les fichiers
– Arc.java
– Lieu.java
– PetrinetFactory.java
– PetrinetPackage.java
– Place.java
– ReseauPetri.java
– Transition.java
– TypeArc.java
J’obtiens également quelque chose d’assez proche pour SimplePDL.
1.7.2
Utilisation du code Java/EMF pour manipuler les modèles
Manipulation de modèles en Java Dans cette section, nous allons manipuler des modèles
EMF à partir du code Java. Je vais limiter mon explication au fichier SimplePDL2PetriNet.java
qui me permet de convertir un Process (SimplePDL) en réseau de Petri (PertiNet). Cela se
matérialisera par la conversion d’un fichier pdl-sujet.xmi en un autre fichier xmi correspondant
au modèle PetriNet associé.
Raffinage sommaire du fichier SimplePDL2PetriNet.java
1. Chargement des différents packages, à savoir SimplePDL.Ecore et PetriNet.Ecore Initialisation du fichier à convertir, initialisation du fichier dans lequel on va écrire.
2. Convertir toutes les WorkDefinition en réseaux de pétri ie en 5 arcs, 2 transitions et 4
places. Relier le tout correctement et l’ajouter au réseau de Pétri.
3. Convertir toutes les WorkSequence en un arc qu’on relie judicieusement aux WorkDefinions
appropriées. Ajouter l’arc au réseau.
4. Convertir toutes les ressources en places et les relier convenablement au reste du réseau.
Ajouter tous les éléments créés au réseau.
Choix d’implantation Afin d’implanter l’algorithme décrit ci-dessus, il faut être en mesure
d’enregistrer les éléments du PetriNet qui sont crées au fur et à mesure. Pour cela j’ai décidé
d’utiliser deux LinkedList : une pour stocker le réseau (utile si éventuellement on décide de traiter plusieurs réseaux) et une pour stocker l’ensemble des Lieux et Arcs. J’ai également créer
plusieurs fonctions permettant de récupérer les éléments à l’intérieur de ces LinkedList.
L’ensemble du code est disponible en annexe.
Projet I
16
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
1.7.3
Exemple de conversion de modèles sans ressources
Prenons l’exemple du pdl-sujet2.xmi en se référant à la figure ci-dessous.
Figure 1.13 – pdl-sujet2.xmi
Le fichier SimplePDL2PetriNet.java permet de convertir pdlsujet2.xmi en
PetriNet PertiNet_From_SimplePDL2.xmi affiché ci-dessous.
Figure 1.14 – PertiNet_From_SimplePDL2.xmi
Le fichier PetriNet2Tinamtl
˙ permet de convertir PetriNet
PertiNet_From_SimplePDL2.xmi en fichier pdlsujetsujet2.net affiché ci-dessous.
Projet I
17
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
Figure 1.15 – PertiNet_From_SimplePDL2.xmi après conversion en pdlsujetsujet2.net
En convertissant ce fichier à l’aide d’un interpréteur graphique nous obtenons la figure suivante :
Figure 1.16 – Résultat de la conversion sous forme graphique
1.7.4
Exemple de conversion de modèles avec ressources
Prenons en compte les ressources disposées suivant le tableau suivant :
Projet I
18
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
Figure 1.17 – Exemple de répartition des ressources
Et associées au SimplePDL de l’introduction :
Cela correspond au pdl-sujet.xmi correspondant à la figure ci-dessous.
Figure 1.18 – pdl-sujet.xmi
Projet I
19
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
Le fichier SimpleP DL2P etriN et.java permet de convertir pdl − sujet.xmi en
P ertiN etF romS impleP DL.xmi affiché ci-dessous.
Figure 1.19 – P ertiN etF romS impleP DL.xmi
Le fichier P etriN et2T ina.mtl permet de convertir PetriNet
P ertiN etF romS impleP DL.xmi en fichier pdl-sujetsujet.net affiché ci-dessous.
Figure 1.20 – P ertiN etF romS impleP DL.xmi après conversion en pdl − sujet.net
En convertissant ce fichier à l’aide d’un interpréteur graphique nous obtenons la figure suivante :
Projet I
20
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
Figure 1.21 – Résultat de la conversion sous forme graphique
1.8
Définition de transformation de modèle à modèle (M2M) avec
ATL
ATLAS Transformation Language (ATL) est un langage de transformation de modèles plus
ou moins inspiré par le standard QVT de l’OMG et développé au LINA à Nantes par l’équipe de
Jean Bézivin.. Il est disponible en tant que plugin dans le projet Eclipse. ATL est un prototype
académique de composant de transformation de modèles du projet Eclipse Modeling. ATL se
compose :
– d’un langage de transformation (déclaratif et impératif) ;
– d’un compilateur et d’une machine virtuelle ;
– d’un IDE s’appuyant sur Eclipse
Nous allons utiliser ATL pour convertir un SimplePDL en PetriNet de façon beaucoup plus
efficace. J’utiliserai exclusivement ce langage dans la suite du projet et de ce rapport.
1.8.1
Utilisation d’ATL pour convertir SimplePDL en PetriNet
Manipulation de modèles en ATL Dans cette section, nous allons manipuler des modèles
EMF à partir du code ATL. Je vais limiter mon explication au fichier SimplePDL2PetriNet.atl
qui me permet de convertir un Process (SimplePDL) en réseau de Petri (PertiNet) de manière
plus efficace qu’avec le code java définit plutôt. Encore une fois, cela se matérialisera par la
conversion d’un fichier pdl-sujet.xmi en un autre fichier xmi correspondant au modèle PetriNet
associé.
Raffinage sommaire du fichier SimplePDL2PetriNet.atl
1. Traduire un Process en un PetriNet de même nom.
2. Convertir toutes les WorkDefinition en réseaux de pétri ie en 5 arcs, 2 transitions et 4
places. Relier le tout correctement et l’ajouter au réseau de Pétri.
3. Convertir toutes les WorkSequence en un arc qu’on relie judicieusement aux WorkDefinions
appropriées. Ajouter l’arc au réseau.
4. Convertir toutes les ressources en places et les relier convenablement au reste du réseau.
Ajouter tous les éléments créés au réseau.
Projet I
21
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
Choix d’implantation Afin d’implanter l’algorithme décrit ci-dessus, il faut être en mesure
d’enregistrer les éléments du PetriNet qui sont crées au fur et à mesure. Pour cela j’utilise une la
méthode thisModule.resolveTemp, qui me permet de chercher le PetriNet dans lequel j’enregistre
le réseau via son nom. Cela a été possible en définissant un ’def’ au début du programme me
permettant de récupérer le Process à partir d’une WorkDefinition.
helper context simplepdl!ProcessElement
def: getProcess(): simplepdl!Process =
simplepdl!Process.allInstances()
->select(p | p.processElements->includes(self))
->asSequence()->first();
L’ensemble du code est disponible en annexe.
1.8.2
Exemple de conversion d’un SimplePDL en PetriNet via ATL
Voici le résultat de la conversion de l’exemple du sujet sans les ressources en utilisant ATL.
Figure 1.22 – Résultat de la conversion sous forme graphique
1.9
Synthèse de la transformation
Voici la synthèse de la transformation réalisée pour la première partie.
Projet I
22
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
Figure 1.23 – Synthèse de la transformation effectuée à la Partie I
M2T : transformation Modèle à Texte
M2M : transformation de Modèle à Modèle
Projet I
23
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
Partie II - Ressources alternatives
2.1
Modèle du processus SimplePDL avec les ressources alternatives
La deuxième partie du rapport est axée sur l’ajout de ressources : pour réaliser une activité,
celle-ci doit disposer d’un certain nombre de ressources. Une extension du modèle de processus
est également proposée en considérant des ressources alternatives. Plusieurs configurations de
ressources pourront permettre de réaliser une activité. Par exemple, rédiger les tests peut nécessiter soit un testeur et deux machines, soit un analyste et un générateur de test et une machine.
Si l’un de ces deux ensembles de ressources est disponible, il est utilisé par l’activité qui peut
alors commencer.
2.1.1
Mise à jour du Méta-modèle
Pour prendre en compte les ressources alternées, il fallait mettre à jour le digramme UML
de SimplePDL. J’ai repris le digramme avec les ressources simple en y ajoutant une notion
de groupe à l’aide de la classe GroupeRessources. Ainsi, GroupeRessources contient plusieurs
GroupeRessources qui peuvent être associée à un ou plusieurs groupe. Le reste ne change pas
comme en témoigne la figure 24.
Projet I
24
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
Figure 2.24 – Méta-modèle de SimplePDL conforme à EMOF/Ecore - Avec les ressources alternées
2.1.2
Mise à jour de l’équivalence WorkDefinition - PetriNet
J’ai défini une nouvelle équivalence pour traduire une WorkDefinition en PetriNet :
– ajout d’une place ressources_disponibles
– ajout d’une place rendre_ressources
Ces deux places serviront à interagir avec le groupe de ressources.
Projet I
25
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
Figure 2.25 – équivalence WorkDefinition - PetriNet
2.2
Ressources alternatives, transformation SimplePDL - PetriNet
Étude d’un cas simple Pour illustrer et aborder les ressources alternatives, nous allons
considérer un premier cas simple dans lequel, seule une WorkDefinition ’Activité’ est envisagée
dans le Process. L’activité peut être réalisée soit par 1 ingénieur et 1 cerveau ou par 3 machines
et 2 opérateurs.
2.2.1
Ressources alternatives, première possibilité
La première possibilité envisagée est celle représentée par la figure 26.
Figure 2.26 – Un Groupe de ressources - PetriNet
Projet I
26
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
Ce qui nous permet de générer un PetriNet global relatif à l’exemple tel que celui de la figure
27.
Figure 2.27 – Ressources alternatives, première possibilité
Interprétation : Il est possible d’allouer, au choix, le groupe de ressources que l’on souhaite.
Cependant, lorsqu’un groupe de ressources à été alloué, ces ressources ne pourront être rendu
qu’une seule fois l’activité terminée. Aussi, si l’on alloue un groupe de ressources à une activité
déjà terminée, les ressources ne pourront jamais être rendues. Si on alloue plusieurs groupes de
ressources simultanément à une même activité non commencée,seul un unique groupe pourra à
nouveau disposer de ses ressources lorsque l’activité sera terminée.
2.2.2
Ressources alternatives, deuxième possibilité
Comme développé dans l’interprétation de la première possibilité, il est envisageable de pallier
à certains petits inconvénients. Pour cela, j’ai mis en place un second traitement de la traduction
SimplePDL - PetriNet illustré par la figure 28. Il est alors possible de désalouer les ressources.
Projet I
27
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
Figure 2.28 – Un Groupe de ressources - PetriNet
Ce qui nous permet de générer un PetriNet global relatif à l’exemple tel que celui de la figure
29.
Figure 2.29 – Ressources alternatives, deuxième possibilité
Interprétation : Comme précédemment, il est possible d’allouer, au choix, le groupe de
ressources que l’on souhaite. Ce cas nous permet néanmoins une certaine amélioration :
Projet I
28
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
– possibilité d’allouer un groupe de ressources à une activité déjà terminée, on peut la désalouer si l’activité ne l’utilise pas.
– possibilité de commencer le travail avec un groupe de ressources, puis allouer un autre
groupe de ressource pour cette activité et libérer les ressources du premier groupe.
2.3
Utilisation d’ATL pour convertir SimplePDL en PetriNet
Manipulation de modèles en ATL Les figures précédentes sont issues de la traduction
du langage SimplePDL en langage PetriNet. Pour cela j’ai utiliser ATL en mettant à jour SimplePDL2PetriNet.atl.
Raffinage sommaire du fichier SimplePDL2PetriNet.atl
1. Traduire un Process en un PetriNet de même nom.
2. Convertir toutes les WorkDefinition en réseaux de pétri ie en 5 arcs, 2 transitions et 4
places. Relier le tout correctement et l’ajouter au réseau de Pétri.
3. Convertir toutes les WorkSequence en un arc qu’on relie judicieusement aux WorkDefinions
appropriées. Ajouter l’arc au réseau.
4. Convertir toutes les ressources disponibles en places et les ajouter au réseau.
5. Traduire chaque groupe de ressource en réseau de Petri (3 transitions, 1 place et 5 arcs),
le relier à sa WorkDefinition et l’ajouter au réseau.
6. Relier les ressources disponibles aux groupes.
Choix d’implantation
Le choix d’implantation fut le même que pour la partie I. L’ensemble du code est disponible
en annexe. Je n’ai fourni que le code pour la deuxième possibilité, car la première possibilité est
obtenue à partir de celle-ci en enlevant certaines places/arcs/transitions.
2.4
Contraintes LTL - Linear Temporal Logic
Les contraintes LTL permettent d’exprimer des propriétés portants sur les exécutions des
systèmes.
Il s’agit de spécification non opérationnelle : pas de relation de transition explicite, pas de notion
d’états initiaux. Une logique est définie par :
– une syntaxe : opérateurs de logique classique plus des opérateurs temporels pour parler du
futur et du passé.
– une sémantique : domaine des objets (appelés modèles) sur lesquels on va tester la validité
des formules, plus l’interprétation des téléopérateurs.
Dans notre cas, l’exécution d’un réseau de Petri correspond à une séquence d’états caractérisés
par le marquage du réseau. Le passage d’un état au suivant immédiat correspond à une transition
unique du réseau. Nous allons donner des contraintes sur le marquage d’un réseau de Petri pour
que les propriétés suivantes qui portent sur le modèle de processus de la figure soient satisfaites
(ces propriétés peuvent se formaliser en logique temporelle linéaire – LTL).
Contraintes sur les propriétés de terminaison d’un processus
1. [] (finished => dead) : Lors qu’un processus est terminé, plus aucune action n’est possible
2. [] <> dead : Il est possible qu’il n’y ait plus aucune action à exécuter
3. [] (dead => finished) : Si il n’y a plus aucune action à exécuter, alors les processus sont
terminés.
4. - <> finished : Les processus ne sont jamais terminés.
Projet I
29
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
Contraintes de validations de transformation SimplePDL - PetriNet
1. - <> finished : Ne processus ne peut pas se terminer.
2. [] (finished => - <> ready) : Lorsqu’une activité est terminée, elle ne peut pas redémarrer.
3. [] (finished => - <> running) : Lorsqu’une activité est terminée, elle n’est plus en cours.
4. [] (started => - <> ready) : Lorsqu’une activité est a commencée, il n’est plus possible de
la redémarrer.
5. [] (finished => started) : Lorsqu’une activité est terminée, elle a été commencée.
2.4.1
Génération et interprétation des contraintes LTL à l’aide d’Acceleo
Contraintes sur les propriétés de terminaison d’un processus Il faut donc pouvoir
générer est vérifier les contraintes suivantes, ces contraintes peuvent être TRUE ou FALSE suivant
la démarche de conception :
1. [] (finished => dead) : Lors qu’un processus et terminé, plus aucune action est possible.
2. [] <> dead : Il est possible qu’il n’y ait plus aucune action à exécuter.
3. [] (dead => finished) : Si il n’y a plus aucune action à exécuter, alors les processus sont
terminés.
4. - <> finished : Les processus sont toujours terminés.
Ces contraintes seront générée par le ficher SimplePDLfinish.mtl disponible en annexe.
Contraintes de validations de transformation SimplePDL - PetriNet Il faut donc
pouvoir générer est vérifier les contraintes suivantes :
1. - <> finished : doit être à FALSE
2. [] (finished => - <> ready) : doit être à TRUE
3. [] (finished => - <> running) : doit être à TRUE
4. [] (started => - <> ready) : doit être à TRUE
5. [] (finished => started) : doit être à TRUE
Ces contraintes seront générée par ce code le ficher validationPetri.mtl disponible en annexe.
2.4.2
Résultats des contraintes LTL
Résultat pour la première possibilité avec le fichier : SimplePDLfinish.mtl et interprétation :
1. FALSE : Lors qu’un processus et terminé, on peut encore allouer les ressources, bien que
cela ne serve à rien.
2. TRUE : Lorsque le processus est terminé et que toutes les ressources sont allouées, on ne
peut plus rien faire.
3. TRUE : Si il n’y a plus aucune action à exécuter, alors les processus sont terminés.
4. FALSE : Le processus peut se terminer.
Résultat pour la deuxième possibilité avec le fichier : SimplePDLfinish.mtl et interprétation :
1. FALSE Lors qu’un processus et terminé, on peut encore allouer et déallouer les ressources,
bien que cela ne serve à rien.
2. FALSE On pourra toujours exécuter des actions, à savoir allouer et désallouer indéfiniment
les ressources.
Projet I
30
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
3. TRUE Si il n’y a plus aucune action à exécuter, alors les processus sont terminés. (Normal
car cela n’arrive jamais, FAUX implique n’importe quoi).
4. FALSE Le processus peut se terminer.
Ce qui est conforme à une bonne transformation.
Résultat pour la deuxième possibilité avec le fichier : validationPetri.mtl et interprétation :
1. FALSE
2. TRUE
3. TRUE
4. TRUE
5. TRUE
Ce qui est conforme à une bonne transformation, on obtient le même résultat avec la première
possibilité.
2.5
Notre exemple file-rouge
Reprenons les notre exemple de la partie I dont les ressources sont données par le tableau
suivant :
Cependant, cette fois-ci, rédiger les tests peut nécessiter soit un testeur et deux machines,
soit un analyste et un générateur de test et une machine.
2.5.1
Conversion des modèles
J’utilise la possibilité 2 définie page 28. Nous sommes ensuite en mesure de créer le fichier
ExempleFinal.xmi correspondant au SimplePDL inspiré du tableau. S’en suit une conversion
en pdl-sujetExempleFinal.xmi via SimplePDL2PetriNet et correspondant au modèle PetriNet
associé. Il faut alors générer son modèle .net à l’aide de PetriNet2Tina.mtl. Il nous est alors
possible d’afficher le résultat :
Projet I
31
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
Figure 2.30 – Resultat final après conversion sous forme de PetriNet
2.5.2
Réalisations des tests selon les contraintes LTL
En utilisant les fichiers SimplePDLfinish.mtl et validationPetri.mtl, nous obtenons respectivement :
op finished = Conception_finished/\RedactionDoc_finished/\Developpement_finished
/\RedactionTests_finished;
[] (finished => dead);
[] <> dead ;
[] (dead => finished);
- <> finished;
et
op finished = Conception_finished/\RedactionDoc_finished
/\Developpement_finished/\RedactionTests_finished;
op started = Conception_started/\RedactionDoc_started
/\Developpement_started/\RedactionTests_started;
op ready = Conception_ready/\RedactionDoc_ready
/\Developpement_ready/\RedactionTests_ready;
op running = Conception_running/\RedactionDoc_running
/\Developpement_running/\RedactionTests_running;
- <> finished;
[] (finished => - <> ready);
[] (finished => - <> running);
[] (started => - <> ready);
[] (finished => started);
Nous sommes maintenant en mesure d’afficher les résultats :
Pour SimplePDLfinish :
gkempf@lovelace:~/workspace/BE/models$ selt -S ProcessFinal.scn ProcessFinal.ktz -prelude
ProcessFinal.ltl
Selt version 3.0.4 -- 10/09/12 -- LAAS/CNRS
ktz loaded, 314 states, 1090 transitions
0.004s
- source ProcessFinal.ltl;
Projet I
32
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
operator finished : prop
FALSE
state 0: Analyste_ressource Concepteur_ressource*3 Conception_ready
Developpement_ready Developpeur_ressource*2 Generateurdetests_ressource
Machine_ressource*4 Redacteur_ressource RedactionDoc_ready
RedactionTests_ready Testeur_ressource*2
-Conception_recupererRessources ... (preserving T)->
state 64: Analyste_ressource Concepteur_ressource*3 Conception_finished
Conception_started Developpement_finished Developpement_ressourcesRecuperees
Developpement_ressources_disponbiles Developpement_started Generateurdetests_ressource
RedactionDoc_finished RedactionDoc_ressourcesRecuperees
RedactionDoc_ressources_disponbiles RedactionDoc_started RedactionTests_finished
RedactionTests_started Testeur_ressource*2
-RedactionDoc_desalouerRessources ... (preserving - dead /\
RedactionDoc_finished /\ RedactionTests_finished /\ Conception_finished /\
Developpement_finished)->
state 65: Analyste_ressource Concepteur_ressource*3 Conception_finished
Conception_started Developpement_finished Developpement_ressourcesRecuperees
Developpement_ressources_disponbiles Developpement_started Generateurdetests_ressource
Machine_ressource Redacteur_ressource RedactionDoc_finished RedactionDoc_started
RedactionTests_finished RedactionTests_started Testeur_ressource*2
[accepting all]
FALSE
state 0: Analyste_ressource Concepteur_ressource*3 Conception_ready
Developpement_ready Developpeur_ressource*2 Generateurdetests_ressource
Machine_ressource*4 Redacteur_ressource RedactionDoc_ready RedactionTests_ready
Testeur_ressource*2
-Conception_recupererRessources ... (preserving T)->
state 64: Analyste_ressource Concepteur_ressource*3 Conception_finished
Conception_started Developpement_finished Developpement_ressourcesRecuperees
Developpement_ressources_disponbiles Developpement_started Generateurdetests_ressource
RedactionDoc_finished RedactionDoc_ressourcesRecuperees
RedactionDoc_ressources_disponbiles RedactionDoc_started RedactionTests_finished
RedactionTests_started Testeur_ressource*2
-RedactionDoc_desalouerRessources ... (preserving - dead)->
* [accepting] state 65: Analyste_ressource Concepteur_ressource*3 Conception_finished
Conception_started Developpement_finished Developpement_ressourcesRecuperees
Developpement_ressources_disponbiles Developpement_started Generateurdetests_ressource
Machine_ressource Redacteur_ressource RedactionDoc_finished RedactionDoc_started
RedactionTests_finished RedactionTests_started Testeur_ressource*2
-Developpement_desalouerRessources ... (preserving - dead)->
state 65: Analyste_ressource Concepteur_ressource*3 Conception_finished
Conception_started Developpement_finished Developpement_ressourcesRecuperees
Developpement_ressources_disponbiles Developpement_started Generateurdetests_ressource
Machine_ressource Redacteur_ressource RedactionDoc_finished RedactionDoc_started
RedactionTests_finished RedactionTests_started Testeur_ressource*2
TRUE
FALSE
state 0: Analyste_ressource Concepteur_ressource*3 Conception_ready
Developpement_ready Developpeur_ressource*2 Generateurdetests_ressource
Machine_ressource*4 Redacteur_ressource RedactionDoc_ready RedactionTests_ready
Testeur_ressource*2
-Conception_recupererRessources ... (preserving T)->
state 64: Analyste_ressource Concepteur_ressource*3 Conception_finished
Conception_started Developpement_finished Developpement_ressourcesRecuperees
Developpement_ressources_disponbiles Developpement_started Generateurdetests_ressource
RedactionDoc_finished RedactionDoc_ressourcesRecuperees
RedactionDoc_ressources_disponbiles RedactionDoc_started RedactionTests_finished
Projet I
33
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
RedactionTests_started Testeur_ressource*2
-RedactionDoc_desalouerRessources ... (preserving Developpement_finished /\
RedactionDoc_finished /\ RedactionTests_finished /\ Conception_finished)->
state 65: Analyste_ressource Concepteur_ressource*3 Conception_finished
Conception_started Developpement_finished Developpement_ressourcesRecuperees
Developpement_ressources_disponbiles Developpement_started Generateurdetests_ressource
Machine_ressource Redacteur_ressource RedactionDoc_finished RedactionDoc_started
RedactionTests_finished RedactionTests_started Testeur_ressource*2
[accepting all]
0.004s
Pour validationPetri :
gkempf@lovelace:~/workspace/BE/models$ selt -S ProcessFinal.scn ProcessFinal.ktz -prelude ProcessFina
Selt version 3.0.4 -- 10/09/12 -- LAAS/CNRS
ktz loaded, 314 states, 1090 transitions
0.000s
- source ProcessFinalVP.ltl;
operator finished : prop
operator started : prop
operator ready : prop
operator running : prop
FALSE
state 0: Analyste_ressource Concepteur_ressource*3 Conception_ready Developpement_ready
Developpeur_ressource*2 Generateurdetests_ressource Machine_ressource*4
Redacteur_ressource RedactionDoc_ready RedactionTests_ready Testeur_ressource*2
-Conception_recupererRessources ... (preserving T)->
state 64: Analyste_ressource Concepteur_ressource*3 Conception_finished Conception_started
Developpement_finished Developpement_ressourcesRecuperees
Developpement_ressources_disponbiles Developpement_started Generateurdetests_ressource
RedactionDoc_finished RedactionDoc_ressourcesRecuperees RedactionDoc_ressources_disponbiles
RedactionDoc_started RedactionTests_finished RedactionTests_started Testeur_ressource*2
-RedactionDoc_desalouerRessources ... (preserving Developpement_finished /\
RedactionDoc_finished /\ RedactionTests_finished /\ Conception_finished)->
state 65: Analyste_ressource Concepteur_ressource*3 Conception_finished Conception_started
Developpement_finished Developpement_ressourcesRecuperees
Developpement_ressources_disponbiles Developpement_started Generateurdetests_ressource
Machine_ressource Redacteur_ressource RedactionDoc_finished RedactionDoc_started
RedactionTests_finished RedactionTests_started Testeur_ressource*2
[accepting all]
TRUE
TRUE
TRUE
TRUE
0.008s
Les résultats sont bien ceux de la deuxième possibilité déjà analysés plus haut !
Projet I
34
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
2.6
Synthèse de la transformation
Voici la synthèse de la transformation réalisée pour la deuxième partie.
Figure 2.31 – Synthèse de la transformation effectuée à la Partie II
M2T : transformation Modèle à Texte
M2M : transformation de Modèle à Modèle
Projet I
35
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
Conclusion
Ce projet m’a permis de développer et d’analyser la transformation de méta-modèles. J’ai ainsi
pu mettre en pratiques les notions développées en cours et me familiariser les différents outils
de développements utilisés. Le projet nous incitait à intervenir sur l’ensemble de la chaine de
transformation d’un SimplePDL en un PetriNet. A savoir, l’élaboration des deux méta-modèles
avec Ecore ; la définition de leur sémantique statique avec OCL (Objet Constraint Language) pour
capturer les contraintes qui n’ont pu l’être lors de la conception des méta-modèles ; l’utilisation
de l’infrastructure fournie par EMF (Eclipse Modeling Framework) pour manipuler les métamodèles ; la définition de la transformation modèle à texte (M2T) avec Accleo ; la définition de
syntaxes concrètes textuelles avec Xtext ; la définition de syntaxes concrètes graphiques avec
Obeo Designer ; et la définition de transformation de modèle à modèle (M2M).
La force de ce projet a été de mettre en lumière la nécessite d’une bonne conception des
modèles que nous utilisons. Pour cela, il faut prendre en compte les différentes interactions entre
les classes java et réfléchir à l’utilisation que l’on va en faire. Cela est particulièrement important
dans la mesure où j’ai généré l’ensemble du code java relative à la définition de SimplePDL et
de PetriNet à partir des fichiers Ecore. Concernant la transformation M2M, j’ai été amené à la
faire de deux manières différentes et il s’avère que la manipulation des modèles EMF à partir
du code ATL (ATLAS Transformation Language) est bien plus efficace que l’utilisation brute de
java. Pour s’assurer que la conception est faite de manière optimale, j’ai pu utiliser les outils de
model-checking définis sur les réseaux de Petri au travers de la boîte à outil Tina en produisant,
notamment, une chaîne de vérification de modèle de processus SimplePDL.
Le coté stimulant de ce projet était d’avantage présent dans la partie II, qui nous donnait
une liberté d’action dans l’intégration des ressources. En effet, il était nécessaire de bien penser
la cohérence du PetriNet qui allait être généré. J’ai proposé deux manières de les intégrer qui
avaient chacune des avantages et des inconvénients, bien que la deuxième possibilité est, à mon
sens, une version améliorée de la première.
Enfin, j’ai été amené à appréhender la syntaxe graphique pour le langage de modélisation
SimplePDL décrit en Ecore et engendrer un éditeur graphique intégré à Eclipseà l’aide de Obeo
Designer. Il est ainsi possible de créer graphiquement le Process, les WorkDefinition, les WorkSequence reliant les WorkDefinition, même si cette partie n’était pas demandée pour le projet et
a été d’avantage une introduction à la syntaxe abstraite du DSML (Directory Service Markup
Language).
Projet I
36
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
ANNEXES
Projet I
37
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
Partie I - Chaîne de vérification de
modèle de processus
1.1
SimplePDL2PetriNet.java
/* Transforme un modele de processus en un modele de reseau de Petri.
* Auteur : Guillaume Kempf 2INA
* TP5 3.4
* */
package petrinet.utils;
import
import
import
import
import
java.io.IOException;
java.util.Collections;
java.util.LinkedList;
java.util.List;
java.util.Map;
import
import
import
import
import
org.eclipse.emf.common.util.URI;
org.eclipse.emf.ecore.resource.Resource;
org.eclipse.emf.ecore.resource.ResourceSet;
org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
import
import
import
import
import
import
import
import
import
import
import
simplepdl.Process;
simplepdl.RessourcesDisponibles;
simplepdl.RessourcesRequises;
simplepdl.Ressources;
simplepdl.WorkDefinition;
simplepdl.WorkSequence;
simplepdl.WorkSequenceType;
simplepdl.SimplepdlFactory;
simplepdl.SimplepdlPackage;
petrinet.*;
petrinet.impl.*;
/*
* Classe principale
* Contient le reseau de petri, le petri Factory et une linkedlist de StockageWd
*/
public class SimplePDL2PetriNet {
public static PetrinetFactory petriFactory;
private static ReseauPetri pertiNet;
public static LinkedList<StockageWd> stockageReseaux;
Projet I
38
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
public static LinkedList<StockagePR> stockagePlacesRessources;
public static int nbWDC = 0; //compte le nombre de WD converties
public static int nbRC = 0; //compte le nombre de Ressources converties
/**
* Constructeur SimplePDL2PetriNet
* @param process
*/
public SimplePDL2PetriNet(Process process){
petriFactory = PetrinetFactory.eINSTANCE;
setPertiNet(petriFactory.createReseauPetri());
stockageReseaux = new LinkedList<StockageWd>();
stockagePlacesRessources = new LinkedList<StockagePR>();
}
public static ReseauPetri getPertiNet() {
return pertiNet;
}
public static void setPertiNet(ReseauPetri pertiNet) {
SimplePDL2PetriNet.pertiNet = pertiNet;
}
/*
* StockageWd : Classe qui permet de stocker les arcs a relier entre eux pour
chaque Workdefinition
*/
public class StockageWd {
public String nameWd;
public Arc starts_Started;
public Arc finishes_Finished;
/**
* Constructeur de la class
* @param nomwd
* @param arc_starts_Started
* @param arc_finishes_Finished
*/
public StockageWd(String nomwd,Arc arc_starts_Started,Arc arc_finishes_Finished){
nameWd = nomwd;
starts_Started = arc_starts_Started;
finishes_Finished = arc_finishes_Finished;
}
}
/*
* Stockage : Classe qui permet de stocker les places des ressources
*/
public class StockagePR {
public String namePR;
public Place placeRessource;
/**
Projet I
39
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
* Constructeur de la class
* @param namePR
* @param placeRessource
*/
public StockagePR(String nompr,Place placeressource){
namePR = nompr;
placeRessource = placeressource;
}
}
/**
* getTransitionStarts : recupere la transition starts
* @param NomWd
* @return Transition
*/
public static Lieu getPlaceRessource(String nompr){
int i = 0;
System.out.println(stockagePlacesRessources.get(i).namePR);
System.out.println(nompr);
while (!(stockagePlacesRessources.get(i).namePR).equalsIgnoreCase(nompr) & i <
stockagePlacesRessources.size())
{
i++;
System.out.println(i);
}
System.out.println("getPlaceRessource :" +
stockagePlacesRessources.get(i).namePR);
return stockagePlacesRessources.get(i).placeRessource;
}
/**
* getTransitionStarts : recupere la transition starts
* @param NomWd
* @return Transition
*/
public static Lieu getTransitionStarts(String NomWd){
int i = 0;
while (stockageReseaux.get(i).nameWd != NomWd & i < stockageReseaux.size())
{
i++;
}
System.out.println("getTransitionStarts :" + stockageReseaux.get(i).nameWd);
System.out.println("Lieu raccorde :" +
stockageReseaux.get(i).starts_Started.getPredecessor());
return stockageReseaux.get(i).starts_Started.getPredecessor();
}
/**
* getTransitionFinishes : recupere la transition finishes
* @param NomWd
* @return Transition
*/
public static Lieu getTransitionFinishes(String NomWd){
int i = 0;
while (stockageReseaux.get(i).nameWd != NomWd & i < stockageReseaux.size())
{
i++;
Projet I
40
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
}
System.out.println("getTransitionFinishes :" + stockageReseaux.get(i).nameWd);
System.out.println("Lieu raccorde :" +
stockageReseaux.get(i).finishes_Finished.getPredecessor());
return stockageReseaux.get(i).finishes_Finished.getPredecessor();
}
/**
* getPlaceStarted : recupere la place started
* @param NomWd
* @return Place
*/
public static Lieu getPlaceStarted(String NomWd){
int i = 0;
while (stockageReseaux.get(i).nameWd != NomWd & i < stockageReseaux.size())
{
i++;
}
System.out.println("getPlaceStarted :" + stockageReseaux.get(i).nameWd);
System.out.println("Lieu raccord :" +
stockageReseaux.get(i).starts_Started.getPredecessor());
return stockageReseaux.get(i).starts_Started.getSuccessor();
}
/**
* getPlaceFinished : recupere la pace finished
* @param NomWd
* @return Place
*/
public static Lieu getPlaceFinished(String NomWd){
int i = 0;
while (stockageReseaux.get(i).nameWd != NomWd & i < stockageReseaux.size())
{
i++;
}
System.out.println("getPlaceFinished :" + stockageReseaux.get(i).nameWd);
System.out.println("Lieu raccorde :" +
stockageReseaux.get(i).finishes_Finished.getPredecessor());
return stockageReseaux.get(i).finishes_Finished.getSuccessor();
}
/**
* Ajoute l’arc de liaison au reseau de petri
* @param arc
*/
public static void ajouterArc(Arc arc)
{
getPertiNet().getArcs().add(arc);
}
/**
* Convertie une ressource en reseau de Petri
* @param WorkDefinition
*/
public void convertionRessourcePetri(RessourcesDisponibles ressource){
nbRC++;
//Creation de la Place
Place ressourcePlace = petriFactory.createPlace();
Projet I
41
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
ressourcePlace.setName(ressource.getRessourceType());
System.out.println("nom place ressource" + ressource.getRessourceType());
ressourcePlace.setNbJeton(ressource.getRessourceNombre());
//ajouter les elements au reseau pertri
getPertiNet().getLieux().add(ressourcePlace);
//Ajouter les elements au StockageReseaux
StockagePR resEnPetri = new
StockagePR(ressource.getRessourceType(),ressourcePlace);
stockagePlacesRessources.add(resEnPetri);
}
/**
* Convertie un Process en reseau de Petri
* @param WorkDefinition
*/
public void convertionWDPetri(WorkDefinition wd){
nbWDC++;
Place notStarted = petriFactory.createPlace();
notStarted.setName("notStarted" + wd.getName() + nbWDC);
notStarted.setNbJeton(1);
Transition starts = petriFactory.createTransition();
starts.setName("starts" + wd.getName() + nbWDC);
Place started = petriFactory.createPlace();
started.setName("started" + wd.getName() + nbWDC);
Place running = petriFactory.createPlace();
running.setName("running" + wd.getName() + nbWDC);
Transition finishes = petriFactory.createTransition();
finishes.setName("finishes" + wd.getName() + nbWDC);
Place finished = petriFactory.createPlace();
finished.setName("finished" + wd.getName() + nbWDC);
Arc notStarted_Starts = petriFactory.createArc();
notStarted_Starts.setValeur(1);
Arc starts_Started = petriFactory.createArc();
starts_Started.setValeur(1);
Arc starts_Running = petriFactory.createArc();
starts_Running.setValeur(1);
Arc running_Finishes = petriFactory.createArc();
running_Finishes.setValeur(1);
Arc finishes_Finished = petriFactory.createArc();
finishes_Finished.setValeur(1);
//Relier les arcs
notStarted_Starts.setSuccessor(starts);
notStarted_Starts.setPredecessor(notStarted);
starts_Started.setSuccessor(started);
starts_Started.setPredecessor(starts);
starts_Running.setSuccessor(running);
starts_Running.setPredecessor(starts);
running_Finishes.setSuccessor(finishes);
running_Finishes.setPredecessor(running);
finishes_Finished.setSuccessor(finished);
finishes_Finished.setPredecessor(finishes);
//ajouter les elements au reseau pertri
getPertiNet().getLieux().add(notStarted);
getPertiNet().getLieux().add(started);
getPertiNet().getLieux().add(running);
getPertiNet().getLieux().add(finished);
getPertiNet().getLieux().add(starts);
getPertiNet().getLieux().add(finishes);
Projet I
42
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
getPertiNet().getArcs().add(notStarted_Starts);
getPertiNet().getArcs().add(starts_Started);
getPertiNet().getArcs().add(starts_Running);
getPertiNet().getArcs().add(running_Finishes);
getPertiNet().getArcs().add(finishes_Finished);
//ajouter les elements au StockageReseaux
StockageWd wdEnPetri = new
StockageWd(wd.getName(),starts_Started,finishes_Finished);
stockageReseaux.add(wdEnPetri);
}
public static void main(String[] args) {
// Chargement du package SimplePDL afin de l’enregistrer dans le registre
d’Eclipse.
SimplepdlPackage packageInstance = SimplepdlPackage.eINSTANCE;
// Enregistrer l’extension ".xmi" comme devant ere ouverte a
// l’aide d’un objet "XMIResourceFactoryImpl"
Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE;
Map<String, Object> m = reg.getExtensionToFactoryMap();
m.put("xmi", new XMIResourceFactoryImpl());
// Creer un objet resourceSetImpl qui contiendra une ressource EMF (notre modele)
ResourceSet resSet = new ResourceSetImpl();
// Definir la ressource (notre modele en PertiNet)
URI modelPetri = URI.createURI("models/PertiNet_From_SimplePDL.xmi");
Resource resourcePerti = resSet.createResource(modelPetri);
// Charger la ressource (notre modele en SimplePDL)
URI modelSimplePL = URI.createURI("SimplePDL/pdl-sujet.xmi");
Resource resourcePDL = resSet.getResource(modelSimplePL, true);
// Recuperer le premier element du modele SimplePDL (element racine)
Process process = (Process) resourcePDL.getContents().get(0);
//Creer un reseau de petri
SimplePDL2PetriNet simplePDL2PetriNet = new SimplePDL2PetriNet(process);
simplePDL2PetriNet.pertiNet.setName(process.getName());
// Ajouter le Process dans notre modele
resourcePerti.getContents().add(SimplePDL2PetriNet.getPertiNet());
/**
* Manipulation de notre instance
*/
// Acceder aux informations du processus chargee
System.out.println("Processus : " + process.getName());
// Naviguer dans les references
Integer nbPE = process.getProcessElements().size();
System.out.println("Nombre de ProcessElement dans " + process.getName() + " : "
+ nbPE);
// Convertir les WorkDefinition en elements de reseau de petri
for (Object o : process.getProcessElements()) {
if (o instanceof WorkDefinition) {
Projet I
43
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
WorkDefinition wd = (WorkDefinition) o;
simplePDL2PetriNet.convertionWDPetri(wd);
}
}
// Convertir les Ressources en elements de reseau de petri
for (Object r : process.getProcessElements()) {
if (r instanceof RessourcesDisponibles) {
RessourcesDisponibles ressource = (RessourcesDisponibles) r;
simplePDL2PetriNet.convertionRessourcePetri(ressource);
}
}
// Relier les WorkDefinition entre elles
for (Object o : process.getProcessElements()) {
if (o instanceof WorkSequence) {
WorkSequence ws = (WorkSequence) o;
WorkSequenceType valeur = ws.getLinkType();
System.out.println("WS :" + ws.getLinkType());
Arc arc = petriFactory.createArc();
arc.setValeur(1);
arc.setType(TypeArc.READ_ARC_LITERAL);//utiliser un ReadArc
if(valeur==WorkSequenceType.START_TO_START_LITERAL)
{
arc.setSuccessor(SimplePDL2PetriNet.
getTransitionStarts(ws.getSuccessor()
.getName()));//TransitionStarts
arc.setPredecessor(SimplePDL2PetriNet.
getPlaceStarted(ws.getPredecessor()
.getName()));//PlaceStarted
}
else if(valeur==WorkSequenceType.START_TO_FINISH_LITERAL)
{
arc.setSuccessor(SimplePDL2PetriNet.
getTransitionFinishes(ws.getSuccessor()
.getName()));//TransitionFinishes
arc.setPredecessor(SimplePDL2PetriNet.getPlaceStarted(ws
.getPredecessor().getName()));//PlaceStarted
}
else if(valeur==WorkSequenceType.FINISH_TO_START_LITERAL)
{
arc.setSuccessor(SimplePDL2PetriNet.
getTransitionStarts(ws.getSuccessor()
.getName()));//TransitionStarts
arc.setPredecessor(SimplePDL2PetriNet.
getPlaceFinished(ws.getPredecessor()
.getName()));//PlaceFinished
}
else
{
arc.setSuccessor(SimplePDL2PetriNet.
getTransitionFinishes(ws.getSuccessor()
.getName()));//TransitionFinishes
arc.setPredecessor(SimplePDL2PetriNet.
getPlaceFinished(ws.getPredecessor(
).getName()));//PlaceFinished
}
simplePDL2PetriNet.ajouterArc(arc);
Projet I
44
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
}
}
// Relier les Ressources aux Workdefinitions
// Parcourir chaque Besoin en ressource pour chaque WD
for (Object o : process.getProcessElements()) {
if (o instanceof WorkDefinition) {
WorkDefinition wd = (WorkDefinition) o;
for (Object r : wd.getBesoinRessource()) {
System.out.println(r);
if (r instanceof RessourcesRequises) {
RessourcesRequises ressource = (RessourcesRequises) r;
String typeRessource = ressource.getRessourceType();
int nbRessourcesNecessaires = ressource.getRessourceNombre();
// Creer deux arcs
Arc arcRessource_to_Starts = petriFactory.createArc();
arcRessource_to_Starts
.setValeur(nbRessourcesNecessaires);
Arc arcFinishes_to_Ressource = petriFactory
.createArc();
arcFinishes_to_Ressource.
setValeur(nbRessourcesNecessaires);
// Les relier convenablement
arcRessource_to_Starts.
setPredecessor(SimplePDL2PetriNet.
getPlaceRessource(typeRessource));
arcRessource_to_Starts.
setSuccessor(SimplePDL2PetriNet.
getTransitionStarts(wd.getName()));
arcFinishes_to_Ressource.
setPredecessor(SimplePDL2PetriNet.
getTransitionFinishes(wd.getName()));
arcFinishes_to_Ressource.
setSuccessor(SimplePDL2PetriNet.
getPlaceRessource(typeRessource));
// Ajouter les arcs au reseau
simplePDL2PetriNet.ajouterArc(arcRessource_to_Starts);
simplePDL2PetriNet.ajouterArc(arcFinishes_to_Ressource);
}
}
}
}
// Sauver la ressource
try {
resourcePerti.save(Collections.EMPTY_MAP);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Projet I
45
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
1.2
PetriNet2dot.mtl
[comment encoding = UTF-8 /]
[module PetriNet2dot(’http://petrinet/1.0’)/]
[template public PetriNet2dot(element : petrinet::ReseauPetri)]
[comment @main /]
[file (element.Name.concat(’.dot’), false, ’UTF-8’)]
digraph [element.Name/]{
[for(trans : Transition | element.Lieux->getTrs())]
[for(arc : Arc |trans.linksToPredecessors)]
[trans.Name/] -> [arc.Successor.Name /]
[/for]
[for (arc : Arc |trans.linksToSuccessor)]
[arc.Predecessor.Name /] -> [trans.Name/]
[/for]
[/for]
}
[/file]
[/template]
[comment Generation de la syntaxe PDL1 a partir d’un modele de processus /]
[query public getTrs(elements : OrderedSet(Lieu)) : OrderedSet(Transition) =
elements->select( e | e.oclIsTypeOf(Transition) )
->collect( e | e.oclAsType(Transition))
->asOrderedSet()
/]
[query public getPlaces(elements : OrderedSet(Lieu)) : OrderedSet(Place) =
elements->select( e | e.oclIsTypeOf(Place))
->collect( e | e.oclAsType(Place) )
->asOrderedSet()
/]
[template public EcrirePlacesSuivantes(tr : Transition)]
[for (arc : Arc |tr.linksToPredecessors)][arc.Successor.Name /][arc.getArcValeur()/]
[/for]
[/template]
[template public EcrirePlacesPrecedentes(tr : Transition)]
[for (arc : Arc |tr.linksToSuccessor)][arc.Predecessor.Name /][arc.getArcValeur()/]
[/for]
[/template]
[template public getArcValeur(arc : Arc)]
[if(arc.Type=TypeArc::ReadArc)]?[arc.Valeur/][elseif(arc.Valeur>1)]*[arc.Valeur/][/if]
[/template]
1.3
PetriNet2Tina.mtl
[comment encoding = UTF-8 /]
[module PetriNet2Tina(’http://petrinet/1.0’)/]
Projet I
46
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
[template public PetriNet2Tina(element : petrinet::ReseauPetri)]
[comment @main /]
[file (element.Name.concat(’ViaSimplePDL2PetriNetViaATLRessourcesMultiples.net’),
false, ’UTF-8’)]
[for (trans : Transition | element.Lieux->getTrs())]
tr [trans.Name/] [EcrirePlacesPrecedentes(trans)/] ->
[EcrirePlacesSuivantes(trans)/]
[/for]
[for (pl : Place | element.Lieux->getPlaces())]
[if(pl.NbJeton>0)] pl [pl.Name/] ([pl.NbJeton/])
[/if]
[/for]
net ifip
[/file]
[/template]
[comment Generation de la syntaxe PDL1 a partir d’un modele de processus /]
[query public getTrs(elements : OrderedSet(Lieu)) : OrderedSet(Transition) =
elements->select( e | e.oclIsTypeOf(Transition) )
->collect( e | e.oclAsType(Transition))
->asOrderedSet()
/]
[query public getPlaces(elements : OrderedSet(Lieu)) : OrderedSet(Place) =
elements->select( e | e.oclIsTypeOf(Place))
->collect( e | e.oclAsType(Place) )
->asOrderedSet()
/]
[template public EcrirePlacesSuivantes(tr : Transition)]
[for (arc : Arc |tr.linksToPredecessors)][arc.Successor.Name /][arc.getArcValeur()/]
[/for]
[/template]
[template public EcrirePlacesPrecedentes(tr : Transition)]
[for (arc : Arc |tr.linksToSuccessor)][arc.Predecessor.Name /][arc.getArcValeur()/]
[/for]
[/template]
[template public getArcValeur(arc : Arc)]
[if(arc.Type=TypeArc::ReadArc)]?[arc.Valeur/][elseif(arc.Valeur>1)]*[arc.Valeur/][/if]
[/template]
1.4
PDL1.xtext
grammar beTP6.PDL1 with org.eclipse.xtext.common.Terminals
generate pDL1 "http://www.PDL1.beTP6"
Process :
’process’ name=ID ’{’
processElements+=ProcessElement*
’}’
Projet I
47
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
;
ProcessElement :
WorkDefinition
| WorkSequence
| Guidance
;
WorkDefinition :
’wd’ name=ID
;
WorkSequence :
’ws’ linkType=WorkSequenceType
’from’ predecessor=[WorkDefinition]
’to’ successor=[WorkDefinition]
;
Guidance:
text=STRING
;
enum WorkSequenceType :
start2start = ’s2s’
| finish2start = ’f2s’
| start2finish = ’s2f’
| finish2finish = ’f2f’
;
1.5
PDL2.xtext
grammar beTP6.PDL2 with org.eclipse.xtext.common.Terminals
generate pDL2 "http://www.PDL2.beTP6"
Process :
’process’ name=ID ’{’
processElements+=ProcessElement*
’}’
;
ProcessElement :
WorkDefinition
| Guidance
;
WorkDefinition :
’wd’ name=ID ’{’
(’start’ ’if’ (linksToPredecessors+=DependanceStart)+)?
(’finish’ ’if’ (linksToSuccessors+=DependanceFinish)+)?
’}’
;
DependanceStart :
predecessor=[WorkDefinition] link=WorkSequenceKindStart
;
Projet I
48
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
WorkSequenceKindStart:
Started2Start = ’started’
| Started2Finish = ’finished’
;
DependanceFinish :
predecessor=[WorkDefinition] link=WorkSequenceKindFinish
;
WorkSequenceKindFinish:
Finished2Start = ’started’
| Finished2Finish = ’finished’
;
Guidance:
text=STRING
;
1.6
Perti1.xtext
grammar beTP6.PETRI1 with org.eclipse.xtext.common.Terminals
generate pETRI1 "http://www.PETRI1.beTP6"
Process :
’ReseauPerti’ name=ID ’{’
((Lieux+=Lieu)+ ’->’)*
(Arcs+=Arc)+
’}’
;
Lieu:
Place
(linksToPredecessors+=Arc)*
(linksToSuccessors+=Arc)*
| Transition
(linksToPredecessors+=Arc)*
(linksToSuccessors+=Arc)*
;
Place :
’pl’ name=ID
(NbJeton = INT)
;
Transition :
’tr’ name=ID
;
Arc:
valeur=INT
type = Typearc
predecessor=[Lieu]
successor=[Lieu]
Projet I
49
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
;
enum Typearc :
Normal
| readArc
;
1.7
Perti2.xtext
grammar beTP6.PETRI2 with org.eclipse.xtext.common.Terminals
generate pETRI2 "http://www.PETRI2.beTP6"
Process:
Lieu+=Lieu*
’net ifip’
;
Lieu:
Place
| Transition
;
Place :
’pl’ name=ID
’(’(NbJeton = INT)’)’
;
Transition :
’tr’ name=ID
linksToPredecessors+=Arc+
’->’
linksToSuccessors+=Arc+
;
Arc:
valeur=INT
type = Typearc
predecessor=[Lieu]
successor=[Lieu]
;
enum Typearc :
Normal
| readArc
;
readArc:
’?’;
1.8
SimplePDL2PetriNet.atl
module SimplePDL2PetriNet;
Projet I
50
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
create OUT: petrinet from IN: simplepdl;
-- Obtenir le processus qui contient ce process element.
-- Remarque: Ce helper ne serait pas utile si une reference opposite
-- avait ete placee entre Process et ProcessElement
helper context simplepdl!ProcessElement
def: getProcess(): simplepdl!Process =
simplepdl!Process.allInstances()
->select(p | p.processElements->includes(self))
->asSequence()->first();
--helper context simplepdl!Ressources
def: getProcessViaRes(): simplepdl!Process =
simplepdl!Process.allInstances()
->select(p | p.ressourcesElements->includes(self))
->asSequence()->first();
-- Traduire un Process en un PetriNet de meme nom
rule Process2PetriNet {
from p: simplepdl!Process
to pn: petrinet!ReseauPetri (Name <- p.name)
}
-- Traduire une WorkDefinition en un motif sur le reseau de Petri
rule WorkDefinition2PetriNet {
from wd: simplepdl!WorkDefinition
to
-- creer PLACES et TANSITIONS d’une WorkDefinition
p_ready: petrinet!Place(
Name <- wd.name + ’_ready’,
NbJeton <- 1),
tr_starts: petrinet!Transition(
Name <- wd.name + ’_starts’),
p_started: petrinet!Place(
Name <- wd.name + ’_started’,
NbJeton <- 0),
p_running: petrinet!Place(
Name <- wd.name + ’_running’,
NbJeton <- 0),
tr_finishes: petrinet!Transition(
Name <- wd.name + ’_finishes’),
p_finished: petrinet!Place(
Name <- wd.name + ’_finished’,
NbJeton <- 0),
-- creer ARCS d’une WorkDefinition
ready_Starts: petrinet!Arc(
Valeur <- 1,
Predecessor <- p_ready,
Successor <- tr_starts
),
starts_started: petrinet!Arc(
Valeur <- 1,
Predecessor <- tr_starts,
Successor <- p_started
),
starts_running: petrinet!Arc(
Valeur <- 1,
Projet I
51
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
Predecessor <- tr_starts,
Successor <- p_running
),
running_finishes: petrinet!Arc(
Valeur <- 1,
Predecessor <- p_running,
Successor <- tr_finishes
),
finishes_finished: petrinet!Arc(
Valeur <- 1,
Predecessor <- tr_finishes,
Successor <- p_finished
)
-- Ajouter les Lieux et Arcs au ReseauPetri
do {
thisModule.resolveTemp(wd.getProcess(), ’pn’).Lieux
thisModule.resolveTemp(wd.getProcess(), ’pn’).Lieux
thisModule.resolveTemp(wd.getProcess(), ’pn’).Lieux
thisModule.resolveTemp(wd.getProcess(), ’pn’).Lieux
thisModule.resolveTemp(wd.getProcess(), ’pn’).Lieux
thisModule.resolveTemp(wd.getProcess(), ’pn’).Lieux
thisModule.resolveTemp(wd.getProcess(), ’pn’).Lieux
thisModule.resolveTemp(wd.getProcess(), ’pn’).Lieux
thisModule.resolveTemp(wd.getProcess(), ’pn’).Lieux
thisModule.resolveTemp(wd.getProcess(), ’pn’).Lieux
thisModule.resolveTemp(wd.getProcess(), ’pn’).Lieux
}
<<<<<<<<<<<-
p_ready;
tr_starts;
p_started;
p_running;
tr_finishes;
p_finished;
ready_Starts;
starts_started;
starts_running;
running_finishes;
finishes_finished;
}
-- Traduire une WorkSequence en un motif sur le reseau de Petri
rule WorkSequence2PetriNet {
from ws: simplepdl!WorkSequence
to
-- Creer l’arc
arc_WS: petrinet!Arc(
Valeur <- 1,
Type <- #ReadArc,
Predecessor <- if( ws.linkType = #startToStart or ws.linkType =
#startToFinish) then
thisModule.resolveTemp(ws.predecessor, ’p_started’)
else
thisModule.resolveTemp(ws.predecessor, ’p_finished’)
endif,
Successor <- if( ws.linkType=#startToStart or ws.linkType=#finishToStart)
then
thisModule.resolveTemp(ws.successor, ’tr_starts’)
else
thisModule.resolveTemp(ws.successor, ’tr_finishes’)
endif
)
-- Ajouter les Lieux et Arcs au ReseauPetri
do {
thisModule.resolveTemp(ws.getProcess(), ’pn’).Lieux <- arc_WS;
}
}
-- Traduire une Ressource en places sur le reseau de Petri
Projet I
52
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
rule Ressource2PetriNet {
from proc: simplepdl!Process
to
-- Creer la place
p_concepteur: petrinet!Place(
Name <- ’concepteur’ + ’_ressource’,
NbJeton <- proc.ressourcesElements.ressourceNombre
),
p_developpeur: petrinet!Place(
Name <- ’developpeur’ + ’_ressource’,
NbJeton <- res.ressourceNombre
),
p_machine: petrinet!Place(
Name <- ’machine’ + ’_ressource’,
NbJeton <- res.ressourceNombre
),
p_redacteur: petrinet!Place(
Name <- ’redacteur’ + ’_ressource’,
NbJeton <- res.ressourceNombre
),
p_testeur: petrinet!Place(
Name <- ’testeur’ + ’_ressource’,
NbJeton <- res.ressourceNombre
)
-- Ajouter le Lieu au ReseauPetri
do {
thisModule.resolveTemp(res.getProcessViaRes(), ’pn’).Lieux <- p_ressource;
}
}
-- Traduire une Ressource en places sur le reseau de Petri
rule Ressource2PetriNet {
from res: simplepdl!Ressources
to
-- Creer la place
p_ressource: petrinet!Place(
Name <- ’res.ressourceType’ + ’_ressource’,
NbJeton <- res.ressourceNombre
)
-- Ajouter le Lieu au ReseauPetri
do {
thisModule.resolveTemp(res.getProcessViaRes(), ’pn’).Lieux <- p_ressource;
}
}
-- Traduire une Ressource en arcs sur le reseau de Petri
rule WorkDefinitionRessources2Arcs {
from wd: simplepdl!WorkDefinition
to
-- Creer l’arc
arc_WD_ressource: petrinet!Arc(
Valeur <- wd.getRessources().NbJeton,
Predecessor <- wd.tr_starts,
Successor <- wd.getRessources()
),
arc_ressource_WD: petrinet!Arc(
Projet I
53
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
Valeur <- wd.getRessources().NbJeton,
Predecessor <- wd.tr_finishes,
Successor <- wd.wd.getRessources()
)
-- Ajouter les Lieux et Arcs au ReseauPetri
do {
thisModule.resolveTemp(wd.getProcess(), ’pn’).Lieux <- arc_WD_ressource;
thisModule.resolveTemp(wd.getProcess(), ’pn’).Lieux <- arc_ressource_WD;
}
}
Projet I
54
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
Partie II - Ressources alternatives
1.9
SimplePDL2PetriNet.atl
module SimplePDL2PetriNet;
create OUT: petrinet from IN: simplepdl;
-- Obtenir le processus qui contient ce process element.
-- Remarque: Ce helper ne serait pas utile si une reference opposite
-- avait ete placee entre Process et ProcessElement
helper context simplepdl!ProcessElement
def: getProcess(): simplepdl!Process =
simplepdl!Process.allInstances()
->select(p | p.processElements->includes(self))
->asSequence()->first();
-- Traduire un Process en un PetriNet de meme nom
rule Process2PetriNet {
from p: simplepdl!Process
to pn: petrinet!ReseauPetri (Name <- p.name)
}
-- Traduire une WorkDefinition en un motif sur le reseau de Petri
rule WorkDefinition2PetriNet {
from wd: simplepdl!WorkDefinition
to
-- creer PLACES et TRANSITIONS d’une WorkDefinition
p_ready: petrinet!Place(
Name <- wd.name + ’_ready’,
NbJeton <- 1),
tr_starts: petrinet!Transition(
Name <- wd.name + ’_starts’),
p_started: petrinet!Place(
Name <- wd.name + ’_started’,
NbJeton <- 0),
p_running: petrinet!Place(
Name <- wd.name + ’_running’,
NbJeton <- 0),
tr_finishes: petrinet!Transition(
Name <- wd.name + ’_finishes’),
p_finished: petrinet!Place(
Name <- wd.name + ’_finished’,
NbJeton <- 0),
p_ressources_disponbiles:petrinet!Place(
Name <- wd.name + ’_ressources_disponbiles’,
NbJeton <- if(wd.besoinRessource.notEmpty()) then
Projet I
55
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
0
else
1
endif
),
p_rendre_ressources:petrinet!Place(
Name <- wd.name + ’_rendre_ressources’,
NbJeton <- if(wd.besoinRessource.notEmpty()) then
0
else
1
endif
),
-- creer ARCS d’une WorkDefinition
ready_Starts: petrinet!Arc(
Valeur <- 1,
Predecessor <- p_ready,
Successor <- tr_starts
),
starts_started: petrinet!Arc(
Valeur <- 1,
Predecessor <- tr_starts,
Successor <- p_started
),
starts_running: petrinet!Arc(
Valeur <- 1,
Predecessor <- tr_starts,
Successor <- p_running
),
running_finishes: petrinet!Arc(
Valeur <- 1,
Predecessor <- p_running,
Successor <- tr_finishes
),
finishes_finished: petrinet!Arc(
Valeur <- 1,
Predecessor <- tr_finishes,
Successor <- p_finished
),
ressources_disponbiles_Starts: petrinet!Arc(
Valeur <- 1,
Predecessor <- p_ressources_disponbiles,
Successor <- tr_starts,
Type <- if( wd.besoinRessource.notEmpty()) then
#Normal
else
#ReadArc
endif
),
finishes_rendre_ressource: petrinet!Arc(
Valeur <- 1,
Predecessor <- tr_finishes,
Successor <- p_rendre_ressources
)
-- Ajouter les Lieux et Arcs au ReseauPetri
do {
thisModule.resolveTemp(wd.getProcess(), ’pn’).Lieux <- p_ready;
Projet I
56
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
thisModule.resolveTemp(wd.getProcess(),
thisModule.resolveTemp(wd.getProcess(),
thisModule.resolveTemp(wd.getProcess(),
thisModule.resolveTemp(wd.getProcess(),
thisModule.resolveTemp(wd.getProcess(),
thisModule.resolveTemp(wd.getProcess(),
thisModule.resolveTemp(wd.getProcess(),
thisModule.resolveTemp(wd.getProcess(),
thisModule.resolveTemp(wd.getProcess(),
thisModule.resolveTemp(wd.getProcess(),
thisModule.resolveTemp(wd.getProcess(),
p_ressources_disponbiles;
thisModule.resolveTemp(wd.getProcess(),
ressources_disponbiles_Starts;
thisModule.resolveTemp(wd.getProcess(),
thisModule.resolveTemp(wd.getProcess(),
finishes_rendre_ressource;
’pn’).Lieux
’pn’).Lieux
’pn’).Lieux
’pn’).Lieux
’pn’).Lieux
’pn’).Lieux
’pn’).Lieux
’pn’).Lieux
’pn’).Lieux
’pn’).Lieux
’pn’).Lieux
<<<<<<<<<<<-
tr_starts;
p_started;
p_running;
tr_finishes;
p_finished;
ready_Starts;
starts_started;
starts_running;
running_finishes;
finishes_finished;
’pn’).Lieux <’pn’).Lieux <- p_rendre_ressources;
’pn’).Lieux <-
}
}
-- Traduire une WorkSequence en un motif sur le reseau de Petri
rule WorkSequence2PetriNet {
from ws: simplepdl!WorkSequence
to
-- Creer l’arc
arc_WS: petrinet!Arc(
Valeur <- 1,
Type <- #ReadArc,
Predecessor <- if( ws.linkType = #startToStart or ws.linkType =
#startToFinish) then
thisModule.resolveTemp(ws.predecessor, ’p_started’)
else
thisModule.resolveTemp(ws.predecessor, ’p_finished’)
endif,
Successor <- if( ws.linkType=#startToStart or ws.linkType=#finishToStart)
then
thisModule.resolveTemp(ws.successor, ’tr_starts’)
else
thisModule.resolveTemp(ws.successor, ’tr_finishes’)
endif
)
-- Ajouter les Lieux et Arcs au ReseauPetri
do {
thisModule.resolveTemp(ws.getProcess(), ’pn’).Lieux <- arc_WS;
}
}
-- Traduire une Ressource disponible en places sur le reseau de Petri
rule RessourceDispo2PetriNet {
from res: simplepdl!RessourcesDisponibles
to
-- Creer la place
p_ressource_dispo: petrinet!Place(
Name <- res.ressourceType + ’_ressource’,
NbJeton <- res.ressourceNombre
)
-- Ajouter le Lieu au ReseauPetri
Projet I
57
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
do {
thisModule.resolveTemp(res.getProcess(), ’pn’).Lieux <- p_ressource_dispo;
}
}
-- Traduire un groupe de Ressource en reseau de Petri
rule GroupeRessources2Petri {
from resGroupe: simplepdl!GroupeRessources
to
p_pressourcesRecuperees: petrinet!Place(
Name <- resGroupe.name + ’_ressourcesRecuperees’,
NbJeton <- 0),
tr_trrecupererRessources: petrinet!Transition(
Name <- resGroupe.name + ’_recupererRessources’),
tr_trrendreRessources: petrinet!Transition(
Name <- resGroupe.name + ’_rendreRessources’),
tr_desalouerRessources: petrinet!Transition(
Name <- resGroupe.name + ’_desalouerRessources’),
-- creer ARCS d’une WorkDefinition
arc_trrecupererRessources_pressourcesRecuperees: petrinet!Arc(
Valeur <- 1,
Predecessor <- tr_trrecupererRessources,
Successor <- p_pressourcesRecuperees
),
arc_trrecupererRessources_started: petrinet!Arc(
Valeur <- 1,
Predecessor <- tr_trrecupererRessources,
Successor <- thisModule.resolveTemp(resGroupe.utilisateur,
’p_ressources_disponbiles’)
),
arc_started_trrecupererRessources: petrinet!Arc(
Valeur <- 1,
Predecessor <- thisModule.resolveTemp(resGroupe.utilisateur,
’p_ressources_disponbiles’),
Successor <- tr_desalouerRessources
),
arc_pressourcesRecuperees_tr_trrendreRessources: petrinet!Arc(
Valeur <- 1,
Predecessor <- p_pressourcesRecuperees,
Successor <- tr_trrendreRessources
),
arc_finished_trrendreRessources: petrinet!Arc(
Valeur <- 1,
Predecessor <- thisModule.resolveTemp(resGroupe.utilisateur,
’p_rendre_ressources’),
Successor <- tr_trrendreRessources
),
arc_desalouerRessources: petrinet!Arc(
Valeur <- 1,
Predecessor <- p_pressourcesRecuperees,
Successor <- tr_desalouerRessources
)
--Ajouter les Lieux et Arcs au ReseauPetri
do {
Projet I
58
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
thisModule.resolveTemp(resGroupe.getProcess(), ’pn’).Lieux
p_pressourcesRecuperees;
thisModule.resolveTemp(resGroupe.getProcess(), ’pn’).Lieux
tr_trrecupererRessources;
thisModule.resolveTemp(resGroupe.getProcess(), ’pn’).Lieux
tr_trrendreRessources;
thisModule.resolveTemp(resGroupe.getProcess(), ’pn’).Lieux
arc_trrecupererRessources_pressourcesRecuperees;
thisModule.resolveTemp(resGroupe.getProcess(), ’pn’).Lieux
arc_trrecupererRessources_started;
thisModule.resolveTemp(resGroupe.getProcess(), ’pn’).Lieux
arc_pressourcesRecuperees_tr_trrendreRessources;
thisModule.resolveTemp(resGroupe.getProcess(), ’pn’).Lieux
arc_finished_trrendreRessources;
thisModule.resolveTemp(resGroupe.getProcess(), ’pn’).Lieux
arc_started_trrecupererRessources;
thisModule.resolveTemp(resGroupe.getProcess(), ’pn’).Lieux
arc_desalouerRessources;
thisModule.resolveTemp(resGroupe.getProcess(), ’pn’).Lieux
tr_desalouerRessources;
<<<<<<<<<<-
}
}
-- Relier les ressources disponibles aux groupes
rule RessourcesRequises2Arcs {
from resreq: simplepdl!RessourcesRequises
to
-- Creer l’arc
arc_groupe_ressource: petrinet!Arc(
Valeur <- resreq.ressourceNombre,
Predecessor <- thisModule.resolveTemp(resreq.groupesAssocies,
’tr_trrendreRessources’),
Successor <- thisModule.resolveTemp(resreq.ressourceAssociee,
’p_ressource_dispo’)
),
arc_ressource_groupe: petrinet!Arc(
Valeur <- resreq.ressourceNombre,
Predecessor <- thisModule.resolveTemp(resreq.ressourceAssociee,
’p_ressource_dispo’),
Successor <- thisModule.resolveTemp(resreq.groupesAssocies,
’tr_trrecupererRessources’)
),
arc_annuler_allocation_ressources: petrinet!Arc(
Valeur <- resreq.ressourceNombre,
Predecessor <- thisModule.resolveTemp(resreq.groupesAssocies,
’tr_desalouerRessources’),
Successor <- thisModule.resolveTemp(resreq.ressourceAssociee,
’p_ressource_dispo’)
)
-- Ajouter les Lieux et Arcs au ReseauPetri
do {
thisModule.resolveTemp(resreq.getProcess(), ’pn’).Lieux <arc_groupe_ressource;
thisModule.resolveTemp(resreq.getProcess(), ’pn’).Lieux <arc_ressource_groupe;
thisModule.resolveTemp(resreq.getProcess(), ’pn’).Lieux <arc_annuler_allocation_ressources;
Projet I
59
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
}
}
1.10
SimplePDLfinish.mtl
[comment encoding = UTF-8 /]
[module SimplePDLfinish(’http://petrinet/1.0’)/]
[template public SimplePDLfinish(element : petrinet::ReseauPetri)]
[comment @main /]
[file (element.Name.concat(’.ltl’), false, ’UTF-8’)]
[for(pl : Place | element.Lieux->getPlaces())before (’op finished = ’) separator
(’/\\’) after (’;’)][pl.Name/][/for]
[ ’[’ /][ ’]’ /] (finished => dead);
[ ’[’ /][ ’]’ /] <> dead ;
[ ’[’ /][ ’]’ /] (dead => finished);
- <> finished;
[/file]
[/template]
[query public getPlaces(elements : OrderedSet(Lieu)) : OrderedSet(Place) =
elements->select( e | e.oclIsTypeOf(Place))
->collect( e | e.oclAsType(Place) )
->asOrderedSet()->select(e | e.Name.contains(’finished’))
/]
1.11
validationPetri.mtl
[comment encoding = UTF-8 /]
[module validationPetri(’http://petrinet/1.0’)/]
[template public validationPetri(element : petrinet::ReseauPetri)]
[comment @main /]
[file (element.Name.concat(’VP.ltl’), false, ’UTF-8’)]
[for(pl : Place | element.Lieux->getPlacesfinished())before (’op finished = ’)
separator (’/\\’) after (’;’)][pl.Name/][/for]
[for(pl : Place | element.Lieux->getPlacesstarted())before (’op started = ’)
separator (’/\\’) after (’;’)][pl.Name/][/for]
[for(pl : Place | element.Lieux->getPlacesready())before (’op ready = ’) separator
(’/\\’) after (’;’)][pl.Name/][/for]
[for(pl : Place | element.Lieux->getPlacesrunning())before (’op running = ’)
separator (’/\\’) after (’;’)][pl.Name/][/for]
[
[
[
[
<> finished;
’[’ /][ ’]’ /]
’[’ /][ ’]’ /]
’[’ /][ ’]’ /]
’[’ /][ ’]’ /]
(finished => - <> ready);
(finished => - <> running);
(started => - <> ready);
(finished => started);
[/file]
Projet I
60
INP-ENSEEIHT 2IMA
Projet I
2013/2014
Guillaume Kempf 2ina
Génie du logiciel et des systèmes
[/template]
[query public getPlacesfinished(elements : OrderedSet(Lieu)) : OrderedSet(Place) =
elements->select( e | e.oclIsTypeOf(Place))
->collect( e | e.oclAsType(Place) )
->asOrderedSet()->select(e | e.Name.contains(’finished’))
/]
[query public getPlacesstarted(elements : OrderedSet(Lieu)) : OrderedSet(Place) =
elements->select( e | e.oclIsTypeOf(Place))
->collect( e | e.oclAsType(Place) )
->asOrderedSet()->select(e | e.Name.contains(’started’))
/]
[query public getPlacesready(elements : OrderedSet(Lieu)) : OrderedSet(Place) =
elements->select( e | e.oclIsTypeOf(Place))
->collect( e | e.oclAsType(Place) )
->asOrderedSet()->select(e | e.Name.contains(’ready’))
/]
[query public getPlacesrunning(elements : OrderedSet(Lieu)) : OrderedSet(Place) =
elements->select( e | e.oclIsTypeOf(Place))
->collect( e | e.oclAsType(Place))
->asOrderedSet()->select(e | e.Name.contains(’running’))
/]
Projet I
61
INP-ENSEEIHT 2IMA