Commit 0e37f732 authored by Denis Laxalde's avatar Denis Laxalde
Browse files

[profile gen] Account for bdo's user cardinality or its parent's in...

[profile gen] Account for bdo's user cardinality or its parent's in "Integrity" element (CONSEJIRA-663)

See also https://jira.mtpl.bs.fr.atos.net/browse/CONSEJIRA-663

For more details, quoting verbatim the customer request for future reference:

| Sur les documents multi occurrences (0-n ou 1-n) ou même si l’archive
| est multi occurrence (0-n ou 1-n), il y a une balise integrity qui est
| liée au document dans le bordereau de versement que l’on génère.
| Or, dans le XSD du profil, la balise integrity du document ne possède
| pas l'attribut : maxOccurs="unbounded"
| Donc lors de l'envoi à Asalae du versement, Asalae fait une vérification
| par rapport au profil et affiche une erreur a cause de la balise
| integrity qui est présente plusieurs fois.
|
| Pour moi le correctif à faire doit porter sur le XSD et le RNG sur la
| balise integrity pour qu'elle soit multi-occurrence possible dans les cas
| suivants :
|
|   *   Si le document (Document) est en multi occurrence (0-n ou 1-n)
|       donc avec un attribut maxOccurs="unbounded"
|   *   Si une UA (Contains) supérieure au document est en multi
|       occurrence (0-n ou 1-n) donc avec un attribut
|       maxOccurs="unbounded"

| si une UA supérieur est en cardinalité max unbounded, alors
| l'integrity sur les documents en dessous doit forcément être en
| unbounded également

| il faut que l'integrity soit en facultative ou multi occurrence si une
| UA supérieure est facultative ou en multi occurrence.

This is essentially achieved by looking for the upper parent archive
units of a data object then their cardinality to produce the Integrity element.

