Browse Source

Only send messages once per resource request.

Stefano Cossu 7 years ago
parent
commit
6305baccb3

+ 3 - 2
lakesuperior/api/resource.py

@@ -185,7 +185,7 @@ def create(parent, slug, **kwargs):
     logger.debug('Minted UID for new resource: {}'.format(uid))
     logger.debug('Minted UID for new resource: {}'.format(uid))
     rsrc = LdpFactory.from_provided(uid, **kwargs)
     rsrc = LdpFactory.from_provided(uid, **kwargs)
 
 
-    rsrc.create_or_replace_rsrc(create_only=True)
+    rsrc.create_or_replace(create_only=True)
 
 
     return uid
     return uid
 
 
@@ -210,12 +210,13 @@ def create_or_replace(uid, stream=None, **kwargs):
     @return string Event type: whether the resource was created or updated.
     @return string Event type: whether the resource was created or updated.
     '''
     '''
     rsrc = LdpFactory.from_provided(uid, stream=stream, **kwargs)
     rsrc = LdpFactory.from_provided(uid, stream=stream, **kwargs)
+    create = not rsrc.is_stored
 
 
     if not stream and rsrc.is_stored:
     if not stream and rsrc.is_stored:
         raise InvalidResourceError(rsrc.uid,
         raise InvalidResourceError(rsrc.uid,
                 'Resource {} already exists and no data set was provided.')
                 'Resource {} already exists and no data set was provided.')
 
 
-    return rsrc.create_or_replace_rsrc()
+    return rsrc.create_or_replace(create_only=create)
 
 
 
 
 @transaction(True)
 @transaction(True)

+ 2 - 2
lakesuperior/model/ldp_nr.py

@@ -66,7 +66,7 @@ class LdpNr(Ldpr):
         return nonrdfly.local_path(cksum)
         return nonrdfly.local_path(cksum)
 
 
 
 
-    def create_or_replace_rsrc(self, create_only=False):
+    def create_or_replace(self, create_only=False):
         '''
         '''
         Create a new binary resource with a corresponding RDF representation.
         Create a new binary resource with a corresponding RDF representation.
 
 
@@ -78,7 +78,7 @@ class LdpNr(Ldpr):
         # Try to persist metadata. If it fails, delete the file.
         # Try to persist metadata. If it fails, delete the file.
         logger.debug('Persisting LDP-NR triples in {}'.format(self.uri))
         logger.debug('Persisting LDP-NR triples in {}'.format(self.uri))
         try:
         try:
-            ev_type = super().create_or_replace_rsrc(create_only)
+            ev_type = super().create_or_replace(create_only)
         except:
         except:
             # self.digest is also the file UID.
             # self.digest is also the file UID.
             nonrdfly.delete(self.digest)
             nonrdfly.delete(self.digest)

+ 36 - 19
lakesuperior/model/ldpr.py

@@ -364,35 +364,43 @@ class Ldpr(metaclass=ABCMeta):
         return rdfly.extract_imr(self.uid, ver_uid, **kwargs).graph
         return rdfly.extract_imr(self.uid, ver_uid, **kwargs).graph
 
 
 
 
-    def create_or_replace_rsrc(self, create_only=False):
+    def create_or_replace(self, create_only=False):
         '''
         '''
         Create or update a resource. PUT and POST methods, which are almost
         Create or update a resource. PUT and POST methods, which are almost
         identical, are wrappers for this method.
         identical, are wrappers for this method.
 
 
         @param create_only (boolean) Whether this is a create-only operation.
         @param create_only (boolean) Whether this is a create-only operation.
         '''
         '''
+        pdb.set_trace()
         create = create_only or not self.is_stored
         create = create_only or not self.is_stored
+        ev_type = RES_CREATED if create else RES_UPDATED
 
 
         self._add_srv_mgd_triples(create)
         self._add_srv_mgd_triples(create)
-        #self._ensure_single_subject_rdf(self.provided_imr.graph)
         ref_int = rdfly.config['referential_integrity']
         ref_int = rdfly.config['referential_integrity']
         if ref_int:
         if ref_int:
             self._check_ref_int(ref_int)
             self._check_ref_int(ref_int)
 
 
