Come descritto nella sezione precedente, Mozilla fornisce tre tipi di datasource. Queste sorgenti di base sono in-memory-datasource, xml-datasource e composite-datasource.
Queste saranno descritte in dettaglio in seguito. In più diverse
datasource sono formnite, usate per memorizzare dati particolare.
Per esempio Mozilla fornisce sorgenti dati per i bookmarks, cronologia,
motori di ricerca installati, cartelle di posta e così via.
Alcune di queste datasource sono in realtà basate su
questi tipi principali. Per esempio la sorgente bookmarks
è basata su in-memory-datasource.
Quando viene fatto un cambiamento ai bookmarks, finisce per chiamare la
sorgente in memoria per memorizzare i dati. Questo accade perché
la sorgente dati interna non ha limitazioni sul tipo di dati da
contenere. Comunque la sorgente dati bookmarks deve assicurarsi che i
dati inseriti sono validi nel contesto dei segnalibri. Altre sorgenti
di dati, come la cronologia, sono costruite intorno altre strutture
dati interne.
La in-memory-datasource mantiene tutti i
dati RDF in memoria. E' disegnata per essere efficiente nella
ricerca e nella modifica. Questo è il tipo di sorgente dati che
useresti per i tuoi dati che non sono caricati da un file RDF/XML.
La sorgente in memoria implementa tutti i metodi dell'interfaccia nsIRDFDataSource, come tutte le sorgenti. Implementa anche l'interfaccia nsIRDFInMemoryDataSource, che offre un solo metodo EnsureFastContainment. In genere non ti servirà chiamare questo metodo. E' usato internamente per ottimizzare la memorizzazione. Principalmente, è usato per assicurarsi che una risorsa particolare nella sorgente è memorizzata in maniera tale che l'accesso ad essa sia più veloce. Il prezzo da pagare è che viene usata più memoria. I contenitori RDF la impostano automaticamente quando hanno un gran numero di filgli, visto che altrimenti l'accesso sarebbe più lento.
La xml-datasource è usata per i dati caricati da un file RDF/XML. Questi files possono essere locali o remoti in un sito web. Queste datasource possono essere ricaricate e salvate. Caricare un file RDF/XML è semplice come chiamare il metodo GetDataSource del servizio RDF. Questo caricherà il file e lo parserizzerà in una datasource. La datasource xml-datasource è in realtà costruita intorno a in-memory-datasource. E' questa sorgente interna a contenere i dati.
Il file RDF/XML deve avere un content-type HTTP di tipo text/xml,
application/xml o
text/rdf. Mozilla non è in grado di supportare RDF/XML inviato come application/rdf+xml.
RDF/XML inviato come content-type diverso da quelli elencati sopra non
verrà caricato. Quando si caricano datasource con il
servizio RDF, dovresti sempre specificare l'URL assoluto del file
RDF/XML non un URL relativo.
Le datasource RDF/XML possono essere caricate da qualunque tipo di URL. Attualmente, solo quelle caricate da URL file:///
possono essere modificati con le API di RDF. Una soluzione possibile
per modificare l'origine di RDF è caricare l'RDF e aggiungere i
dati in una
in-memory-datasource.
Il metodo GetDataSource carica il file
in maniera asincrona. Questo significa che la sorgente dati può
non essere caricata quando il metodo ritorna. Un caricamento sincrono
può essere fatto con il metodo GetDataSourceBlocking.
Questo metodo attenderà finché i dati non sono stati
caricati, prima di ritornare. Nota che questo sembrerà bloccare
l'interfaccia utente mentre si aspetta il caricamento della sorgente
dati.
Può essere utile usare il caricamento asincrono e comunque
determinare se la sorgente dati è stata caricata. La sorgente xml-datasource implementa un'interfaccia nsIRDFXMLSink
che è un'interfaccia di aiuto chiamata durante il caricamento e
il parsing RDF. Per la maggior parte è usata internamente, ma
l'interfaccia può essere usata per aggiungere un osservatore che
verrà avvisato quando l'RDF/XML è stato caricato. Ecco un
esempio:
var observer = {
onBeginLoad : function(sink){},
onInterrupt : function(sink){},
onResume : function(sink){},
onError : function(sink,status,msg){},
onEndLoad : function(sink){
sink.removeXMLSinkObserver(this);
sink.QueryInterface(Components.interfaces.nsIRDFDataSource);
}
};
var ds=rdfService.GetDataSource("http://www.xulplanet.com/tutorials/xultu/animals.rdf");
ds.QueryInterface(Components.interfaces.nsIRDFXMLSink);
ds.addXMLSinkObserver(observer);
Il metodo addXMLSinkObserver è usato per aggiungere un osservatore durante il processo di caricamento. L'osservatore ha bisogno di implementare l'interfaccia nsIRDFXMLSinkObserver che nell'esempio è impleementata da un oggetto Javascript. Di particolare interesse è il metodo onEndLoad, che sarà chiamato quando i dati sono caricati completametne. In questo metodo, abbiamo l'opportunità di rimuovere l'osservatore usando il metodo removeXMLSinkObserver. E' qui che dovresti aggiungere il codice da eseguire quando la sorgente è stata caricata. Nota che la sorgente può essere direttamente lanciata da e verso nsIRDFXMLSink.
La xml-datasource implementa anche l'interfaccia nsIRDFRemoteDataSource.
Nonostante il nome, questa interfaccia è disponibile sia per
files locali che per conenuto remoto. Questa interfaccia contiene
metodi per ricaricare e salvare la sorgente dati. Sarà discusso
in seguito su come salvare le sorgenti dati.
Per ricaricare una sorgente dati, chiama il metodo Refresh.
Prende un argomento, se bloccare durante il caricamento o no. Se
è impostato a true, il metodo aspetterà fino a
caricamento avvenuto prima di ritornare. Se è falso
ritornerà immediatamente. L'esempio seguente prenderà una
sorgente e la ricaricherà.
var ds=rdfService.GetDataSource("file:///main/data/animals.rdf");
ds.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
ds.Refresh(true);
Puoi anche parserizzare RDF/XML da una stringa. Questo implica la creazione di un parser RDF/XML e fornire una datasource in cui mettere i risultati. La sorgente xml-datasource ha la capacità di parserizzare all'interno di se stessa, ma il parser può aggiungere dati a qualunque sorgente modificabile. Il parser usa i metodi di modifica dell'interfaccia nsIRDFDataSource, così tutto quello che è richiesto è una sorgente di dati che gestisca in maniera appropriata questi metodi.
L'interfaccia nsIRDFXMLParser
ha un metodo che può essere usato per parserizzare una stringa
di RDF/XML. In questo esempio, parserizziamo i dati in una in-memory-datasource.
function parseRDFString(str, url)
{
var memoryDS = Components.classes["@mozilla.org/rdf/datasource;1?name=in-memory-datasource"]
.createInstance(Components.interfaces.nsIRDFDataSource);
var ios=Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
baseUri=ios.newURI(url,null,null);
var parser=Components.classes["@mozilla.org/rdf/xml-parser;1"]
.createInstance(Components.interfaces.nsIRDFXMLParser);
parser.parseString(memoryDS,baseUri,str);
return memoryDS;
}
Questa funzione può essere divisa in tre parti. La prima parte crea una nuova sorgente dati vuota. La seconda parte crea un oggetto URI, dal momento che tutte le sorgenti devono avere un URI. Dal momento che stiamo parserizzando da una stringa, non abbiamo un URI preciso, così dovremmo farne uno. Ogni riferimento relativo nel RDF/XML sarà risolto relativamente a questo URI. Infine, il parser RDF/XML viene creato e noi parserizziamo il contenuto usando il metodo parseString. Questo metodo ha bisogno di tre argomenti, la datasource in cui parserizzare, l'URI di base nella seconda parte e la stringa da parserizzare.
Se passi un xml-datasource al metodo parseString, i nuovi dati verranno aggiunti a qualunque cosa sia già nella sorgente. Potresti usare questo metodo per costruire una grande sorgente dati da una piccola.
Quando i dati sono rimpiazzati in un xml-datasource,
vengono fatte delle manovre speciali per assicurare che i nuovi dati
cancellino dati se esistono già. Al momento della
parserizzazione, vengono tenuti prima le dichiarazioni RDF nella
sorgente dati. Quando una nuova dichiarazione viene aggiunta e
giè esiste, viene tenuta la vecchia dichiarazione. Se la nuova
dichiarazione non esiste, viene aggiunta. Finita la parserizzazione, le
dichiarazioni che esistevano nei vecchi dati, ma non nei nuovi sono
eliminate. Questo processo insolito viene usato per assicurare che gli
oggetti risorsa non siano cancellati e ricreati, il che potrebbe avere
effetti collaterali indesiderati. Questo processo richiede l'uso
dell'interfaccia nsIRDFPurgeableDataSource. Questa interfaccia interna è fatta per essere usata solo per questo scopo (tu non dovresti usarla).
Il metodo parseString funziona in maniera sincrona. C'è anche un metodo parseAsync
che può essere usato in maniera asincrona. Prende la sorgente di
dati e l'URI di base e ritorna un oggetto che implemente l'interfaccia nsIStreamListener.
Avrai bisogno di chiamare i metodi di questa interfaccia e passarle
RDF. Questo è un pò strano, perciò probabilmente
non userai questo metodo.
Una sorgente composite-datasource contiene
una lista di altre sorgenti. Quando ricerchi in questa sorgente,
farà una ricerca di tutte le datasource a turno,
finché una non risponde, che è quella che verrà
ritornata. Se cerchi di cambiare una composite-datasource,
chiamerà tutte le datasource in lista, finché una
di loro non accetta il cambiamento. Per i metodi di ricerca che
ritornano solo un valore, o per i metodi di modifica, solo una sorgente
ritornerà un valore o verrà cambiata. Una volta trovata
una sorgente con il risultato, o che accetta il cambiamento,
nelle altre non verrà effettuata una ricerca. Per i metodi di
ricerca che ritornano valori multipli, sono ritornati tutti i possibili
valori in tutte le datasource. Naturalmente, puoi ancora
ricercare e modificare separatamente le datasource.
Dal momento che il composite-datasource contiene una lista di datasource, può essere usato come se le datasource che contiene fossero combinate in una sorgente sola. Questa combinazione a volte viene detta aggregazione. Ogni datasource può essere agginta a una datasource composita, o a sorgenti RDF/XML, a sorgenti incorporate in Mozilla e anche altre sorgenti composite.
La datasource aggiunta a un elemento XUL quando usa un attributo datasources è una sorgente di tipo composite-datasource, così puoi aggiungere e rimuovere datasource in ogni momento.
Una composite-datasource implementa l'interfaccia nsIRDFCompositeDataSource,
che è utilizzata per rimuovere le datasource. Per
aggiungere una sorgente usa il metodo AddDataSource. Prende un
argomento, cioè la sorgente da aggiungere. Dovresti passare la
datasource stessa, non l'URI. Tieni presente che questo metodo
non controlla l'unicità. Se la datasource è
già inclusa nella lista, sarà aggiunta di nuovo. Il
codice seguente è un esempio per aggiungere una datasource:
var rdfService = Components.classes["@mozilla.org/rdf/rdf-service;1"].
getService(Components.interfaces.nsIRDFService);
var compositeDS = rdfService.GetDataSource("rdf:composite-datasource");
var ds1=rdfService.GetDataSource("http://www.xulplanet.com/tutorials/xultu/animals.rdf");
var ds2=rdfService.GetDataSource("rdf:bookmarks");
compositeDS.QueryInterface(Components.interfaces.nsIRDFCompositeDataSource);
compositeDS.AddDataSource(ds1);
compositeDS.AddDataSource(ds2);
Quando fai una ricerca nella datasource composita,
richiederà dati nella prima sorgente, in questo caso una
sorgente RDF/XML, seguita dalla seconda, la sorgente bookmarks,
finché non trova un risultato.
Il metodo GetDataSources può
essere usato per ottenere una lista delle sorgenti dati usate dalla
composita. Questo metodo ritorna u elenco che può essere usato
per spostarsi tra le sorgenti dati. Saranno ritornate nell'ordine in
cui sono state aggiunge. Nel seguente esempio, recuperiamo le sorgenti
di dati che sono state allegate ad un elemento XUL. Queste sono le
sorgenti che il template userà.
var compositeDS = xulElement.database;
var list = compositeDS.GetDataSources();
while (list.hasMoreElements()){
var ds = list.getNext();
if (ds instanceof Components.interfaces.nsIRDFDataSource){
...
}
}
L'interfaccia composite datasource ha due proprietà. La prima, allowNegativeAssertions
è usata per indicare come la sorgente gestisce le asserzioni
negative. Una asserzione negativa è una dichiarazione RDF che la
datasource considera falsa. Se l'attributo è true,
il valore predefinito, la sorgente supporterà asserzioni
negative. Se una datasource contiene una normale dichiarazione
vera e un'altra contiene la stessa dichiarazione, ma falsa, si
cancelleranno a vicenda. Se la proprietà allowNegativeAssertions
è falsa, non verranno ricercate dichiarazioni negative. Questo
è più veloce, perciò forse vorrai cambiare il
valore se sai che le sorgenti non contengono dichiarazioni
negative. La maggior parte delle sorgenti non le ha.
La proprietà coalesceDuplicateArcs
indica se la sorgente composita deve rimuovere i duplicati se vengono
fatte delle ricerche. Se questo valore è vero, e viene fatta una
ricerca, i valori duplicati saranno rimossi. Questo è utile
quando si combinano diverse datasource che contengono gli stessi
dati. Se questa proprietà è falsa, verranno ritornati dei
duplicati, e le ricerche saranno leggermente più veloci.
La sorgente dati rdf:local-store è
inclusa con Mozilla ed è usata per contenere le informazioni di
stato come la posizione della finestra, quali colonne degli alberi sono
visualizzate, e quali toolbars e sidebars sono mostrate. Queste
informazioni sono salvate allìuscita di Mozilla, e sono
riapplicate automaticamente al contenuto XUL quando la finestra
appropriata aperta di nuovo. Questo processo è spiegato in
dettaglio nella sezione su Dati Persistenti.
Per riassumere, l'attributo persist può essere usato in un
elemento XUL per salvare dati nel Local Store e poterli ripristinare
quando la finestra viene aperta di nuovo. Anche se il local store
contiene generalmente informazioni sullo stato XUL, può in
realtà metterci dentro qualsiasi cosa.
Il local store è salvato in un file RDF/XML
'localstore.rdf' nella tua cartella profile di Mozilla. Dato che
è un file RDF/XML, puoi aprirlo in un editor di testo e vedere
le informazioni che contiene. E' possibile modificare il file, anche se
non è raccomandato, a meno che tu non sappia che cosa stai
cambiando.
Il local-store è sempre incluso in una applicazione XUL chrome quando usi un attributo datasources
su un elemento. Il local store è sempre la prima sorgente di
dati usata. Naturalmente, niente ti vieta di rimuoverlo usando il
metodo RemoveDataSource.
Questo significa che è possibile aggiungere informazioni al local store che scavalcano le informazioni delle altre datasource usate nel template. Per esempio, se aggiungi le giuste informazioni nel file localstore.rdf, puoi farlo apparire come se l'utente avesse un bookmark aggiuntivo, visto che mozilla usa un template per mostrare la lista dei segnalibri all'utente. Chiaramente, il bookmark non funzionerà correttamente finché non si trova nella sorgente dati bookmarks.