Pārlūkot izejas kodu

Ontology overhaul: move to graph-per-aspect pattern; use SPARQL update for bootstrap.

Stefano Cossu 6 gadi atpakaļ
vecāks
revīzija
e4cf372d43

+ 0 - 11
data/bootstrap/default_layout.nq

@@ -1,11 +0,0 @@
-# Bootstrap data set for default RDF layout.
-#
-# This needs to be in N-Quads format because of
-# https://github.com/RDFLib/rdflib/issues/436
-
-<info:fcsystem:root> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/ns/ldp#RDFSource> <info:fcgraph:main> .
-<info:fcsystem:root> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/ns/ldp#Container> <info:fcgraph:main> .
-<info:fcsystem:root> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/ns/ldp#BasicContainer> <info:fcgraph:main> .
-<info:fcsystem:root> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://fedora.info/definitions/v4/repository#RepositoryRoot> <info:fcgraph:main> .
-<info:fcsystem:root> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://fedora.info/definitions/v4/repository#Resource> <info:fcgraph:main> .
-<info:fcsystem:root> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://fedora.info/definitions/v4/repository#Container> <info:fcgraph:main> .

+ 0 - 11
data/bootstrap/default_layout.trig

@@ -1,11 +0,0 @@
-# Bootstrap data for simple RDF store layout.
-
-@prefix ldp: <http://www.w3.org/ns/ldp#> .
-@prefix fcrepo: <http://fedora.info/definitions/v4/repository#> .
-
-<info:fcgraph:main> {
-  <info:fcsystem:root>
-    a ldp:RDFSource , ldp:Container , ldp:BasicContainer ,
-      fcrepo:RepositoryRoot , fcrepo:Resource , fcrepo:Container ;
-    .
-}

+ 0 - 7
data/bootstrap/rsrc_centric_layout.nq

@@ -1,7 +0,0 @@
-<info:fcres/> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/ns/ldp#RDFSource> <info:fcsystem/__root__> .
-<info:fcres/> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/ns/ldp#Container> <info:fcsystem/__root__> .
-<info:fcres/> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/ns/ldp#BasicContainer> <info:fcsystem/__root__> .
-<info:fcres/> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://fedora.info/definitions/v4/repository#RepositoryRoot> <info:fcsystem/__root__> .
-<info:fcres/> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://fedora.info/definitions/v4/repository#Resource> <info:fcsystem/__root__> .
-<info:fcres/> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://fedora.info/definitions/v4/repository#Container> <info:fcsystem/__root__> .
-

+ 22 - 0
data/bootstrap/rsrc_centric_layout.sparql

@@ -0,0 +1,22 @@
+PREFIX dcterms: <http://purl.org/dc/terms/>
+PREFIX fcrepo: <http://fedora.info/definitions/v4/repository#>
+PREFIX foaf: <http://xmlns.com/foaf/0.1/>
+PREFIX ldp: <http://www.w3.org/ns/ldp#>
+
+INSERT DATA {
+  GRAPH <info:fcsystem/graph/userdata/_main/> {
+      <info:fcres/> dcterms:title "Repository Root" .
+  }
+
+  GRAPH <info:fcsystem/graph/admin/> {
+    <info:fcres/> a
+      fcrepo:RepositoryRoot , fcrepo:Resource , fcrepo:Container ,
+      ldp:Container , ldp:BasicContainer , ldp:RDFSource ;
+    .
+  }
+
+  GRAPH <info:fcsystem/meta> {
+    <info:fcsystem/graph/admin/> foaf:primaryTopic <info:fcres/> .
+    <info:fcsystem/graph/userdata/_main/> foaf:primaryTopic <info:fcres/> .
+  }
+}

+ 0 - 12
data/bootstrap/rsrc_centric_layout.trig

@@ -1,12 +0,0 @@
-PREFIX fcrepo: <http://fedora.info/definitions/v4/repository#>
-PREFIX ldp: <http://www.w3.org/ns/ldp#>
-
-<info:fcsystem/meta> {
-}
-
-<info:fcsystem/__root__> {
-    <info:fcres/> a
-        fcrepo:RepositoryRoot , fcrepo:Resource , fcrepo:Container ,
-        ldp:Container , ldp:BasicContainer , ldp:RDFSource ;
-    .
-}