-        rdfly.create_or_replace_rsrc(self.uid, self.provided_imr.graph)
-        self.imr = self.provided_imr
+        # Delete existing triples if replacing.
+        if not create:
+            rdfly.truncate_rsrc(self.uid)
+
+        add_trp = set(self.provided_imr.graph) | self._containment_rel(create)
 
 
-        self._set_containment_rel()
+        self._modify_rsrc(ev_type, add_trp=add_trp)
+        new_gr = Graph()
+        for trp in add_trp:
+            new_gr.add(trp)
 
 
-        return RES_CREATED if create else RES_UPDATED
-        #return self._head(self.provided_imr.graph)
+        self.imr = new_gr.resource(self.uri)
+
+        return ev_type
 
 
 
 
     def put(self):
     def put(self):
         '''
         '''
         https://www.w3.org/TR/ldp/#ldpr-HTTP_PUT
         https://www.w3.org/TR/ldp/#ldpr-HTTP_PUT
         '''
         '''
-        return self.create_or_replace_rsrc()
+        return self.create_or_replace()
 
 
 
 
     def patch(self, update_str):
     def patch(self, update_str):
@@ -535,8 +543,8 @@ class Ldpr(metaclass=ABCMeta):
         elif nsc['ldp'].Container in laz_gr[: RDF.type :]:
         elif nsc['ldp'].Container in laz_gr[: RDF.type :]:
             laz_gr.add((self.uri, RDF.type, nsc['fcrepo'].Container))
             laz_gr.add((self.uri, RDF.type, nsc['fcrepo'].Container))
 
 
-        self._modify_rsrc(RES_CREATED, tstone_trp, set(laz_gr))
-        self._set_containment_rel()
+        laz_set = set(laz_gr) | self._containment_rel()
+        self._modify_rsrc(RES_CREATED, tstone_trp, laz_set)
 
 
         return self.uri
         return self.uri
 
 
@@ -581,7 +589,7 @@ class Ldpr(metaclass=ABCMeta):
             # @TODO Check individual objects: if they are repo-managed URIs
             # @TODO Check individual objects: if they are repo-managed URIs
             # and not existing or tombstones, they are not added.
             # and not existing or tombstones, they are not added.
 
 
-        return self.create_or_replace_rsrc(create_only=False)
+        return self.create_or_replace(create_only=False)
 
 
 
 
     ## PROTECTED METHODS ##
     ## PROTECTED METHODS ##
@@ -610,7 +618,6 @@ class Ldpr(metaclass=ABCMeta):
         @param add_trp (set) Triples to be added.
         @param add_trp (set) Triples to be added.
         @param notify (boolean) Whether to send a message about the change.
         @param notify (boolean) Whether to send a message about the change.
         '''
         '''
-        pdb.set_trace()
         rdfly.modify_rsrc(self.uid, remove_trp, add_trp)
         rdfly.modify_rsrc(self.uid, remove_trp, add_trp)
 
 
         if notify and env.config['application'].get('messaging'):
         if notify and env.config['application'].get('messaging'):
@@ -736,7 +743,7 @@ class Ldpr(metaclass=ABCMeta):
         self.provided_imr.set(nsc['fcrepo'].lastModifiedBy, self.DEFAULT_USER)
         self.provided_imr.set(nsc['fcrepo'].lastModifiedBy, self.DEFAULT_USER)
 
 
 
 
-    def _set_containment_rel(self):
+    def _containment_rel(self, create):
         '''Find the closest parent in the path indicated by the uid and
         '''Find the closest parent in the path indicated by the uid and
         establish a containment triple.
         establish a containment triple.
 
 
@@ -752,6 +759,9 @@ class Ldpr(metaclass=ABCMeta):
           fcres:/a/b/c.
           fcres:/a/b/c.
         - If fcres:/e is being created, the root node becomes container of
         - If fcres:/e is being created, the root node becomes container of
           fcres:/e.
           fcres:/e.
+
+        @param create (bool) Whether the resource is being created. If false,
+        the parent container is not updated.
         '''
         '''
         from lakesuperior.model.ldp_factory import LdpFactory
         from lakesuperior.model.ldp_factory import LdpFactory
 
 
@@ -770,25 +780,32 @@ class Ldpr(metaclass=ABCMeta):
                 parent_rsrc = LdpFactory.new_container(cnd_parent_uid)
                 parent_rsrc = LdpFactory.new_container(cnd_parent_uid)
                 # This will trigger this method again and recurse until an
                 # This will trigger this method again and recurse until an
                 # existing container or the root node is reached.
                 # existing container or the root node is reached.
-                parent_rsrc.create_or_replace_rsrc()
+                parent_rsrc.create_or_replace()
                 parent_uid = parent_rsrc.uid
                 parent_uid = parent_rsrc.uid
         else:
         else:
             parent_uid = ROOT_UID
             parent_uid = ROOT_UID
 
 
-        add_gr = Graph()
-        add_gr.add((nsc['fcres'][parent_uid], nsc['ldp'].contains, self.uri))
         parent_rsrc = LdpFactory.from_stored(
         parent_rsrc = LdpFactory.from_stored(
             parent_uid, repr_opts={'incl_children' : False}, handling='none')
             parent_uid, repr_opts={'incl_children' : False}, handling='none')
