Écrit par Neil Deakin.
Traduit par René-Luc D'Hont (13/06/2005).
Page originale :
http://www.xulplanet.com/tutorials/mozsdk/rdfcontain.php
Cette section décrit comment interroger et manipuler des conteneurs RDF.
Puisque les conteneurs RDF, c.-à-d., les types Seq, Bag et Alt, sont souvent manipulés, Mozilla fournit quelques méthodes additionnelles pour manipuler ces types. Ces méthodes sont contenues dans deux interfaces, nsIRDFContainer et nsIRDFContainerUtils. Il est important de noter que ces interfaces sont seulement des méthodes de convenance qui enveloppent les méthodes de datasource déjà expliquées dans les sections précédentes. Il est possible d'effectuer toutes ces opérations sans employer les classes de conteneur du tout. Ceci pourrait être utile pour faire encore plus de choses spécifiques avec des conteneurs. Pour la plupart des objectifs, cependant, les conteneurs fournissent une manière maniable de manipuler des conteneurs de RDF. Ces conteneurs RDF sont simplement des emballages autour des méthodes de datasource ce qui signifie que tous les datasources supportent des conteneurs, bien que tous les datasources ne les emploient pas pour n'importe quoi. Tous les observateurs RDF attachés au datasource recevront des avis au sujet des changements fondamentaux que le conteneur fait.
L'interface nsIRDFconteneur
est employée pour contenir un
conteneur RDF. Vous pouvez employer cette interface pour interroger,
ajouter et supprimer des enfants du conteneur. Cette interface est utile
puisque l'indexation des enfants est manipulée pour vous. Pour en créer
un, employez le code suivant:
var container = Components.classes["@mozilla.org/rdf/container;1"].
createInstance(Components.interfaces.nsIRDFContainer);
Le code ci-dessus créera un conteneur RDF non initialisé. Son initialisation est décrite ci-dessous.
Le composant du conteneur RDF (nsIRDFconteneur) devrait
être créé comme instance avec createInstance
pas comme service. Il y a un certain nombre de sources et d'exemples qui
emploient inexactement getService
au lieu
de cela.
L'interface nsIRDFconteneurUtils
a quelques méthodes de
service commodes pour que créer des conteneurs et une façon de vérifier
si une ressource est un conteneur ou pas. Cet objet est un service,
ainsi il devrait être créé avec getService
.
var rdfContainerUtils = Components.classes["@mozilla.org/rdf/container-utils;1"].
getService(Components.interfaces.nsIRDFContainerUtils);
Il y a deux manières d'initialiser un objet de conteneur RDF. D'abord,
appeler la méthode Init
de l'interface
nsIRDFconteneur
. Cette méthode prend une ressource et
initialise le conteneur en utilisant cette ressource. Dans ce cas-ci,
la ressource doit déjà être un conteneur. Si une ressource n'est pas
un conteneur, la méthode Init
renverra
une exception.
var folderRes = rdfService.GetResource("http://www.example.com/folder/simonesbirthday");
var container = Components.classes["@mozilla.org/rdf/container;1"].
createInstance(Components.interfaces.nsIRDFContainer);
try {
container.Init(photosDS, folderRes);
}
catch (ex){}
Dans cet exemple, le conteneur est initialisé à une ressource donnée.
Les deux arguments de la méthode Init
sont
respectivement le datasource et la ressource. Nous devons envelopper
l'appel dans un try-catch bloc au cas où la ressource ne serait pas un
conteneur RDF. Si vous êtes sûr qu'elle le sera, vous n'avez pas besoin
d'exécuter ce contrôle.
La deuxième manière d'initialiser un objet de conteneur RDF est d'en
créer un neuf. Cette méthode transformera une ressource existante en
conteneur. Vous devriez employer cette méthode pour créer de nouveaux
conteneurs. Ceci comporte l'utilisation de trois méthodes dans
l'interface nsIRDFconteneurUtils
, MakeSeq
, MakeBag
et MakeAlt
. Ce que vous allez employer
dépend du type de conteneur que vous voulez créer. Par exemple, la
méthode MakeSeq
transformera une ressource
en Seq. Rappelez-vous, ces conteneurs RDF sont des emballages justes
autour d'autres méthodes de datasource. Il est possible d'employer des
méthodes de datasource pour transformer une ressource en un conteneur
RDF.
var folderRes = rdfService.GetResource("http://www.example.com/folder/simonesbirthday");
var rdfContainerUtils = Components.classes["@mozilla.org/rdf/container-utils;1"].
createInstance(Components.interfaces.nsIRDFContainerUtils);
var container = rdfContainerUtils.MakeSeq(photosDS, folderRes);
La méthode MakeSeq
prend le datasource et
la ressource comme arguments comme avec la méthode Init
du conteneur RDF. Cette méthode renvoie un
nouvel objet conteneur déjà initialisé aux valeurs appropriées. Si la
ressource est déjà un conteneur, les trois méthodes Make renvoient juste
le conteneur existant. Elles ne la recréent pas ni ne commutent pas d'un
type de conteneur à l'autre. Ceci signifie qu'il est possible de créer
et obtenir les conteneurs existants en utilisant seulement les méthodes
Make.
Vous pouvez vérifier si une ressource est un conteneur ou pas en
employant est les méthodes de l'interface nsIRDFconteneurUtils
.
Spécifiquement, IsSeq
vérifie si une
ressource est un Seq, IsBag
vérifie si
une ressource est un Bag, IsAlt
vérifie
si une ressource est un Alt, et IsContainer
vérifie si une ressource est n'importe quel type de conteneur. Chacune
des quatre méthodes renvoie vrai ou faux.
Vous pouvez découvrir quelles ressources sont des enfants d'un conteneur
en employant la méthode GetElements
pour
un conteneur. Comme d'autres méthodes d'interrogation de RDF, il renvoie
une énumération qui peut être employée pour réitérer les enfants du
conteneur. Ils seront retournés dans l'ordre, bien que pour un Bag,
cet ordre n'est pas prévus pour être significatifs.
var ratingProp = rdfService.GetResource("http://www.example.com/rdfns/rating");
var threeProp = rdfService.GetLiteral("3");
var children = container.GetElements();
while (children.hasMoreElements()){
var child = children.getNext();
if (child instanceof Components.interfaces.nsIRDFResource){
photosDS.Assert(child, ratingProp, threeProp, true);
}
}
Ce code réitère pour tous les enfants d'un certain conteneur. Pour chaque enfant, il ajoute un triplet en le plaçant en position 3.
Une méthode additionnelle de conteneur est GetCount
qui peut être employé pour obtenir le nombre d'enfants dans le conteneur sans devoir réitérer un conteneur. En fait, ce n'est pas tout à fait vrai. Il renvoie réellement l'index du dernier enfant du conteneur. Rappelez-vous que tous les index ne sont pas employés dans un conteneur et certains peuvent être employés plusieurs fois. Si vous voulez juste vérifier si un conteneur a des enfants, employez la méthode IsEmpty
de l'interface nsIRDFconteneurUtils
. Cette méthode renverra vrai ou faux.
Vous pouvez souhaiter rechercher un enfant spécifique dans un conteneur,
identifié par son index. Rappel de la section sur le modèle RDF que les conteneurs RDF mettent en
référence des enfants en utilisant des triplets avec des prédicats
comme _ 1, _ 2, et ainsi de suite. Ceci rend assez facile la recherche
d'un enfant spécifique juste en employant GetTarget
sans employer les classes de conteneur.
En fait, les classes de conteneur ne contiennent pas de méthode telle que
GetChild pour rechercher des enfants.
var kidsRes = rdfService.GetResource("http://www.xulplanet.com/rdf/people/KarensKids");
var twoRes = rdfService.GetResource("http://www.w3.org/1999/02/22-rdf-syntax-ns#_2");
var child = datasource.GetTarget(kidsRes, twoRes, true);
L'exemple ci-dessus peut être employé pour rechercher le deuxième enfant
d'un conteneur. En utilisant l'exemple de Karen des sections précédentes,
il retournera le deuxième enfant de Karen. Cette technique n'est différente
d'aucune autre propriété de recherche d'une ressource. L'interface
nsIRDFconteneurUtils
nous fournit une méthode de convenance
pour créer des ressources indexées cependant sous forme d'une méthode
IndexToOrdinalResource. Par exemple, nous pourrions rechercher la
ressource '2' en utilisant l'exemple suivant à la place:
var twoRes = rdfContainerUtils.IndexToOrdinalResource(2);
Ceci peut rendre le code plus lisible. Il y a également une méthode
semblable OrdinalResourceToIndex
pour le
faire d'une autre manière et rechercher l'index de nombre entier d'une
ressource. Naturellement cette méthode échouera sur les ressources
non-ordinales. Vous pouvez vérifier si une ressource est une ressource
ordinale avec la méthode IsOrdinalProperty
.
Notez que des index dans l'API RDF commencent toujours par 1, non 0.
Vous pouvez déterminer l'index d'un enfant dans un conteneur en
employant la méthode de conteneur IndexOf
.
Cette méthode renverra l'index de nombre entier de l'enfant dans le
conteneur. Si l'enfant n'est pas dans le conteneur, la méthode retournera
-1. Ceci signifie que vous pouvez également employer cette méthode pour
vérifier si un enfant existe dans le parent. Il y a une méthode semblable,
la méthode indexOf
de l'interface
nsIRDFconteneurUtils
qui fait la même chose sauf que vous
n'avez pas besoin de créer un objet conteneur RDF d'abord. Notez bien
la différence au cas où entre les deux formes. L'exemple suivant
détermine la position de Sandra dans la liste des enfants de Karen.
var kidsRes = rdfService.GetResource("http://www.xulplanet.com/rdf/people/KarensKids");
var sandraRes = rdfService.GetResource("http://www.xulplanet.com/rdf/people/Sandra");
var idx = rdfContainerUtils.indexOf(datasource,kidsRes,sandraRes);
Vous pouvez souhaiter déterminer ce qu'est le parent d'un enfant, ou déterminer le conteneur d'une ressource qui est à l'intérieur de celui-ci. Les classes de conteneur RDF ne fournissent pas de méthode pour faire ceci. Une manière possible de déterminer le conteneur pour un enfant est la suivante:
var rdfContainerUtils = Components.classes["@mozilla.org/rdf/container-utils;1"].
getService(Components.interfaces.nsIRDFContainerUtils);
var sandraRes = rdfService.GetResource("http://www.xulplanet.com/rdf/people/Sandra");
var parent = null;
var arcsIn = datasource.ArcLabelsIn(sandraRes);
while (arcsIn.hasMoreElements()){
var arc = arcsIn.getNext();
if (arc instanceof Components.interfaces.nsIRDFResource){
if (rdfContainerUtils.IsOrdinalProperty(arc)){
parent = datasource.GetSource(arc, sandraRes, true);
break;
}
}
}
Ce code réitère tout les prédicats (arcs) qui se dirige vers la
ressource 'Sandra'. Cette liste de prédicats peut inclure un certain
nombre de choses. Cependant, si le prédicat est une ressource ordinale,
nous savons que c'est un enfant d'une autre ressource. Nous pouvons
employer la méthode GetSource
pour déterminer
le parent. Rappelez-vous qu'il est possible qu'une ressource soit
immédiatement dans plusieurs conteneurs. Cet exemple suppose que l'enfant
aura seulement un parent. Si vous voulez trouver tous les parents, au
lieu de cela vous devrez employer GetSources
et récupérez une liste.
Ajouter et enlever des enfants d'un conteneur est simple. Il y a
plusieurs méthodes de l'interface nsIRDFconteneur
qui
peuvent être employées pour ajouter et enlever des enfants.
var kidsRes = rdfService.GetResource("http://www.xulplanet.com/rdf/people/KarensKids");
var christaRes = rdfService.GetResource("http://www.xulplanet.com/rdf/people/Christa");
var container = Components.classes["@mozilla.org/rdf/container;1"].
createInstance(Components.interfaces.nsIRDFContainer);
try {
container.Init(datasource, kidsRes);
container.AppendElement(christaRes);
}
catch (ex){}
Les méthodes de modification de conteneurs RDF ne vérifient pas pour
voir si l'enfant est déjà dans le conteneur ou pas. Cela signifie que vous
pouvez ajouter un enfant plusieur fois. La méthode InsertElementAt
peut être employée pour insérer
un enfant à un index spécifique.
container.InsertElementAt(christaRes,2,true);
Cette méthode prend trois arguments. Le premier argument est la ressource d'enfant à ajouter. La seconde est la position en nombre entier pour placer l'enfant. Le troisième argument indique si il faut renuméroter les index des autres enfants pour s'adapter au nouvel enfant. Rappelez-vous que les index sont les ressources justes du prédicat avec une convention de numérotation et qu'il peut y avoir plusieurs enfants avec le même index. Si vous passez true pour le troisième argument, les enfants restants dans la liste seront renumérotés pour s'adapter au nouvel enfant. Dans l'exemple ci-dessus, le nouvel enfant sera ajouté à la deuxième position. L'enfant déjà à la deuxième position aura son index ajusté à trois, le troisième enfant sera déplacé à la quatrième position, et ainsi de suite. Si ce dernier argument est faux, les index ne sont pas renumérotés. Ceci signifierait qu'il y aurait deux enfants en deuxième position dans l'exemple ci-dessus, en supposant qu'il en existait déjà un.
Le processus renumérotant peut maintenir le cas où plusieurs des index doivent être renumérotés avec déjà plusieurs enfants avec cet index. Par exemple, s'il y avait trois ressources d'enfant à l'index 3, chacun des trois serait déplacé à l'index 4. Ceux à l'index 4 seraient déplacés à l'index 5, et ainsi de suite. Si le datasource met en application l'interface nsIRDFPropagatableDataSource, les avis de changement sont mis hors service tandis que la renumérotation est exécutée afin d'éviter un bon nombre de faux avis. Seulement l'affirmation provoquée par la ressource insérée sera envoyée aux observateurs.
Pour enlever un enfant, employez les méthodes RemoveElement
ou RemoveElementAt
. La première méthode enlève un
enfant en donnant sa ressource, alors que la deuxième méthode enlève un
enfant en donnant son index.
container.RemoveElement(christaRes,true);
container.RemoveElementAt(2,true);
En supposant que la ressource ai été insérée comme dans l'exemple
précédent, les deux méthodes feront la même chose. La première enlève
l'enfant donné par sa ressource. Cette méthode déterminera l'index
lui-même. La deuxième méthode enlèvera un élément à un index spécifique.
À la différence de la méthode RemoveElement
,
la méthode RemoveElementAt
renverra
l'élément enlevé comme noeud RDF. S'il y a des enfants multiples à
l'index, la méthode RemoveElementAt
enlèvera
seulement un d'eux.
Ces deux méthodes de suppression prennent également un deuxième argument
qui indique si il faut renuméroter les autres enfants après la suppression
de l'enfant, et ceci fonctionne pareillement à la méthode InsertElementAt
.
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.