Sommaire
Index
OpenTool
9 septembre 97
 

Manuel d'Administration


  1. Organisation générale
    1. Présentation
    2. Fichier "opentool.ini"
    3. Fichiers de configuration
    4. Répertoires de sauvegarde
    5. Le fichier main.mn
    6. Choix de la langue
  2. Langage des fichiers du méta-modèle
    1. Organisation
    2. Configuration
    3. Erreurs au lancement
    4. Langage
  3. OTScript: langage sur le méta-modèle
    1. Conventions
    2. Principes
    3. Expressions
    4. Opérateurs généraux
    5. Opérateurs ensemblistes
    6. Opérateurs Booléen
    7. Opérateurs Entiers
    8. Opérateurs Chaînes
    9. Opérateurs énumération
    10. Opérateurs d'IHM
    11. Opérateurs d'entrée-sortie
    12. Ordres OTScript propres aux éditeurs
  4. Formulaires de saisie des informations
  5. Les browsers textuels
    1. Présentation
    2. Exemple commenté
    3. Format général
  6. Les diagrammes
    1. Présentation
    2. Exemple commenté
    3. Format général
    4. Méthodes de DISPLAY
  7. Les règles
    1. Règles de base
    2. Méta-Règles
  8. Les méthodes
    1. Portée des méthodes
    2. Enrichissement des menus
    3. Paramètres et Temporaires
    4. Méthodes automatiquement appelées
  9. Documentation configurable
    1. Configuration de documents génériques
    2. Formats de sortie de la documentation
    3. Configuration sur la base des méthodes
  10. Fichiers et formats de sauvegarde
    1. Fichiers sémantiques
    2. Fichiers de diagrammes
  11. Exécution de fichiers de commandes

Organisation générale

Présentation

La configuration générale de l'outil se trouve dans le fichier opentool.ini du répertoire bin.suf correspondant à votre configuration matérielle et logicielle. Si vous désirez modifier des valeurs de variables de ce fichier, il est recommandé de créer un nouveau fichier opentool.ini dans le répertoire C:\windows et de préciser uniquement les variables à modifier. Par ailleurs, les variables du fichier opentool.ini peuvent être affectées lors du lancement de l'outil sur la ligne de commande. Par exemple, le lancement suivant permet de sélectionner la configuration UML :
opentool.exe Main=uml
La configuration méthodologique comporte deux niveaux : Les fichiers *.br sont le lieu d'expression:  

Le fichier "opentool.ini"