-        parent_rsrc._modify_rsrc(RES_UPDATED, add_trp=add_gr)
+
+        # Only update parent if the resource is new.
+        if create:
+            add_gr = Graph()
+            add_gr.add(
+                    (nsc['fcres'][parent_uid], nsc['ldp'].contains, self.uri))
+            parent_rsrc._modify_rsrc(RES_UPDATED, add_trp=add_gr)
 
 
         # Direct or indirect container relationship.
         # Direct or indirect container relationship.
-        self._add_ldp_dc_ic_rel(parent_rsrc)
+        return self._add_ldp_dc_ic_rel(parent_rsrc)
 
 
 
 
     def _dedup_deltas(self, remove_gr, add_gr):
     def _dedup_deltas(self, remove_gr, add_gr):
         '''
         '''
         Remove duplicate triples from add and remove delta graphs, which would
         Remove duplicate triples from add and remove delta graphs, which would
         otherwise contain unnecessary statements that annul each other.
         otherwise contain unnecessary statements that annul each other.
+
+        @return tuple 2 "clean" sets of respectively remove statements and
+        add statements.
         '''
         '''
         return (
         return (
             remove_gr - add_gr,
             remove_gr - add_gr,
@@ -834,7 +851,7 @@ class Ldpr(metaclass=ABCMeta):
             target_rsrc = LdpFactory.from_stored(rdfly.uri_to_uid(s))
             target_rsrc = LdpFactory.from_stored(rdfly.uri_to_uid(s))
             target_rsrc._modify_rsrc(RES_UPDATED, add_trp={(s, p, o)})
             target_rsrc._modify_rsrc(RES_UPDATED, add_trp={(s, p, o)})
 
 
-        self._modify_rsrc(RES_UPDATED, add_trp=add_trp)
+        return add_trp
 
 
 
 
     def _sparql_update(self, update_str, notify=True):
     def _sparql_update(self, update_str, notify=True):

+ 22 - 8
lakesuperior/store/ldp_rs/rsrc_centric_layout.py

@@ -282,6 +282,20 @@ class RsrcCentricLayout:
         return rsrc
         return rsrc
 
 
 
 
+    def get_user_data(self, uid):
+        '''
+        Get all the user-provided data.
+
+        @param uid (string) Resource UID.
+        '''
+        # @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])
+
+        return userdata_gr | Graph()
+
+
     def get_version_info(self, uid, strict=True):
     def get_version_info(self, uid, strict=True):
         '''
         '''
         Get all metadata about a resource's versions.
         Get all metadata about a resource's versions.
@@ -422,20 +436,20 @@ class RsrcCentricLayout:
         # Remove versions.
         # Remove versions.
         for ver_uri in self.ds.graph(nsc['fcadmin'][uid])[
         for ver_uri in self.ds.graph(nsc['fcadmin'][uid])[
                 uri : nsc['fcrepo'].hasVersion : None]:
                 uri : nsc['fcrepo'].hasVersion : None]:
-            self._delete_rsrc(uid_fn(ver_uri), True)
+            self.delete_rsrc(uid_fn(ver_uri), True)
 
 
         # Remove resource itself.
         # Remove resource itself.
-        self._delete_rsrc(uid)
+        self.delete_rsrc(uid)
 
 
 
 
-    def create_or_replace_rsrc(self, uid, trp):
+    def truncate_rsrc(self, uid):
         '''
         '''
-        Create a new resource or replace an existing one.
+        Remove all user-provided data from a resource and only leave admin and
+        structure data.
         '''
         '''
-        if self.ask_rsrc_exists(uid):
-            self._delete_rsrc(uid)
+        userdata = set(self.get_user_data(uid))
 
 
-        return self.modify_rsrc(uid, add_trp=trp)
+        return self.modify_rsrc(uid, remove_trp=userdata)
 
 
 
 
     def modify_rsrc(self, uid, remove_trp=set(), add_trp=set()):
     def modify_rsrc(self, uid, remove_trp=set(), add_trp=set()):
@@ -490,7 +504,7 @@ class RsrcCentricLayout:
             meta_gr.add((gr_uri, RDF.type, gr_type))
             meta_gr.add((gr_uri, RDF.type, gr_type))
 
 
 
 
-    def _delete_rsrc(self, uid, historic=False):
+    def delete_rsrc(self, uid, historic=False):
         '''
         '''
         Delete all aspect graphs of an individual resource.
         Delete all aspect graphs of an individual resource.