Home > Models

Contraintes, triggers et fonctions

Les facettes permettent de définir des contraintes sur les Master Data dans les modèles d'adaptation. EBX.Platform supporte les facettes XML Schema et fournit des facettes étendues et programmatiques afin de définir des contrôles avancés.


Facettes XML Schema supportées

length

min

Length

max

Length

pattern

enumeration

white

Space

fraction

Digits

total

Digits

max

Inclusive

max

Exclusive

min

Inclusive

min

Exclusive

string

X

X

X

X

X

(1)

(2)

(2)

(2)

(2)

boolean

X

(1)

decimal

X

X

(1)

X

X

X

X

X

X

dateTime

X

X

(1)

X

X

X

X

time

X

X

(1)

X

X

X

X

date

X

X

(1)

X

X

X

X

anyURI

X

X

X

X

X

(1)

Name

X

X

X

X

X

(1)

(2)

(2)

(2)

(2)

integer

X

X

(1)

X

X

X

X

X

X

resource (3)

Notes :

Exemple:

<xs:element name="loanRate">
      <xs:simpleType>
            <xs:restriction base="xs:decimal">
                          <xs:minInclusive value="4.5"/>
                          <xs:maxExclusive value="17.5"/>
            </xs:restriction>
      </xs:simpleType>
</xs:element>

Contrainte d'unicité

Il est possible de définir une contrainte d'unicité en utilisant la définition standard XML Schema xs:unique . Cette contrainte permet d'indiquer qu'une valeur doit être unique dans une table.

Dans l'exemple ci-dessous, une contrainte d'unicité est définie sur la table publisher pour le champ cible name (cela signifie que deux occurrences de la table publisher ne peuvent pas avoir le même nom) : 

<xs:element name="publisher">
    ...
    <xs:complexType>
        <xs:sequence>
            ...
            <xs:element name="nametype="xs:string"/>
            ...
        </xs:sequence>
    </xs:complexType>
    <xs:unique name="uniqueName">
        <xs:selector xpath="."/>
        <xs:field xpath="name"/>
    </xs:unique>
</xs:element>

La contrainte d'unicité doit être définie dans une table et doit comporter les propriétés suivantes :

Propriété

Description

Obligatoire

Attribut name

Identifie la contrainte dans le schéma.

Oui

Elément xs:selector

Indique, au moyen d'une expression XPath, la table dans laquelle la contrainte d'unicité s'applique. L'expression XPath doit être simple, la notation '..' est interdite.

Oui

Elément xs:field

indique le champ sur lequel porte la contrainte d'unicité, au moyen d'une expression XPath relative à xs:selector

Oui

Limitations :

  1. Le champ cible de l'élément xs:field doit être dans une table.

  2. La contrainte d'unicité ne peut pas s'appliquer si le champ cible est à l'intérieur d'une liste agrégée.

  3. Une seule contrainte d'unicité sur plusieurs champs cible n'est pas supportée.

Facettes étendues

EBX.Platform fournit des contraintes avancées qui ne sont pas définies dans XML Schema mais sont utiles pour le Master Data Management.

Afin de conserver la conformité du document par rapport à la norme XML Schema, ces facettes sont définies sous l’élément annotation/appinfo/otherFacets .

Clés étrangères

Une référence à une clé primaire de table est définie par une facette étendue tableRef . L'élément doit être du type xs:string

Element

Description

Obligatoire

tablePath

Expression XPath qui spécifie la table cible.

Oui.

container

Optionnel, référence de l'instance qui contient la table cible.

Non, si cet élément n'est pas spécifié, l'instance est celle contenant la table.

branch

Optionnel, référence la branche contenant l'instance cible.

Non, par défaut la branche courante est utilisée.

display

Présentation personnalisée de la clé sélectionnée dans l'enregistrement courant et de la liste triée des clés possibles. Deux variantes peuvent être spécifiées : 

  • Expression par défaut et expressions localisées. Ces expressions sont définies au moyen des éléments display et pattern , par exemple : 

    <display>

    <pattern>Product : ${./ProductID}</pattern>

    <pattern xml:lang="fr-FR">Produit : ${./ProductID}</pattern>

    <pattern xml:lang="en-US">Product : ${./ProductID}</pattern>

    </display>

  • Un JavaBean qui implémente l'interface TableRefDisplay . Il est défini au moyen de l'élément osd:class , par exemple : 

    <display osd:class="com.wombat.MyLabel"></display>

Non.

filter

Spécifie une contrainte additionnelle qui filtre les occurrences de de la table cible. Deux types de filtres sont disponibles : 

  • Le filtre XPath est un prédicat XPath dans le contexte de la table cible. Il est défini au moyen de l'élément predicate , par exemple : 

    <filter><predicate>type = ${../refType}</predicate></filter>

    (ici 'type' est un élément de la table cible et 'refType' fait référence à un élément dans le contexte courant du noeud qui définit la clé étrangère).

  • Le filtre programmatique est un JavaBean qui implémente l'interface TableRefFilter . Il est défini au moyen de l'attribut osd:class , par exemple:

    <filter osd:class="com.wombat.MyFilter"></filter>

Note : 
  • L'attribut osd:class et l'élément predicate sont mutuellement exclusifs.

Non.

L'exemple ci-dessous spécifie une référence (clé étrangère) vers une occurrence de l'élément catalog .

<xs:annotation>
        <xs:appinfo>
          <osd:otherFacets>
            <osd:tableRef>
              <tablePath>../catalog</tablePath>
              <label xml:lang="en-US">Product: ${./ProductID}</label>
              <filter>
                <predicate>type = ${../refType} </predicate>
              </filter>
            </osd:tableRef>
          </osd:otherFacets>
        </xs:appinfo>
</xs:annotation>

Note: Différentes combinaisons peuvent être spécifiées pour définir le libellé d'une clé étrangère. L'ordre de priorité des balises est le suivant : 

  1. balise label définissant un libellé programmatique.

  2. balise label définissant une expression localisée.

  3. balise label définissant une expression par défaut.

La facette tableRef est interprétée comme une énumération. La clé étrangère formatée est la valeur de l'élément (type xs:string ). Le libellé peut être composé en ajoutant les chemins d'autres champs des occurrences référencées par l'élément labelPaths (les chemins sont absolus dans le contexte de l'occurrence).

Voir aussi :

Contraintes dynamiques

Les facettes suivantes supportent le référencement de la valeur d’un autre noeud :

Cette propriété permet de modifier les contraintes du modèle de données dynamiquement, dans les adaptations ou même dans un contexte.

Par rapport aux facettes standards, le nom de l’élément est conservé, cependant l’attribut statique value est remplacé par l’attribut path

Exemple :

<xs:element name="amount">
      <xs:annotation>
            <xs:appinfo>
                  <osd:otherFacets>
                                <osd:minInclusive path="/domain/Loan/Pricing/AmountMini/amount"/>
                  </osd:otherFacets>
            </xs:appinfo>
      </xs:annotation>
      ...
</xs:element>

Dans cet exemple, la borne de la facette minInclusive n’est pas définie statiquement, la valeur de la borne est détenue par le nœud " /domain/Loan/Pricing/AmountMini/amount ".

Contrainte FacetOResource

La facette doit être définie pour chaque type resource. Elle a les attributs suivants :

Cette facette a le même comportement qu’une facette énumération : l’ensemble des valeurs est obtenu en listant récursivement tous les fichiers situés dans ‘local path’ du répertoire spécifié ‘resource type’ dans le ‘module’ spécifié.

Exemple :

<xs:element  name="promotiontype="osd:resource" > 
    <xs:annotation> 
      <xs:appinfo> 
        <osd:otherFacets> 
          <osd:FacetOResource 
                osd:moduleName="wbp
                osd:resourceType="ext-images
                osd:relativePath="promotion/" /> 
        </osd:otherFacets> 
      </xs:appinfo> 
    </xs:annotation > 
</ xs:element> 

Un aperçu de la structure des répertoires dans un module EBX.Platform (application Web J2EE) est donné dans la section Modules - Structure .

Contrainte excludeValue

Cette facette vérifie qu’une instance est différente d’une valeur donnée.

Exemple :

<xs:element  name="roleName" > 
    <xs:annotation> 
      <xs:appinfo> 
        <osd:otherFacets> 
          <osd:excludeValue value=""> 
            <osd:defaultErrorMessage> 
              Please select address role(s). 
            </osd:defaultErrorMessage> 
          </osd:excludeValue> 
        </osd:otherFacets> 
      </xs:appinfo> 
    </xs:annotation> 
    <xs:simpleType type="xs:string"/> 
