[hook] Don't check for unhandled cardinality on the seda_binary_data_object relation
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Wed, 11 Oct 2017 09:24:03 +0200
changeset 2740 80c39123d029
parent 2739 71c3d7cf079a
child 2741 79239b803783
[hook] Don't check for unhandled cardinality on the seda_binary_data_object relation in case the profile is a simplified profile. This is because this relation is there because of the SEDA 2 underlying model, where all data objects are below the transfer node, but it is not used in SEDA 0.2 and 1.0, where data objects are dispatched under the archive units tree. So we don't want to prevent having several data objects with cardinality != 1 at different level of the tree. Closes extranet #37372358
cubicweb_seda/hooks.py
test/test_hooks.py
--- a/cubicweb_seda/hooks.py	Mon Oct 09 17:04:39 2017 +0200
+++ b/cubicweb_seda/hooks.py	Wed Oct 11 09:24:03 2017 +0200
@@ -1,4 +1,4 @@
-# copyright 2016-2017 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2016 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr -- mailto:contact@logilab.fr
 #
 # This program is free software: you can redistribute it and/or modify it under
@@ -414,7 +414,7 @@
             (parent.eid, rtype, self.entity.eid))
 
 
-class CheckChildrenUnhandledCardinalityOp(hook.DataOperationMixIn, hook.Operation):
+class CheckChildrenUnhandledCardinalityOp(hook.DataOperationMixIn, hook.LateOperation):
     """Check we don't run into the case of an with more than one child through a
     same relation with `user_cardinality != '1'` (otherwise it won't be
     validable by RelaxNG validator like Jing).
@@ -428,11 +428,34 @@
 
     * eid of the entity on which the `ValidationError` will be raised in case of
       error.
+
+    This is a late operation since it has to be executed once the 'container' relation is set.
     """
 
     def precommit_event(self):
         for parent_eid, rtype, added_entity_eid in self.get_data():
             parent = self.cnx.entity_from_eid(parent_eid)
+            # if the container is a simplified profile, allow to have several
+            # entities with cardinality != 1 under the seda_binary_data_object
+            # relation because data objects are all linked to the transfer
+            # through this relation, but this is only relevant for SEDA 2 export
+            # and we don't want to prevent this in profiles for SEDA 0.2 and 1.0
+            # export.
+            if rtype == 'seda_binary_data_object':
+                if parent.cw_etype == 'SEDAArchiveTransfer':
+                    container = parent
+                else:
+                    if not parent.container:
+                        # we may have to clear the container cache if the parent has
+                        # been added in the same transaction
+                        parent.cw_clear_relation_cache('container', 'subject')
+                    container = parent.cw_adapt_to('IContained').container
+                if container.cw_etype != 'SEDAArchiveTransfer':
+                    # component archive unit, don't check the relation, it will
+                    # be checked upon import of the component into a transfer
+                    continue
+                if container.simplified_profile:
+                    continue
             has_non_single_cardinality = False
             # sort to attempt to return the child with the greatest eid
             for child in sorted(parent.related(rtype, 'object', entities=True),
--- a/test/test_hooks.py	Mon Oct 09 17:04:39 2017 +0200
+++ b/test/test_hooks.py	Wed Oct 11 09:24:03 2017 +0200
@@ -1,4 +1,4 @@
-# copyright 2016-2017 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2016 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr -- mailto:contact@logilab.fr
 #
 # This program is free software: you can redistribute it and/or modify it under
@@ -150,6 +150,17 @@
             with self.assertValidationError(cnx):
                 testutils.create_data_object(unit_alt_seq, user_cardinality=u'1..n',
                                              seda_binary_data_object=transfer)
+            unit2, unit2_alt, unit2_alt_seq = testutils.create_archive_unit(transfer)
+            with self.assertValidationError(cnx):
+                testutils.create_data_object(unit2_alt_seq, user_cardinality=u'0..n',
+                                             seda_binary_data_object=transfer)
+            # though adding a data object with card != to another archive unit
+            # *on a simplified profile* is fine
+            transfer.cw_set(simplified_profile=True)
+            unit2, unit2_alt, unit2_alt_seq = testutils.create_archive_unit(transfer)
+            testutils.create_data_object(unit2_alt_seq, user_cardinality=u'0..n',
+                                         seda_binary_data_object=transfer)
+            cnx.commit()
 
     def test_multiple_child_unhandled_cardinality_keyword(self):
         with self.admin_access.cnx() as cnx: