1.7 Modification de sources de données RDF

Écrit par Neil Deakin. Traduit par René-Luc D'Hont (13/06/2005).
Page originale : http://www.xulplanet.com/tutorials/mozsdk/rdfmods.php xulplanet.com

Cette section décrit comment ajouter, modifier et supprimer des informations d'un datasource RDF.

Modification de datasource

Les datasources ont quatre méthodes qui peuvent être employées pour modifier un datasource. Il est possible de modifier un datasource en utilisant seulement ces quatre méthodes. Pas tous les datasources sont modifiables. Ces datasources renveront une exception quand vous essaierez d'appeler les méthodes. Par exemple, des fichiers RDF/XML chargés d'un emplacement distant ne peuvent pas être modifiés directement.

Pour ajouter un triplet RDF à un datasource, employez la méthode Assert. Donné un sujet, un attribut et une cible, cette méthode ajoutera ce lien au datasource. Si le lien existe déjà, on l'ajoute encore. Cela signifie que vous pouvez souhaiter employer la méthode GetTarget et vérifier le lien d'abord. Dans la terminologie de Mozilla, un triplet ou le lien RDF s'appelle une affirmation (assertion), voici d'où vient le nom de la méthode. Essentiellement, nous affirmons de l'information.

Disons que nous avons voulu ajouter un nom pour une personne. Voici un exemple de comment faire cela.


var subject = rdfService.GetResource("http://www.xulplanet.com/rdf/people/David");
var predicate = rdfService.GetResource("http://www.xulplanet.com/rdf/people/name");
var name = rdfService.GetLiteral("David");

datasource.Assert(subject, predicate, name, true);

D'abord, nous obtenons des objets ressource pour le sujet et le prédicat. Nous voulons ajouter un nom, ainsi nous employons le prédicat 'name', qualifié par le namespace. Le nom lui-même est un literal ainsi nous obtenons un objet literal pour celui-ci. Chacun des trois sont recherché par le service RDF. Nous pourrions avoir employé GetAnonymousResource pour obtenir le sujet si nous voulions nous assurer que l'URI de la ressource était unique.

En conclusion, Assert s'utilise avec quatre arguments, le sujet, le prédicat, la cible et la valeur de vérité. Ce dernier argument peut être employé pour indiquer que quelque chose est faux. C'est rarement utile, ainsi le quatrième argument devrait presque toujours être vrai.

Le datasource peut ne pas accepter le changement. Par exemple, quand un datasource n'est pas inscriptible ou vous essayez d'ajouter des données inadmissibles, le datasource rejettera le changement. En code natif, vous pouvez détecter ceci car le datasource renverra un code de statut NS_RDF_ASSERTION_REJECTED. Ce code de statut n'est cependant pas une erreur.

Pour enlever un lien d'un datasource, il y a une méthode semblable Unassert. Cette méthode enlèvera un seul lien à partir des arguments de sujet, de prédicat et de cible. Par exemple, nous pourrions enlever le lien précédant que nous venons juste d'ajouter avec ce qui suit:


datasource.Unassert(subject, predicate, name);

Il n'importe pas que le lien existe ou pas. La méthode Unassert ne causera pas d'erreur si il n'existe pas.

La méthode Change peut être employée pour changer la cible d'un lien en une autre valeur. Par exemple, ceci pourrait être employé pour changer le nom d'une personne en une autre valeur. C'est équivalent à enlever la vieille valeur en appelant Unassert et en ajoutant alors la nouvelle valeur en appelant Assert. Cependant, la méthode Change fait les deux en une étape.

Voici un exemple:


var subject = rdfService.GetResource("http://www.xulplanet.com/rdf/people/George");
var predicate = rdfService.GetResource("http://www.xulplanet.com/rdf/people/name");
var oldName = rdfService.GetLiteral("George");
var newName = rdfService.GetLiteral("Georgina");

datasource.Change(subject, predicate, oldName, newName);

Dans ce cas-ci, nous changeons la valeur du prédicat 'name' de la ressource 'George' de la valeur 'George' en 'Georgina'. L'ancienne valeur sera enlevée du datasource et remplacée par la nouvelle valeur.

En conclusion, la méthode Move peut être employée pour changer la source de lien en une autre valeur. Ceci serait employé pour changer la ressource qui a un nom donné. Par exemple, nous pourrions décider que le nom de Georgina devrait être associé réellement à une ressource 'Georgina'.


var oldSubject = rdfService.GetResource("http://www.xulplanet.com/rdf/people/George");
var newSubject = rdfService.GetResource("http://www.xulplanet.com/rdf/people/Georgina");
var predicate = rdfService.GetResource("http://www.xulplanet.com/rdf/people/name");
var name= rdfService.GetLiteral("Georgina");

datasource.Move(oldSubject, newSubject, predicate, name);

Comme avec la méthode Change, la vieille valeur est enlevée et la nouvelle valeur est ajoutée. La méthode Move est l'inverse parce qu'elle change les sources au lieu des cibles.

Les deux méthodes Change et Move ne s'arrêtent pas si la vieille valeur n'était pas présente. Pour les deux méthodes, elles veulent absolument ajouter la nouvelle valeur. Pour cette raison, vous devriez vous assurer que la vieille valeur existe d'abord si c'est un souci.

Exemple de modification

Disons que vous construisez un catalogue de photos. Vous pourriez avoir une variété d'informations à stocker pour chaque photo, telle que l'endroit, la date et une description de la photo. Pour chaque photo nous prendrons une ressource et un certain nombre de propriétés. Les propriétés ne doivent pas être les mêmes pour chaque photo, ainsi nous pouvons omettre des choses pour quelques photos et ajouter plus de détail pour d'autres. Une interface utilisateur montrant les données pourrait seulement montrer les champs qui sont présents.

D'abord, commençons en créant un nouveau datasource vide dans la mémoire (in-memory) :


var rdfService = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService(Components.interfaces.nsIRDFService);

var photosDS = Components.classes["@mozilla.org/rdf/datasource;1?name=in-memory-datasource"].createInstance(Components.interfaces.nsIRDFDataSource);

Après, ajoutons quelques données pour chaque photo. Nous pourrions employer GetAnonymousResource pour produire des UIRs de ressource anonyme pour chaque photo. Ou, nous pourrions employer l'Uri du site Web où la photo est placée. Nous pourrions employer l'un ou l'autre puisque RDF emploie l'Uri seulement comme gardien de place (placeholder) et que nous ne téléchargeons pas le contenu. Dans notre exemple, prenons l'exemple d'URI suivant http://www.example.com/image/clown.jpeg.

La première photo a deux propriétés, une date et une description. Nous devrons faire deux appels à la méthode Assert pour ajouter cette information. Par exemple:


var photoRes = rdfService.GetResource("http://www.example.com/image/clown.jpeg");
var dateProp = rdfService.GetResource("http://www.example.com/rdfns/date");
var descriptionProp = rdfService.GetResource("http://www.example.com/rdfns/description");

var photoDate = rdfService.GetLiteral("January 20, 2003");
var photoDescription = rdfService.GetLiteral(
      "The clown at Simone's birthday party makes a funny face.");

photosDS.Assert(photoRes, dateProp, photoDate, true);
photosDS.Assert(photoRes, descriptionProp, photoDescription, true);

D'abord, nous obtenons les objets ressource et literal requis. Nous pourrions utilisé nsIRDFDate au lieu d'un simple literal pour la date, mais ce n'est pas le sujet de cet exemple.

Les deux lignes Assert ajoutent respectivement la date et la description. Si nous décidons plus tard que nous voulons enlever une propriété, nous pouvons juste employer la méthode Unassert.

Ajoutons une deuxième photo, dans ce cas-ci une prise à la même date.


var photo2Res = rdfService.GetResource("http://www.example.com/image/cake.jpeg");

var photo2Description = rdfService.GetLiteral(
      "Simone blows out the candles on her cake to officially mark that she is four.");

photosDS.Assert(photo2Res, dateProp, photoDate, true);
photosDS.Assert(photo2Res, descriptionProp, photo2Description, true);

