cubicweb_seda/__init__.py
author Denis Laxalde <denis.laxalde@logilab.fr>
Thu, 02 May 2019 09:29:04 +0200
changeset 3003 fcb890e6d9d7
parent 2898 8bd8b3533dec
permissions -rw-r--r--
[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.

# copyright 2016-2017 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
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 2.1 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
"""cubicweb-seda application package

Data Exchange Standard for Archival
"""

from cubicweb_compound import skip_rtypes_set, structure_def, CompositeGraph


# control of compound graph by adding etype / rtype to the corresponding set below
GRAPH_SKIP_ETYPES = set()
GRAPH_SKIP_RTYPES = set(['container', 'clone_of'])


def seda_profile_container_def(schema):
    """Define container for SEDAArchiveTransfer, as a list of (etype, parent_rdefs)."""
    return structure_def(schema, 'SEDAArchiveTransfer',
                         skipetypes=GRAPH_SKIP_ETYPES, skiprtypes=GRAPH_SKIP_RTYPES).items()


def _iter_external_rdefs(eschema, skip_rtypes):
    """Return an iterator on (rdef, role) of external relations from entity schema (i.e.
    non-composite relations).
    """
    for rschema, targets, role in eschema.relation_definitions():
        if rschema in skip_rtypes:
            continue
        for target_etype in targets:
            rdef = eschema.rdef(rschema, role, target_etype)
            if rdef.composite:
                continue
            yield rdef, role


def iter_all_rdefs(schema, container_etype):
    """Return an iterator on (rdef, role) of all relations of the compound graph starting from the
    given entity type, both internal (composite) and external (non-composite).
    """
    graph = CompositeGraph(schema, skipetypes=GRAPH_SKIP_ETYPES, skiprtypes=GRAPH_SKIP_RTYPES)
    skip_external_rtypes = skip_rtypes_set(GRAPH_SKIP_RTYPES)
    stack = [container_etype]
    visited = set(stack)
    while stack:
        etype = stack.pop()
        for (rtype, role), targets in graph.child_relations(etype):
            rschema = schema.rschema(rtype)
            for target in targets:
                if role == 'subject':
                    rdef = rschema.rdefs[(etype, target)]
                else:
                    rdef = rschema.rdefs[(target, etype)]
                yield rdef, role

                if target not in visited:
                    visited.add(target)
                    stack.append(target)
        for rdef, role in _iter_external_rdefs(schema[etype], skip_external_rtypes):
            yield rdef, role