def create_objects_from_relations(relationships: List[Tuple],
                                  metadata: List[Tuple[dict]]=None):
    """Given a list of relationships, create all corresponding DB objects.

    Optional 'metadata' list can be passed, which contains corresponding
    metadata items for each of the relationships, i.e., a triplet of Source,
    Relation and Target metadata.

    E.g.:
        relationships = [
            ('A', Relation.Cites, 'B'),
            ('C', Relation.Cites, 'D'),
        ]

        metadata = [
            ({<source-1>}, {<relation-1>}, {<target-1>}),
            ({<source-2>}, {<relation-2>}, {<target-2>}),
        ]

        Will create Identifier, Relationship, Group and all M2M objects.
    """
    if not metadata:
        metadata = [({}, {}, {}) for _ in range(len(relationships))]
    assert len(relationships) == len(metadata)
    identifiers = sorted(set(sum([[a, b] for a, _, b in relationships], [])))
    groups = []  # Contains pairs of (Identifier2Group, Group2Group)
    for i in identifiers:
        id_ = Identifier(value=i, scheme='doi')
        db.session.add(id_)
        groups.append(get_or_create_groups(id_))
    rel_obj = []
    for (src, rel, tar), (src_m, rel_m, tar_m) in zip(relationships, metadata):
        src_, tar_ = Identifier.get(src, 'doi'), \
            Identifier.get(tar, 'doi')
        r = Relationship(source=src_, target=tar_, relation=rel)
        db.session.add(r)
        rel_obj.append(r)
        s_id_gr, s_ver_gr = groups[identifiers.index(src)]
        t_id_gr, t_ver_gr = groups[identifiers.index(tar)]
        id_gr_rel = GroupRelationship(
            source=s_id_gr, target=t_id_gr, relation=rel,
            type=GroupType.Identity, id=uuid.uuid4())
        s_id_gr.data.update(src_m, validate=False)
        t_id_gr.data.update(tar_m, validate=False)

        grm = GroupRelationshipMetadata(group_relationship_id=id_gr_rel.id)
        db.session.add(grm)
        grm.update(rel_m, validate=False)
        db.session.add(Relationship2GroupRelationship(
            relationship=r, group_relationship=id_gr_rel))
        db.session.add(id_gr_rel)
        ver_gr_rel = GroupRelationship(
            source=s_ver_gr, target=t_ver_gr, relation=rel,
            type=GroupType.Version)
        db.session.add(GroupRelationshipM2M(
            relationship=ver_gr_rel, subrelationship=id_gr_rel))
        db.session.add(ver_gr_rel)
    db.session.commit()
Beispiel #2
0
def test_get_or_create_groups(db):
    """Test creating groups (Identity and Version) for an identifier."""
    id1 = Identifier(value='A', scheme='doi')
    db.session.add(id1)
    # id2 = Identifier(value='B', scheme='doi')
    # rel = Relationship(source=id1, target=id2,
    #                    relation=Relation.IsIdenticalTo)
    assert not Group.query.count()
    assert not GroupM2M.query.count()
    assert not Identifier2Group.query.count()
    id_g, ver_g = get_or_create_groups(id1)
    db.session.commit()

    def _check_groups(identifier, id_g, ver_g):
        assert Group.query.count() == 2
        assert GroupM2M.query.count() == 1
        assert Identifier2Group.query.count() == 1
        assert Group.query.filter_by(type=GroupType.Identity).one() == id_g
        assert Group.query.filter_by(type=GroupType.Version).one() == ver_g
        id2g = Identifier2Group.query.one()
        g2g = GroupM2M.query.one()
        assert id2g.identifier == identifier
        assert id2g.group == id_g
        assert g2g.group == ver_g
        assert g2g.subgroup == id_g

    _check_groups(id1, id_g, ver_g)

    # Fetch the ID again and try to create groups again
    id2 = Identifier.get('A', 'doi')
    assert id2
    id_g, ver_g = get_or_create_groups(id1)
    db.session.commit()

    # Make sure nothing changed
    _check_groups(id2, id_g, ver_g)

    # Add a new, separate identifier
    id3 = Identifier(value='B', scheme='doi')
    db.session.add(id3)
    id_g, ver_g = get_or_create_groups(id3)

    assert Group.query.count() == 4
    assert GroupM2M.query.count() == 2
    assert Identifier2Group.query.count() == 2
Beispiel #3
0
def id_obj(identifier, scheme):
    """Identifier DB object generator."""
    return Identifier(value=identifier, scheme=scheme)
def id_obj(identifier, scheme):
    return Identifier(value=identifier, scheme=scheme)