Datasource RDF

Le sorgenti dati RDF

Mozilla memorizza le informazioni RDF in qualcosa chiamato datasource. Ogni datasource contiene una serie di triple RDF. Puoi fare una ricerca delle triple nelle sorgenti di dati con diversi metodi. Questo ti permette di navigare nel grafico RDF o determinare i dati contenuti nella datasource. Alcune sorgenti di dati sono modificabili, così si possono aggiungere o rimuovere triple dalla datasource. Puoi usare le sorgenti di dati indipendentemente l'una dall'altra, oppure puoi combinarle in ciò che viene detto datasource composita. La datasource composita è un gruppo di sorgenti di dati RDF

Generalmente, ogni datasource contiene dati relazionati in qualche modo. Per esempio, Mozilla usa una datasource bookmarks che contiene informazioni sui segnalibri. Mozilla usa diverse sorgenti di dati, che contengono informazioni e se stai costruendo un'estenzione per Mozilla, dovresti usare queste sorgenti di dati. Comunque, puoi anche creare le tue sorgenti di dati. Mozilla supporta anche il parsing di files RDF/XML in sorgenti di dati.

Tutte le sorgenti di dati implementano l'interfaccia nsIRDFdatasource. Questa interfaccia offre metodi per ricercare e modificare le informazioni nella datasource. Queste sono le più comuni sorgenti di dati offerte da Mozilla che potresti usare:

datasource
Descrizione
in-memory-datasource Questo tipo di datasource tiene le triple RDF in memoria. Molte delle altre sorgenti di dati sono basate su questa datasource. Questo tipo di sorgente può essere modificata.
xml-datasource Questa datasource contiene le triple lette da un file RDF/XML. Può tenere traccia del file da cui è stata caricata e salvare le modifiche nel file originale. Questa sorgente supporta anche i files RDF/XML caricati da un URL remoto, anche se questi non possono essere modificati o salvati. Tutte le sorgenti XML implementano l'interfaccia nsIRDFRemotedatasource, anche quelle caricate da files locali.
composite-datasource Contiene un insieme di altre sorgenti. Quando fai una ricerca in questa datasource, ricercherai in una sorgente alla volta. Allo stesso modo, le modifiche si propagheranno ad ogni sorgente, finché una di loro accetta il cambiamento. Queste sorgenti implementano l'interfaccia nsIRDFCompositedatasource

Ci sono molte altri sorgenti di dati, ma queste contengono i dati specifici per le applicazioni Mozilla

Ottenere sorgenti di dati RDF

Mozilla usa un servizio RDF che è responsabile dell'acquisizione di sorgenti di dati RDF. Il servizio ritorna anche altri oggetti riguardanti RDF come oggetti risorsa e letterale. Le  sorgenti di dati sono identificate da un URI. Se usi un URI, questo risulterà in genere nella creazione di una datasource xml che caricherà RDF/XML da quell'URI.

Mozilla offre alcune sorgenti dati addizionali, che possono essere recuperate usando un URI che inizia con 'rdf:'. Per esempio, l'URI rdf:history  ritornerà la sorgente dati history che contiene dati relativi alla cronologia delle pagine visitate. Quando chiedi una sorgente dati di questo tipo, cioè una sorgente con un URI che inizia con 'rdf:', Mozilla cercherà un componente che gestisca quella sorgente. Trova questo componente prendendo la parte di URI dopo il prefisso e la concatena alla stringa @mozilla.org/rdf/datasource;1?name= per formare il nome di un componente. Per esempio l'URI rdf:bookmarks, produrrà il componente @mozilla.org/rdf/datasource;1?name=bookmarks.

Tutte le sorgenti di dati funzionano in questo modo. Se crei un'estensione usando questa nomenclatura, sarai in grado di recuperare la sorgente dati usando il servizio RDF. Puoi anche creare la sorgente dati in un template impostando l'URI su un attributo di sorgente dati di un elemento. Le sorgenti di dati 'rdf:' hanno in genere una gestione speciale dei metodi delle sorgenti di dati, o memorizzano i dati in maniera diversa. Per esempio, la sorgente dati history memorizza i dati in un formato diverso e usa del codice per circondare i dati così che possano essere usate le API RDF per cercare i dati. La sorgente dati bookmarks memorizza i dati in un formato proprietario, ma usa una in-memory-datasource per tenere i dati quando caricata.

Il servizio RDF ha due metodi per recuperare le sorgenti dati. Il primo metodo, GetDataSource è usato per caricare una sorgente dati in maniera asincrona. Questa funzione può ritornare prima che la sorgente dati sia completamente caricata, anche se i dati già caricati saranno subito disponibili. Le sorgenti dati 'rdf:' sono in genere disponibili subito, visto che il browser ne farà già uso. Inoltre, le sorgenti 'rdf:' faranno subito tutte le inizializzazioni. Questo significa che il metodo GetDataSource è adatto a caricare questo tipo di sorgenti di dati. Dovresti usare questo metodo per caricare file RDF/XML remoti, in modo da poterli caricare in background. Più tardi vedremo un metodo per capire se il caricamento è completo.

Il secondo metodo, GetDataSourceBlocking preleva una datasource e aspetta che sia caricata. Questo metodo può essere usato per files locali RDF/XML. Questo metodo ritornerà non appena la datasource è stata caricata e parserizzata. Questo metodo per ora non funziona su files remoti.

Entrambe i metodi prendono un argomento singolo, l' URI  della sorgente dati da caricare ed entrambe ritornano la sorgente dati. Nel caso della funzione GetDataSource, la sorgente dati è ritornata, ma può non contenere ancora dati. Ecco alcuni esempi delle funzioni

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

var historyDS = rdfService.GetDataSource("rdf:history");

var fileDS = rdfService.GetDataSourceBlocking("file:///somedir/somefile.rdf");

Prima, otteniamo il servizio RDF. Dal momento che è un servizio, usiamo getService invece di createInstance. La linea successiva carica la datasource history usando la funzione  GetDataSource. Infine, carichiamo un file RDF/XML usando la funzione GetDataSourceBlocking, che può essere modificato immediatamente. Ognuna delle sorgenti di dati caricate implementa l'interfaccia nsIRDFDataSource.

Per le sorgenti di dati 'rdf:', GetDataSource e GetDataSourceBlocking creano la nuova datasource come servizio. Questo significa che può esistere solo una copia della sorgente dati alla volta. Fai attenzione a questo quando implementi le tue sorgenti dati. Se vuoi che sia creata una sorgente dati differente ogni volta, avrai bisogno di creare il componente nella normale maniera XPCOM, con il metodo createInstance. Per esempio, per creare una nuova in-memory-datasource (sorgente dati in memoria), fai così:

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

Questo è necessario perché non volevi usare ogni volta gli stessi dati in memoria.

Il servizio RDF tiene in memoria ("cache") le sorgenti di dati che sono state caricate. Questo significa che quando tu provi a richiamare lo stesso URI usando le funzioni GetDataSource o GetDataSourceBlocking, il servizio RDF ritornerà lo stesso oggetto. Questo evita di creare e caricare continuamente la stessa sorgente dati ogni volta che la si richiede. Inoltre, significa che puoi chiamare il servizio RDF per la stessa sorgente dati diverse volte e ottenere sempre lo stesso oggetto.

Tecnicamente, la precedente descrizione non dice esattamente come lavora la cache. Quando viene chiamata la funzione GetDataSource o GetDataSourceBlocking, queste funzioni guardano nella cache del server RDF per cercare sorgenti dati già caricate. Se l'URI viene trovato, viene caricata quella sorgente dati. Se l'URI non è trovato, viene creata una nuova sorgente dati del tipo appropriato, come descritto sopra. Il servizio RDF non aggiunge comunque in cache le sorgenti dati appena create. Questa è responsabilità della sorgente dati stessa, che deve chiamare il metodo RegisterDataSource del servizio RDF. Se la sorgente dati non chiama mai questo metodo, non apparirà mai in cache.

Questo creerà una nuova datasource ogni volta. Le altre sorgenti chiameranno RegisterDataSource così che non venga creato un nuovo oggetto ogni volta. Quando RegisterDataSource è chiamato, il servizio RDF richiama l'URI della datasource e la memorizza nella cache. Nota che è possibile per una datasource ritornare un URI diverso da quello con cui è stata creata, che può permettere possibilità interessanti. La datasource xml, chiama il metodo RegisterDataSource, ma l'URL sarà l'URL del file RDF/XML. Una datasource può chiamare il metodo RegisterDataSource in ogni momento, così è possibile inserire una sorgente dati in cache subito prima.

Per rimuovere le sorgenti dati dalla cache si usa il corrispettivo metodo UnregisterDataSource. Questo in genere viene chiamato dal distruttore della sorgente dati, cioè quando la sorgente dati viene cancellata. Una sorgente dati viene cancellata quando non esistono più riferimenti nei suoi confronti. Quando è cancellata, la sorgente dati dovrebbe deregistrarsi con il servizio RDF e sarà rimossa dalla cache. Quando l'URL viene chiesto di nuovo, la sorgente dati avrà bisogno di essere ricreata. Anche se è possibile rimuovere una datasource dal servizio RDF in ogni momento usando UnRegisterDataSource, la sorgente e i suoi dati continueranno ad esistere finché ci saranno dei riferimenti nei suoi confronti.

Come funzionano le sorgenti dati nei templates XUL

Gli elementi XUL posson avere una sorgente dati associata. Ogni elemento XUL in un documento XUL può avere una sorgente dati, inoltre per altri tipi di elementi inseriti in un documento XUL è possibile avere delle sorgenti dati. Gli elementi che non sono in un documento XUL non possono usare i templates. La sorgente dati associatao con un elemento può essere recuperata chiamando il valore della proprietà database dell'elemento. Il database è sempre una sorgente dati composita (composite-datasource). che contiene un certo numero di sorgenti RDF. Può avere qualsiasi numero di sorgenti dati, anche nessuna, e il set di sorgenti può essere modificato usando i metodi dell'interfaccia nsIRDFCompositeDataSource.

La maggior parte degli elementi non avranno una sorgente dati associata, così la proprietà database sara di tipo null.  Puoi indicare che vuoi che un elemento abbia un database aggiungendo l'attributo datasources all'elemento. Il valore di questo attributo sovrebbe essere una lista di URI delle sorgenti di dati che devono essere aggiunte al database, con gli elementi separati da spazi. Mentre puoi cambiare le sorgenti dati usando i metodi dell'interfaccia nsIRDFCompositeDataSource, l'attributo datasources rappresenta solo la sorgente dati iniziali da usare. Cambiare il valore dell'attributo non cambia le sorgenti dati nel database.

Per esempio nell'esempio sotto, sono assegnate due sorgenti, così che esse siano associate all'elemento tree.

<tree datasources="rdf:bookmarks animals.rdf">

Questo farà concatenare una sorgente dati composita all'albero che contiene le due sorgenti dati specificate. La prima sorgente dati è rdf:bookmarks, che è la sorgente dati usata da Mozilla per memorizzare i bookmarks. La seconda sorgente è trattata come l'URI di un file XML/RDF, in questo caso il path è relativo al file XUL.

In questo esempio, la sorgente dati bookmarks sarebbe usata solo se il codice ha privilegi, il che significa che sta funzionando su un'applicazione chrome. Codice senza privilegi non sarà in grado di accedere alla sorgente dati bookmarks.

Un'ulteriore differenza tra codice con e senza privilegi è che per il codice con privilegi, la sorgente dati rdf:local-store è sempre inclusa nella lista delle sorgenti dati, senza necessità di essere specificata. Questa sorgente è normalmente usata per memorizzare dati riguardo a informazioni come le dimensioni delle finestre, le barre degli strumenti, la dimensione delle colonne dei Tree, e così via. Questo significa che il database nell'esempio di sopra avrà tre sorgenti dati, local store, bookmarks e animals.rdf. Codice senza privilegi che gira da un sito remoto non include questa sorgente dati, perché contiene informazioni sull'utente.

Una volta che un database è stato applicato a un elemento, non è rimosso finché il documento non è distrutto, che avviene quando l'utente va su un'altra pagina o chiude la finestra. Perciò, rimuovendo un elemento e riaggiungendolo al documento farà mantenere lo stesso database. Se un elemento, con un attributo datasource, che non era prima nel documento, viene inserito, per questo elemento verrà creato un nuovo database.

In genere si usa un template dentro l'elemento con un database, anche se non è sempre necessario. Il template deve essere o un elemento template, che è figlio diretto dell'elemento con l'attributo datasources, oppure ci si deve riferire ad esso tramite l'attributo template. Nel secondo caso, il valore dell'attributo dovrebbe essere il valore dell'attributo id in un elemento template da qualche parte nel documento. Questo permetter di usare un singolo template in diversi posti, anche se non accade spesso di doverlo fare.

Un costruttore di template sarà usato per costruire il contenuto reale dal template.  Userà il template per costruire nuovi nodi DOM che saranno inseriti nel documento. Se i dati in una datasource associata con un elemento cambiano, il costruttore di template rigenererà i dati, aggiungendo, rimuovendo o cambiando il contenuto se necessario. Il costruttore di template gestisce questo registrandosi come observer della sorgente dati, così da poter essere avvisato nei cambiamenti.

La ricostruzione automatica del contenuto del template avviene solo in due situazioni. La prima è quando la sorgente RDF sottostante cambia. Quando l'RDF cambia, il costruttore di template verrà avvisato del cambiamento. Il costruttore di template ricostruirà le parti modificate, ma non quelle che non hanno subito modifiche. Questa ricostruzione automatica avviene ogni volta che si realizza un'operazione Assert, Unassert o Change. Ma non con un'operazione Move. Il costruttore di template ricostruirà anche automaticamente dopo un'operazione batch quando viene chiamato un metodo onEndUpdateBatch.

La seconda situazione che provocherà una ricostruzione automatica del contenuto del template è quando viene cambiato un attributo ref sull'elemeto esterno del database. Questo farà sì che venga ricostruito l'intero contenuto. Il valore deve essere cambiato a un valore differente. Impostare l'attributo ref allo stesso valore non provocherà una ricostruzione. Fai attenzione a questo, visto che che le versioni precedenti di Mozilla effettuavano una ricostruzione anche quando veniva reimpostato lo stesso valore.

Tutte le altre modifiche non provocano una ricostruzione. Più precisamente, aggiungere o rimuovere sorgenti dati, cambiare l'attributo datasources o modificare il contenuto del template non provocano una ricostruzione automatica. Se sei in dubbio, fai una ricostruzione manuale.

La ricostruzione manuale può essere fatta chiamando il metodo rebuild del costruttore di template. Tutti gli elementi XUL hanno una proprietà builder che è un riferimento al costruttore di template associato all'elemento. Se non c'è un costruttore di template associato con un elemento, il valore di questa proprietà sarà null. Il seguente codice è usato per ricostruire i contenuti da un template, dove element è l'elemento con il database:

element.builder.rebuild();

Cambiare l'attributo ref ha lo stesso effetto che farebbe se il codice sottostante venisse riscostruito manualmente, eccetto che per ricostruire il contenuto viene usato il nuovo nodo radice.

Il costruttore di template creerà pigramente il contenuto. Questo significa che creerà realmente il contenuto solo quando è necessario visualizzarlo. Per esempio, il contenuto di un menu non è generato finché il menu non viene aperto. Allo stesso modo, i nodi figli di un tree non sono creati finché non viene aperto il nodo genitore. Bisogna fare attenzione a questo quando si esamina un albero DOM.