Un fichier opentool.ini est livré dans le répertoire qui contient l'exécutable : il contient tous les paramètres possibles que peut contenir un tel fichier.
Il peut être successivement surchargé partiellement en plaçant un fichier opentool.ini sous :
  • C:\windows (PC) ou $HOME (Unix)
  • le répertoire local

  • Une surcharge ultime peut se faire sur la ligne de commande.

    Les fichiers de configuration

    Les fichiers de configuration sont cherchés dans les répertoires spécifiés dans la variable ConfigPath du fichier opentool.ini. Les fichiers que l'on veut prendre en compte sont déclarés dans le dernier fichier main.mn trouvé dans la liste de répertoires précédente, main étant la valeur de la variable Main du fichier opentool.ini.

    Les répertoires de sauvegarde

    Les applications utilisateurs présentées à l'ouverture d'OpenTool proviennent des répertoires spécifiés dans la variable SavePath du fichier opentool.ini.
    Lors du passage à une autre méthode (UML à OOA par exemple), il faut non seulement configurer la variable Main (Main = ooa), mais aussi penser éventuellement à changer le chemin d'accès aux répertoires de sauvegarde.

    Le fichier main.mn

    Voici un exemple de fichier main.mn :
    UML:
    LABEL "UML"
    {
            kernel
            stereo
            types
            systems
            state_md
            diagrams
            ooa
            uml
            code
            
            methods
            menus
            methsuml
            accesooa
            refatooa
            methsooa
            rules
            
            uiuml
            ui
            
            form_cmt
            forms
            formsuml
            form_cod
            
            cpp
            stk
            o2
            docs
            
            form_ref
    };
    Ce fichier déclare, sans précision de suffixe, les fichiers de configuration .ml et .br à lire au lancement de l'outil.

    Une déclaration peut correspondre à 2 fichiers: la déclaration cpp provoque la prise en considération de cpp.ml et cpp.br; d'autres ne correspondent qu'à un fichier .ml ou un fichier .br.

    La configuration de ce fichier permet de mettre de côté des éléments inutiles à l'utilisateur. Un utilisateur ne travaillant qu'en C++ éliminera la déclaration stk des spécificités Smalltalk par exemple.

    L'ordre de prise en compte des fichiers est d'autre part fondamental pour la compilation lors du lancement de l'outil: il faut toujours que la définition d'une méthode précède son utilisation. L'appel d'un fichier contenant du code utilisant la méthode A doit être ultérieur à l'appel du fichier contenant la définition de la méthode A.

    Choix de la langue

    Le choix de la langue se fait sur la ligne de commande en y rajoutant:
    -l fra
    pour une version en Français
    -l eng
    pour une version en Anglais
    exemple: N:\ot3\bin.w32\opentool.exe -l fra

    Dans les fichiers de configuration .br, l'utilisation de la barre verticale | permet de saisir les chaînes de caractères en Anglais et en Français de la manière suivante:

    "private" | "privé"
    retournera "privé" avec -l fra sur la ligne de commande
    "protected" | "protégé"
    retournera "protected" avec -l eng sur la ligne de commande

    Langage des fichiers du méta-modèle

    La description du méta-modèle est contenue sous le répertoire config, dans un ensemble de fichiers suffixés .ml .
    Lors du lancement d'OpenTool, l'ensemble des fichiers déclarés dans le fichier main.mn est lu, et cet ensemble (réunion de l'information contenue dans ces fichiers) doit constituer une description cohérente de méta-modèle, sans quoi le lancement ne peut aboutir. 

    Organisation

    Dans la livraison, chaque fichier est dédié à un aspect particulier du méta-modèle: Une classe du méta-modèle est généralement décrite partiellement dans plusieurs fichiers; l'outil opère la synthèse de cette information fractionnée:

    Configuration

    Tous les fichiers peuvent être modifiés par l'utilisateur; il peut également en créer de nouveaux, ou en supprimer certains. Il est cependant fortement conseillé de ne pas modifier les fichiers contenant les notions centrales du méta-modèle, comme le fichier kernel.ml , mais plutôt de l'enrichir par des informations supplémentaires placées dans d'autres fichiers, soit existants, soit créés par l'utilisateur. 

    Erreurs au lancement

    Lorsqu'il y a incohérence au chargement du méta-modèle, des messages explicatifs apparaissent: il convient alors de corriger l'erreur et de relancer OpenTool. 

    Langage

    Notions utilisées

    La structure de donnée objet du méta-modèle est exprimée en termes de: La notion d'association entre classes y est totalement exprimée et la cohérence issue des cardinalités garantie :
    si l'on veut exprimer que la classe Class contient des attributs Attribute, il s'agit bien d'une association entre Class et Attribute; il faut alors préciser les rôles de cette association avec les cardinalités associées afin de pouvoir garantir une cohérence sans faille du modèle.
    Voici comment le langage du méta-modèle permet de l'exprimer :
    Class : TypingObject  // Class hérite de TypingObject
       {attributes: Attribute [0..*] INVERSE class
          // l'attribut attributes est issu d'une association,
          // reconnaissable au mot-clé INVERSE, avec Attribute;
                // sa cardinalité va de 0 à l'infini;
                // l'attribut pendant (rôle opposé) du lien est
                // class dans Attribute, mentionné dans la
                // description de la classe Attribute ci-dessous  
    }
    
    Attribute : AbstractAttribute {
       class: Class INVERSE attributes (id) 
          // l'attribut class est issu d'une association avec Class;
          // sa cardinalité (non explicitement mentionnée) est 1;        
    }
    

    Mots réservés

    Types prédéfinis

    Synonymes

        TYPE Name : String   // Name est synonyme de String
    

    Définition de classe

    < classe > : < superclasse > < options > { < attributs > };

    options est optionnel.
    Seul l'héritage simple est supporté.

    Attributs simples

    < attribut > : < type > < options >
    type fait partie des types prédéfinis (String, Integer, ...).

    Attributs issus d'association

    < attribut > : < classe > < cardinalité > INVERSE < attribut inverse >
    < options >
    Une cardinalité non mentionnée exprime une cardinalité simple ( [1..1] ).
    La cardinalité s'exprime, lorsqu'elle n'est pas simple, par un intervalle [a..b] où a est la borne naturelle inférieure et b la borne supérieure, l'infini étant exprimé par le caractère * .

    Classe du méta-modèle

    Le stéréotype cluster permet de déclarer une classe du méta-modèle comme point d'entrée d'un fichier de sauvegarde.
    Le stéréotype abstract permet de déclarer une classe du méta-modèle comme étant non instanciable.

    Attribut simple ou issu d'association du méta-modèle

    Le stéréotype id permet de déclarer un attribut (simple ou issu d'association) comme identifiant.

    Un attribut identifiant n'a pas besoin de règles écrites pour que son caractère identifiant soit vérifié: l'outil gère de base les identifiants; ainsi, par exemple, si deux classes (instances de la classe Class du méta-modèle) portent le même nom, cette anomalie est immédiatement signalée par l'outil car l'attribut name de Class est déclaré comme identifiant.

    Noms français/anglais

    Il est possible de donner un nom français et un nom anglais à toute classe ou tout attribut (simple ou issu d'association) du méta-modèle:
    Class : TypingObject
    {
            is_type: Boolean LABEL "is a type"|"est un type";
            abstract: Boolean LABEL "abstract"|"abstraite";
            ...
    } LABEL "Class"|"Classe";

    Surcharge de noms français/anglais

    Il est également possible de surcharger des noms définis dans le méta-modèle, ce qui est utile lorsqu'un même concept méthodologique porte des noms différents selon la méthode. Par exemple, pour la méthode OOA (Shlaer et Mellor), le fichier namesooa.br permet de redéfinir certains noms; namesooa.br doit être présent dans le fichier ooa.mn.
    System {
            LABEL "System"|"Système";
            LABEL subsystems "domains"|"domaines";
    }
    RootSystem {
            LABEL "Domain"|"Domaine";
    }
    SubSystem {
            LABEL "SubSystem"|"SousSystème";
    }
    Action_Activity {
            LABEL "Process"|"Processus";
    }

    Extrait d'un fichier .ml

    TYPE Access : ENUM {read_write LABEL "read/write"|"lecture/écriture", read_only LABEL "read only"|"lecture seule", write_only LABEL "write only"|"écriture seule"} LABEL ""|"Accès";
    
    TYPE Visibility : ENUM {public, protected LABEL ""|"protégé", private LABEL ""|"privé"} LABEL ""|"Visibilité";
    
    TYPE CollectionKind : ENUM {none LABEL ""|"néant", ordered LABEL ""|"ordonné", sorted LABEL ""|"trié", keyed LABEL ""|"par clé"} LABEL ""|"GenreCollection";
     
     
     
    // Entity : superclass of any meta-model class
    
    Entity -abstract
          // classe racine abstraite
    {
    } LABEL ""|"Entité";
    
    
    // TypingObject : abstract class for classes and atomic types
    
    TypingObject : Type -abstract
    {
            name: Identifier -id LABEL "name"|"nom";
            typed_services: Service [0..*] INVERSE type LABEL "typed operations"|"opérations typées";
                    // collection of services using the type instance
            typed_parameters: Parameter [0..*] INVERSE type LABEL "typed parameters"|"paramètres typés";
                    // collection of parameters using the type instance
            typed_attributes: Attribute [0..*] INVERSE type LABEL "typed attributes"|"attributs typés";
                    // collection of attributes using the type instance
    } LABEL "Typing Object"|"Objet Typant";
    
    
    
    
    Class : TypingObject
    {
            is_type: Boolean LABEL "is a type"|"est un type";
            abstract: Boolean LABEL "abstract"|"abstraite";
                    // if a class must not be instanciated, then this flag must be true
            is_utility: Boolean LABEL "is utility"|"est utilitaire";
                    // must be true for a dummy class that encapsulates attributes and operations that are not part of a class, such as global variables and procedures
            is_persistent: Boolean LABEL "persistent"|"persistante";
            inst_card_min: Integer LABEL "inst card min"|"nb min inst";
                    // min number of instances for the class
            inst_card_max: Integer LABEL "inst card max"|"nb max inst";
                    // max number of instances for the class (* for infinity)
            last_update: Integer LABEL "last update"|"dernière mise à jour";
            attributes: Attribute [0..*] INVERSE class LABEL ""|"attributs";
                    // collection of attributes not coming from associations
          // l'attribut attributes est issu d'une association,
          // reconnaissable au mot-clé INVERSE, avec Attribute;
             // sa cardinalité va de 0 à l'infini;
             // l'attribut pendant (role opposé) du lien est
             // class dans Attribute, mentionné dans la
             // description de la classe Attribute ci-dessous  
            services: Service [0..*] INVERSE class;
                    // collection of methods in the class
            specializations: Inheritance [0..*] INVERSE superclass LABEL "subclasses inheritance links"|"liens d'héritage sous-classes";
                    // collection of inheritance objects leading to subclasses
            generalizations: Inheritance [0..*] INVERSE subclass LABEL "superclass(es) inheritance link(s)"|"lien(s) d'héritage superclasse(s)";
                    // collection of inheritance objects leading to superclasses
            acquaintances: Acquaintance [0..*] INVERSE class LABEL ""|"accointances";
                    // collection of attributes issued from associations
            associative_association: AssAssoc [0..1] INVERSE associative_class LABEL "associative association"|"association associative";
    } LABEL "Class"|"Classe";
    
    ...
    
    Attribute : AbstractAttribute
    {
            meta: Boolean LABEL "class attribute"|"attribut de classe";
                    // true for class variable; false for instance variable
            is_derived: Boolean LABEL "is derived"|"est dérivé";
            derivation_expression: Text LABEL "derivation expression"|"expression de dérivation";
            class: Class INVERSE attributes -id LABEL "class"|"classe";
                    // class the attribute belongs to
         // l'attribut class est issu d'une association avec Class;
          // sa cardinalité (non explicitement mentionnée) est 1;     
          // il constitue un identifiant (id) pour la classe Attribute; 
            type: TypingObject INVERSE typed_attributes LABEL "type"|"type";
                    // attribute type
            qualifies: Acquaintance [0..*] INVERSE qualifiers;
    } LABEL ""|"Attribut";
    
    ...
    
    

    OTScript: langage sur le méta-modèle

    Conventions

    Principes

    OTScript est un langage de navigation sur le méta-modèle:
    il permet, à partir de n'importe quelle instance du méta-modèle, d'accéder à ses champs et aux instances auxquelles elle est reliée au travers des associations du méta-modèle; exemple à partir d'une instance A de la classe Class du méta-modèle TNI: acquaintances.association.associative_association.associative_class fournit toutes les classes associatives des associations dont l'instance A de la classe Class participe.
    Il maintient en cohérence les associations exprimées dans le méta-modèle sur la base des cardinalités:
    toute opération (création, destruction, modification, ajout, retrait, affectation) est considérée avec les cardinalités des liens qu'elle engage; les deux accointances d'une association permettant de gérer totalement le lien sont toujours en cohérence.
    C'est un langage ensembliste:
    tout est ensemble: un champ non initialisé est un ensemble vide (typé), un champ simple est un ensemble à un élément; une instance ne peut figurer qu'une seule fois dans un ensemble; on peut réaliser des unions, intersections, complémentaires, ... entre ensembles; les ensembles sont ordonnés, les éléments créés étant ajoutés à la fin de l'ensemble.
    C'est un langage d'itération:
    lorsque une expression du genre exp1.exp2 est évaluée, exp2 est bien appliquée à chaque élément de l'ensemble retourné par exp1.
    C'est un langage typé,
    sur la base des types prédéfinis et des classes du méta-modèle choisi.
    C'est un langage compilé:
    à chaque lancement de l'outil OpenTool, les fichiers .br pris en considération sont parsés et transformés en un code interne; les erreurs syntaxiques, de type, ... sont signalées à l'administrateur au lancement de l'outil .
    Voici un extrait du méta-modèle de la configuration TNI sous forme de représentations graphiques d'une partie du fichier kernel.ml exprimé selon le graphisme UML; cet extrait n'est en aucun cas exhaustif quant aux classes du méta-modèle représentées.

    Extrait 1 du méta-modèle de la configuration TNI
    (représentation graphique d'une partie de kernel.ml) : 

    Extrait 2 du méta-modèle de la configuration TNI
    (représentation graphique d'une partie de kernel.ml) : 

    Sur la base des éléments exprimés dans ces extraits du méta-modèle TNI, voici un petit exemple de classes avec attributs, méthodes et associations, qui sont donc des instances de classes du méta-modèle TNI.


    Exemple 1 (c'est une instance du méta-modèle TNI) : 
     
    AAA, BBB et CCC
    sont des instances de la classe Class du méta-modèle
    aaaAtt1 et aaaAtt2
    sont des instances de la classe Attribute du méta-modèle, de classe AAA
    bbbAtt1 et bbbAtt2
    sont des instances de la classe Attribute du méta-modèle, de classe BBB
    l'association entre AAA et BBB
    est une instance de la classe Association avec pour accointances bbbColl dans AAA et aaaRef dans BBB
     

    Voici maintenant quelques expressions OTScript et leur résultat :

    attributes.name appliqué à AAA
     renvoie l'ensemble des noms des attributs de AAA: {"aaaAtt1", "aaaAtt2", "AaaClassAtt"}
    attributes[meta] appliqué à AAA
     réalise une sélection des attributs de AAA pour lesquels meta est vrai, et renvoie donc les attributs de classe: {AaaClassAtt}
    services.parameters appliqué à AAA
     renvoie l'ensemble des paramètres de tous les services (méthodes) de AAA: {p1(aaaMth1), p1(aaaMth2), p2(aaaMth2)}
    services.parameters.name appliqué à AAA
     renvoie l'ensemble des noms des paramètres de tous les services (méthodes) de AAA: {"p1", "p2"}
    Il n'y a aucune limitation dans la profondeur de navigation.

    Un principe fondamental est qu'il n'est jamais renvoyé 2 fois le même élément dans un ensemble: il s'agit donc bien de manipulation ensembliste.

    acquaintances appliqué à AAA
     renvoie l'ensemble des accointances de AAA, c'est-à-dire des attributs potentiels de AAA issus des associations dont AAA participe: {bbbColl, cccRef}
    acquaintances.association appliqué à AAA
     renvoie l'ensemble des associations dont AAA participe: {AAA-BBB, AAA-CCC}
    acquaintances.association.roles[EACH.class/=THIS].class appliqué à AAA
     renvoie l'ensemble des classes différentes de AAA en association avec AAA: {BBB, CCC}

    Expressions

    Dans la liste non exhaustive des expressions du langage OTScript présentée ci-dessous (pour la liste exhaustive, se référer au manuel de Référence du langage OTScript), exp, exp1, exp2 sont des expressions composées quelconques du langage OTScript.
    Les exemples ont pour base les extraits 1 et 2 du méta-modèle configuration TNI et l'Exemple 1 décrit ci-dessus.

    THIS

    désigne l'objet récepteur de l'expression courante
    soit ALL Attribute[EACH.class=THIS] appliqué à AAA :
     ALL Attribute renvoie toutes les instances de la classe du méta-modèle Attribute; [EACH.class=THIS] sélectionne parmi ces instances ceux appartenant à AAA

    A0

    synonyme de THIS

    A1 .. An

    autres variables (expressions multi-variables) permettant d'avoir accès à des valeurs précédentes dans le contexte courant
    si, dans un browser de projet, la première liste présente des systèmes, la deuxième les classes du système sélectionné, la troisième les attributs de la classe sélectionnée, et qu'un attribut est sélectionné, alors THIS est l'attribut sélectionné, A1 la classe de l'attribut, A2 le système de la classe, et A3 le projet du système

    EACH

    variable de boucle dans une sélection ou une itération récursive

    EACHINDEX

    indice de l'itération courante

    exp.att

    accès à l'attribut att.
    name appliqué à AAA
    renvoie le nom de la classe AAA: {"AAA"}
    attributes appliqué à AAA
    renvoie la liste de ses attributs
    class appliqué à l'attribut aaaAtt1
    renvoie sa classe: {AAA}
    class.acquaintances.association appliqué à l'attribut aaaAtt1
    renvoie les associations dont participe sa classe AAA: {AAA-BBB, AAA-CCC}
    THIS.generalizations.superclass où THIS est une classe
     renvoie l'ensemble dees superclasses immédiates de THIS

    exp[cond]

    sélection suivant la condition cond
    pour accéder un élément de la liste exp dans cond, utiliser le mot réservé EACH
    pour faire référence au récepteur de exp dans cond, utiliser THIS
    attributes[NOT(EACH.meta)] appliqué à AAA
     renvoie l'ensemble des attributs d'instance de AAA
    acquaintances.association.roles[EACH.class/=THIS].class appliqué à AAA
     renvoie l'ensemble des classes différentes de AAA en association avec AAA: {BBB, CCC}

    exp1.(exp2)

    itération de exp2 sur le résultat de exp1
    attributes.(EACH.meta IF TRUE: "att. de classe" IF FALSE: "att. d'instance")
     

    exp1.*(exp2)

    itération récursive (arborescente) de exp2 sur le résultat de exp1
    THIS.*(generalizations.superclass) où THIS est une classe
     renvoie l'ensemble de toutes les superclasses de tout niveau de THIS

    Opérateurs généraux

    STR(x)

    représentation chaîne de x
    utilise la méthode print si elle existe, sinon utilise les identifiants directs (name par ex) s'il y en a, sinon utilise les identifiants sur association (class pour Attribute par ex), sinon affiche une chaîne normalisée

    x ISA C

    teste si x est de la classe C
    AAA ISA Class
     renvoie TRUE
    AAA ISA Attribute
     renvoie FALSE
    aaaMth1 ISA Service
     renvoie TRUE

    ALL C

    toutes les instances de la classe C, C étant une classe du méta-modèle
    ALL Class
     renvoie {AAA, BBB, CCC}
    ALL Attribute
     renvoie {aaaAtt1, aaaAtt2, AaaClassAtt, bbbAtt1}

    NEW C

    crée une instance de la classe C, C étant une classe du méta-modèle

    VOID C

    ensemble vide de type C, C étant une classe du méta-modèle

    a := exp

    affectation du résultat de exp dans a; si a est un ensemble non vide, a est vidé puis le contenu de exp est mis dans a.

    a += exp

    ajout du résultat de exp dans a; le contenu de exp est ajouté à la fin de a.

    a -= exp

    retrait du résultat de exp de a.

    cond IF TRUE: exp1 IF FALSE: exp2

    test booléen
    meta IF TRUE: "att. de classe" IF FALSE: "att. d'instance"
     

    val IF val1: exp1 IF val2: exp2 IF val3: exp3

    switch/case
    visibility IF #public: "public" IF #protected: "protected"|"protégé" IF #private: "private"|"privé"
     la barre verticale | permet une définition multi-langue Anglais/Français (le choix se fait sur la ligne de commande: voir )

    val IF val1: exp1 IF val2: exp2 ELSE: exp3

    switch/case avec default

    exp1 DEFAULT exp2

    retourne exp1 si non vide, exp2 sinon 

    Opérateurs ensemblistes

    exp1 = exp2

    égalité

    exp1 /= exp2

    inégalité

    exp1 $+ exp2

    union

    exp1 $* exp2

    intersection

    exp1 $- exp2

    complémentaire de exp2 dans exp1

    exp1 $< exp2

    teste si exp1 est inclus dans exp2

    $CNT(s)

    nombre d'éléments de s

    $STR(s)

    représentation chaîne de s

    $REV(s)

    inverse l'ordre des éléments de s

    $SORT(s)

    trie les éléments de s;

    $FIRST(s)

    extrait le premier élément de s

    $LAST(s)

    extrait le dernier élément de s

    $AT(s,i)

    extrait le ième élément de s

    $INDEX(s,e)

    index de l'élément e dans s

    $MIN(s)

    extrait l'élément minimal de s

    $MAX(s)

    extrait l'élément maximal de s

    $INTERVAL(s)

    complète s de tous les éléments absents entre son min et son max
    $INTERVAL(1 $+ 10)
     renvoie {1,2,3,4,5,6,7,8,9,10} (1 $+ 10 est l'ensemble {1,10})

    Remarque sur MIN, MAX, SORT, INTERVAL

    Pour les ensembles ne contenant pas de nombre, le tri se fait sur la forme textuelle de l'élément, issue soit de la méthode print si elle existe, sinon de l'identifiant calculé par l'outil. 

    Opérateurs Booléen

    Mots réservés: TRUE et FALSE

    NOT(b)

    négation de b

    b1 + b2

    b1 ou inclusif b2

    b1 * b2

    b1 et b2 

    Opérateurs Entiers

    Mots réservés: INFINITY pour l'infini (utile pour tester si une cardinalité est infinie)

    e1 + e2

    addition d'entiers

    e1 - e2

    soustraction d'entiers

    e1 * e2

    multiplication d'entiers

    e1 / e2

    division d'entiers 

    Opérateurs Chaînes

    Caractères spéciaux: "abc"ndef""ghi" réalise:
    abc
    def"ghi

    str1 + str2

    concaténation de str1 et str2
    "aaa"+"bbb"
     renvoie "aaabbb"

    SUBSTR(s,i,j)

    extraction d'une sous-chaîne de la chaîne s, à partir du caractère i, de longueur j
    SUBSTR("abcdefg",2,3)
     renvoie "bcd"

    STRCNT(s)

    nombre de caractères de la chaîne s

    STRISID(s)

    teste si s est un identificateur, c'est-à-dire, si s commence par un caractère alphabétique et ne contient ensuite que des lettres, chiffres ou underscore.
    Utile pour distinguer un identifiant d'un opérateur en génération de code par exemple.

    STRUPPER(s)

    convertit la chaîne s en majuscules

    STRUPPER1ST(s)

    convertit le premier caractère de la chaîne s en majuscule

    STRLOWER(s)

    convertit la chaîne s en minuscules

    STRLOWER1ST(s)

    convertit le premier caractère de la chaîne s en minuscule 

    Types énumérés

    #symb

    accès à un élément d'une énumération
    par exemple #public
    dans la déclaration de type:

    TYPE Visibility : ENUM {public, protected, private};

    Type#symb

    accès à un élément d'énumération de type Type, à utiliser si ambiguïté

    Dans le méta-modèle TNI sont définies les deux énumérations:

    Il est nécessaire de lever l'ambiguïté pour accéder à #none:
    CollectionKind#none
    permet d'accéder au #none de l'énumération CollectionKind
    ReferencePlace#none
    permet d'accéder au #none de l'énumération ReferencePlace

    Opérateurs d'IHM

    SHOWMSG(info)

    ouvre une boîte d'information

    SHOWTEXT(text,title)

    affiche un texte text avec un titre title

    SHOWLIST(list,title)

    ouvre une liste list avec un titre title

    INPUTLINE(str)

    ouvre une boîte de demande d'information; str est le label

    INPUTBOOL(str)

    ouvre une boîte de demande de confirmation; str est le label

    BEEP()

    émet un bip 

    Opérateurs d'entrée-sortie

    SAVEDIR

    répertoire de sauvegarde du fichier courant

    SYS(str)

    exécute une commande système; str est une chaîne

    GETCONFIG(sect,clé)

    lit une entrée dans le fichier de configuration (.opentoolrc ou opentool.ini)

    UNIX

    teste si la plateforme courante est unix

    WIN

    teste si la plateforme courante est Windows (3.xx, 95 ou NT)

    FOPENW(filename)

    ouvre un fichier en écriture

    DDEOPEN(service, topic)

    ouvre une connexion DDE

    OPENBUFF

    ouvre un tampon interne

    CLOSE

    ferme le stream courant (FOPENW, DDEOPEN ou OPENBUFF)

    PUT(s)

    écrit s sur le stream courant

    INDENT(n)

    niveau d'indentation; pris en compte par les PUT() 

    Ordres OTScript propres aux éditeurs

    Ces ordres sont liés aux configurations des browsers, diagrammes, formulaires.

    CREATE

    Sa présence autorise l'instanciation du type de l'expression sur lequel on se trouve dans une configuration d'éditeur, et permet d'exécuter du code sur création d'une instance.

    Format:

    BROWSER RootSystem::System_browser_UML : ...
    {...
    attributes :
    // expression de type Attribute dans le méta-modèle TNI
            LABEL "Attributes"|"Attributs"
            PRINT print_UML
            CREATE {class := A1;
                    CHECKID(THIS); ASK name;
                    ASK type: $SORT(ALL AtomicType
                            $+ (ALL Class)[is_type * (visibility=#public)]);
                    };
    ...
    }
    Si un éditeur présente une expression, et qu'il n'est précisé aucun CREATE après cette expression, cela signifie qu'on ne peut instancier le type de l'expression à cet endroit de la configuration.

    L'ordre CREATE peut être limité à une ou plusieurs sous-classes du type de l'expression: on précise alors la sous-classe juste après le mot-clé CREATE, puis le code de création, et ceci autant de fois qu'il y a de sous-classes que l'on veut pouvoir instancier.

    BROWSER RootSystem::System_browser_UML : ...
    {...
    servers_diagram $+ system_diagram 
    $+ class_diagrams $+ interaction_diagrams :
    // expression de type Diagram dans le méta-modèle TNI,
    // car c'est la super-classe commune à l'union de ces diagrammes
            LABEL "Diagrams"|"Diagrammes"
            PRINT print_br_UML
            CREATE UMLSystemDiagram {system := A1; ASK name;}
            CREATE UMLClassDiagram {system := A1; ASK name;}
            CREATE UML_OID {system := A1; ASK name;}
    ...
    }

    INSERT

    Cet ordre permet de lier une instance déjà existante à une autre instance. INSERT est suivi d'un domaine de définition permettant de calculer les instances "insérables", puis de code à exécuter pour réaliser cette insertion.

    Format:

    BROWSER RootSystem::System_browser_UML : ...
    {...
    used_systems :
            ...
            INSERT (ALL System $- THIS $- used_systems):
            // les systèmes potentiellement utilisés sont à prendre
            // parmi toutes les instances de System MOINS
            // le système courant, MOINS ceux déjà utilisés
            // par le système courant
                    {users += NEW Use;
                    $LAST(users).user_system := A1;};
                    // le code permet la mise à jour d'autres pointeurs
    ...
    }
    Contrairement au CREATE, l'insertion dans les formulaires est proposée par défaut si elle n'est pas explicitée dans la configuration: pour empêcher une insertion dans la configuration, il faut le dire explicitement par INSERT NONE.

    ASK

    ASK est un ordre de demande à l'utilisateur de la valeur d'un attribut dans du code OTScript: il provoque l'ouverture d'une boîte de dialogue.

    Une propriété remarquable est qu'un groupe de ASK consécutifs provoque l'ouverture d'une seule boîte de dialogue demandant les valeurs de l'ensemble des attributs.

    Format:

    BROWSER RootSystem::System_browser_UML : ...
    {...
    acquaintances.association :
            LABEL "Associations"
            CREATE 
                    {...
                    ASK $FIRST(roles).name;
                            // demande du nom du premier rôle
                    ASK $FIRST(roles).card_max;
                            // demande de la cardinalité du premier rôle
                    ASK $LAST(roles).name;
                            // demande du nom du 2ème rôle
                    ASK $LAST(roles).class: system.visibleClasses
                            CREATE {system := A3;};
                            // permet de créer éventuellement une classe à cet endroit
                            // si elle n'existe pas dans le domaine de définition:
                            // elle devra satisfaire aux restrictions
                            // du domaine de définition
                    ASK $LAST(roles).card_max;
            // une seule boîte de dialogue s'ouvrira pour
            // l'ensemble de ces requêtes consécutives
    ...
    }

    CHECKID(inst)

    permet de créer un identifiant non redondant pour l'objet inst. Ce calcul tient compte des règles marquées -id: par exemple, un nom d'attribut dans une classe est calculé en tenant compte du fait que des règles expriment l'unicité de ce nom dans la hiérarchie d'héritage.

    Le calcul se fait sur la base d'un nom par défaut, auquel on ajoute un nombre incrémenté jusqu'à ce qu'il devienne un identifiant

    DISPLAY exp ...

    permet dans un formulaire de déclarer un champ présenté comme non éditable; exp est une expression OTScript quelconque.

    FILL ...

    permet, dans une configuration de formulaire, de remplir volontairement de vide certaines zones; exemple: "FILL WIDTH 6;" .

    CLICK ...

    dans du code de création d'une configuration de diagramme, permet de demander de choisir par clic souris un élément graphique.

    Exemple:

    DIAGRAM UMLStateDiagram::theDiagram -dblclick :
    LABEL "UML State Diagram"|"Diagramme d'états UML"
    {...
            {...
            transitions INVERSE (source $+ target) :
                    DISPLAY ...
                    CREATE{CLICK source; CLICK target;}
                            // permet de demander à l'utilisateur
                            // de cliquer sur l'état source, puis
                            // sur l'état cible pour créer une transition
            ...
            };
    ...
    };

    SELECT ...

    dans du code de création d'une configuration de browser, permet de prendre en compte la sélection courante.

    WHEN condition

    dans une configuration de formulaire, permet de griser le champ pour le rendre inactif si condition renvoie FALSE (condition est une expression booléenne OTScript quelconque).

    Exemple:

    Attribute {
            FORM MainUML  : LABEL "General"|"Général" WIDTH 12
                    {...
                    is_derived WIDTH 2+1;
                    derivation_expression WHEN is_derived WIDTH 9 HEIGHT 2;
                    ...
                    };
    }

    Formulaires de saisie des informations

    Lorsque l'on ouvre un éditeur de diagramme ou un browser textuel, une fenêtre contenant des formulaires de saisie des informations s'ouvre simultanément: ces formulaires de saisie classés dans des boîtes à onglet se configurent dynamiquement en fonction de l'élément sélectionné graphiquement dans un diagramme ou dans une liste d'un browser.

    La configuration des formulaires se fait généralement dans des fichiers .br appropriés; dans la configuration TNI, les noms des fichiers de formulaire commencent par form ou fref....

    L'ordre de présentation des onglets est fonction de leur identificateur.

    Format général :

    classe {
    FORM identifiant1 :
       LABEL titre onglet
       WIDTH entier donnant la largeur totale
       {form_expression11  ...
             // définit le 1er champ
        form_expression12  ...
             // définit le 2ème champ
        form_expression13  ...
             // définit le 3ème champ
        ...
       };
       
    FORM identifiant2 :
       LABEL titre onglet
       WIDTH entier donnant la largeur totale
       {form_expression21  ...
             // définit le 1er champ
        ...
       };
    }
    form_expression peut être (exp est une expression OTScript quelconque) :
    exp.attribut
    il y a possibilité d'édition du champ
    exp.attribut[expbool]
    il y a possibilité d'édition du champ
    DISPLAY exp
    le champ n'est pas éditable
    FILL
    permet de remplir une zone
    Un exemple commenté d'onglets de formulaire sur la classe Class est présenté dans Exemples Administrateur: il montre ce par quoi form_expression peut être suivi dans les différents cas.

    L'aspect des zones de saisie dépend du type de l'expression présentée:

    Le placement des zones de saisie est réalisé par l'outil en tenant compte de l'ordre des éléments dans la définition du formulaire et des indications de largeur (WIDTH) et de hauteur (HEIGHT) éventuellement spécifiées. L'outil cherche de manière générale à combler les trous.

    Des menus contextuels accessibles par le bouton 2 de la souris sont associés à certaines de ces zones de saisie:

    L'ordre DISPLAY permet d'interdire toute modification d'un champ par l'utilisateur. 

    Les browsers textuels

    Les browsers textuels sont constitués de listes, et sont liés aux formulaires.

    Les principaux noms des fichiers .br contenant les browsers commencent par ui... 

    Présentation

    Un browser est relatif à une classe du méta-modèle; il s'ouvre sur une instance de cette classe, racine de la connaissance du browser: les listes des onglets de la première zone de liste vont présenter des éléments issus d'une expression OTScript quelconque appliquée à cette instance. Chaque groupe d'onglets des listes suivantes est défini relativement à un onglet de la liste précédente: cet onglet référence définit une liste d'éléments de même type; les sous-listes seront le résultat d'expressions OTScript quelconques sur des instances de ce type.

    Exemple commenté

    BROWSER Service::br_service -dblclick :
          // mot réservé BROWSER
          // suivi du nom de la classe du méta-modèle
          // sur laquelle le browser est défini (Service),
          // suivi du nom identifiant le browser (br_service)
          // suivi éventuellement de -dblclick signifiant
          // l'utilisation par défaut de ce browser
          // sur double-clic sur une instance de service si plusieurs 
          // éditeurs existent sur la classe Service
       LABEL "Operations Browser" | "Browser d'Opération"
          // titre du browser
       {parameters : LABEL "Parameters"|"Paramètres" 
          // éléments présentés dans la 1ère liste:
          // les paramètres de l'instance de Service
          // sur laquelle le browser a été ouvert
          PRINT name + " : " + type.printType
            // optionnel; permet de préciser la présentation
            // textuelle dans le browser du paramètre
          CREATE {service := A1;};
            // optionnel; permet d'exécuter du code
            // à la création d'un paramètre: ici, on relie
            // le nouveau paramètre à l'instance courante de
            // Service, représentée par A1
       };

    Format général

    BROWSER classe::identifiant : LABEL titre
       {expression1 : ...
             // définit les éléments du 1er onglet
             // de la 1ère zone de liste
          {expression11 : ...;
                // définit les éléments du 1er onglet
                // de la 2ème zone de liste
          expression12 : ...
                // définit les éléments du 2ème onglet
                // de la 2ème zone de liste
             {expression121 : ...;
                   // définit les éléments du 1er onglet
                   // de la 3ème zone de liste
              ...
             };
          };
       expression2 : ...;
             // définit les éléments du 2ème onglet
             // de la 1ère zone de liste
       ...
       };
    Chaque expression peut être suivie par :
    expression :
       LABEL titre onglet
       PRINT expression retournant une chaîne // optionnel
       COLOR #couleur prédéfinie dans opentool.ini // optionnel
       CREATE ... // optionnel
       INSERT ... // optionnel
    Le nombre de listes d'un browser n'est pas limité: chaque indentation supplémentaire se fait par l'ouverture d'une accolade; les expressions après l'accolade ouvrante sont relatives à une instance de classe de l'expression figurant avant l'accolade ouvrante.

    Un exemple de browser sur la classe System, conséquent et commenté, est présenté dans Exemples Administrateur

    Options

    L'option -dblclick permet d'ouvrir par défaut sur double-clic le browser lié à l'objet sélectionné.

    Les diagrammes

    Les éditeurs de diagramme sont constitués d'une zone d'édition graphique, et sont liés à la fenêtre de formulaires.

    Les principaux noms des fichiers .br contenant les diagrammes commencent par ui... 

    Présentation

    La configuration d'un diagramme utilise des expressions sémantiques OTScript de navigation, mais la logique arborescente d'imbrication des expressions dépend de la représentation graphique: l'entité racine d'un diagramme est la vue; une vue est une instance d'une sous-classe de Diagram dans le méta-modèle. Une vue va contenir des entités graphiques, typiquement des boîtes, dont elle sera le parent graphique.

    Chaque entité graphique (vue, boîte, champ, lien, ...) :

    Dans un diagramme, la configuration permet de décider de réaliser En effet, l'expression OTScript de navigation d'une configuration de diagramme fournit un ensemble d'entités sémantiques (instances de classes du méta-modèle), mais le diagramme ne les représente pas obligatoirement toutes graphiquement: l'utilisateur va pouvoir "Créer", "Détruire" des entités sémantiques dans l'éditeur de diagramme, mais aussi "Montrer" graphiquement des entités sémantiques pré-existantes, ou en "Cacher" d'autres représentées graphiquement.

    La représentation exhaustive a l'avantage d'assurer à l'utilisateur qu'il a bien sous les yeux la totalité des entités sémantiques existantes présentées dans son diagramme; la représentation partielle a l'avantage de pouvoir rendre plus lisible certains diagrammes, surtout lorsqu'il s'agit de faire une sortie documentaire.

    Exemple complet commenté

    DIAGRAM UMLStateDiagram::theDiagram -dblclick :
    // Diagramme d'état UML: UMLStateDiagram est la classe
    // du méta-modèle qui permet de décrire graphiquement
    // une instance de StateModel à laquelle elle est associée
    LABEL "UML State Diagram"|"Diagramme d'états UML"
    {state_model.states:
                    // l'expression de navigation fournit l'ensemble
                    // des états du modèle d'état, mais tous ne sont pas
                    // forcément représentés graphiquement dans l'instance
                    // courante de UMLStateDiagram sur laquelle travaille
                    // l'utilisateur;
                    // l'utilisateur va pouvoir "Créer", "Détruire"
                    // des états dans l'éditeur de diagramme,
                    // mais aussi "Montrer" graphiquement des états
                    // pré-existants (créés dans un browser par exemple),
                    // ou en "Cacher" d'autres.
                    // state_model est l'accointance qui relie une
                    // vue d'état (instance de UMLStateDiagram)
                    // à son modèle d'état (instance de StateModel)
            DISPLAY BoxWithLists(
                    #Round $+ #Opt2
                    $+ (state_kind IF #normal: #Default ELSE: #Thick)
                    $+ (isActive
                                    IF TRUE: #Filled $+ #Color5
                                    IF FALSE: #Default),
                    name)
                            // dit comment on dessine un état dans ce diagramme:
                            // BoxWithLists est une boîte pouvant contenir
                            // des zones de champs;
                            // #Round précise que les coins sont arrondis
                            // #Opt2 précise de centrer le titre lorsqu'il
                            //     n'y a pas de champ dans la boîte;
                            // #Thick dessine un bord gras pour un état
                            //     initial ou final
                            // #Filled $+ #Color5 pour un état possédant
                            //     des sous-états le signale en remplissant
                            //     l'état de la couleur Color5 définie dans 
                            //     le fichier "opentool.ini";
                            // name est ce qui est affiché comme titre
                            //     de l'état
            CREATE {state_model := A1.state_model;
                    CHECKID(THIS);}
                            // sur création d'un état, on le relie au state_model
                            // associé à la vue (A1 ici)
            {
            transitions INVERSE (source $+ target) :
                            // transitions est une méthode de la classe
                            // State du méta-modèle (définie dans methods.br) qui
                            // renvoie les transitions entrantes et sortantes
                            // d'un état;
                            // la relation INVERSE fournit les parents graphiques
                            // d'une transition, à savoir l'état source (source)
                            // et l'état cible (target): elle permet une
                            // optimisation de l'éditeur
                    DISPLAY Link(#Default, VOID String, #Default, #OpenArrowTip)
                            // dit comment la transition est dessinée:
                            // #Default : trait fin plein
                            // VOID String : pas de label
                            // #Default : pas de flèche côté source
                            // #OpenArrowTip : flèche simple ouverte côté cible
                    CREATE {CLICK source; CLICK target; }
                            // pour créer une transition, il est demandé à
                            // l'utilisateur de cliquer d'abord sur l'état
                            // source graphique (CLICK source),
                            // puis sur l'état cible graphique (CLICK target)
                            
                    {trigger INVERSE trans_firing_on_event:
                                    // trigger est l'événement porté
                                    // par une transition; son parent graphique
                                    // est ici la transition graphique
                            EXHAUSTIVE TRUE
                                    // si une transition porte un evt,
                                    // il doit être obligatoirement affiché
                            DISPLAY SimpleName(#Bold, name) -linked
                                    // exprime que l'evt est affiché comme un champ
                                    // (SimpleName), en gras (#Bold),
                                    // accroché au lien (-linked)
                            CREATE Event {CLICK trans_firing_on_event;
                                            receiver := A3.state_model.on_class;
                                            CHECKID(THIS);}
                                    // pour créer, un evt, il faut que l'utilisateur
                                    // clique sur une transition (CLICK trans_firing_on_event);
                                    // le récepteur de l'evt est connu: c'est
                                    // la classe sur laquelle on décrit l'automate
                                    // d'états, obtenue par A3.state_model.on_class,
                                    // où A3 est une v. contextuelle qui à ce niveau,
                                    // contient le diagramme
                            INSERT THIS.source.on_class.received_events;
                                    // permet d'insérer un evt existant sur une 
                                    // transition, en le choisissant parmi
                                    // les evts reçus par la classe dont on décrit
                                    // l'automate d'états
                    };
            actions INVERSE state :
                            // fournit les actions/activités définies
                            // sur un état; le parent graphique
                            // d'une action/activité est l'état
                    LABEL "Actions/Activities"|"Actions/Activités" 
                    DISPLAY SimpleName(#Default, print) -inbox -vspace
                            // affiche l'action comme un champ (SimpleName),
                            // à l'intérieur de son parent (-inbox),
                            // en laissant un espace / titre (-vspace),
                    CREATE{CLICK state;
                            CHECKID(THIS);};
                            // pour créer une action, l'utilisateur sélectionne
                            // un état; CHECKID(THIS) crée un nom identifiant
                            // valide
        };
    notes :
                    // permet d'introduire des remarques textuelles
                    // non sémantiques dans la zone graphique
                    // sous forme de rectangles éditables
            EXHAUSTIVE TRUE
        DISPLAY BoxWithLists(#Sheet $+ #Gray $+ #Filled $+ #Color1 $+ #Left, comment)
                    // BoxWithLists dessine une boîte;
                    // ses arguments précisent l'affichage:
                    // #Sheet pour une boîte avec un coin replié,
                    // #Gray pour exprimer que le tour est en gris,
                    // #Filled $+ #Color1 pour exprimer
                    //    que le fond est rempli par la couleur Color1
                    //    définie dans  le fichier "opentool.ini",
                    // #Left pour justifier le texte à gauche;
                    // comment fournit le texte affiché
        CREATE {diagram := A1; };
                    // relie la "note" au diagramme
    };

    Format général

    Il est comparable à celui d'un browser.
    DIAGRAM classe::identifiant : LABEL titre
            // classe est une sous-classe de la classe
            // abstraite Diagram du méta-modèle
       {expression1 : ...
             // définit le 1er ensemble de fils potentiels
             // graphiques du diagramme;
                     // la relation INVERSE n'est pas précisée
                     // car on sait à ce niveau que le parent
                     // graphique est le diagramme
          {expression11 INVERSE exp_inv11 : ...;
                // définit le 1er ensemble de fils potentiels
                    // graphiques d'un élément de expression1;
                            // exp_inv11 est la relation inverse qui,
                            // à partir d'un élément de expression11,
                            // fournit le ou les parents graphiques ce
                            // cet élément; exp_inv11 peut fournir 
                            // un surensemble
          expression12 INVERSE exp_inv12 : ...
                // définit le 2ème ensemble de fils potentiels
                    // graphiques d'un élément de expression1;
             {expression121 INVERSE exp_inv121 : ...;
                    // définit le 1er ensemble de fils potentiels
                            // graphiques d'un élément de expression12;
              ...
             };
          };
       expression2 : ...;
             // définit le 2ème ensemble de fils potentiels
             // graphiques du diagramme
       ...
       };
    Chaque expression peut être suivie par :
    expression :
       LABEL label du bouton de création // optionnel
       EXHAUSTIVE expression booléenne // optionnel:
                    // permet de définir un ensemble d'entité
                    // qui doivent obligatoirement apparaître
                    // sur le diagramme
       DISPLAY expression de dessin // voir ci-après
                    // les méthodes de dessin
       PRINT expression retournant une chaîne // optionnel:
                    // est utilisé pour présenter textuellement les éléments
                    // dans la boîte de dialogue issue de "Montrer"
       CREATE ... // optionnel
       INSERT ... // optionnel
    Un exemple commenté complexe, concernant le diagramme des paquetages UML, est présenté dans Exemples Administrateur.

    Options

    L'option -dblclick permet d'ouvrir par défaut sur double-clic le diagramme lié à l'objet sélectionné.

    Les méthodes de DISPLAY

    DISPLAY SimpleBox (
            attributs,
            label )
    DISPLAY BoxWithLists (
            attributs,
            label )
    
    attributs :
            Couleur: #Red ...
            Forme: #Square #Round #Circle #Hexagon #Folder #Sheet
            Style: #Thick #Dash
                    
                    
    DISPLAY SimpleName (
            attributs,
            label )
    
    attributs :
            Couleur: #Red ...
    
    
    DISPLAY Link (
            attributs trait,
            label milieu,
            attributs début,
            attributs fin,
            label début,    
            label fin )
    
    attributs trait :
            Couleur: #Red ...
            Style: #Thick #Dash
    
    attributs début/fin :
            Couleur: #Red ...
            Forme:
                    #OpenArrowTip #ClosedArrowTip #BallTip
                    #BoxTip #PegTip #DiamondTip
            Style: #Thick #Dash #Filled 
                    #Small #Large

    Les règles

    Les règles sont des expressions booléennes associées à des classes du méta-modèle. Lors d'une transaction utilisateur, des instances du méta-modèle sont créées, d'autres modifiées, d'autres détruites; pour toutes les instances impliquées dans cette transaction, les règles à vérification immédiate définies sur leur classe seront déclenchées.

    La commande "Tout Vérifier" permet d'autre part de déclencher toutes les règles, immédiates et différées, sur toutes les instances concernées.

    Il est parfois nécessaire que, sur une transaction utilisateur, il faille spécifier le déclenchement d'une règle pour une instance non "touchée" dans la transaction: par exemple, une règle vérifiant la non circularité dans l'héritage est définie sur la classe Class du méta-modèle, mais si une instance de la classe Inheritance qui relie 2 classes est modifiée, il faut bien déclenchée cette même règle: une méta-règle est alors définie; elle permet d'appeler une ou plusieurs règles déjà existantes sur d'autres instances.

    Les noms des fichiers .br contenant les règles commencent par rules... 

    Règles de base

    Format

     &ltclasse>  {
    RULE  &ltruleName1>  &ltoptions> :
         &ltruleExpression1>
         LABEL  "&ltlabel11>"
         EXPLAIN  &ltexplainExpression>
         LABEL  "&ltlabel12>" ; 
    
    RULE  &ltruleName2>  &ltoptions> :
         &ltruleExpression2>
         LABEL  "&ltlabel21>"
         REPAIR  &ltrepairExpression> ;
    ...
    }
    classe
    est la classe du méta-modèle sur laquelle on va définir une (des) règle(s).
    ruleExpression
    est l'expression de la règle; son écriture se fait avec le langage OTScript.
    options :
     
    label11
    est la signification textuelle de la règle, entre caractères ".
    explainExpression
    est l'expression retournant un ensemble d'éléments explicatifs si la règle n'est pas vérifiée.
    label12 est optionnel:
    il exprime textuellement la signification du résultat retourné par explainExpression .
    repairExpression
    est automatiquement exécuté si la règle n'est pas vérifiée.

    Exemples

    RULE Class::inheritance_circularity -now -e1 :
            // déclaration de règle sur la classe Class du méta-modèle
            // inheritance_circularity est l'identifiant de la règle
            // -now indique que la règle doit être immédiatement
            // vérifiée
            // -e1 indique que la transaction en cours est annulée
            // si la règle n'est pas vérifiée
            NOT(THIS $<
                    generalizations.superclass.*(generalizations.superclass))
                    // expression devant être constamment vérifiée
            LABEL "Inheritance cannot be circular"
                    |"L'héritage ne peut pas être circulaire"
                    // information textuelle lorsque la règle n'est pas vérifiée
            EXPLAIN
            generalizations.superclass.*(generalizations.superclass);
                    // éléments fournis lorsque la règle n'est pas vérifiée
    
    
    RULE Acquaintance::aggregation_on_one_side_only -now :
            NOT(aggregation)
                    + (aggregation * NOT(other.aggregation))
            LABEL "Aggregation can only be on one side"
                    |"L'agrégation ne peut être exprimée que d'un côté"
                    // pour une règle à réparation automatique (REPAIR),
                    // l'explication textuelle n'est utile que si la règle
                    // n'est toujours pas vérifiée après réparation
            REPAIR {BEEP(); aggregation := FALSE;};
                    // code automatiquement exécuté lorsque
                    // la règle n'est pas vérifiée
    

    Méta-Règles

    Une méta-règle est une règle qui appelle d'autres règles de base ou d'autres méta-règles.

    Les méta-règles permettent d'élargir à des instances non "touchées" par une transaction utilisateur le déclenchement des règles immédiates.

    Exemple

    // META Rule
    RULE Inheritance::inheritance_circularity -now -e1 : {
            subclass.inheritance_circularity;
            // fait appel à la règle définie plus haut pour la
            // "sous-classe" du lien d'héritage
            TRUE;
    } LABEL "inheritance circularity"|"circularité dans l'héritage";
    

    Les méthodes

    Portée des méthodes

    Les méthodes associées aux classes du méta-modèle permettent de définir: Les méthodes font partie du langage OTScript, et leur corps est exprimé également au moyen du langage OTScript. 

    Enrichissement des menus de la barre de menus OpenTool

    L'option -menu permet d'enrichir un item de la barre de menu par une méthode, voire d'ajouter un item à la barre de menus; ceci se réalise en précisant un LABEL sur la méthode contenant:
    "item barre de menu,sous-menu1,...,méthode"
    METHOD Entity::findServices -menu :
      // findServices est une méthode
      // définie dans la classe Entity;
      // -menu indique qu'elle est définie pour un menu
      // de la barre de menus OpenTool
      {
      TMP A1: String;
      A1 := INPUTLINE("*", "Search pattern"|"Motif de recherche");
      SHOWLIST(ALL Service[STRMATCH(name,A1)],
        "Operations"|"Opérations");
      }
      LABEL "Outils,Chercher,Opération...";
      // findServices est une méthode qui peut être
      // déclenchée par l'item Outils de la barre de menus
      // via le sous-menu Chercher sous lequel se trouve
      // la commande Opération
    L'item Outils existe déjà de base dans la barre de menus; mais si l'on spécifie un nouvel item, il est alors ajouté dans la barre de menus.

    Passage de paramètres et temporaires

    Les méthodes OTScript permettent avec les contraintes suivantes: Les exemples suivants illustrent la définition de paramètres et de temporaires:
    METHOD Toto::mth_exemple1(A1: Integer, A2: Integer):
      {TMP A3: Integer; A3 := 0;
      A3 := A1 * A2;
      (3 * A3) + (2 * A2) + A1;
      };
    
    METHOD Toto::mth_exemple2:
      {TMP A1: String; A1 := "";
      ...
      };

    Méthodes automatiquement appelées

    Les méthodes print , initialize et create sont systématiquement appelées si elles existent, la première pour la présentation par défaut du nom de l'objet (dans les browsers par exemple), la seconde à la création d'un objet avant dialogue, et la troisième à la création d'un objet après dialogue.
    Class
    {
       METHOD initialize: {
         // A chaque création d'une instance de la classe
         // Class du méta-modèle, cette méthode sera exécutée
         categories := (ALL Category[name = "unclassified"])
                DEFAULT (NEW Category).initialize ;
         THIS;};
    
    
       METHOD print: {
         // Pour toute présentation textuelle non redéfinie
         // d'une instance de Class, cette méthode eest appelée
         STR(number) + "." + name
            + " (" + key_name + ")"; };
    
       METHOD create_key_name: {
          key_name := $FIRST(SUBSTR(name,1 ,
               $INTERVAL(1  $+ STRCNT(name)))
             [NOT(EACH $< THIS.system.classes.key_name)]);
       };
        // 1 $+ STRCNT(name) donne l'ensemble
        //       {1, nameSize}
        // $INTERVAL(1 $+ STRCNT(name))
        //       complète l'ensemble {1, nameSize}
        //       de tous les elts absents
        //       entre son min et son max,
        //       soit A = {1, 2, ..., nameSize}
        // SUBSTR(name,1 , A) [cond] renvoie
        //       alors toutes les combinaisons de
        //       chaînes de 1, 2, ..., nameSize caractères
        //       vérifiant la condition cond
        // $FIRST(...) extrait la 1ère chaîne Str1
        //       de cet ensemble
        // key_name := Str1 provoque
        //       l'affectation de Str1 dans key_name
    
    
       METHOD create_number: {
          number :=  FIRST( INTERVAL(system.base_num
                   + ( CNT(system.classes) + system.base_num))
             [NOT(EACH $< THIS.system.classes.number)]);
       };
    
       METHOD create: {
         // lors d'un dialogue de création d'une instance de Class,
         // la cloture positive de ce dialogue provoque l'exécution
         // de cette méthode
          create_key_name;
          create_number;
          // les méthodes create_key_name et create_number
          // ont dû être définies avant la méthode create,
          // sans quoi la compilation provoquerait une erreur
       };
    } 
    
    
    METHOD Association::print:
          {$FIRST(roles).class.name
             + "(" + $FIRST(roles).name + ")-"
             + $LAST(roles).class.name
             + "(" + $LAST(roles).name + ")"; };
    
    ...
    

    Documentation configurable

    Les points d'entrée de documentation sont des méthodes qui contiennent l'option -menu, et dont l'accès se fait en leur donnant une place dans la barre de menu (voir la section ci-dessus consacrée à ce sujet).

    Configuration de documents génériques

    doc instanciée filtrage 

    Formats de sortie de la documentation

    Les formats de sortie sont nombreux: Les éléments de configuration de ces formats se trouvent dans les répertoires de formats de génération de documentation (ascii.dg, html.dg, ...) sous le répertoire config.

    Configuration sur la base des méthodes

    La documentation configurable s'exprime au moyen de méthodes, dont le code contient des expressions particulières propres à la génération de document.

    Les méthodes de documentation ne se distinguent des autres méthodes que par le fait qu'elles contiennent des ordres de génération de documentation. Elles peuvent faire appel à n'importe quelle méthode OTScript.

    Les expressions propres à la documentation

    Première page, en-tête et pied de page

    f1, f2, f3
    sont 3 zones successives permettant de mettre des informations sur la première page
    t1, t2, t3
    sont les zones à gauche, au milieu et à droite de l'en-tête de page
    b1, b2, b3
    sont les zones à gauche, au milieu et à droite du pied de page
    Exemple:
    METHOD RootSystem::doc_header: {
        \set("f1", name);
            // affecte le nom du RootSystem name
            // à la zone f1 de la première page
        \set("f2", author);
            // affecte l'auteur du RootSystem author
            // à la zone f2 de la première page
        \set("f3", date);
        \set("t1", name + " System");
            // affecte le nom du RootSystem name
            // concatené à " System" à la zone à gauche
            // de l'en-tête de page
        \set("t3", project.name + " Project ");
            // affecte le nom du projet project.name
            // concatené à " Project" à la zone à droite
            // de l'en-tête de page
        \set("b1", date);
        \set("b3", release);
            // affecte la version release du RootSystem
            // à la zone à droite du pied de page
    };

    Fonctions de génération de documentation

    \sect(str) et \sect_
    marques de début et de fin de section; ces ordres peuvent être imbriqués, la numérotation des sous-sections se faisant automatiquement; str est une chaîne de caractères représentant le titre de la section.
    \par et \par_
    marques de début et de fin de paragraphe.
    \text(str)
    ordre d'écriture de la chaîne de caractères str
    FIG(dgrm, scale, str)
    ordre de sortie du diagramme dgrm, à l'échelle scale (entier entre 0 et 100), avec le titre str
    \bold et \bold_
    permet de mettre en gras les textes entre ces 2 instructions
    \fixed et \fixed_
    permet de mettre en fonte fixe les textes entre ces 2 instructions
    \italic et \italic_
    permet de mettre en italique les textes entre ces 2 instructions
    \verb et \verb_
    permet de mettre en mode verbatim les textes entre ces 2 instructions

    Exemple de méthodes de documentation

    Cet exemple est un extrait de méthodes de sortie documentaire, et ne fournit pas toutes les méthodes pour réaliser une sortie complète documentaire.
    METHOD Attribute::docIn(A1: Class): {
            \par;
                            // début de paragraphe
                    \bold;
                            // début de fonte bold
                    \text(name + " : " + type.printType);
                    \bold_;
                            // fin de fonte bold
                    A1 = class IF FALSE: docInheritance;
                            // appel à la méthode de doc docInheritance
            \par_;
                            // fin de paragraphe
            class = A1 IF TRUE: doc_par(comment);
                            // appel à la méthode de doc doc_par
                            // avec l'argument comment
    };
    
    METHOD Class::doc -doc : {
            TMP A1: Class, A2: Stereotype;
            A1 := all_superclasses;
            \sect(""|"Classe " + name + " class"|"");
                    \par;
                    \italic;
                    \text("  Inherits from: "|"  Hérite de : ");
                    \italic_;
                    \bold;
                    \text($STR(superclasses.name));
                    \bold_;
                    \par_;
                    doc_par_title(comment, "Description");
                    
                    $CNT(A1) > 0 IF TRUE: {
                            \sect("Inherited attributes"|"Attributs hérités");
                                    A1.attributes.docIn(THIS);
                            \sect_;
                    };
                    \sect("Attributes"|"Attributs");
                            $CNT(attributes.stereotype)=0
                                    IF TRUE: attributes.docIn(THIS)
                                    IF FALSE: attributes.stereotype.{
                                            A2 := EACH;
                            // EACH est ici un stéréotype
                                            \sect(EACH.name);
                                            THIS.attributes[EACH.stereotype = A2].docIn(THIS);
                                            \sect_;};
                    \sect_;
            \sect_;
    } LABEL "Class"|"Classe";
    
    
    METHOD Diagram::doc : {
            FIG(THIS, scale, name);
                    // ordre de sortie de diagramme
            \par; \text(comment); \par_;
    };
    
    
    METHOD System::doc   : {
            \sect(""|"Système " + name + " system"|"");
                    system_diagram.doc;
                            // appel de la méthode doc sur tous les
                            // diagrammes de système
                    class_diagrams.doc;
                            // appel de la méthode doc sur tous les
                            // diagrammes de classe
                    classes.doc;
                            // appel de la méthode doc sur toutes les
                            // classes
            \sect_;
    } LABEL "System"|"Système";
    
    
    METHOD RootSystem::doc_final_report -menu : {
                    // point d'entrée de la documentation
                    // accessible par la barre de menu de l'outil
                    // grâce à l'option -menu
            doc_header;
            THIS.*System::(subsystems).doc;
                    // appel de la méthode doc sur l'instance
                    // de RootSystem courante (THIS) et tous ses
                    // sous-systèmes, récursivement
    } LABEL "Tools,Doc,Final report"|"Outils,Doc,Rapport final";
                    // le point d'entrée de la documentation
                    // est accessible par l'item Tools/Outils
                    // de la barre de menu,
                    // sous-menu Doc,
                    // commande Final report/Rapport final

    Fichiers et formats de sauvegarde

    Un "cluster" est un ensemble sémantique et graphique qui fait l'objet d'une création de répertoire: typiquement, un répertoire est créé lorsque l'utilisateur crée un paquetage racine UML, ou un domaine OOA par exemple, ou un projet.

    Ce répertoire contient les fichiers:

    Fichiers sémantiques

    Tout le contenu sémantique d'un cluster est enregistré dans des fichiers sous forme textuelle explicite.

    Principes

    Chaque objet (instance d'une classe du méta-modèle) est numéroté. L'objet est sauvegardé textuellement sous la forme suivante:
    &ltno> &ltclasse> {
    &ltattribut1> : &ltvaleur1>
    &ltattribut2> : &ltvaleur2>
    ...
    }
    Pour les attributs simples (non issus d'association) de l'objet, le format de leur valeur dépend de leur type: Le type n'est pas mentionné dans ce format car il est connu dans l'expression du méta-modèle.
    Pour les attributs issus d'association , il s'agit d'exprimer une ou plusieurs références à d'autres objets du méta-modèle:
    le, ou les numéros séparés par une virgule, attribués aux objets référencés sont placés comme valeur de l'attribut.

    Récupération d'existant

    Pour injecter dans OpenTool V3 une structure de classes issue d'une application existante, il n'y a pas nécessité d'exprimer le double chaînage des références:
    l'outil complètera automatiquement la référence manquante.

    Exemple

       1 RootSystem {
             name "mwoven"   // String dans le méta-modèle
             type "application" // symbole de l'enum SystemType
                                   // du méta-modèle
             currentPhase 0       // Integer dans le méta-modèle
             subsystems 2         // référence à l'objet no 2
             project 55           // référence à l'objet no 55
       }
       
       2 SubSystem {
             name "ovenDesc"
             ocm 3
             type "application"
             currentPhase 0
             predefined_types 40
             classes 5,9,38   // références aux objets no 5,9 et 38
             supersystem 1
       }
       
       3 ObjectCommunicationModel {
             name "OCM ovendesc"
             system 2
             coms 4,10,37
       }
       
       4 Communication {
             sender 5
             receiver 9
             trigger 32
             ocm 3
       }
       
       5 Class {
             name "Oven"
             abstract 0      // Boolean dans le méta-modèle
             isPersistent 0
             referential_attributes 6,43
             out_coms 4,10,37
             keyName "O"
             number 1
             stateModel 14
             receivedEvents 26,21,30,53
             visibility "public"
             system 2
       }
       
       6 LinkAttribute {
             name "light"
             visibility "public"
             access "readWrite"
             cardMin 1
             cardMax 1
             collectionKind "ordered"
             aggregation 0
             mutable 0
             class 5
             relation 7
       }
       
       7 Association {
             label ""
             isDerived 0
             roles 6,8
       }
       ...
    

    Fichiers de diagrammes

    L'exemple ci-dessous est sans rapport avec le contenu sémantique du fichier précédent.
    1 {
            sem 9  // l'entité graphique n°1 est rattachée
                    // à l'entité sémantique n°9.
            // comme aucun parent graphique n'est fourni,
            // il s'agit d'une instance de diagramme.
            box 0,0,80,14
                    
    }
    
    2 {
            sem 1  // l'entité graphique n°2 est rattachée
                    // à l'entité sémantique n°1
            par 1  // et a pour parent graphique
                    // l'entité graphique n°1
            box 42,17,122,77
                    // coordonnées du rectangle dans le diagramme
    }
    
    3 {
            sem 12 // l'entité graphique n°3 est rattachée
                    // à l'entité sémantique n°12
            par 5,2  // et a pour parents graphiques
                    // les entités graphiques n°5 et n°2
            link 218,51,122,51
                    // coordonnées des points du lien dans le diagramme
    }
    
    4 {
            sem 22
            par 6,2
            link 219,179,85,179,85,77
    }
    
    5 {
            sem 11
            par 1
            box 218,20,303,80
    }
    
    6 {
            sem 21
            par 1
            box 219,149,307,209
    }
    
    ...

    Langage de commandes

    Introduction

    OpenTool comporte un langage de commandes nommé OTShell. Ce langage est complémentaire du langage OTScript. En effet, OTScript est un langage de requêtes et de manipulation qui ne peut être exécuté que dans le contexte d'un fichier ouvert. Afin d'automatiser totalement certaines tâches, il est nécessaire de disposer d'un langage permettant de préparer ce contexte : c'est le but de OTShell.

    Un programme OTShell typique permet de désigner un fichier de travail (Select), de l'ouvrir (Open), d'exécuter des requêtes OTScript grâce à la notation { }, et éventuellement de quitter OpenTool (Quit).

    La liste des instructions OTShell est la suivante :

    Select("name")
    Sélectionne le fichier de nom "name".
    List
    Retourne la liste des fichiers.
    Quit
    Quitte OpenTool.
    Beep
    Produit un beep.
    Echo("text")
    Ouvre une boîte de message contenant "text".
    Exec("filename")
    Exécute les commandes contenues dans le fichier "filename".
    Open
    Ouvre le fichier sélectionné (par le dernier Select).
    Save
    Sauve le fichier sélectionné.
    Close
    Ferme le fichier sélectionné.
    { code OTScript }
    Exécute le code OTScript dans le contexte du fichier sélectionné.
    Voici un exemple de programme OTShell qui lance une génération de documentation :
    Select("gps")
    Open
    {
            DOCOPENW(SAVEDIR+"docSpec.tps", "ileaf");
            docSpec;
            DOCCLOSE;
    }
    Close
    Echo("End of generation")
    Quit

    Exécution des programmes OTShell

    Il y a plusieurs façons de soumettre un programme OTShell à OpenTool :
    1. Au lancement, en affectant le programme dans la variable StartUp de la section Actions. Par exemple, en Windows:
    2. [Actions]
      StartUp=Select("gps") Open
      Si le programme est long, il est recommandé de le mettre dans un fichier et de soumettre ce fichier grâce à l'instruction Exec :
      [Actions]
      StartUp=Exec("C:\example\gps.osh")
    3. Par communication DDE (Windows)

    4. Connecter à OPENTOOL, Service = System, Topic = programme OTShell
    5. Par communication via le serveur X11 (Unix/Motif)
    Lancement de OpenTool sans fenêtre : option -nodisplay 

    Auteurs: Didier Simoneau, Jean-Marie Lions