Introduction
Generic System permet de créer des types, des sous-types et des instances. Il est aussi possible de créer des attributs et des propriétés, et de leur attribuer des valeurs en créant des holders.
Mais comment relier les types entre eux ? Il existe pour cela des relations et des liens (links). Les relations peuvent impliquer plusieurs éléments :
- binaire (2 éléments) ;
- ternaire (3 éléments) ;
- …
- n-aire (n éléments).
Contrairement aux bases de données relationnelles, la gestion des relations n-aires est particulièrement simple avec Generic System.
Nous allons poursuivre cette démonstration avec notre exemple de l’article Les bases – Création de types, de sous-types et d’instances.
Cas simple : relation binaire
Une relation binaire nous permet de relier deux types. Pour reprendre notre exemple, on peut imaginer que nos véhicules possèdent une couleur.
Création de la relation
Nous allons donc créer un nouveau type Color ainsi que deux instances red et yellow :
1 2 3 4 |
// Create a new type (Color) and a few instances (colors) Generic color = engine.addInstance("Color"); Generic red = color.addInstance("red"); Generic yellow = color.addInstance("yellow"); |
Ensuite, nous allons créer la relation entre nos deux types :
1 2 3 4 5 |
// Create a relation between Vehicle and Color Generic vehicleColor = vehicle.addRelation("VehicleColor", color); // Or use an alternate syntax Generic vehicleColorAlt = engine.addInstance("vehicleColorAlt", vehicle, color); |
Vous remarquerez qu’il y a deux façons de créer une relation :
- utiliser la méthode addRelation sur le premier élément Vehicle de la relation, et préciser le second élément Color en argument ;
- utiliser la méthode addInstance sur la relation, en précisant l’ensemble des éléments impliqués dans la relation.
Ces deux méthodes sont équivalentes (en interne, la méthode addRelation fait appel à la méthode addInstance). Cependant, la méthode addRelation est plus explicite.
Création du link
La relation permet de relier les types, c’est donc le link qui symbolise la relation entre les instances. Ainsi, si l’on souhaite attribuer la couleur rouge à notre véhicule, il faudra créer un lien entre myVehicle et red :
1 2 3 4 5 6 7 8 |
// Create a link between myVehicle and red Generic myVehicleRed = myVehicle.addLink(vehicleColor, "myVehicleRed", red); // Or, we can use an alternate syntax Generic myVehicleYellow = vehicleColor.addInstance("myVehicleYellow", myVehicle, yellow); // Persist the changes engine.getCurrentCache().flush(); |
Comme pour la création d’une relation, il existe deux façons de créer un lien : addLink et addInstance.
Représentation schématique
Voici comment l’on peut représenter de façon schématique la structure que l’on vient de créer :
Importance de l’ordre
L’ordre des éléments est important lors de la création d’une relation. En effet, le premier élément de la relation est considéré comme maître et les autres sont esclaves :
1 2 |
Generic vehicleColor = vehicle.addRelation("VehicleColor", color); Generic vehicleColorAlt = engine.addInstance("vehicleColorAlt", vehicle, color); |
Ici, lors de la création des relations VehicleColor et VehicleColorAlt, Vehicle est déclaré comme maître et Color comme esclave.
Vous pourrez donc supprimer myVehicle et myVehicleRed, mais vous ne pourrez pas supprimer red puisque c’est une instance de Color, qui est esclave dans la relation VehicleColor :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// Remove myVehicle (master) myVehicle.remove(); System.out.println(myVehicle.isAlive()); // false System.out.println(myVehicleRed.isAlive()); // false System.out.println(red.isAlive()); // true // Remove red (slave) try { red.remove(); } catch (RollbackException e) { assert e.getCause() instanceof ReferentialIntegrityConstraintViolationException; } // Cancel the changes engine.getCurrentCache().clear(); |
Vous trouverez plus de détails sur la suppression d’un Generic dans l’article Avancé – Supprimer un generic.
Cas avancé : relation ternaire (n-aire)
Nous avons vu au début de l’article que Generic System pouvait gérer très facilement les relations n-aires.
Complétons notre exemple en ajoutant une notion de temps. Nous allons créer un nouveau type
Time et une instance
now :
1 2 3 |
// Create a third type (Time) and an instance (now) Generic time = engine.addInstance("Time"); Generic now = time.addInstance("now"); |
Puis nous créons notre relation ternaire entre Vehicle, Color et Time :
1 2 |
// Create a ternary relation between Vehicle, Color and Time Generic vehicleColorTime = engine.addInstance("VehColTime", vehicle, color, time); |
Nous avons utilisé la méthode addInstance pour déclarer la relation, mais il aurait été possible d’obtenir le même résultat en utilisant myVehicle.addRelation("VehColTime", color, time).
Enfin, complétons notre exemple en ajoutant un lien entre nos différentes instances :
1 2 3 4 |
// Create the links between the three instances Generic myVehicleYellowNow = myVehicle.addLink(vehicleColorTime, "myVehYelNow", yellow, now); // Or, we can use an alternate syntax Generic myVehicleRedNow = vehicleColorTime.addInstance("myVehRedNow", myVehicle, red, now); |
Vous voyez, la gestion des relations ternaires est extrêmement simple !
Représentation schématique
Voici comment l’on pourrait représenter notre exemple de façon schématique :
Ordre des éléments
Nous avons vu précédemment que l’ordre des éléments était important lors de la création d’une relation. Dans notre exemple, Vehicle est le maître et Color ou Time sont les esclaves.
Relation binaire
Lors de la création d’un link, Generic System peut réordonner les éléments pour retrouver l’ordre de la relation. Dans le cas de notre relation binaire
VehicleColor, Generic System peut facilement réordonner les éléments car ils ne sont pas du même type.
Ainsi, un link peut être créé indifféremment depuis
myVehicle ou depuis
red :
1 2 3 4 5 6 7 8 |
// Create the relation between Vehicle (master) and Color (slave) Generic vehicleColor = vehicle.addRelation("VehicleColor", color); // Create a link between myVehicle and red Generic myVehicleRed = myVehicle.addLink(vehicleColor, "myVehicleRed", red); // Or, alternatively create a link between red and myVehicle Generic myVehicleRed = red.addLink(vehicleColor, "myVehicleRed", myVehicle); |
Relation unaire
Dans le cas d’une relation unaire, s’il a y ambiguïté Generic System ne change pas l’ordre des élément et garde celui donné lors de la création du link.
Prenons l’exemple d’une relation unaire largerThan sur Vehicle qui permet de définir si un véhicule est plus grand qu’un autre. Elle peut être définie de cette façon :
1 2 |
// Create an unary relation largenThan Generic largerThan = vehicle.addRelation("largerThan", vehicle); |
Créons ensuite deux instances de Vehicle pour pouvoir les comparer :
1 2 3 |
// Create two new vehicles Generic myCar = vehicle.addInstance("myCar"); Generic myBike = vehicle.addInstance("myBike"); |
Créons deux liens : pour carLargerThanBike à partir de myCar, et bikeLargerThanCar à partir de myBike :
1 2 3 4 5 6 7 8 |
// myCar is larger than myBike Generic carLargerThanBike = myCar.addLink(largerThan, "carLargenThanBike", myBike); // myBike is larger than myCar Generic bikeLargerThanCar = myBike.addLink(largerThan, "bikerLargenThanCar", myCar); // Persist changes engine.getCurrentCache().flush(); |
Comme Generic System ne cherche pas à réordonner les éléments du même type, pour carLargerThanBike la voiture sera plus grande que la moto ; et inversement pour bikeLargerThanCar la moto sera plus grande que la voiture.
En résumé
Generic System permet de relier des types à l’aide de relations, et les instances de ces types à l’aide de links. Un link correspond donc à l’instance d’une relation.
On peut déclarer une relation en utilisant la méthode :
- addRelation d’un type, en passant les autres types en paramètre ;
- addInstance du moteur, en passant la liste des éléments de la relation en paramètre.
Par analogie, on peut déclarer un link en utilisant la méthode :
- addLink de l’instance d’un type, en passant les autres instances en paramètre ;
- addInstance de la relation, en passant la liste des éléments du link en paramètre.
La gestion des relations n-aires dans Generic System est simple, puisqu’il suffit de lister les éléments de la relations lors de la déclaration de la relation. Par exemple, pour déclarer une relation tertiaire :
1 |
Generic vehicleColorTime = engine.addInstance("VehColTime", vehicle, color, time); |