</xs:element >

Ici, la chaîne vide est exclue des valeurs possibles.

Contrainte excludeSegment

Cette facette vérifie qu’une instance n’appartient pas à un segment de valeurs. Les bornes elles-mêmes sont exclues.

Exemple :

<xs:element  name="zipCode"> 
    <xs:annotation> 
      <xs:appinfo> 
        <osd:otherFacets> 
          <osd:excludeSegment minValue="20000maxValue="20999"> 
            <osd:defaultErrorMessage> 
            Postal code not valid. 
            </osd:defaultErrorMessage> 
          </osd:excludeSegment> 
        </osd:otherFacets> 
      </xs:appinfo> 
    </xs:annotation> 
    <xs:simpleType  type="xs:string"/> 
</xs:element>  

Ici, les valeurs comprises entre 20000 et 20999 sont exclues.

Facette énumération alimentée par un autre noeud

Par défaut, une facette énumération est décrite statiquement en XML Schema.

Le contenu de la facette énumération peut être alimenté par un autre nœud du modèle de données.

Alimentation par une liste

En ajoutant l’information suivante, on indique que le contenu de la facette énumération provient du nœud frère CountryList

<xs:annotation>
    <xs:appinfo>
      <osd:otherFacets>
        <osd:enumeration osd:path="../CountryList"/>
      </osd:otherFacets>
    </xs:appinfo>
</xs:annotation>
Le nœud frère CountryList  : 

Exemple :

< xs:element name="FacetEnumBasedOnList"> 
    <xs:complexType> 
      <xs:sequence> 
        <xs:element name="CountryListmaxOccurs="unbounded"> 
          <xs:simpleType> 
            <xs:restriction base="xs:string"> 
              <xs:enumeration value="DEosd:label="Allemagne"/> 
              <xs:enumeration value="ATosd:label="Autriche"/> 
              <xs:enumeration value="BEosd:label="Belgique"/> 
              <xs:enumeration value="JPosd:label="Japon"/> 
              <xs:enumeration value="KRosd:label="Corée"/> 
              <xs:enumeration value="CNosd:label="Chine"/> 
            </xs:restriction> 
          </xs:simpleType> 
        </xs:element> 
        <xs:element name="CountryChoicetype="xs:string"> 
          <xs:annotation> 
            <xs:appinfo> 
              <osd:otherFacets> 
                <osd:enumeration osd:path="../CountryList"/> 
              </osd:otherFacets> 
            </xs:appinfo> 
          </xs:annotation> 
        </xs:element> 
      </xs:sequence> 
    </xs:complexType > 
</xs:element > 


Facettes programmatiques

EBX.Platform propose d'implémenter des contraintes qui ne sont ni spécifiées par XML Schema, ni proposées en extension par EBX.Platform, via une simple déclaration de classe Java dans le schéma.

Afin de conserver la conformité du document par rapport à la norme XML Schema, ces facettes sont définies sous l’élément

annotation/appinfo/otherFacets

Contraintes programmatiques

Une facette programmatique est définie par une classe Java implémentant l'interface Java Constraint

Il est possible d'associer des paramètres à la facette. Par conséquent, la classe Java implémentée doit être conforme au protocole JavaBean. Dans l'exemple ci-dessous, elle doit définir les méthodes :  getParam1(), setParam1(String), ..., getParamX(), setParamX(String), etc.

Exemple :

<xs:element name="amount">
        <xs:annotation>
          <xs:appinfo>
            <osd:otherFacets>
              <osd:constraint class="com.foo.CheckAmount">
                <param1>...</param1>
                <param...n>...</param...n>
              </osd:constraint>
            </osd:otherFacets>
          </xs:appinfo>
        </xs:annotation>
        ...
</xs:element>

Voir aussi :

Contraintes programmatiques de type Enumération

Une contrainte énumération ajoute à une contrainte programmatique basique la définition d'une liste ordonnée de valeurs. Pour cela, on définit une classe Java implémentant l'interface ConstraintEnumeration . Cette facette permet la sélection d'une valeur dans une liste.

Exemple :

