4.3 - Modifications RDF

Attention : Ce tutoriel est ancien, incomplet, et n'est pas mis à jour. Il ne contient pas toutes les nouveautés du système de template de Gecko 1.9 / Firefox 3.0 qui est largement simplifié et permet d'utiliser sqlite ou xml comme source de données. Aussi est-il préférable d'aller consulter la version anglaise sur developer.mozilla.org.

Le troisième type d'observateur invoqué dans un constructeur de gabarits est un nsIRDFObserver. Le constructeur de gabarits implémente cette interface pour surveiller toutes modifications RDF. Lorsqu'elle est modifiée, la source de données va notifier à tous les observateurs la modification. Le constructeur de gabarits utilise ces notifications pour mettre à jour le gabarit si nécessaire en fonction des informations nouvelles ou supprimées. Vous n'avez pas besoin d'implémenter cet observateur vous même, bien que vous pouvez ajouter un observateur à la source de données si vous désirez être notifié d'éventuelles modifications de données.

Il existe deux situations principales déclenchant les notifications. La première se produit lorsque les fonctions de modifications de la source de données sont appelées. Il existe quatre de ces fonctions : 'Assert' pour ajouter un nouveau triplet (ou arc) au graphe RDF, 'Unassert' pour supprimer un triplet, 'Change' pour ajuster la cible d'un triplet, et 'Move' pour ajuster la source d'un triplet. Dans le cas des sources de données de Mozilla, l'avant dernière fonction réalise une suppression de l'ancien triplet et un ajout du nouveau, en créant ainsi l'effet de modification de valeur. Cependant, une seule notification est lancée.

Par exemple, l'appel de la fonction Assert ressemble à ceci :

var source = RDF.GetResource("http://www.xulplanet.com/ndeakin/images/t/obelisk.jpg");
var predicate = RDF.GetResource("http://purl.org/dc/elements/1.1/description");
var target = RDF.GetLiteral("Un sur la trentaine ou plus d'obélisques égyptiens");
datasource.Assert(source, predicate, target, true);

L'appel de la fonction Assert ajoute un nouveau triplet à la source de données RDF. Lorsque cet ajout se produit, tous les gabarits observant la source de données seront notifiés via la méthode onAssert de l'observateur RDF.

La seconde situation déclenchant les notifications survient lorsque la source de données est en train de se charger ou de se recharger. En réalité, en interne, ces notifications ne sont pas vraiment différentes des autres, mais elles valent la peine d'en discuter séparément. Lorsque le processeur RDF charge le RDF/XML, il appelle la fonction Assert de l'objet datasource pour ajouter chaque triplet trouvé. En effet, cela revient au même résultat que d'ajouter vous même chaque série de triplets en utilisant la méthode Assert.

Lors du rechargement de la source de données, vous pourriez penser que le processeur RDF supprime toutes les données existantes, recharge les nouvelles données, et les ajoute à la source de données. Vous pourriez également penser qu'il crée une source de données rafraîchie avec les nouvelles données. En réalité, le processeur RDF réalise quelque chose de plus subtil. Lors du rechargement de la source de données, il conserve les triplets RDF existants intacts, et ne modifie que les données qui ont changé. Lors du traitement, tous les triplets existants ne sont pas ajoutés de nouveau. Si un triplet n'existait pas, il est ajouté. Tous les triplets qui n'existent plus avec les nouvelles données sont supprimés. En clair, l'observateur sera appelé pour tous les triplets qui diffèrent entre les anciennes données et les nouvelles. Si la source de données rechargée n'a pas été modifiée, le constructeur ne recevra aucune notification. Ce mode de fonctionnement est optimisé.

L'observateur RDF a également deux méthodes onBeginUpdateBatch et onEndUpdateBatch. Elles sont appelées lors de la réalisation de nombreuses opérations sur la source de données. Lorsque la source de données est modifiée, les modifications sont pratiquées du début à la fin. Ensuite, plutôt qu'une notification soit lancée à chaque modification, la source de données enverra une seule notification globale indiquant la fin des changements. Le constructeur de gabarits peut alors reconstruire entièrement le gabarit. Ce fonctionnement est très utile dans le cas de très nombreuses modifications pour éviter de devoir recalculer trop rapidement des parties du gabarit.

Ajout de triplets RDF

Ajoutons le triplet ci-dessous à la source de données.

subject: http://www.xulplanet.com/ndeakin/images/t/obelisk.jpg
predicate: http://purl.org/dc/elements/1.1/description
object: Un sur la trentaine ou plus d'obélisques égyptiens