Dans ce cas-ci, nous n'avons pas besoin d'obtenir autant d'objets ressource et literal puisque nous avons déjà les objets d'avant. Il n'y a aucun avantage à demander au service RDF ces objets à plusieurs reprises puisque le service RDF renverra le même objet de toute façon. La date est identique également ainsi nous pouvons juste réutiliser l'objet. La méthode Assert est aussi appelé deux fois comme avant, mais en utilisant les données pour la deuxième photo.

Puisque les deux dates sont identiques, nous pouvons interroger le datasource pour toutes les photos à cette date en employant la méthode GetSources. Le code d'exemple ci-dessous renverra une énumération avec deux items en lui, puisqu'il y a deux photos enregistrées pour la date du '20 janvier 2003'. Notez que la chaîne de caractère doit être exactement la même.


var sources = photosDS.GetSources(dateProp, photoDate, true);
while (sources.hasMoreElements()){
  var photoRes = sources.getNext();
  if (photoRes instanceof Components.interfaces.nsIRDFResource){
    var description = photosDS.GetTarget(photoRes, descriptionProp, true);
    if (description instanceof Components.interfaces.nsIRDFLiteral){
      alert(description.Value);
    }
  }
}

Pour chaque item de l'énumération, nous réclamons la méthode GetTarget pour obtenir la description de la photo. En donnant seulement la date de la photo, nous aurions trouvé les deux descriptions. Ces genres de questions nous permettent de naviguer à travers les informations du graphique RDF facilement.

Après, nous décidons de changer la description de la première photo. Nous ne voulons pas créer une nouvelle ressource et encore ajouter les données. Nous emploierons à la place juste la méthode Change pour réaliser ceci. Cette méthode permettra à la valeur d'une propriété d'être changée d'une valeur à l'autre. Nous ne pouvons pas simplement appeler Assert puisque cela ajoutera une deuxième valeur, et n'enlèvera pas l'autre. Ceci pourrait être utile dans certains cas cependant. Voici un exemple pour changer une valeur.


var photoNewDescription = rdfService.GetLiteral(
      "Simone laughs when the clown at her birthday party makes a funny face.");

photosDS.Change(photoRes, descriptionProp, photoDescription, photoNewDescription);

Parfois plus tard, nous pourrons découvrir que les descriptions des photos sont renversées. Nous pourrons employer la méthode Move pour les changer de sorte que les descriptions soient associées aux bonnes ressources. Il est également possible d'enlever les vieilles valeurs et réinsérer les valeurs au bon endroit.


photosDS.Move(photoRes, photo2Res, descriptionProp, photoNewDescription);
photosDS.Move(photo2Res, photoRes, descriptionProp, photo2Description);

La première ligne ajuste la première description de la première ressource photo sur la deuxième ressource. La deuxième ligne ajuste la deuxième description de la deuxième photo sur la première. C'est un exemple plutôt insignifiant, mais certainement utile. Un exemple plus efficace de l'utilisation de la méthode Move est de déplacer une ressource d'un endroit à l'autre. Par exemple, si des photos sont stockées dans un ensemble de groupes, on pourrait déplacer une photo d'un groupe à l'autre en employant la méthode Move pour changer le groupe au quel elle a été associé. Par exemple :


var oldFolderRes = rdfService.GetResource("http://www.example.com/folder/unsorted");
var newFolderRes = rdfService.GetResource("http://www.example.com/folder/simonesbirthday");
var photoChildProp = rdfService.GetResource("http://www.example.com/rdfns/photo");

photosDS.Move(oldFolderRes, newFolderRes, photoChildProp, photoRes);

Cet exemple déplacera une photo d'un groupe à l'autre. Nous pourrions employer un code semblable pour déplacer un groupe à l'intérieur d'un autre groupe. Dans ce cas-ci nous employons une propriété pour indiquer qu'une photo est dans un groupe. Nous pourrions vouloir utiliser un conteneur RDF à la place. Ceci est décrit dans la prochaine section.

Observer des changements de datasource

Les datasources RDF peuvent avoir un ou plusieurs observateurs attachés à eux. Les observateurs sont appelés toutes les fois que le datasource change. Il peut être utile d'observer les datasources fournis par Mozilla ou vos propres datasources. Par exemple, ceci pourrait aider à garder certain code séparé l'un de l'autre, si désiré. Le constructeur de template de XUL emploie des observateurs pour observer des changements de datasource RDF de sorte que le contenu du template puisse être reconstruit.