+ 175 - 0
doc/examples/store_layouts/graph_per_aspect.trig

@@ -0,0 +1,175 @@
+# This layout follows the graph-per-aspect pattern
+# (http://patterns.dataincubator.org/book/graph-per-aspect.html).
+
+PREFIX dc: <http://purl.org/dc/elements/1.1/>
+PREFIX fcrepo: <http://fedora.info/definitions/v4/repository#>
+PREFIX fcsystem: <info:fcsystem/>
+PREFIX fcg: <info:fcsystem/graph/>
+PREFIX foaf: <http://xmlns.com/foaf/0.1/>
+PREFIX ldp: <http://www.w3.org/ns/ldp#>
+PREFIX ns: <http://example.edu/lakesuperior/ns#>
+PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
+
+# Admin data graphs.
+# Triples used by the application business logic are stored here.
+# These are a convenient way to get resource metadata (e.g. with a HEAD
+# request) without loading large graphs, e.g. ones with many children
+# or many user-provided properties.
+
+# System root.
+<info:fcsystem/graph/admin/> {
+  <info:fcres/> a
+    fcrepo:RepositoryRoot , fcrepo:Resource , fcrepo:Container ,
+    ldp:Container , ldp:BasicContainer , ldp:RDFSource ;
+  .
+}
+
+<info:fcsystem/graph/admin/a/b/c> {
+  <info:fcres/a/b/c> a fcrepo:Resource ;
+    # Timestamps are simplified for readability.
+    fcrepo:created "2017-11-23"^^xsd:date ;
+    fcrepo:lastModified "2017-11-27"^^xsd:date ;
+    fcrepo:hasVersion
+      <info:fcres/a/b/c;v1> , <info:fcres/a/b/c;v2> , <info:fcres/a/b/c;v3> ;
+    .
+}
+
+<info:fcsystem/graph/admin/a/b/c;v1> {
+  <info:fcres/a/b/c;v1> a fcrepo:Version ;
+    fcrepo:created "2017-11-23"^^xsd:date ;
+    fcrepo:lastModified "2017-11-23"^^xsd:date ;
+  .
+}
+
+<info:fcsystem/graph/admin/a/b/c;v2> {
+  <info:fcres/a/b/c;v2> a fcrepo:Version ;
+    fcrepo:created "2017-11-23"^^xsd:date ;
+    fcrepo:lastModified "2017-11-24"^^xsd:date ;
+  .
+}
+
+<info:fcsystem/graph/admin/a/b/c;v3> {
+  <info:fcres/a/b/c;v3> a fcrepo:Version ;
+    fcrepo:created "2017-11-23"^^xsd:date ;
+    fcrepo:lastModified "2017-11-25"^^xsd:date ;
+  .
+}
+
+# Pairtree information used to mimic hierarchical structures.
+<info:fcsystem/graph/admin/a> {
+  <info:fcres/a>
+    a ldp:Container , ldp:BasicContainer , ldp:Resource , ldp:RDFSSource ;
+    a fcrepo:Pairtree ;
+}
+
+<info:fcsystem/graph/admin/a/b> {
+  <info:fcres/a/b>
+    a ldp:Container , ldp:BasicContainer , ldp:Resource , ldp:RDFSSource ;
+    a fcrepo:Pairtree ;
+  .
+}
+
+# "Structural" data. This separation is made mostly to optimize retrieval of
+# information needed by the application business logic without having to
+# retrieve or filter out predicates with potentially large amounts of objects,
+# such as `ldp:contains`.
+<info:fcsystem/graph/structure/> {
+  <info:fcres/> ldp:contains <info:fcres/a/b/c> .
+  # fcsystem:contains is used to mimic path hierarchies. It does not coincide
+  # with LDP containment.
+  <info:fcres/> fcsystem:contains <info:fcres/a> .
+}
+
+<info:fcsystem/graph/structure/a> {
+  <info:fcres/a> fcsystem:contains <info:fcres/a/b> .
+}
+
+<info:fcsystem/graph/structure/a/b> {
+  <info:fcres/a/b> fcsystem:contains <info:fcres/a/b/c> .
+}
+
+# Resource graphs. These statements are user-provided and not used for any
+# application business logic.
+# Note that "fragments", i.e. hash URIs, are stored within the same graph.
+<info:fcsystem/graph/userdata/_main/a/b/c> {
+  <info:fcres/a/b/c> a ns:Book ;
+    fcrepo:hasParent <info:fcres/a> ;
+    dc:title "Moby Dick" ;
+    dc:creator "Herman Melville" ;
+    dc:subject "Fishing" ;
+    .
+  <info:fcres/a/b/c#chapter1> a ns:BookChapter ;
+    dc:title "Loomings." ;
+    .
+  <info:fcres/a/b/c#chapter2> a ns:BookChapter ;
+    dc:title "The Carpet-Bag." ;
+    .
+}
+
+# Previous states (versions) of a resource.
+<info:fcsystem/graph/userdata/_main/a/b/c;v1> {
+  <info:fcres/a/b/c;v1> a ns:Book ;
+    fcrepo:hasParent <info:fcres/> ;
+    dc:title "Moby Dick" ;
+    .
+}
+
+<info:fcsystem/graph/userdata/_main/a/b/c;v2> {
+  <info:fcres/a/b/c;v2> a ns:Book ;
+    fcrepo:hasParent <info:fcres/> ;
+    dc:title "Moby Dick" ;
+    dc:creator "Herman Melvil" ;
+    .
+}
+
+<info:fcsystem/graph/userdata/_main/a/b/c;v3> {
+  <info:fcres/a/b/c;v3> a ns:Book ;
+    fcrepo:hasParent <info:fcres/> ;
+    dc:title "Moby Dick" ;
+    dc:creator "Herman Melville" ;
+    .
+}
+
+# Metadata graph. This contains information about graphs and their
+# relationships.
+<info:fcsystem/graph/meta> {
+  # This may not be used by the application logic if we use naming
+  # conventions, but is still good LD practice.
+  <info:fcsystem/graph/admin/> foaf:primaryTopic <info:fcres/> .
+  <info:fcsystem/graph/userdata/_main/> foaf:primaryTopic <info:fcres/> .
+  <info:fcsystem/graph/structure/> foaf:primaryTopic <info:fcres/> .
+
+  <info:fcsystem/graph/admin/a/b/c> foaf:primaryTopic <info:fcres/a/b/c> .
+  <info:fcsystem/graph/userdata/_main/a/b/c> foaf:primaryTopic <info:fcres/a/b/c> .
+  # Pairtree information is kept in one graph so no metadata are needed.
+}
+
+# Historic version metadata. This is kept separate to optimize current resource
+# lookups.
+<info:fcsystem/graph/historic>  {
+  <info:fcsystem/graph/admin/a/b/c;v1>
+    foaf:primaryTopic <info:fcres/a/b/c;v1> ;
+    fcrepo:created "2017-11-24"^^xsd:date ;
+  .
+  <info:fcsystem/graph/admin/a/b/c;v2>
+    foaf:primaryTopic <info:fcres/a/b/c;v2> ;
+    fcrepo:created "2017-11-25"^^xsd:date ;
+  .
+  <info:fcsystem/graph/admin/a/b/c;v3>
+    foaf:primaryTopic <info:fcres/a/b/c;v3> ;
+    fcrepo:created "2017-11-26"^^xsd:date ;
+  .
+
+  <info:fcsystem/graph/userdata/_main/a/b/c;v1>
+    foaf:primaryTopic <info:fcres/a/b/c;v1> ;
+    fcrepo:created "2017-11-24"^^xsd:date ;
+  .
+  <info:fcsystem/graph/userdata/_main/a/b/c;v2>
+    foaf:primaryTopic <info:fcres/a/b/c;v2> ;
+    fcrepo:created "2017-11-25"^^xsd:date ;
+  .
+  <info:fcsystem/graph/userdata/_main/a/b/c;v3>
+    foaf:primaryTopic <info:fcres/a/b/c;v3> ;
+    fcrepo:created "2017-11-26"^^xsd:date ;
+  .
+}

