Last modified 5 years ago Last modified on 10/26/11 11:23:17

Implémentation du Métamodèle dans Fedora

Hiérarchie d'objets prévues dans FEDORA

  • Objet fedora: Ressources
    • 0..n Datastream: BLOB importés (si les métadonnées sont moissonées). Il peut y avoir plus d'un format moissoné.
    • Datastream: NativeRecord (Ne sera pas utilisé dans un premier temps) Voir Architecture/MetaModel
    • Datastream: MetadataView La représentation "native" de COMET. Voir Architecture/MetaModel
    • Datastream: 0..n HarvestingInfo?. En théorie, plus d'un harvester peut moissoner une même ressource.
  • Objet fedora: Ontology
    • Datastream: Un datastream pour chaque terme
  • Objet fedora: Identité

Gestion des identifiants

Ressources
Identifiants OAI (dans la mesure du possible) Si impossible, composer des identifiants OAI à partir du dépôt moissoné.
Identités
Identifiants purement locaux.
Vocabulaires
Gestion considérablement plus complexe. Dans bien des cas, il y aura plus d'un identifiant pour le même vocabulaire, ainsi que des cas particulier. Ex: Vocabulaires du Lom de base.

Il faudra en même temps respecter les règles de Fedora pour les identifiants

Relations

D'abord, dans Fedora:

  • RELS-EXT permet d'exprimer des triples ayant pout sujet l'objet dans son ensemble. (sauf DC, dans son propre Stream.)
  • RELS-INT permet d'exprimer des triples ayant pout sujet l'un des streams de l'objet.

On ne peut rien exprimer sur un autre sujet.

On veut pouvoir exprimer les relations permettant de déduire la MetadataView. Chaque MetadataRecord, qu'il vienne de l'extérieur (NativeRecord) ou de nos données, devrait avoir son stream dans l'objet. S'il vient de l'extérieur, on peut l'exprimer avec dc:source dans RELS-INT.

Pour chaque record, on aura :

  • Un lien fedora:IsMetadataFor vers l'objet.