Vous pouvez ajouter un observateur à un datasource avec la méthode de datasource AddObserver. Vous pouvez l'enlever en employant encore la méthode RemoveObserver. Les datasources peuvent avoir plusieurs observateurs et ils seront tous appellés quand le datasource changera. Les observateurs devraient appliquer des méthodes de l'interface nsIRDFObserver.

L'observateur reçoit un avis séparé pour chaque modification du datasource. Les arguments fournis aux méthodes de l'observateur indiquent ce qui a changé. L'observateur devrait appliquer une méthode pour chacun des quatre types de changement qui peuvent se produire dans le datasource, comme décrit ci-dessus. Ces changements sont insertion, désinsertion, changement et mouvement. Le nsIRDFObserver a quatre méthodes correspondant à ces quatre types, avec pour en tête 'on'. Par exemple, la méthode onAssert sera appelée toutes les fois que Assert sera appelé sur le datasource.

Deux méthodes, onBeginUpdateBatch et onEndUpdateBatch additionnels sont appelées quand les méthodes correspondantes du datasource sont appelées. Bien qu'il n'y ait rien de spécial que ces méthodes doivent faire, elles sont un indicateur au datasource et ses observateurs qu'un grand nombre de changements vont être faits au datasource. Puisqu'il pourrait être inefficace de manipuler chaque changement, les méthodes en lots vous permettent de détecter quand un groupe de changements commence et fini, et optimisent le code pour ce cas. Par exemple, quand une opération en lots commence, le constructeur de template de XUL ne reconstruit aucun contenu de template jusqu'à ce que l'opération en lots finisse. Si les changements étaient faits sans les traiter en lots, le constructeur reconstruirait sur chaque changement qui serait inefficace.

Vous devez appliquer les six méthodes de l'interface nsIRDFObserver, bien que vous n'ayez pas besoin de prendre toutes les étapes parmis celles offertes. Voici un exemple :


var observer = {
  onAssert            : function(ds, source, predicate, target)
  {
    var dateProp = rdfService.GetResource("http://www.example.com/rdfns/date");
    var photoDate = rdfService.GetLiteral("January 20, 2003");
    if ((dateProp == predicate) && (photoDate == target)){
      alert("That is Simone's birthday!");
    }
  },
  onUnassert          : function(ds, source, predicate, target){},
  onChange            : function(ds, source, predicate, oldTarget, newTarget){},
  onMove              : function(ds, oldSource, newSource, predicate, target){},
  onBeginUpdateBatch  : function(ds){},
  onEndUpdateBatch    : function(ds){}
};

photosDS.AddObserver(observer);

Dans cet exemple, nous voulons seulement écouter les liens étant ajoutés au datasource, ainsi nous ne faisons rien avec les autres méthodes. Nous devons toujours les déclarer ou des erreurs se produiront. Les arguments de la méthode onAssert indiquent les données qui ont été ajoutées. Ceci est employé pour comparer la date à une date spécifique et pour afficher un message d'alerte si la date est le '20 janvier 2003'. Notez que nous pouvons comparer des ressources et des literals en utilisant l'opérateur ==.

Le in-memory-datasource implémente l'interface nsIRDFPropagatableDataSource. Elle a une simple propriété propagateChanges qui peut être placé à vrai ou faux. Par défaut, la valeur de cette propriété est vraie, mais si vous la changez en faux, la notification de l'observateur sera mis hors service. Ceci neutralisera tous les avis des observateurs ainsi ils ne seront plus appellés. En replaçant la valeur sur true les avis seront réactivé. Les changements réalisés tandis que la valeur est sur false n'atteindront pas les observateurs. Comme exemple, le datasource de signets neutralise les avis en triant un dossier, puisqu'une grande quantité de données est brassée pendant l'opération de trie.


Mozilla® est une marque déposée de la fondation Mozilla.
Mozilla.org™, Firefox™, Thunderbird™, Mozilla Suite™ et XUL™ sont des marques de la fondation Mozilla.