<xs:element name="amount">
        <xs:annotation>
          <xs:appinfo>
            <osd:otherFacets>
              <osd:constraintEnumeration class="com.foo.CheckAmountInEnumeration">
              <param1>...</param1>
              <param...n>...</param...n>
              </osd:constraintEnumeration>
            </osd:otherFacets>
          </xs:appinfo>
        </xs:annotation>
        ...
</xs:element>

Contraintes programmatiques de type Nomenclature

Une contrainte nomenclature ajoute à une contrainte programmatique basique la définition d'une liste ordonnée de "valeurs-labels". Pour cela, on définit une classe Java implémentant l'interface ConstraintNomenclature . Cette facette permet la sélection d'une valeur dans une liste.

Notons qu'une contrainte énumération (décrite précédemment) est davantage appropriée lorsque l'on souhaite afficher des "valeurs localisées" ou lorsque le nombre d'éléments de la liste de sélection est important.

Exemple :

<xs:element  name="amount">
        <xs:annotation>
          <xs:appinfo>
            <osd:otherFacets>
              <osd:constraintNomenclature class="com.foo.CheckAmountInNomenclature">
              <param1>...</param1>
              <param...n>...</param...n>
              </osd:constraintNomenclature>
            </osd:otherFacets>
          </xs:appinfo>
        </xs:annotation>
        ...
</xs:element >

Contrainte sur valeur nulle

Parfois une valeur n'est obligatoire que si certaines conditions sont vérifiées (par exemple si un autre champ a une certaine valeur). Cependant l'attribut standard de XML Schema, minOccurs , ne répond pas à un besoin de ce type, puisqu'il est statique.

Pour vérifier si un élément est obligatoire ou non obligatoire selon son contexte : 

  1. une contrainte programmatique doit être définie par une classe Java (voir ci-dessus) ; 

  2. cette classe doit de plus implémenter l'interface ConstraintOnNull ;

  3. enfin les attributs de cardinalité XML Schema doivent spécifier que l'élément est optionnel ( minOccurs="0" et maxOccurs="1").

Note : par défaut, la contrainte sur valeur nulle n'est pas vérifiée lorsque l'utilisateur soumet sa saisie via l'outil EBX.Manager. Pour activer cette vérification à la saisie, il faut définir la propriété checkNullInput et si l'élément est terminal, activer l'instance.

Exemple :

<xs:element  name="amountminOccurs="0maxOccurs="1>
        <xs:annotation>
          <xs:appinfo>
            <osd:otherFacets>
              <osd:constraint class="com.foo.CheckIfNull">
              <param1>...</param1>
              <param...n>...</param...n>
              </osd:constraint>
            </osd:otherFacets>
          </xs:appinfo>
        </xs:annotation>
        ...
</xs:element >

Contraintes sur tables

Une contrainte portant sur une table est définie par une classe Java implémentant l'interface Java ConstraintOnTable

Une contrainte portant sur une table peut uniquemement être définie sur un noeud table.

Il est possible d'associer des paramètres à  la contrainte. Par conséquent, la classe Java implémentée doit être conforme au protocole JavaBean. Dans l'exemple ci-dessous, elle doit définir les méthodes :  getParam1(), setParam1(String), ..., getParamX(), setParamX(String), etc.

Exemple :

<xs:element name="myTabletype="MyTableTypeminOccurs="0maxOccurs="unbounded">
   <xs:annotation>
      <xs:appinfo>
            <osd:table>
               <primaryKeys>/key</primaryKeys>
            </osd:table>
            <osd:otherFacets>
              <osd:constraint class="com.foo.checkTable">
                <param1>...</param1>
                <param...n>...</param...n>
              </osd:constraint>
            </osd:otherFacets>
      </xs:appinfo>
   </xs:annotation>
</xs:element>

Important: Les contraintes définies au niveau d'une table sont uniquement vérifiées lors d'un appel à  un rapport de validation d'une instance ou d'une table. Autrement dit, pour des raisons de performances, ce type de contrainte n'est pas vérifié lors d'une mise à jour telle que l'insertion, la suppression ou la modification d'un enregistrement sur la table associée à  cette contrainte. Cependant, le mécanisme interne de validation incrémentale optimise le nombre de vérifications de ce type de contrainte si des dépendances sont définies. Pour plus d'information sur le mécanisme de validation incrémentale, voir la section performances .

Voir aussi :

Triggers et fonctions

Valeurs calculées