+ 157 - 0
doc/examples/store_layouts/graph_per_resource+.trig

@@ -0,0 +1,157 @@
+# Resource-centric layout. This separates resources into separate named
+# graphs and follows the graph-per-resource pattern
+# (http://patterns.dataincubator.org/book/graph-per-resource.html). This aligns
+# quite well with the resource-centrism of LDP and of the SPARQL Graph Store
+# Protocol (https://www.w3.org/TR/sparql11-http-rdf-update/) which should be
+# used by the software implementation to minimize data structure translation.
+#
+# A graph identified by the resource UID is the current state of that resource.
+# Other resources (graphs) can be present representing various previous states
+# of the resource and are identified by the resource UUID with a `:` (colon)
+# and the version UID appended.
+# E.g. a resource with a UID of `a/b/c` will be internally stored within a
+# named graph `info:fcstate/a/b/c`; the subject will be `info:fcres/a/b/c`;
+# a previous version could be `info:fcstate/a/b/c:version1` and the publicly
+# exposed URL could be http://webroot.org/ldp/a/b/c`.
+#
+# The relationships between resources and thir versions and other metadata not
+# meant to be directly exposed by the LDP API are in one "metadata" graph.
+
+PREFIX dc: <http://purl.org/dc/elements/1.1/>
+PREFIX fcrepo: <http://fedora.info/definitions/v4/repository#>
+PREFIX fcsystem: <info:fcsystem/>
+PREFIX foaf: <http://xmlns.com/foaf/0.1/>
+PREFIX ldp: <http://www.w3.org/ns/ldp#>
+PREFIX ns: <http://example.edu/lakesuperior/ns#>
+PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
+
+# System root. It cannot be deleted.
+fcsystem:__root__ {
+    <info:fcres/> a
+        fcrepo:RepositoryRoot , fcrepo:Resource , fcrepo:Container ,
+        ldp:Container , ldp:BasicContainer , ldp:RDFSource ;
+    .
+}
+
+# Metadata graphs. Each of these is a "companion" of the content graph.
+# All triples that describe the stored resource state go here. Also triples
+# used by the application business logic are stored here.
+# These are a convenient way to get resource metadata (e.g. with a HEAD
+# request) without loading large graphs, e.g. ones with many children
+# or many user-provided properties.
+<info:fcmeta/a/b/c> {
+  <info:fcstate/a/b/c> a fcsystem:CurrentState ;
+    # This may be redundant if we use naming conventions, but still good LD practice.
+    fcsystem:stateOf <info:fcres/a/b/c> ;
+    fcsystem:hasVersion
+      <info:fcstate/a/b/c:v1> , <info:fcstate/a/b/c:v2> , <info:fcstate/a/b/c:v3> ;
+  .
+  <info:fcres/a/b/c> a fcrepo:Resource ;
+    # Timestamps are simplified for readability.
+    fcrepo:created "2017-11-23"^^xsd:date ;
+    fcrepo:lastModified "2017-11-27"^^xsd:date ;
+}
+
+<info:fcmeta/a/b/c:v1> {
+  <info:fcstate/a/b/c:v1>
+    fcsystem:stateOf <info:fcres/a/b/c:v1> ;
+    fcrepo:created "2017-11-24"^^xsd:date ;
+  .
+  <info:fcres/a/b/c:v1> a fcrepo:Version ;
+    fcrepo:created "2017-11-23"^^xsd:date ;
+    fcrepo:lastModified "2017-11-23"^^xsd:date ;
+  .
+}
+
+<info:fcmeta/a/b/c:v2> {
+  <info:fcstate/a/b/c:v2>
+    fcsystem:stateOf <info:fcres/a/b/c:v2> ;
+    a fcrepo:Version ;
+    fcrepo:created "2017-11-25"^^xsd:date ;
+  .
+  <info:fcres/a/b/c:v2> a fcrepo:Version ;
+    fcrepo:created "2017-11-23"^^xsd:date ;
+    fcrepo:lastModified "2017-11-24"^^xsd:date ;
+  .
+}
+
+<info:fcmeta/a/b/c:v3> {
+  <info:fcstate/a/b/c:v3>
+    fcsystem:stateOf <info:fcres/a/b/c:v3> ;
+    a fcrepo:Version ;
+    fcrepo:created "2017-11-26"^^xsd:date ;
+  .
+  <info:fcres/a/b/c:v3> a fcrepo:Version ;
+    fcrepo:created "2017-11-23"^^xsd:date ;
+    fcrepo:lastModified "2017-11-25"^^xsd:date ;
+  .
+}
+
+# Pairtree information not passed to the client but used to mimic
+# hierarchical structures.
+<info:fcmeta/a> {
+  <info:fcstate/a>
+    fcsystem:stateOf <info:fcres/a> ;
+  .
+  <info:fcres/a>
+    a ldp:Container , ldp:BasicContainer , ldp:Resource , ldp:RDFSSource ;
+    a fcrepo:Pairtree ;
+    # fcsystem:contains only applies to Pairtrees and is used to mimic path
+    # hierarchies.
+    fcsystem:contains <info:fcres/a/b> ;
+    ldp:contains <info:fcres/a/b/c> ;
+  .
+}
+
+<info:fcmeta/a/b> {
+  <info:fcstate/a/b>
+    fcsystem:currentStateOf <info:fcres/a/b> ;
+  .
+  <info:fcres/a/b>
+    a fcrepo:Pairtree ;
+    fcsystem:contains <info:fcres/a/b/c> ;
+  .
+
+}
+
+# Resource graph. These statements are user-provided and not used for any
+# application business logic.
+# Note that "fragments", i.e. hash URIs, are stored within the same graph.
+<info:fcstate/a/b/c> {
+  <info:fcres/a/b/c> a ns:Book ;
+    fcrepo:hasParent <info:fcres/a> ;
+    dc:title "Moby Dick" ;
+    dc:creator "Herman Melville" ;
+    dc:subject "Fishing" ;
+    .
+  <info:fcres/a/b/c#chapter1> a ns:BookChapter ;
+    dc:title "Loomings." ;
+    .
+  <info:fcres/a/b/c#chapter2> a ns:BookChapter ;
+    dc:title "The Carpet-Bag." ;
+    .
+}
+
+# Previous states (versions) of a resource.
+<info:fcstate/a/b/c:v1> {
+  <info:fcres/a/b/c> a ns:Book ;
+    fcrepo:hasParent <info:fcres/a> ;
+    dc:title "Moby Dick" ;
+    .
+}
+
+<info:fcstate/a/b/c:v2> {
+  <info:fcres/a/b/c> a ns:Book ;
+    fcrepo:hasParent <info:fcres/a> ;
+    dc:title "Moby Dick" ;
+    dc:creator "Herman Melvil" ;
+    .
+}
+
+<info:fcstate/a/b/c:v3> {
+  <info:fcres/a/b/c> a ns:Book ;
+    fcrepo:hasParent <info:fcres/a> ;
+    dc:title "Moby Dick" ;
+    dc:creator "Herman Melville" ;
+    .
+}

