Gestion d'états¶
Modèle d'états¶
Ewt permet de décrire un ou plusieurs modèles d'états au format XML. On appelle modèle d'états l'enchaînement de plusieurs états qui définissent ainsi un cycle de vie de dossier. Précisons au passage qu'une application Ewt peut parfaitement fonctionner sans gestion d'états.
Le modèle d'états permet de décrire des règles d'enchaînement d'états. Cela
se fait au moyen de transitions, auxquelles on associe un nom
(attribut name
) et un état cible (target
).
Lorsque l'on souhaite mettre en place une gestion d'états, on commence par
définir des modèles d'états (ou cycles de vie) sous la forme de fichiers XML
dans le sous-dossier states
de l'application. Chaque fichier XML permet de
décrire un modèle d'état. Exemple:
1 2 3 4 5 6 7 8 |
|
Le modèle d'états doit être identifié au moyen d'un nom (attribut name
).
Ce nom servira au référencement du modèle d'état depuis le modèle de
dossier (fichier descript.xml
).
En option, on peut également définir un attribut changemode
qui permet de
personnaliser le mode de changement d'état que l'on souhaite autoriser. Il
est possible de changer d'état de différentes façons:
- De façon explicite : on indique explicitement quel nouvel état le dossier doit avoir
- Par transition : on active une transition et le dossier prendra l'état cible associé à cette transition
- Par événement : un événement déclenche une transition (ce cas peut être associé au mode précédent)
Le changement d'état peut également être réalisé par un script (via les
méthodes $doc.setState
ou
$doc.fireStateTransition
), mais il
s'agit ici d'un cas particulier sur lequel nous revenons plus bas.
L'attribut peut donc prendre les valeurs name
(ou state
, ou explicit
),
transition
ou both
, cette dernière étant la valeur par défaut.
États¶
Chaque état est décrit au moyen d'un élément state
et doit avoir un attribut
name
qui permet de nommer l'état. Il est également possible de spécifier
une classe (attribut class
) et des transitions (éléments transition
).
La classe permet de spécifier si l'état est l'état initial
(classe initial
) et/ou l'état final (classe final
). Un état peut être à
la fois initial et final, auquel cas on notera class="initial final"
(il
est aussi possible de séparer les termes au moyen d'une virgule).
Il est possible d'associer des événements à un état. Un événement est une sorte de notification (en référence aux notifications décrites dans le fichier de configuration), c'est-à-dire une référence de script qui sera exécuté automatiquement par le moteur dans un contexte particulier. Le moteur prévoir deux types d'événements à associer aux états
onleave
: cet événement est déclenché lorsque le dossier quitte un état donnéonenter
: cet événement est déclenché lorsque le dossier arrive dans un état donné
Ces attributs permettent de spécifier un ou plusieurs noms de scripts
(séparés par une virgule) à évaluer lorsque l'événement se produit.
Les scripts sont évalués selon le même principe que les notifications
déclarées dans le config.xml
. Veuillez lire la note plus bas concernant
la cohabitation entre les notifications de la configuration et les
événements du modèle d'états.
Comme dans le cas des notifications, les événements ont la possibilité
d'interrompre le changement d'état en invoquant la méthode
$thread.abortNotifiedAction()
.
L'exécution du script peut également être contrainte à l'aide de
l'annotation @accept
. Cela évite que le script ne soit évalué dans un
autre contexte qu'une notification.
@accept(trigger = "notification")
Transitions¶
Les transitions indiquent les règles de passage d'un état à l'autre.
Chaque transition doit au minimum indiquer un nom (attribut name
) et
l'état de destination (attribut target
).
Il est possible de spécifier un événement à déclencher lors de la transition
via l'attribut ontransition
. Cet attribut indiquera le nom d'un ou de
plusieurs scripts à évaluer lorsque la transition est invoquée. Les noms de
scripts peuvent être séparés par une virgule, par exemple:
<transition name="ticket.cloturer" target="ticketTermine"
ontransition="stateChange,finalizeTicket"/>
Il est également possible de spécifier des événements onleave
et onenter
sur une transition. Lorsqu'ils sont définis, ces derniers surchargent les
événements correspondants des états source/destination lorsque la transition
est invoquée. Cela signifie que si l'application déclenche une transition,
le moteur évaluera, dans l'ordre:
- L'événement
onleave
de l'état de départ - L'événement
ontransition
de la transition - L'événement
onenter
de l'état d'arrivée
Les étapes 1 et 3 ci-dessus peuvent être modifiées voire neutralisées en redéfinissant les attributs correspondants au niveau de la transition.
Transitions publiques/privées¶
Par défaut, les transitions sont publiques, ce qui signifie qu'elles sont
déclenchables par un utilisateur depuis l'interface web via l'action
setState
.
Il est possible de définir des transitions non publiques en ajoutant un
attribut public="false"
sur la transition. Les transitions non publiques
ne pourront pas être déclenchées explicitement par l'utilisateur. Elles
seront uniquement déclenchables par un script.
Pour comprendre l'idée, voyons l'exemple suivant: un dossier "Demande" peut prendre les états "création", "accepté" ou "refusé". À partir de l'état "création", le changement d'état vers "accepté" ou "refusé" dépend de règles avancées définies au sein d'un script. L'utilisateur n'est pas en mesure de déterminer quelle transition appliquer. Il peut uniquement déclencher l'exécution du script qui décidera lui-même si le changement d'état est possible et, le cas échéant, vers quel état ce changement doit être fait.
En pratique, on représentera ce cas de figure ainsi:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
Événements d'état et notifications
Ewt permet de définir des notifications doc-leavestate
et
doc-enterstate
dans le fichier de configuration, ainsi que des
événements1 au niveau des éléments <state>
ou <transition>
du
modèle d'états. Les notifications du config et les événements d'états
remplissent le même rôle. La majeure différence se situe au niveau de la
condition de déclenchement:
-
Les notifications du config sont déclenchées lors d'une action envoyée par le client (l'utilisateur) via une requête HTTP. Le moteur envoie les notifications
doc-leavestate
etdoc-enterstate
pour tout changement d'état.Les notifications ne sont par défaut pas envoyées automatiquement lors des changements d'états déclenchés par script via les méthodes
$doc.setState
ou$doc.fireStateTransition
. La notification peut toutefois être forcée via le paramètrenotify
de ces méthodes. -
Les événements d'état ou de transition sont déclenchés uniquement lors d'un changement porte sur l'état ou la transition pour lesquels ils sont définis.
Au contraire des notifications, les événements sont automatiquement déclenchés lors d'un changement d'état par script. Les méthodes
$doc.setState
ou$doc.fireStateTransition
permettent toutefois de piloter le déclenchement d'événements au moyen du paramètreevents
.
Lorsque les notifications et les événements sont activés simultanément, les opérations sont réalisées dans l'ordre suivant:
- notification
doc-leavestate:before
- notification
doc-enterstate:before
- événement
onleave
- événement
ontransition
- événement
onenter
- notification
doc-leavestate:after
- notification
doc-enterstate:after
Notification | Événement | |
---|---|---|
Déclaration | Déclaré via les notifications doc-leavestate et doc-enterstate du config.xml |
Déclaré via les attributs onleave , onenter et ontransition des états et transitions d'un modèle d'état |
Changement d'état par action | Déclenché lors de tout changement d'état | Uniquement déclenché lors d'un changement relatif à l'état ou la transition concernée |
Changement d'état par script | Non déclenché automatiquement | Déclenché automatiquement si le changement porte sur l'état ou la transition concernée |
Propriétés¶
De façon analogue à la descript (fichier descript.xml
), le modèle d'états
et ses éléments (state
et transition
) peuvent définir des propriétés. La
syntaxe et les namespaces utilisables sont les mêmes que pour la descript.
Voici un exemple dans lequel on utilise des propriétés pour lier une icone
et une couleur aux états, et extraction des valeurs depuis la base de
données. Ces dernières seront reprises dans l'arbre de sortie.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
Référencement de modèle d'état¶
Pour appliquer un modèle d'états à un modèle de dossier, il suffit de
référencer le premier dans le second à l'aide de l'attribut statesmodel
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Un modèle d'états n'est pas forcément lié à un et un seul modèle de dossier. Plusieurs modèles de dossier peuvent référencer un même modèle d'états.
En plus du modèle d'états, le modèle de dossier qui souhaite appliquer une
gestion d'états doit fournir un champ de statut. Il s'agit d'un champ de la
base de données qui servira à enregistrer l'état du dossier. Pour ce faire,
on spécifie le nom de champ en question au moyen de l'attribut statefield
dans le fichier descript.xml
.
Internationalisation¶
La gestion des libellés reprend le même principe que celui qui vaut pour le
fichier de descript, à savoir: les libellés peuvent être définis inline sur
les états et transitions via un attribut label
ou à l'aide des bundles de
langues. Il en va de même pour les descriptions (attribut description
).
Lorsque les libellés doivent être internationalisés, il est recommandé de s'appuyer sur les bundles de langue. Ewt prévoit un format d'étiquettes pour les éléments des bundles de langues. Les libellés décrivant les états et les transitions sont à spécifier au niveau des bundles de l'application.
Par convention, une étiquette désignant un nom d'état doit avoir la forme suivante:
states.<states-model-name>.state.<state-name>.label
où <states-model-name>
est le nom du modèle d'états et <state-name>
est
le nom de l'état.
Pour les transitions, il existe deux syntaxes d'étiquettes possibles: la version standard et la version précise.
La version standard utilise la notation suivante:
states.<states-model-name>.transition.<transition-name>.label
où <transition-name>
est le nom de la transition.
La version précise peut être utilisée s'il existe plusieurs transitions de même nom et qu'on souhaite leur attribuer un libellé spécifique selon l'état de départ. La version précise reprend le nom de l'état dans le libellé, ce qui donne:
states.<states-model-name>.state.<state-name>.transition.<transition-name>.label
où state-name
est le nom de l'état à partir duquel la transition est
effectuée.
La notation précise prime sur la notation standard qui n'inclut pas le nom d'état.
Prenons l'exemple suivant:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
Pour renseigner les libellés de chaque élément, on pourra par exemple utiliser la définition suivante:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
Dans l'exemple ci-dessus, on surcharge le libellé de la transition "ticket.cloturer" pour l'état "standby" par un libellé différent.
Le principe de nommage est le même pour la description : l'attribut
description
permet de spécifier un texte explicatif sur l'état ou la
transition. Ce libellé peut être défini au niveau des bundles de langues.
Dans ce cas les noms d'étiquettes sont les mêmes, à la différence que le
suffixe .label
est changé en .description
.
-
Le terme "événement" est utilisé ici dans le but de clarifier le propos (et de reprendre la nomenclature de la norme SCXML de laquelle Ewt s'inspire), mais en réalité événements et notifications fonctionnent selon le même principe du point de vue du moteur. ↩