Par défaut, les valeurs des nœuds d’une adaptation sont lues et persistées dans le référentiel EBX. Néanmoins, il est possible d’alimenter la valeur d’un nœud d’adaptation de manière spécifique.

Par exemple, une valeur peut provenir d’un système de persistance externe (base de données relationnelle, système central, etc.). Elle peut aussi être le résultat d'un calcul. Ce calcul (ou l'accès à la base) peut même prendre en compte des paramètres de l'adaptation courante.

Ceci est rendu possible par l’utilisation d’une fonction .

Une fonction est spécifiée dans le schéma XML au moyen de l’élément osd:function (voir exemple ci-dessous).

Exemple:

<xs:element name="computedValue">
        <xs:annotation>
          <xs:appinfo>
            <osd:function class="com.foo.ComputeValue">
              <param1>...</param1>
              <param...n>...</param...n>
            </osd:function>
          </xs:appinfo>
        </xs:annotation>
        ...
</xs:element>

Triggers

Il est possible d'associer à des instances ou à des occurrences de tables des méthodes qui seront exécutées automatiquement lorsque certaines opérations sont effectuées : création, mise à jour, suppression, etc.

Dans le document XML Schéma, on spécifie ce cas de figure en utilisant la balise osd:trigger dans la balise annotation/appinfo .

Pour la définition de triggers sur des instances d'un schéma, on doit définir dans la balise osd:trigger , une classe Java qui étend la classe abstraite InstanceTrigger

Notons que dans le cas de triggers d'instances, il est conseillé de définir les balises annotation/appinfo/osd:trigger juste en dessous de l'élément racine du schéma XML concerné.

Exemple :

<xs:element name="rootosd:access="--">

   <xs:annotation>
       <xs:appinfo>
          <osd:trigger class="com.foo.MyInstanceTrigger">    
             <param1>...</param1> 
             <param...n>...</param...n> 
          </osd:trigger>    
       </xs:appinfo>
   </xs:annotation>

   <xs:complexType>
      <xs:sequence>
         ...
      </xs:sequence>
   </xs:complexType>

</xs:element>

Pour la définition de triggers sur des occurrences de tables, on doit définir dans la balise osd:trigger une classe Java qui étend la classe abstraite TableTrigger

Dans le cas de triggers sur des occurrences de table, il est conseillé de définir les balises annotation/appinfo/osd:trigger juste en dessous de l'élément définissant la table ou le type de la table concernée.

Exemple :

Sur une table :

<xs:element name="myTabletype="MyTableTypeminOccurs="0maxOccurs="unbounded">
   <xs:annotation>
      <xs:appinfo>

         <osd:table>
            <primaryKeys>/key</primaryKeys>
         </osd:table>

         <osd:trigger class="com.foo.MyTableTrigger"/>

      </xs:appinfo>
   </xs:annotation>
</xs:element>

ou sur un type associé à une table :

<xs:complexType name="MyTableType">

   <xs:annotation>
       <xs:appinfo>
          <osd:trigger class="com.foo.MyTableTrigger">    
             <param1>...</param1> 
             <param...n>...</param...n> 
          </osd:trigger>    
       </xs:appinfo>
   </xs:annotation>

   <xs:sequence>
      ...
   </xs:sequence>
   
</xs:complexType>

Notons qu'il est possible d'associer des paramètres à un trigger. Par conséquent, la classe Java implémentée doit être conforme au protocole JavaBean. Dans l'exemple ci-dessus, elle doit définir les méthodes :  getParam1(), setParam1(String), ..., getParamX(), setParamX(String), etc.

Valeurs auto incrémentées

Il est possible de définir des valeurs auto-incrémentées. Les valeurs auto-incrémentées sont uniquement autorisées à l'intérieur de tables et doivent être de type xs:int ou xs:integer .

Un auto-incrément est spécifié dans le document XML Schéma en utilisant la balise osd:autoIncrement dans la balise annotation/appinfo .

Exemple :

<xs:element name="autoIncrementedValuetype="xs:integer"> 
        <xs:annotation> 
          <xs:appinfo> 
              <osd:autoIncrement /> 
          </xs:appinfo> 
        </xs:annotation> 
</xs:element> 

Les deux éléments start et step sont optionnels.

Exemple :

< xs:element  name="autoIncrementedValuetype="xs:integer"> 
        <xs:annotation> 
          <xs:appinfo> 
              <osd:autoIncrement> 
                <start>100</start> 
                <step>5</step> 
              </osd:autoIncrement> 
          </xs:appinfo> 
        </xs:annotation> 
</xs:element> 

L'attribut start représente la valeur de départ de l'incrément. Si cet attribut n'est pas renseigné, alors la valeur 1 est utilisée par défaut.

L'attribut step indique le pas pour la prochaine valeur de l'auto incrément. Si cet attribut n'est pas renseigné, alors la valeur 1 est utilisée par défaut.

Un champ utilisant la balise osd:autoIncrement a le comportement suivant : 

En interne, la dernière value d'un auto incrément est stockée dans la table 'Auto Incréments' de l'adaptation ebx-repository . Ce champ est automatiquement mis à jour, de telle sorte qu'il contienne la plus grande valeur ayant été affectée pour le champ osd:autoIncrement associé, et ce dans toute instance et branche du référentiel. Cette valeur est calculée en tenant compte de la plus grande valeur de la colonne auto-incrémentée dans la table en cours de mise à jour.

Dans certaines situations particulières, il peut être souhaitable d'éviter ce comportement (ex: gestion multi-environnement _dev/test/prod, avec des plages d'auto incréments différentes). Ce comportement particulier est supporté en activant la propriété disableMaxTableCheck :

Remarque : il n'est pas conseillé d'utiliser cette option, les valeurs des auto-incréments générées pouvant entrer en conflit.

Controles des Entrées Utilisateurs

Contrôle de la saisie d'une valeur nulle

Selon la stratégie générale de validation, afin de permettre temporairement la saisie incomplète des données, le contrôle du caractère obligatoire d'un élément n'est pas exécuté lorsque l'utilisateur saisit une valeur nulle via l'outil EBX.Manager, mais lors de la validation globale de l'adaptation. Pour déclencher un contrôle immédiat à la saisie utilisateur, l'élément doit spécifier l'attribut osd:checkNullInput="true" .

Note : le caractère obligatoire d'une valeur n'est vérifié que si le schéma spécifie que l'élément est obligatoire, soit de façon statique ( minOccurs="1"), soit de façon dynamique (au moyen d'une contrainte sur valeur nulle). L'adaptation doit aussi être activée si l'élément obligatoire est terminal.

Exemple:

<xs:element  name="amountosd:checkNullInput="trueminOccurs="1"   >
        ...
</xs:element >

Voir aussi :

Gestion des espaces sur les types de données par EBX.Platform

Conformément à XML Schema ( cf. http://www.w3.org/TR/xmlschema-2/#rf-whiteSpace ), la gestion des espaces pour un type donné doit suivre l'une des procédures suivantes : 

Procédure générale de EBX.Platform

EBX.Platform est conforme à la recommandation XML Schema :

Exceptions : Pour les noeuds de type osd:html ou osd:password , les espaces sont toujours preservés et la chaîne vide est convertie à null . Pour les noeuds de type xs:string définissant la propriété osd:checkNullInput="true" la chaîne vide est considérée comme null lors de la vérification de la saisie utilisateur par EBX.Manager.

Cas spécifique pour la gestion des espaces sur les clés primaires de type string

Pour les colonnes de clé primaire de type xs:string , EBX.Platform définit une contrainte par défaut. Cette contrainte interdit les chaînes vides et les valeurs dont les espaces ne sont pas "collapsés" à la validation.

Cependant, si le noeud de la clé primaire définit une facette xs:pattern , cette dernière remplace la contrainte par défaut de EBX.Platform. Par exemple, un pattern spécifique peut autoriser tout type de chaîne. Ce pattern peut donc avoir la forme suivante :  .* . Ce cas de figure n'est cependant pas recommandé.

La contrainte par défaut permet d'empêcher certaines ambiguïtés. Par exemple, il sera difficile pour un utilisateur final de distinguer entre les chaînes de caractères suivantes : "12 34" et "12  34". Pour les valeurs usuelles cela ne pose pas de problèmes. En revanche, pour les clés primaires, cela peut porter à confusion et provoquer des erreurs.

Note : EBX.Platform permet de définir des tables qui permettent d'organiser et de gérer des Master Data avec des fonctionnalités semblables à celles des bases de données relationnelles.

Home > Models