Adding tests for new integrity_cardinality() function based on customer
examples.
parent 1fe87336af7c
......@@ -123,6 +123,24 @@ def serialize(value, build_url):
return text_type(value)
def integrity_cardinality(data_object):
minvalue, maxvalue = minmax_cardinality(data_object.user_cardinality)
itree = data_object.cw_adapt_to('ITreeBase')
for parent in itree.iterancestors():
try:
parent_cardinality = parent.user_cardinality
except AttributeError:
continue
minc, maxc = minmax_cardinality(parent_cardinality)
minvalue = min(minc, minvalue)
maxvalue = max(maxc, maxvalue)
if maxvalue == graph_nodes.INFINITY:
maxvalue = 'n'
if minvalue == maxvalue == 1:
return '1'
return '{}..{}'.format(minvalue, maxvalue)
def minmax_cardinality(string_cardinality, _allowed=('0..1', '0..n', '1', '1..n')):
"""Return (minimum, maximum) cardinality for the cardinality as string (one of '0..1', '0..n',
'1' or '1..n').
......@@ -1096,9 +1114,10 @@ class SEDA1XSDExport(SEDA2ExportAdapter):
self.xsd_agency(parent, 'OriginatingAgency', content.originating_agency)
def xsd_integrity(self, parent, data_object):
cardinality = integrity_cardinality(data_object)
algorithm = data_object.seda_algorithm[0] if data_object.seda_algorithm else None
self.element_schema(parent, 'Integrity', 'qdt:ArchivesHashcodeBinaryObjectType',
cardinality='0..1',
cardinality=cardinality,
xsd_attributes=[XAttr('algorithme', 'xsd:string',
cardinality='1',
fixed_value=_concept_value(
......@@ -1298,7 +1317,8 @@ class SEDA02XSDExport(SEDA1XSDExport):
)
def xsd_integrity(self, parent, data_object):
integrity = self.element_schema(parent, 'Integrity', cardinality='0..1')
cardinality = integrity_cardinality(data_object)
integrity = self.element_schema(parent, 'Integrity', cardinality=cardinality)
algorithm = data_object.seda_algorithm[0] if data_object.seda_algorithm else None
self.element_schema(integrity, 'Contains', 'qdt:ArchivesHashcodeBinaryObjectType',
xsd_attributes=[XAttr('algorithme', 'xsd:string',
......
......@@ -148,7 +148,7 @@
</rng:element>
</rng:optional>
</rng:element>
<rng:optional>
<rng:zeroOrMore>
<rng:element name="Integrity">
<rng:element name="Contains">
<rng:attribute name="algorithme">
......@@ -160,7 +160,7 @@
<rng:data type="string"/>
</rng:element>
</rng:element>
</rng:optional>
</rng:zeroOrMore>
<rng:oneOrMore>
<rng:element name="Contains" xml:id="id%(unit-eid)s">
<xsd:annotation>
......
......@@ -86,7 +86,7 @@
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element minOccurs="0" name="Integrity">
<xsd:element maxOccurs="unbounded" minOccurs="0" name="Integrity">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Contains">
......
......@@ -563,14 +563,14 @@
</rng:attribute>
<rng:data type="string"/>
</rng:element>
<rng:optional>
<rng:zeroOrMore>
<rng:element name="Integrity">
<rng:attribute name="algorithme">
<rng:value type="string">md5</rng:value>
</rng:attribute>
<rng:data type="string"/>
</rng:element>
</rng:optional>
</rng:zeroOrMore>
<rng:element name="Type">
<rng:attribute name="listVersionID">
<rng:value type="token">edition 2009</rng:value>
......
......@@ -460,7 +460,7 @@
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
<xsd:element minOccurs="0" name="Integrity">
<xsd:element minOccurs="0" maxOccurs="unbounded" name="Integrity">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="qdt:ArchivesHashcodeBinaryObjectType">
......
......@@ -312,6 +312,50 @@ class PathTargetValuesTC(CubicWebTC):
self.assertEqual(target_value[0], None)
self.assertEqual(target_value[1].eid, bdo.eid)
def test_integrity_cardinality(self):
with self.admin_access.cnx() as cnx:
transfer = cnx.create_entity('SEDAArchiveTransfer', title=u'test profile')
bdo = cnx.create_entity('SEDABinaryDataObject',
user_annotation=u'I am mandatory',
seda_binary_data_object=transfer)
assert pg.integrity_cardinality(bdo) == '1'
bdo = cnx.create_entity('SEDABinaryDataObject',
user_cardinality=u'0..1',
user_annotation=u'opt',
seda_binary_data_object=transfer)
assert pg.integrity_cardinality(bdo) == '0..1'
_, _, unit_alt_seq = testutils.create_archive_unit(
None, cnx=cnx)
bdo = testutils.create_data_object(unit_alt_seq)
assert pg.integrity_cardinality(bdo) == '0..n'
_, _, unit_alt_seq = testutils.create_archive_unit(
None, cnx=cnx, user_cardinality=u'1..n')
bdo = testutils.create_data_object(unit_alt_seq, user_cardinality=u'0..1')
assert pg.integrity_cardinality(bdo) == '0..n'
_, _, unit_alt_seq = testutils.create_archive_unit(
None, cnx=cnx, user_cardinality=u'1..n')
_, _, unit_alt_seq2 = testutils.create_archive_unit(
unit_alt_seq, cnx=cnx, user_cardinality=u'0..n')
bdo = testutils.create_data_object(unit_alt_seq2, user_cardinality=u'1')
assert pg.integrity_cardinality(bdo) == '0..n'
_, _, unit_alt_seq = testutils.create_archive_unit(
None, cnx=cnx, user_cardinality=u'1')
_, _, unit_alt_seq2 = testutils.create_archive_unit(
unit_alt_seq, cnx=cnx, user_cardinality=u'1..n')
bdo = testutils.create_data_object(unit_alt_seq2, user_cardinality=u'0..1')
assert pg.integrity_cardinality(bdo) == '0..n'
_, _, unit_alt_seq = testutils.create_archive_unit(
None, cnx=cnx, user_cardinality=u'0..1')
_, _, unit_alt_seq2 = testutils.create_archive_unit(
unit_alt_seq, cnx=cnx, user_cardinality=u'1')
bdo = testutils.create_data_object(unit_alt_seq2, user_cardinality=u'1..n')
assert pg.integrity_cardinality(bdo) == '0..n'
class SEDA2RNGExportTC(RelaxNGTestMixin, CubicWebTC):
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment