예제 #1
0
    def add(self, first_pid, second_pid):
        """Create a new relation between first and second.

        Use cases:

          * first or second have no relations of this type: simply create
            the relation by using the first has parent and the second as child.

          * first or second have already an existing relation of this type.
            In this case, all PIDs of any relation of first or second are
            removed from the db.
            All PIDs, including the new ones, are added to a set for new
            relations to create. A new parent is randomly chosen from this set
            and new relations are created.

        Example:
            1 -> 2 <rel-type-1>
            1 -> 3 <rel-type-1>
            4 -> 5 <rel-type-1>

            add(3, 4)

            1 -> 2 <rel-type-1>
            1 -> 3 <rel-type-1>
            1 -> 4 <rel-type-1>
            1 -> 5 <rel-type-1>

        """
        # get all relations where first is a parent or a child, or second is
        # a parent or a child (any relation where first or second are involved)
        all_relations = self.get_any_relation_of(first_pid, second_pid)

        if not all_relations:
            # parent or child has no relations yet
            PIDRelation.create(first_pid, second_pid, self.relation_type.id)
        else:
            if self.relation_exists(first_pid, second_pid):
                # there should be only one possible relation for this PID
                # for a given `relation_type`
                # do not raise because it might be that user is just adding
                # metadata to an existing relation
                return

            # parent or child has already at least one relation

            # compute a `set` with all PIDs
            pids_to_relate = set()
            for rel in all_relations:
                pids_to_relate.add(rel.parent)
                pids_to_relate.add(rel.child)

            # add to the set the first and the second (the new relation)
            pids_to_relate.add(first_pid)
            pids_to_relate.add(second_pid)

            self._recreate_relations_with_random_parent(
                all_relations, pids_to_relate
            )
예제 #2
0
def serialize_relations(pid):
    """Serialize the relations for given PID."""
    data = {}
    relations = PIDRelation.get_child_relations(pid).all()
    for relation in relations:
        rel_cfg = resolve_relation_type_config(relation.relation_type)
        dump_relation(rel_cfg.api(relation.parent), rel_cfg, pid, data)
    parent_relations = PIDRelation.get_parent_relations(pid).all()
    rel_cfgs = set([resolve_relation_type_config(p) for p in parent_relations])
    for rel_cfg in rel_cfgs:
        dump_relation(rel_cfg.api(pid), rel_cfg, pid, data)
    return data
예제 #3
0
    def _recreate_relations_with_random_parent(self, relations_to_delete,
                                               pids_to_relate):
        """Delete existing relations and re-create them with a new parent."""
        # elect a new parent randomly
        new_parent = pids_to_relate.pop()
        # get the remaining PIDs, future children
        remaining_pids = list(pids_to_relate)

        with db.session.begin_nested():
            # delete all existing relations
            for rel in relations_to_delete:
                db.session.delete(rel)

            # re-create all relations with the new parent
            for pid in remaining_pids:
                PIDRelation.create(new_parent, pid, self.relation_type.id)
예제 #4
0
def serialize_relations(pid):
    """Serialize the relations for given PID."""
    data = {}
    relations = PIDRelation.get_child_relations(pid).all()
    parent_relation = PIDRelation.get_parent_relations(pid).first()
    if parent_relation:
        relations.append(parent_relation)

    for relation in relations:
        rel_cfg = resolve_relation_type_config(relation.relation_type)
        schema_class = rel_cfg.schema
        schema = schema_class()
        schema.context['pid'] = pid
        result, errors = schema.dump(rel_cfg.api(relation=relation))
        data.setdefault(rel_cfg.name, []).append(result)
    return data
예제 #5
0
    def add(self, parent_pid, child_pid):
        """Add a new relation between parent and child."""
        if self.relation_exists(parent_pid, child_pid):
            raise RecordRelationsError(
                "The relation `{}` between PID `{}` and PID `{}` already "
                "exists".format(
                    self.relation_type.name,
                    parent_pid.pid_value,
                    child_pid.pid_value,
                ))

        with db.session.begin_nested():
            return PIDRelation.create(parent_pid, child_pid,
                                      self.relation_type.id)
예제 #6
0
    def add(self, previous_pid, next_pid):
        """Add a new relation between previous and next pid."""
        if self.relation_exists(previous_pid, next_pid):
            raise RecordRelationsError(
                "The relation `{}` between parent PID `{}` and child PID `{}` "
                "already exists".format(
                    self.relation_type.name,
                    previous_pid.pid_value,
                    next_pid.pid_value,
                ))

        with db.session.begin_nested():
            return PIDRelation.create(previous_pid, next_pid,
                                      self.relation_type.id)