+ 0 - 0
doc/examples/store_layouts/resource_centric.trig → doc/examples/store_layouts/graph_per_resource.trig


+ 0 - 1
etc.skeleton/namespaces.yml

@@ -12,7 +12,6 @@ geo : http://www.w3.org/2003/01/geo/wgs84_pos#
 hw : http://projecthydra.org/works/models#
 oa : http://www.w3.org/ns/oa#
 ore : http://www.openarchives.org/ore/terms/
-pcdm : http://pcdm.org/models#
 rel : http://id.loc.gov/vocabulary/relators/
 skos : http://www.w3.org/2004/02/skos/core
 

+ 9 - 7
lakesuperior/dictionaries/namespaces.py

@@ -12,19 +12,21 @@ core_namespaces = {
     'dcterms' : rdflib.namespace.DCTERMS,
     'ebucore' : Namespace(
         'http://www.ebu.ch/metadata/ontologies/ebucore/ebucore#'),
-    'fcrepo' : Namespace('http://fedora.info/definitions/v4/repository#'),
+    'fcmeta' : Namespace('info:fcmeta/'),
     'fcrconfig' : Namespace('http://fedora.info/definitions/v4/config#'),
+    'fcrepo' : Namespace('http://fedora.info/definitions/v4/repository#'),
+    'fcadmin' : Namespace('info:fcsystem/graph/admin/'),
+    'fcres' : Namespace('info:fcres/'),
+    'fcmain' : Namespace('info:fcsystem/graph/userdata/_main/'),
+    'fcstruct' : Namespace('info:fcsystem/graph/structure/'),
+    'fcsystem' : Namespace('info:fcsystem/'),
     'iana' : Namespace('http://www.iana.org/assignments/relation/'),
     'ldp' : Namespace('http://www.w3.org/ns/ldp#'),
+    # This is used in the layout attribute router.
+    'pcdm': Namespace('http://pcdm.org/models#'),
     'premis' : Namespace('http://www.loc.gov/premis/rdf/v1#'),
     'rdf' : rdflib.namespace.RDF,
     'rdfs' : rdflib.namespace.RDFS,
-    # For info: vs. urn:, see https://tools.ietf.org/html/rfc4452#section-6.3
-    'fcres' : Namespace('info:fcres/'),
-    'fcmeta' : Namespace('info:fcmeta/'),
-    'fcstate' : Namespace('info:fcstate/'),
-    'fcstruct' : Namespace('info:fcstruct/'),
-    'fcsystem' : Namespace('info:fcsystem/'),
     'webac' : Namespace('http://www.w3.org/ns/auth/acl#'),
     'xml' : Namespace('http://www.w3.org/XML/1998/namespace'),
     'xsd' : rdflib.namespace.XSD,

+ 0 - 1
lakesuperior/dictionaries/srv_mgd_terms.py

@@ -12,7 +12,6 @@ srv_mgd_predicates = {
     nsc['fcrepo'].lastModified,
     nsc['fcrepo'].lastModifiedBy,
     nsc['fcrepo'].writable,
-    #nsc['fcsystem'].fragmentOf,
     nsc['iana'].describedBy,
     nsc['ldp'].contains,
     nsc['premis'].hasMessageDigest,

+ 1 - 2
lakesuperior/model/ldp_factory.py

@@ -38,8 +38,7 @@ class LdpFactory:
         @param uid UID of the instance.
         '''
         #__class__._logger.info('Retrieving stored resource: {}'.format(uid))
-        imr_urn = nsc['fcres'][uid] if uid else (
-                model.ldpr.ROOT_RSRC_URI)
+        imr_urn = nsc['fcres'][uid]
 
         rsrc_meta = current_app.rdfly.get_metadata(uid)
         #__class__._logger.debug('Extracted metadata: {}'.format(

+ 2 - 13
lakesuperior/model/ldpr.py

@@ -22,7 +22,6 @@ from lakesuperior.model.ldp_factory import LdpFactory
 
 
 ROOT_UID = ''
-ROOT_GRAPH_URI = nsc['fcsystem']['__root__']
 ROOT_RSRC_URI = nsc['fcres'][ROOT_UID]
 
 
@@ -142,8 +141,7 @@ class Ldpr(metaclass=ABCMeta):
         '''
         self.uid = g.tbox.uri_to_uuid(uid) \
                 if isinstance(uid, URIRef) else uid
-        self.urn = nsc['fcres'][uid] \
-                if self.uid else ROOT_RSRC_URI
+        self.urn = nsc['fcres'][uid]
         self.uri = g.tbox.uuid_to_uri(self.uid)
 
         self.rdfly = current_app.rdfly
@@ -341,7 +339,6 @@ class Ldpr(metaclass=ABCMeta):
         @return set(rdflib.term.URIRef)
         '''
         if not hasattr(self, '_types'):
-            #import pdb; pdb.set_trace()
             if len(self.metadata.graph):
                 metadata = self.metadata
             elif getattr(self, 'provided_imr', None) and \
@@ -671,12 +668,6 @@ class Ldpr(metaclass=ABCMeta):
         # Remove resource itself.
         self.rdfly.modify_rsrc(self.uid, {(self.urn, None, None)}, types=None)
 
-        ## Remove fragments.
-        #for frag_urn in imr.graph[
-        #        : nsc['fcsystem'].fragmentOf : self.urn]:
-        #    self.rdfly.modify_rsrc(
-        #            self.uid, {(frag_urn, None, None)}, types={})
-
         # Remove snapshots.
         for snap_urn in self.versions:
             remove_trp = {
@@ -895,9 +886,7 @@ class Ldpr(metaclass=ABCMeta):
           pairtree nodes are created for a/b and a/b/c.
         - If e is being created, the root node becomes container of e.
         '''
-        if self.urn == ROOT_RSRC_URI:
-            return
-        elif '/' in self.uid:
+        if '/' in self.uid:
             # Traverse up the hierarchy to find the parent.
             parent_uid = self._find_parent_or_create_pairtree()
         else:

+ 35 - 33
lakesuperior/store_layouts/ldp_rs/rsrc_centric_layout.py

@@ -18,7 +18,6 @@ from lakesuperior.dictionaries.namespaces import ns_mgr as nsm
 from lakesuperior.dictionaries.namespaces import ns_pfx_sparql
 from lakesuperior.exceptions import (InvalidResourceError, InvalidTripleError,
         ResourceNotExistsError, TombstoneError)
-from lakesuperior.model.ldpr import ROOT_UID, ROOT_GRAPH_URI, ROOT_RSRC_URI
 
 
 class RsrcCentricLayout:
@@ -54,10 +53,8 @@ class RsrcCentricLayout:
 
     _logger = logging.getLogger(__name__)
 
-    META_GRAPH_URI = nsc['fcsystem'].meta
-
     attr_map = {
-        nsc['fcmeta']: {
+        nsc['fcadmin']: {
             # List of server-managed predicates. Triples bearing one of these
             # predicates will go in the metadata graph.
             'p': {
@@ -92,10 +89,11 @@ class RsrcCentricLayout:
             },
         },
         nsc['fcstruct']: {
-            # These are placed in a separate graph for optimization purposees.
+            # These are placed in a separate graph for optimization purposes.
             'p': {
                 nsc['fcsystem'].contains,
                 nsc['ldp'].contains,
+                nsc['pcdm'].hasMember,
             }
         },
     }
@@ -128,7 +126,7 @@ class RsrcCentricLayout:
         It is a machine-friendly version of the static attribute `attr_map`
         which is formatted for human readability and to avoid repetition.
         The attributes not mapped here (usually user-provided triples with no
-        special meaning to the application) go to the `fcstate:` graph.
+        special meaning to the application) go to the `fcmain:` graph.
         '''
         if not hasattr(self, '_attr_routes'):
             self._attr_routes = {'p': {}, 't': {}}
@@ -149,9 +147,12 @@ class RsrcCentricLayout:
         self.ds.update('DROP SILENT ALL')
 
         self._logger.info('Initializing the graph store with system data.')
-        self.ds.default_context.parse(
-                source='data/bootstrap/rsrc_centric_layout.nq', format='nquads')
+        #self.ds.default_context.parse(
+        #        source='data/bootstrap/rsrc_centric_layout.nq', format='nquads')
+        with open('data/bootstrap/rsrc_centric_layout.sparql', 'r') as f:
+            self.ds.update(f.read())
 
+        self.ds.store.commit()
         self.ds.store.close()
 
 
@@ -173,9 +174,9 @@ class RsrcCentricLayout:
         #  }
         #}
         #''' if incl_inbound else ''
-        mg = ROOT_GRAPH_URI if uid == '' else nsc['fcmeta'][uid]
-        strg = ROOT_GRAPH_URI if uid == '' else nsc['fcstruct'][uid]
-        sg = self._state_uri(uid, ver_uid)
+        mg = self._admin_uri(uid, ver_uid)
+        strg = nsc['fcstruct'][uid]
+        sg = self._main_uri(uid, ver_uid)
 
         if incl_children:
             incl_child_qry = 'FROM {}'.format(strg.n3())
@@ -231,7 +232,7 @@ class RsrcCentricLayout:
         '''
         See base_rdf_layout.ask_rsrc_exists.
         '''
-        meta_gr = self.ds.graph(nsc['fcmeta'][uid])
+        meta_gr = self.ds.graph(self._admin_uri(uid))
         return bool(
                 meta_gr[nsc['fcres'][uid] : RDF.type : nsc['fcrepo'].Resource])
 
@@ -241,17 +242,29 @@ class RsrcCentricLayout:
         This is an optimized query to get everything the application needs to
         insert new contents, and nothing more.
         '''
-        gr = self.ds.graph(self._meta_uri(uid, ver_uid)) | Graph()
+        gr = self.ds.graph(self._admin_uri(uid, ver_uid)) | Graph()
 
         return Resource(gr, nsc['fcres'][uid])
 
 
+    def create_snapshot(self, uid, ver_uid):
+        '''
+        Create a version snapshot.
+        '''
+        state_gr = self.ds.graph(self._main_uri(uid))
+        state_ver_gr = self.ds.graph(self._main_uri(uid, ver_uid))
+        meta_gr = self.ds.graph(self._admin_uri(uid))
+        meta_ver_gr = self.ds.graph(self._admin_uri(uid, ver_uid))
+
+
+
+
     def get_version(self, uid, ver_uid):
         '''
         See base_rdf_layout.get_version.
         '''
         # @TODO
-        gr = self.ds.graph(self._state_uri(uid, ver_uid))
+        gr = self.ds.graph(self._main_uri(uid, ver_uid))
         return Resource(gr | Graph(), nsc['fcres'][uid])
 
 
@@ -259,10 +272,10 @@ class RsrcCentricLayout:
         '''
         Create a new resource or replace an existing one.
         '''
-        sg_uri = self._state_uri(uid)
-        mg_uri = ROOT_GRAPH_URI if uid == '' else nsc['fcmeta'][uid]
+        sg_uri = self._main_uri(uid)
+        mg_uri = self._admin_uri(uid)
         if ver_uid:
-            ver_uri = self._state_uri(uid, ver_uid)
+            ver_uri = self._main_uri(uid, ver_uid)
             drop_qry = 'MOVE SILENT {sg} TO {vg};\n'.format(
                     sg=sg_uri.n3(), vg=ver_uri.n3())
         else:
@@ -304,44 +317,33 @@ class RsrcCentricLayout:
 
     ## PROTECTED MEMBERS ##
 
-    def _state_uri(self, uid, ver_uid=None):
+    def _main_uri(self, uid, ver_uid=None):
         '''
         Convert a UID into a request URL to the graph store.
         '''
-        if not uid:
-            #raise InvalidResourceError(uid,
-            #        'Repository root does not accept user-defined properties.')
-            return ROOT_GRAPH_URI
-
         if ver_uid:
             uid += ':' + ver_uid
 
-        return nsc['fcstate'][uid]
+        return nsc['fcmain'][uid]
 
 
-    def _meta_uri(self, uid, ver_uid=None):
+    def _admin_uri(self, uid, ver_uid=None):
         '''
         Convert a UID into a request URL to the graph store.
         '''
-        if not uid:
-            return ROOT_GRAPH_URI
-
         if ver_uid:
             uid += ':' + ver_uid
 
-        return nsc['fcmeta'][uid]
+        return nsc['fcadmin'][uid]
 
 
     def _map_graph_uri(self, t, uid):
         '''
         Map a triple to a namespace prefix corresponding to a graph.
         '''
-        if not uid:
-            return ROOT_GRAPH_URI
-
         if t[1] in self.attr_routes['p'].keys():
             return self.attr_routes['p'][t[1]][uid]
         elif t[1] == RDF.type and t[2] in self.attr_routes['t'].keys():
             return self.attr_routes['t'][t[2]][uid]
         else:
-            return nsc['fcstate'][uid]
+            return nsc['fcmain'][uid]

+ 2 - 4
lakesuperior/toolbox.py

@@ -10,7 +10,7 @@ from rdflib import Graph
 from rdflib.term import URIRef, Variable
 
 from lakesuperior.dictionaries.namespaces import ns_collection as nsc
-from lakesuperior.model.ldpr import ROOT_GRAPH_URI, ROOT_RSRC_URI
+from lakesuperior.model.ldpr import ROOT_RSRC_URI
 
 
 class Toolbox:
@@ -52,9 +52,7 @@ class Toolbox:
 
         @return string
         '''
-        if uri == ROOT_GRAPH_URI or uri == ROOT_RSRC_URI:
-            return None
-        elif uri.startswith(nsc['fcres']):
+        if uri.startswith(nsc['fcres']):
             return str(uri).replace(nsc['fcres'], '')
         else:
             return str(uri).replace(g.webroot, '').strip('/')