Le constructeur de gabarits sera notifié de la modification au travers du mécanisme d'observateur RDF. Il devra alors tester toutes les règles pour vérifier si le triplet entraînera une modification dans l'affichage. Si le triplet n'entraîne aucun changement, le constructeur ne fera aucun changement. Si l'affichage doit être modifié, le constructeur devra ajuster la sortie, soit par l'ajout d'un nouveau résultat, la suppression d'un ancien résultat, ou par la modification d'une partie des valeurs des résultats. Le constructeur est suffisamment intelligent pour ne modifier que l'essentiel en laissant les parties restantes intactes. Supposons que nous ayons une seule règle avec les conditions suivantes :

<conditions>
  <content uri="?start"/>
  <member container="?start" child="?photo"/>
  <triple subject="?photo"
             predicate="http://purl.org/dc/elements/1.1/title"
             object="?title"/>
  <triple subject="?photo"
             predicate="http://purl.org/dc/elements/1.1/description"
             object="?description"/>
</conditions>

Ces conditions vont afficher toutes les photos ayant à la fois un titre et une description. Supposons que la photo 'obélisque' n'a pas encore de description, l'ajout du triplet décrit plus haut entraînera un nouveau résultat disponible pour cette photo. Le constructeur analyse les conditions une par une.

La balise content peut être sautée sans problème à ce stade du processus, donc le constructeur continue sur la condition member. Ce type de condition ne peut entraîner une modification que si un item est ajouté ou retiré d'un conteneur. Puisque nous avons un nouveau triplet RDF qui n'est pas ajouté ou retiré d'un conteneur, cette condition peut être sautée. Effectivement, si le processus de génération des résultats devait évaluer cette condition membre, les mêmes résultats seraient produits pour la variable ?photo que la nouvelle donnée en fasse partie ou non. Ainsi, la condition membre peut être sautée.

La condition suivante est un triple impliquant le prédicat http://purl.org/dc/elements/1.1/title. Nous se sommes pas en train d'ajouter un arc impliquant ce triplet donc nous pouvons ignorer également cette condition. Le second triplet, toutefois, peut entraîner des modifications puisque l'attribut predicate correspond au prédicat ajouté. Le sujet et l'objet sont des variables que le constructeur accepte comme modification possible, et continue vers l'étape suivante. Si le prédicat était différent, le constructeur aurait continué jusqu'à la fin des conditions et se serait arrêté là. Par exemple, si le prédicat du triplet ajouté était http://purl.org/dc/elements/1.1/date, le constructeur l'aurait ignoré car le gabarit ne met en pas jeu de champ date. De même, si le triplet n'utilise pas de variable mais une valeur statique, cette valeur devrait correspondre pour que le processus continue.

Maintenant que nous connaissons les conditions pouvant entraîner une modification dans le gabarit, la seconde étape est de remplir les variables pour cette condition avec ce qui devrait être potentiellement le nouveau résultat. Dans cette situation, les variables ?photo et ?description sont remplies en utilisant les valeurs du triplet nouvellement ajouté.

