Dettagli sulle sorgenti dati RDF

Sorgenti dati di base

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.

Sorgenti dati in memoria

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.

Sorgente XML

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);

Parserizzare RDF/XML da una stringa

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.

Composite Datasources

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.

Puoi rimuovere una datasource dalla sorgente composita, chiamando il metodo RemoveDataSource. Ha bisogno di un argomento, cioè la datasource da rimuovere.

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.

Local Store

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.