Nos objets ont tous au moins un stream qui est la vue. Pour la vue, on aura:

  • Un lien fedora:IsMetadataFor vers l'objet. (<MetadataView [stream interne]> <vue de> <MetadataRecord [url externe et/ou stream interne]>)
  • Un lien fedora:derivedFrom vers les records utilisés.
  • un lien comete:policy vers la PriorityPolicy. (<MetadataView [stream interne]> <calculé d'après> <PriorityPolicy [objet Fedora distinct]>)

(Nous pourrions spécifier que comete:policy est une spécialisation d'un lien fedora?)

Nous pourrions conserver le lien comete:corrects entre les fiches de correction nous appartenant et les fiches venant de l'extérieur. (<MetadataView [stream interne]> <vue de> <!CorrectionMetadataRecord [stream interne]>)

Le ContentModel de COMETE devrait spécifier une méthode permettant de produire une vue à partir d'une ressource (ayant des MetadataRecord associés) et d'une PriorityPolicy.

version 1: Une fonction donne la vue à partir d'une politique de priorité. La rendre explicite même si c'est initialement un singleton non-éditable. Nous devrions nous servir de la MessagingQueue de Fedora (qui a un topic pour les updates) pour produire une vue partant de la PriorityPolicy canonique du système (singleton...) chaque fois qu'une ressource est modifiée. Cette vue serait stockée dans son stream propre et indexée. On peut l'obtenir par une requête

?m <fedora:isMetadataFor> ?o . ?m <comete:policy> <repository policy object>

TODO

Notes pratiques

  • Dans server/config/fedora-users.xml il y a un paramètre:

<user name="fedoraIntCallUser" password="changeme"> Attention, c'est l'utilisateur pour ingester une ressource, et non l'usager admin.

QUESTIONS

  • Devrions-nous décomposer la vue de façon à ce que les triples pertinents soient dans RELS-EXT, RELS-INT et DC, de façon appropriée?
    • Dans le cas contraire, peut-on s'assurer que les triples contenus dans la vue sont stockés dans la base RDF?
    • La même question vaut même si nous décomposons: Certains triples ne pourront entrer dans aucun des streams canoniques
    • Stocker les triples dans les streams canoniques empêche d'avoir plusieurs vues.
  • De quelles ontologies parle-t-on dans la hierarchie des objets prévus dans Fedora ? les vocabulaires ? Si oui n'est-ce pas suffisant d'avoir l'ontologie indexée dans Mulgara plutôt qu'autant de Datastreams qu'il y a de termes? Est-ce que ça revient au même ?
    • Question subsidiaire: est-il facile d'ajouter des triples à Mulgara à partir des APIs de Fedora? Peut-on désigner un stream autre que les streams canoniques comme contenant du RDF?
  • La gestion globale de Harvesting se faisant dans ORI-OAI, doit-on avoir un (ou des) datastream relatifs au moissonage. ORI gère les relations entre fiches et leurs provenances.
  • Pour les identités ? Si on utilise foaf, on le gère comme le Datastream DC ? Soit un digital object représentant John Dow avec un Datastream FOAF de type inner XML qui contient le xml FOAF ? Parce que ici aussi, comme pour les onto, on pourrait imaginer un datastream pour chaque élement pertinent (nom, prénom, adresses emails) R (MAP): Ici, je crois qu'on peut utiliser une combinaison DC/RELS-EXT dans le DO.
  • Pour les ressources, avoir un identifiant local et un lien RDF vers l'identifiant OAI literal n'est-il pas une meilleure solution ? (permet du filtrage SPARQL.. en plus c'est déjà codé :-)
  • Est-il judicieux d'utiliser le lien fedora:hasEquivalent pour les equivalences de vocabulaires ?
  • Pour le DS metadataView, est-ce un DS dynamique calculé par un service ? Si oui peux-tu fournir un cas de figure ? R (MAP): Je voyais des vues dynamiques dans un futur lointain, si nous avions des policy par usager. Mais pas à court terme. La solution proposée me semble convenable.

Essais Sparql et iTQL

La construction du métamodèle devrait idéalement pouvoir être exprimée en SPARQL+Update, ou, à défaut (si l'extension update n'est pas disponible, comme pour Mulgara) soit en ajoutant les triples à partir d'une requête sparql, voire en iTQL. Chaque MetadataRecord? moissonné doit être exprimé dans un stream Fedora propre, et doit être instancié dans un graphe propre. Il n'est pas nécessaire de stocker ces graphes; beaucoup de bases de triples permettent de créer une base transiente, en mémoire. Dans le cas particulier de Fedora, il serait même concevable de traduire les données LOM, ILOX, etc. en RDF en temps réel, à partir d'un Resolver ad hoc. Mais pour l'instant, supposons quand même un graphe par MetadataRecord?. L'URI du graphe pourrait être mis en rapport avec l'URI du stream Fedora correspondant. On aurait donc un graphe "méta" pour la ressource, qui permettrait de désigner les autres graphes; celui-ci peut être extrait mécaniquement des RELS-INT; un graphe transient par MetadataRecord?, et un graphe résultant, stocké.

J'ai fait quelques essais pour exprimer tout ça à l'aide de sparql et itql. Ce n'est évidemment pas complet, mais ça montre au moins que c'est possible. D'abord, en iTQL, les données de base pour l'essai:

alias <http://purl.org/dc/elements/1.1/> as dc;   # on voudra notre propre namespace, mais j'ai fait des essais avec DC
alias <rmi://localhost:8080/server1#> as triplestore;   # Mulgara
alias <rmi://localhost:8080/server1#ressource12345_> as tstoreRsrc; # préfixe pour les calculs sur une ressource donnée
alias <rmi://localhost/fedora/ressource123456> as fedoraRsrc;  # préfixe Fedora pour la même ressource
alias <http://example.com/> as example;   # URI pour la ressource, qui peut différer de ses repositories d'origine
alias <http://cometeproject.org/ns/meta/> as meta;  # Notre namespace de méta-données 
alias <http://cometeproject.org/ns/policy/> as policy;  # Notre namespace de policy
alias <http://www.w3.org/1999/02/22-rdf-syntax-ns#> as rdf;

create <triplestore:policy>;
# Donner priorité à un repository
insert <http://repository1Uri> <policy:priority> <http://repository2Uri> into <triplestore:policy>;

# Les espaces de données liés à une ressource
create <tstoreRsrc:meta>;
create <tstoreRsrc:s1>;
create <tstoreRsrc:s2>;
create <tstoreRsrc:result>;

# Les métadonnées sur les MetadataRecords, extraites de RELS-EXT et/ou RELS-INT
insert <tstoreRsrc:s1> <rdf:InstanceOf> <meta:metadata_record> into <tstoreRsrc:meta>;
insert <tstoreRsrc:s1> <meta:from_stream> <fedoraRsrc:s1> into <tstoreRsrc:meta>;
insert <tstoreRsrc:s1> <meta:from_repository> <http://repository1Uri> into <tstoreRsrc:meta>;

insert <tstoreRsrc:s2> <rdf:InstanceOf> <meta:metadata_record> into <tstoreRsrc:meta>;
insert <tstoreRsrc:s2> <meta:from_stream> <fedoraRsrc:s2> into <tstoreRsrc:meta>;
insert <tstoreRsrc:s2> <meta:from_repository> <http://repository2Uri> into <tstoreRsrc:meta>;


# Des données d'exemples, qui devraient couvrir les principaux cas
insert <example:example> <dc:title> 'premier titre'@fr into <tstoreRsrc:s1>;
insert <example:example> <dc:format> 'text/html' into <tstoreRsrc:s1>;
insert <example:example> <dc:author> 'Una Uteure' into <tstoreRsrc:s1>;

insert <example:example> <dc:title> 'un autre titre'@fr into <tstoreRsrc:s2>;
insert <example:example> <dc:format> 'text/xhtml' into <tstoreRsrc:s2>;
insert <example:example> <dc:author> 'Una Uteure' into <tstoreRsrc:s2>;
insert <example:example> <dc:subject> 'tout' into <tstoreRsrc:s2>;

Une policy plus élaborée permettrait des distinctions supplémentaires sur les propriétés où on veut faire un ajout vs celles où on a remplacement absolu. Il serait également souhaitable d'exprimer la transitivité des préférences. Disons qu'il s'agit d'un premier test.

Pour obtenir les triples de S1, ainsi que ceux de S2 qui ne sont pas masqués par S1, il suffit de faire une différence, ce qui s'exprime facilement en iTQL. (La requête fonctionnerait avec plus de deux MetadataRecords?, tant qu'ils sont bien définis dans tstoreRsrc:meta.)

insert
select $s $p $o from <tstoreRsrc:result> where 
	$g <rdf:Instanceof> <meta:metadata_record> in <tstoreRsrc:meta>
	and $s $p $o in $g
minus ($h <rdf:Instanceof> <meta:metadata_record> in <tstoreRsrc:meta>
	and $s $p $o2 in $h
	and $h <rdf:Instanceof> <meta:metadata_record> in <tstoreRsrc:meta>
	and $g <meta:from_repository> $gr in <tstoreRsrc:meta>
	and $h <meta:from_repository> $hr in <tstoreRsrc:meta>
	and $hr <policy:priority> $gr in <triplestore:policy>)
into <tstoreRsrc:result>;

Noter que le minus n'élimine pas les données identiques entre les deux graphes, parce qu'il semble être calculé sur le quadruplet <spog> et non sur le triplet <spo>, assez heureusement.

La même requête est plus délicate en Sparql, qui n'a pas vraiment de négation. Il faut faire un join optionnel, puis exiger qu'il ait échoué.

(je n'ai pas encore encodé en sparql-update, puisque je fais mes tests avec mulgara pour l'instant)

PREFIX dc: <http://purl.org/dc/elements/1.1/>
PREFIX triplestore: <rmi://localhost:8080/server1#>
PREFIX tstoreRsrc: <rmi://localhost:8080/server1#ressource12345_>
PREFIX fedoraRsrc: <rmi://localhost/fedora/ressource123456>
PREFIX example: <http://example.com/>
PREFIX meta: <http://cometeproject.org/ns/meta/>
PREFIX policy: <http://cometeproject.org/ns/policy/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>

select distinct ?s ?p ?o
where {
GRAPH <tstoreRsrc:meta> {?g <rdf:Instanceof> <meta:metadata_record>} .
GRAPH ?g {?s ?p ?o} .
OPTIONAL {
	GRAPH <tstoreRsrc:meta> {
		?h <rdf:Instanceof> <meta:metadata_record> .
		?g <meta:from_repository> ?gr .
		?h <meta:from_repository> ?hr
	} .
	GRAPH <triplestore:policy> {?hr <policy:priority> ?gr} .
	GRAPH ?h {?s ?p ?o2}
} .
FILTER (!BOUND(?h))
}

Dans les deux cas, on obtient correctement

<example:example> <dc:title> 'premier titre'@fr
<example:example> <dc:format> 'text/html'
<example:example> <dc:author> 'Una Uteure'
<example:example> <dc:subject> 'tout'

0.9.8 © 2008-2011 Agilo Software all rights reserved (this page was served in: 0.68947 sec.)