(?photo = http://www.xulplanet.com/ndeakin/images/t/obelisk.jpg,
 ?description = 'Un sur la trentaine ou plus d'obélisques égyptiens')

Ensuite, le constructeur va parcourir les règles en sens inverse afin de remplir les variables restantes. Il procède de façon similaire lorsqu'il génère les résultats mais en traversant les règles dans le sens opposé. Le triplet précédent sera rempli d'une valeur pour la variable ?title puisque nous connaissons une valeur pour la variable ?photo faisant référence à l'attribut subject du triplet. Ensuite, la condition member est examinée, et dans cette situation, le constructeur remplit la variable ?photo connue et cherche un conteneur parent contenant cette valeur. Il existe un conteneur http://www.xulplanet.com/rdf/myphotos, donc la variable ?start sera remplie avec cette valeur. Maintenant, les résultats potentiels sont à ce stade les suivants :

(?photo = http://www.xulplanet.com/ndeakin/images/t/obelisk.jpg,
 ?description = 'Un sur la trentaine ou plus d'obélisques égyptiens',
 ?start = http://www.xulplanet.com/rdf/myphotos,
 ?title = 'Obélisque')

Comme vous pouvez le voir, le résultat semble disposer de toutes les informations nécessaires pour créer un nouvel item à l'affichage. Si une condition n'avait pas généré un résultat, par exemple si la photo n'avait pas de titre ou n'était pas incluse dans un conteneur parent, il n'y aurait pas eu de correspondance et le constructeur aurait interrompu le processus pour ce nouveau triplet. Par exemple, nous aurions pu ajouter une description pour une nouvelle photo mais sans inclure cette photo dans une ressource conteneur. Dès lors qu'elle est ajoutée à un conteneur avec une autre assertion RDF, le processus décrit ci-dessus est appliqué de nouveau et une correspondance sera atteinte cette fois.

Il y a encore deux choses à faire avant qu'un résultat ne soit accepté comme nouvelle correspondance. Tout d'abord, quand le constructeur atteint la condition content, il vérifie quel est le conteneur ou la variable de référence, dans ce cas ?start, comme défini par l'attribut uri. La valeur calculée pour notre nouvelle correspondance potentielle est http://www.xulplanet.com/rdf/myphotos. Le constructeur regarde si cette ressource est susceptible d'être employée comme point de départ dans le gabarit. Lorsque c'est le cas, cette ressource est en cours d'utilisation, puisqu'elle est la valeur de l'attribut ref dans ces exemples. Ce serait également le cas pour n'importe quels points de départ dans la génération récursive. Si la variable calculée ?start était différente, nous n'aurions naturellement aucun changement à l'affichage car cette ressource ne serait pas en cours d'utilisation dans le gabarit.

Finalement, le constructeur traite les autres conditions après celle où nous en étions resté afin de remplir les variables restantes. Dans ce cas, il n'y a pas d'autres conditions, donc le constructeur accepte ce résultat comme nouvelle correspondance. Puisque toutes les variables ont été remplies, le corps d'action des règles peut être traité et un nouveau bloc de contenu peut être généré et inséré à l'affichage. Nous verrons dans une prochaine section comment le constructeur détermine où insérer le nouveau contenu. Cependant, vous verrez comment le constructeur de gabarits peut mettre à jour l'affichage lors de modifications sans devoir reconstruire tout le gabarit.

Lors de l'utilisation de la fonction Unassert, ou qu'une donnée soit supprimée de la source de données, un processus différent est utilisé. Dans ce cas, le constructeur étudie les résultats et détermine lequel a été supprimé. Lorsqu'il a généré au début les résultats, le constructeur a mémorisé des informations supplémentaires pour spécifier quelles parties du graphe étaient concernées. Ces informations l'aide à déterminer les résultats qui ne sont plus nécessaires.

Modifications RDF affectant une liaison

Souvent, un nouveau triplet créé dans la source de données n'affectera qu'une liaison bindings d'une règle de gabarit. Comme la section bindings d'une règle définit des conditions optionnelles, l'ajout ou la suppression de cette donnée RDF entraîne le remplissage d'un libellé par une valeur ou son effacement lorsqu'il s'agit d'un suppression d'un triplet RDF.

Comme décrit plutôt, le constructeur analyse en premier la partie conditions d'une règle pour voir si une modification s'est produite. Ensuite, la partie bindings est examinée. Cet examen s'effectue même si la partie conditions produit un nouveau résultat ou en supprime un, ou si le contenu n'est pas affecté puisqu'une liaison peut affecter n'importe quels résultats existants. Il est possible, par exemple, que toutes les lignes existantes soient affectées par un seul triplet ajouté à la source de données. Considérez la liaison suivante :

<binding subject="?start"
            predicate="http://www.xulplanet.com/rdf/categoryName"
            object="?name"/>

Cette liaison inclut un triplet pointant depuis la variable de départ utilisée dans nos exemples. La valeur de cette liaison sera la même pour chaque résultat, donc si le nom de la catégorie change, tous les résultats seront modifiés. Toutefois, le constructeur peut utiliser un processus bien plus simple pour recalculer les résultats. Au lieu de régénérer le contenu d'un résultat, il cherche simplement les valeurs des attributs qui incluent la variable ?name. Ces attributs sont simplement recalculés après substitution de la nouvelle valeur de ?name. Ce processus est répété pour chaque résultat affecté.

Lorsqu'un gabarit englobe plusieurs règles, le même processus est utilisé pour chaque règle. Comme lors de la génération initiale des résultats, seule la règle la plus prioritaire a besoin d'être appliquée. La seule complication supplémentaire à gérer avec les règles multiples est lorsque le résultat particulier d'une ressource membre correspond déjà à une règle et que le nouveau triplet correspond à une règle plus prioritaire. Comme la règle placée la plus en haut est prioritaire, le constructeur traite ce cas en supprimant d'abord l'ancien contenu avant d'ajouter le nouveau contenu.


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.