Przeglądaj źródła

Replace all RDFLib Resource instances with Graph instances.

Stefano Cossu 7 lat temu
rodzic
commit
3bf850efc1

+ 1 - 1
data/bootstrap/rsrc_centric_layout.sparql

@@ -11,7 +11,7 @@ INSERT DATA {
   GRAPH <info:fcsystem/graph/admin/> {
     <info:fcres/> a
       fcrepo:RepositoryRoot , fcrepo:Resource , fcrepo:Container ,
-      ldp:Container , ldp:BasicContainer , ldp:RDFSource ;
+      ldp:Resource , ldp:Container , ldp:BasicContainer , ldp:RDFSource ;
       fcrepo:created "$timestamp"^^xsd:dateTime ;
       fcrepo:lastModified "$timestamp"^^xsd:dateTime ;
     .

+ 12 - 11
lakesuperior/model/ldp_factory.py

@@ -36,7 +36,7 @@ class LdpFactory:
             raise InvalidResourceError(uid)
         if rdfly.ask_rsrc_exists(uid):
             raise ResourceExistsError(uid)
-        rsrc = Ldpc(uid, provided_imr=Resource(Graph(), nsc['fcres'][uid]))
+        rsrc = Ldpc(uid, provided_imr=Graph(identifier=nsc['fcres'][uid]))
 
         return rsrc
 
@@ -59,8 +59,8 @@ class LdpFactory:
 
         rsrc_meta = rdfly.get_metadata(uid)
         #logger.debug('Extracted metadata: {}'.format(
-        #        pformat(set(rsrc_meta.graph))))
-        rdf_types = set(rsrc_meta.graph[imr_urn : RDF.type])
+        #        pformat(set(rsrc_meta))))
+        rdf_types = set(rsrc_meta[imr_urn : RDF.type])
 
         if LDP_NR_TYPE in rdf_types:
             logger.info('Resource is a LDP-NR.')
@@ -97,19 +97,20 @@ class LdpFactory:
             # Create empty LDPC.
             logger.info('No data received in request. '
                     'Creating empty container.')
-            inst = Ldpc(uid, provided_imr=Resource(Graph(), uri), **kwargs)
+            inst = Ldpc(uid, provided_imr=Graph(identifier=uri), **kwargs)
         elif __class__.is_rdf_parsable(mimetype):
             # Create container and populate it with provided RDF data.
             input_rdf = stream.read()
-            gr = Graph().parse(data=input_rdf, format=mimetype, publicID=uri)
+            imr = Graph(identifier=uri).parse(
+                    data=input_rdf, format=mimetype, publicID=uri)
             #logger.debug('Provided graph: {}'.format(
             #        pformat(set(provided_gr))))
-            provided_imr = Resource(gr, uri)
+            provided_imr = imr
 
             # Determine whether it is a basic, direct or indirect container.
-            if Ldpr.MBR_RSRC_URI in gr.predicates() and \
-                    Ldpr.MBR_REL_URI in gr.predicates():
-                if Ldpr.INS_CNT_REL_URI in gr.predicates():
+            if Ldpr.MBR_RSRC_URI in imr.predicates() and \
+                    Ldpr.MBR_REL_URI in imr.predicates():
+                if Ldpr.INS_CNT_REL_URI in imr.predicates():
                     cls = LdpIc
                 else:
                     cls = LdpDc
@@ -123,13 +124,13 @@ class LdpFactory:
                 raise IncompatibleLdpTypeError(uid, mimetype)
 
             if kwargs.get('handling', 'strict') != 'none':
-                inst._check_mgd_terms(inst.provided_imr.graph)
+                inst._check_mgd_terms(inst.provided_imr)
 
         else:
             # Create a LDP-NR and equip it with the binary file provided.
             # The IMR can also be provided for additional metadata.
             if not provided_imr:
-                provided_imr = Resource(Graph(), uri)
+                provided_imr = Graph(identifier=uri)
             inst = LdpNr(uid, stream=stream, mimetype=mimetype,
                     provided_imr=provided_imr, **kwargs)
 

+ 13 - 10
lakesuperior/model/ldp_nr.py

@@ -45,7 +45,7 @@ class LdpNr(Ldpr):
 
         if not mimetype:
             self.mimetype = (
-                    self.metadata.value(nsc['ebucore'].hasMimeType)
+                    self.metadata.value(self.uri, nsc['ebucore'].hasMimeType)
                     if self.is_stored
                     else 'application/octet-stream')
         else:
@@ -56,13 +56,13 @@ class LdpNr(Ldpr):
 
     @property
     def filename(self):
-        return self.imr.value(nsc['ebucore'].filename)
+        return self.imr.value(self.uri, nsc['ebucore'].filename)
 
 
     @property
     def local_path(self):
-        cksum_term = self.imr.value(nsc['premis'].hasMessageDigest)
-        cksum = str(cksum_term.identifier.replace('urn:sha1:',''))
+        cksum_term = self.imr.value(self.uri, nsc['premis'].hasMessageDigest)
+        cksum = str(cksum_term.replace('urn:sha1:',''))
         return nonrdfly.__class__.local_path(
                 nonrdfly.root, cksum, nonrdfly.bl, nonrdfly.bc)
 
@@ -104,20 +104,23 @@ class LdpNr(Ldpr):
 
         # File size.
         logger.debug('Data stream size: {}'.format(self.size))
-        self.provided_imr.set(nsc['premis'].hasSize, Literal(self.size))
+        self.provided_imr.set((
+            self.uri, nsc['premis'].hasSize, Literal(self.size)))
 
         # Checksum.
         cksum_term = URIRef('urn:sha1:{}'.format(self.digest))
-        self.provided_imr.set(nsc['premis'].hasMessageDigest, cksum_term)
+        self.provided_imr.set((
+            self.uri, nsc['premis'].hasMessageDigest, cksum_term))
 
         # MIME type.
-        self.provided_imr.set(nsc['ebucore']['hasMimeType'], 
-                Literal(self.mimetype))
+        self.provided_imr.set((
+            self.uri, nsc['ebucore']['hasMimeType'], Literal(self.mimetype)))
 
         # File name.
         logger.debug('Disposition: {}'.format(self.disposition))
         try:
-            self.provided_imr.set(nsc['ebucore']['filename'], Literal(
-                    self.disposition['attachment']['parameters']['filename']))
+            self.provided_imr.set((
+                self.uri, nsc['ebucore']['filename'], Literal(
+                self.disposition['attachment']['parameters']['filename'])))
         except (KeyError, TypeError) as e:
             pass

+ 60 - 55
lakesuperior/model/ldpr.py

@@ -7,7 +7,6 @@ from uuid import uuid4
 import arrow
 
 from rdflib import Graph, URIRef, Literal
-from rdflib.resource import Resource
 from rdflib.namespace import RDF
 
 from lakesuperior.env import env
@@ -162,7 +161,7 @@ class Ldpr(metaclass=ABCMeta):
             else:
                 imr_options = {}
             options = dict(imr_options, strict=True)
-            self._imr = rdfly.extract_imr(self.uid, **options)
+            self._imr = rdfly.get_imr(self.uid, **options)
 
         return self._imr
 
@@ -175,11 +174,8 @@ class Ldpr(metaclass=ABCMeta):
         :param v: New set of triples to populate the IMR with.
         :type v: set or rdflib.Graph
         """
-        if isinstance(v, Resource):
-            v = v.graph
-        self._imr = Resource(Graph(), self.uri)
-        gr = self._imr.graph
-        gr += v
+        self._imr = Graph(identifier=self.uri)
+        self._imr += v
 
 
     @imr.deleter
@@ -224,7 +220,7 @@ class Ldpr(metaclass=ABCMeta):
         """
         out_gr = Graph(identifier=self.uri)
 
-        for t in self.imr.graph:
+        for t in self.imr:
             if (
                 # Exclude digest hash and version information.
                 t[1] not in {
@@ -248,8 +244,7 @@ class Ldpr(metaclass=ABCMeta):
         """
         if not hasattr(self, '_version_info'):
             try:
-                #@ TODO get_version_info should return a graph.
-                self._version_info = rdfly.get_version_info(self.uid).graph
+                self._version_info = rdfly.get_version_info(self.uid)
             except ResourceNotExistsError as e:
                 self._version_info = Graph(identifier=self.uri)
 
@@ -272,7 +267,7 @@ class Ldpr(metaclass=ABCMeta):
     def is_stored(self):
         if not hasattr(self, '_is_stored'):
             if hasattr(self, '_imr'):
-                self._is_stored = len(self.imr.graph) > 0
+                self._is_stored = len(self.imr) > 0
             else:
                 self._is_stored = rdfly.ask_rsrc_exists(self.uid)
 
@@ -286,15 +281,15 @@ class Ldpr(metaclass=ABCMeta):
         :rtype: set(rdflib.term.URIRef)
         """
         if not hasattr(self, '_types'):
-            if len(self.metadata.graph):
+            if len(self.metadata):
                 metadata = self.metadata
             elif getattr(self, 'provided_imr', None) and \
-                    len(self.provided_imr.graph):
+                    len(self.provided_imr):
                 metadata = self.provided_imr
             else:
                 return set()
 
-            self._types = set(metadata.graph[self.uri: RDF.type])
+            self._types = set(metadata[self.uri: RDF.type])
 
         return self._types
 
@@ -319,12 +314,13 @@ class Ldpr(metaclass=ABCMeta):
         """
         out_headers = defaultdict(list)
 
-        digest = self.metadata.value(nsc['premis'].hasMessageDigest)
+        digest = self.metadata.value(self.uri, nsc['premis'].hasMessageDigest)
         if digest:
             etag = digest.identifier.split(':')[-1]
             out_headers['ETag'] = 'W/"{}"'.format(etag),
 
-        last_updated_term = self.metadata.value(nsc['fcrepo'].lastModified)
+        last_updated_term = self.metadata.value(
+            self.uri, nsc['fcrepo'].lastModified)
         if last_updated_term:
             out_headers['Last-Modified'] = arrow.get(last_updated_term)\
                 .format('ddd, D MMM YYYY HH:mm:ss Z')
@@ -340,7 +336,7 @@ class Ldpr(metaclass=ABCMeta):
         """
         Get a version by label.
         """
-        return rdfly.extract_imr(self.uid, ver_uid, **kwargs).graph
+        return rdfly.get_imr(self.uid, ver_uid, **kwargs)
 
 
     def create_or_replace(self, create_only=False):
@@ -365,15 +361,15 @@ class Ldpr(metaclass=ABCMeta):
         remove_trp = {
             (self.uri, pred, None) for pred in self.delete_preds_on_replace}
         add_trp = (
-            set(self.provided_imr.graph) |
+            set(self.provided_imr) |
             self._containment_rel(create))
 
         self._modify_rsrc(ev_type, remove_trp, add_trp)
-        new_gr = Graph()
+        new_gr = Graph(identifier=self.uri)
         for trp in add_trp:
             new_gr.add(trp)
 
-        self.imr = new_gr.resource(self.uri)
+        self.imr = new_gr
 
         return ev_type
 
@@ -393,7 +389,7 @@ class Ldpr(metaclass=ABCMeta):
         self.create_rsrc_snapshot(uuid4())
 
         remove_trp = {
-            trp for trp in self.imr.graph
+            trp for trp in self.imr
             if trp[1] != nsc['fcrepo'].hasVersion}
 
         if tstone_pointer:
@@ -408,7 +404,7 @@ class Ldpr(metaclass=ABCMeta):
         self._modify_rsrc(RES_DELETED, remove_trp, add_trp)
 
         if inbound:
-            for ib_rsrc_uri in self.imr.graph.subjects(None, self.uri):
+            for ib_rsrc_uri in self.imr.subjects(None, self.uri):
                 remove_trp = {(ib_rsrc_uri, None, self.uri)}
                 ib_rsrc = Ldpr(ib_rsrc_uri)
                 # To preserve inbound links in history, create a snapshot
@@ -444,7 +440,7 @@ class Ldpr(metaclass=ABCMeta):
         ver_uid = '{}/{}'.format(vers_uid, ver_uid)
         ver_uri = nsc['fcres'][ver_uid]
         ver_add_gr.add((ver_uri, RDF.type, nsc['fcrepo'].Version))
-        for t in self.imr.graph:
+        for t in self.imr:
             if (
                 t[1] == RDF.type and t[2] in {
                     nsc['fcrepo'].Binary,
@@ -483,9 +479,9 @@ class Ldpr(metaclass=ABCMeta):
 
         @EXPERIMENTAL
         """
-        tstone_trp = set(rdfly.extract_imr(self.uid, strict=False).graph)
+        tstone_trp = set(rdfly.get_imr(self.uid, strict=False))
 
-        ver_rsp = self.version_info.graph.query('''
+        ver_rsp = self.version_info.query('''
         SELECT ?uid {
           ?latest fcrepo:hasVersionLabel ?uid ;
             fcrepo:created ?ts .
@@ -494,7 +490,7 @@ class Ldpr(metaclass=ABCMeta):
         LIMIT 1
         ''')
         ver_uid = str(ver_rsp.bindings[0]['uid'])
-        ver_trp = set(rdfly.get_metadata(self.uid, ver_uid).graph)
+        ver_trp = set(rdfly.get_metadata(self.uid, ver_uid))
 
         laz_gr = Graph()
         for t in ver_trp:
@@ -544,13 +540,13 @@ class Ldpr(metaclass=ABCMeta):
         if backup:
             self.create_version()
 
-        ver_gr = rdfly.extract_imr(
+        ver_gr = rdfly.get_imr(
             self.uid, ver_uid=ver_uid, incl_children=False)
-        self.provided_imr = Resource(Graph(), self.uri)
+        self.provided_imr = Graph(identifier=self.uri)
 
-        for t in ver_gr.graph:
+        for t in ver_gr:
             if not self._is_trp_managed(t):
-                self.provided_imr.add(t[1], t[2])
+                self.provided_imr.add((self.uri, t[1], t[2]))
             # @TODO Check individual objects: if they are repo-managed URIs
             # and not existing or tombstones, they are not added.
 
@@ -606,7 +602,7 @@ class Ldpr(metaclass=ABCMeta):
         """
         try:
             rsrc_type = tuple(str(t) for t in self.types)
-            actor = self.metadata.value(nsc['fcrepo'].createdBy)
+            actor = self.metadata.value(self.uri, nsc['fcrepo'].createdBy)
         except (ResourceNotExistsError, TombstoneError):
             rsrc_type = ()
             actor = None
@@ -625,9 +621,14 @@ class Ldpr(metaclass=ABCMeta):
 
 
     def _check_ref_int(self, config):
-        gr = self.provided_imr.graph
+        """
+        Check referential integrity of a resource.
 
-        for o in gr.objects():
+        :param str config: If set to ``strict``, a
+           :class:`lakesuperior.exceptions.RefIntViolationError` is raised.
+           Otherwise, the violation is simply logged.
+        """
+        for o in self.provided_imr.objects():
             if isinstance(o, URIRef) and str(o).startswith(nsc['fcres']):
                 obj_uid = rdfly.uri_to_uid(o)
                 if not rdfly.ask_rsrc_exists(obj_uid):
@@ -637,7 +638,7 @@ class Ldpr(metaclass=ABCMeta):
                         logger.info(
                             'Removing link to non-existent repo resource: {}'
                             .format(obj_uid))
-                        gr.remove((None, None, o))
+                        self.provided_imr.remove((None, None, o))
 
 
     def _check_mgd_terms(self, gr):
@@ -689,28 +690,32 @@ class Ldpr(metaclass=ABCMeta):
         """
         # Base LDP types.
         for t in self.base_types:
-            self.provided_imr.add(RDF.type, t)
+            self.provided_imr.add((self.uri, RDF.type, t))
 
         # Message digest.
-        cksum = self.tbox.rdf_cksum(self.provided_imr.graph)
-        self.provided_imr.set(
-            nsc['premis'].hasMessageDigest,
-            URIRef('urn:sha1:{}'.format(cksum)))
+        cksum = self.tbox.rdf_cksum(self.provided_imr)
+        self.provided_imr.set((
+            self.uri, nsc['premis'].hasMessageDigest,
+            URIRef('urn:sha1:{}'.format(cksum))))
 
         # Create and modify timestamp.
         if create:
-            self.provided_imr.set(nsc['fcrepo'].created, env.timestamp_term)
-            self.provided_imr.set(nsc['fcrepo'].createdBy, self.DEFAULT_USER)
+            self.provided_imr.set((
+                self.uri, nsc['fcrepo'].created, env.timestamp_term))
+            self.provided_imr.set((
+                self.uri, nsc['fcrepo'].createdBy, self.DEFAULT_USER))
         else:
-            self.provided_imr.set(
-                nsc['fcrepo'].created, self.metadata.value(
-                    nsc['fcrepo'].created))
-            self.provided_imr.set(
-                nsc['fcrepo'].createdBy, self.metadata.value(
-                    nsc['fcrepo'].createdBy))
+            self.provided_imr.set((
+                self.uri, nsc['fcrepo'].created, self.metadata.value(
+                    self.uri, nsc['fcrepo'].created)))
+            self.provided_imr.set((
+                self.uri, nsc['fcrepo'].createdBy, self.metadata.value(
+                    self.uri, nsc['fcrepo'].createdBy)))
 
-        self.provided_imr.set(nsc['fcrepo'].lastModified, env.timestamp_term)
-        self.provided_imr.set(nsc['fcrepo'].lastModifiedBy, self.DEFAULT_USER)
+        self.provided_imr.set((
+            self.uri, nsc['fcrepo'].lastModified, env.timestamp_term))
+        self.provided_imr.set((
+            self.uri, nsc['fcrepo'].lastModifiedBy, self.DEFAULT_USER))
 
 
     def _containment_rel(self, create):
@@ -790,7 +795,7 @@ class Ldpr(metaclass=ABCMeta):
 
         :param rdflib.resource.Resouce cont_rsrc:  The container resource.
         """
-        cont_p = set(cont_rsrc.metadata.graph.predicates())
+        cont_p = set(cont_rsrc.metadata.predicates())
 
         logger.info('Checking direct or indirect containment.')
         logger.debug('Parent predicates: {}'.format(cont_p))
@@ -800,8 +805,8 @@ class Ldpr(metaclass=ABCMeta):
         if self.MBR_RSRC_URI in cont_p and self.MBR_REL_URI in cont_p:
             from lakesuperior.model.ldp_factory import LdpFactory
 
-            s = cont_rsrc.metadata.value(self.MBR_RSRC_URI).identifier
-            p = cont_rsrc.metadata.value(self.MBR_REL_URI).identifier
+            s = cont_rsrc.metadata.value(cont_rsrc.uri, self.MBR_RSRC_URI)
+            p = cont_rsrc.metadata.value(cont_rsrc_uri, self.MBR_REL_URI)
 
             if cont_rsrc.metadata[RDF.type: nsc['ldp'].DirectContainer]:
                 logger.info('Parent is a direct container.')
@@ -815,8 +820,8 @@ class Ldpr(metaclass=ABCMeta):
                     self.INS_CNT_REL_URI in cont_p):
                 logger.info('Parent is an indirect container.')
                 cont_rel_uri = cont_rsrc.metadata.value(
-                    self.INS_CNT_REL_URI).identifier
-                o = self.provided_imr.value(cont_rel_uri).identifier
+                    cont_rsrc.uri, self.INS_CNT_REL_URI)
+                o = self.provided_imr.value(self.uri, cont_rel_uri)
                 logger.debug('Target URI: {}'.format(o))
                 logger.debug('Creating IC triples.')
 
@@ -864,7 +869,7 @@ class Ldpr(metaclass=ABCMeta):
         events in a provenance tracking system.
         """
         logger.debug('Provided SPARQL query: {}'.format(q))
-        pre_gr = self.imr.graph
+        pre_gr = self.imr
 
         post_gr = pre_gr | Graph()
         post_gr.update(q)

+ 29 - 30
lakesuperior/store/ldp_rs/rsrc_centric_layout.py

@@ -221,11 +221,11 @@ class RsrcCentricLayout:
         return self.ds.query(qry_str)
 
 
-    def extract_imr(
+    def get_imr(
                 self, uid, ver_uid=None, strict=True, incl_inbound=False,
                 incl_children=True, embed_children=False, **kwargs):
         """
-        See base_rdf_layout.extract_imr.
+        See base_rdf_layout.get_imr.
         """
         if ver_uid:
             uid = self.snapshot_uid(uid, ver_uid)
@@ -241,22 +241,20 @@ class RsrcCentricLayout:
                 for gr in graphs]
         resultset = set(chain.from_iterable(rsrc_graphs))
 
-        gr = Graph()
-        gr += resultset
+        imr = Graph(identifier=nsc['fcres'][uid])
+        imr += resultset
 
         # Include inbound relationships.
-        if incl_inbound and len(gr):
-            gr += self.get_inbound_rel(nsc['fcres'][uid])
+        if incl_inbound and len(imr):
+            imr += self.get_inbound_rel(nsc['fcres'][uid])
 
         #logger.debug('Found resource: {}'.format(
-        #        gr.serialize(format='turtle').decode('utf-8')))
-
-        rsrc = Resource(gr, nsc['fcres'][uid])
+        #        imr.serialize(format='turtle').decode('utf-8')))
 
         if strict:
-            self._check_rsrc_status(rsrc)
+            self._check_rsrc_status(imr)
 
-        return rsrc
+        return imr
 
 
     def ask_rsrc_exists(self, uid):
@@ -276,14 +274,14 @@ class RsrcCentricLayout:
         logger.debug('Getting metadata for: {}'.format(uid))
         if ver_uid:
             uid = self.snapshot_uid(uid, ver_uid)
-        gr = self.ds.graph(nsc['fcadmin'][uid]) | Graph()
         uri = nsc['fcres'][uid]
+        gr = Graph(identifier=uri)
+        gr += self.ds.graph(nsc['fcadmin'][uid])
 
-        rsrc = Resource(gr, uri)
         if strict:
-            self._check_rsrc_status(rsrc)
+            self._check_rsrc_status(gr)
 
-        return rsrc
+        return gr
 
 
     def get_user_data(self, uid):
@@ -295,9 +293,10 @@ class RsrcCentricLayout:
         # *TODO* This only works as long as there is only one user-provided
         # graph. If multiple user-provided graphs will be supported, this
         # should use another query to get all of them.
-        userdata_gr = self.ds.graph(nsc['fcmain'][uid])
+        userdata_gr = Graph(identifier=nsc['fcres'][uid])
+        userdata_gr += self.ds.graph(nsc['fcmain'][uid])
 
-        return userdata_gr | Graph()
+        return userdata_gr
 
 
     def get_version_info(self, uid, strict=True):
@@ -331,12 +330,12 @@ class RsrcCentricLayout:
             'ag': nsc['fcadmin'][uid],
             'hg': HIST_GR_URI,
             's': nsc['fcres'][uid]})
-        rsrc = Resource(gr, nsc['fcres'][uid])
-        # TODO Should return a graph.
+        ver_info_gr = Graph(identifier=nsc['fcres'][uid])
+        ver_info_gr += gr
         if strict:
-            self._check_rsrc_status(rsrc)
+            self._check_rsrc_status(ver_info_gr)
 
-        return rsrc
+        return ver_info_gr
 
 
     def get_inbound_rel(self, subj_uri, full_triple=True):
@@ -566,23 +565,23 @@ class RsrcCentricLayout:
 
     ## PROTECTED MEMBERS ##
 
-    def _check_rsrc_status(self, rsrc):
+    def _check_rsrc_status(self, gr):
         """
         Check if a resource is not existing or if it is a tombstone.
         """
-        uid = self.uri_to_uid(rsrc.identifier)
-        if not len(rsrc.graph):
+        uid = self.uri_to_uid(gr.identifier)
+        if not len(gr):
             raise ResourceNotExistsError(uid)
 
         # Check if resource is a tombstone.
-        if rsrc[RDF.type : nsc['fcsystem'].Tombstone]:
+        if gr[gr.identifier : RDF.type : nsc['fcsystem'].Tombstone]:
             raise TombstoneError(
-                    uid, rsrc.value(nsc['fcrepo'].created))
-        elif rsrc.value(nsc['fcsystem'].tombstone):
+                    uid, gr.value(gr.identifier, nsc['fcrepo'].created))
+        elif gr.value(gr.identifier, nsc['fcsystem'].tombstone):
             raise TombstoneError(
-                    self.uri_to_uid(
-                        rsrc.value(nsc['fcsystem'].tombstone).identifier),
-                        rsrc.value(nsc['fcrepo'].created))
+                self.uri_to_uid(
+                    gr.value(gr.identifier, nsc['fcsystem'].tombstone)),
+                gr.value(gr.identifier, nsc['fcrepo'].created))
 
 
     def _parse_construct(self, qry, init_bindings={}):