예제 #1
0
    def _create_sequence_relation(self, record, relation_type, payload):
        """Create a Sequence relation.

        Expected payload:

            {
                next_pid: <pid_value>,
                next_pid_type: <pid_type>,
                previous_pid: <pid_value>,
                previous_pid_type: <pid_type>,
                relation_type: "<Relation name>",
            }
        """
        next_pid, next_pid_type, previous_pid, previous_pid_type, metadata = \
            self._validate_sequence_creation_payload(record, payload)

        next_rec = IlsRecord.get_record_by_pid(next_pid,
                                               pid_type=next_pid_type)

        previous_rec = IlsRecord.get_record_by_pid(previous_pid,
                                                   pid_type=previous_pid_type)

        relation_sequence = RecordRelationsSequence()
        mod_prev, mod_next = relation_sequence.add(previous_rec=previous_rec,
                                                   next_rec=next_rec,
                                                   relation_type=relation_type,
                                                   **metadata)
        return [mod_prev, mod_next], previous_rec, next_rec
예제 #2
0
    def _delete_sequence_relation(self, record, relation_type, payload):
        """Delete sequence relation.

        Expected payload:

            {
                next_pid_value: <pid_value>,
                next_pid_type: <pid_type>,
                previous_pid_value: <pid_value>,
                previous_pid_type: <pid_type>,
                relation_type: "<Relation name>",
            }
        """
        next_pid_value, next_pid_type, prev_pid_value, prev_pid_type, metadata = self._validate_sequence_creation_payload(
            record, payload
        )

        next_rec = IlsRecord.get_record_by_pid(
            next_pid_value, pid_type=next_pid_type
        )

        previous_rec = IlsRecord.get_record_by_pid(
            prev_pid_value, pid_type=prev_pid_type
        )

        relation_sequence = RecordRelationsSequence()
        relation_sequence.remove(
            previous_rec=previous_rec,
            next_rec=next_rec,
            relation_type=relation_type,
        )
        return previous_rec, next_rec
예제 #3
0
    def _create_sibling_relation(self, record, relation_type, payload):
        """Create a Siblings relation from current record to the given PID.

        Expected payload:

            {
                pid_value: <pid_value>,
                pid_type: <pid_type>,
                relation_type: "<relation name>",
                [note: "<note>"]
            }
        """
        pid_value, pid_type, metadata = self._validate_siblings_creation_payload(
            payload
        )

        if pid_value == record["pid"] and pid_type == record._pid_type:
            raise RecordRelationsError(
                "Cannot create a relation for PID `{}` with itself".format(
                    pid_value
                )
            )

        second = IlsRecord.get_record_by_pid(pid_value, pid_type=pid_type)

        rr = RecordRelationsSiblings()
        modified_record = rr.add(
            first=record,
            second=second,
            relation_type=relation_type,
            **metadata
        )
        return modified_record, record, second
예제 #4
0
    def _build_sequence(self, rec_pid, relation_type):
        """Return the relation object with metadata."""
        pid = rec_pid.pid_value
        pid_type = rec_pid.pid_type

        r = self._build_relations_object(pid, pid_type)

        # retrieve any extra `relations_metadata`
        from invenio_app_ils.records.api import IlsRecord
        seq_record = IlsRecord.get_record_by_pid(pid, pid_type=pid_type)

        metadata = RecordRelationsMetadata.get_metadata_for(
            self.record, relation_type, pid, pid_type
        )
        r.update(metadata or {})
        r["title"] = seq_record.get("title", "")

        edition = seq_record.get("edition")
        if edition:
            r["edition"] = edition

        languages = seq_record.get("languages")
        if languages:
            r["languages"] = languages

        r["relation_type"] = relation_type
        return r
예제 #5
0
    def _build_sibling(self, related_pid, relation_type):
        """Return the relation object with metadata."""
        pid = related_pid.pid_value
        pid_type = related_pid.pid_type

        r = self._build_relations_object(pid, pid_type)

        # fetch the sibling to retrieve any extra `relations_metadata`
        from invenio_app_ils.records.api import IlsRecord
        sibling = IlsRecord.get_record_by_pid(pid, pid_type=pid_type)

        # get `relations_metadata` field data from the sibling referring to
        # this record
        metadata = RecordRelationsMetadata.get_metadata_for(
            self.record, relation_type, pid, pid_type
        )
        # merge with any `relations_metadata`
        r.update(metadata or {})

        # add also title, language and edition of the sibling
        r["title"] = sibling.get("title", "")
        r["document_type"] = sibling.get("document_type", "")
        r["mode_of_issuance"] = sibling.get("mode_of_issuance", "")
        languages = sibling.get("languages")
        if languages:
            r["languages"] = languages

        edition = sibling.get("edition", "")
        if edition:
            r["edition"] = edition

        r["relation_type"] = relation_type

        return r
예제 #6
0
 def _get_record(self, record, pid, pid_type):
     """Return record if same PID or fetch the record."""
     if record.pid == pid and record._pid_type == pid_type:
         rec = record
     else:
         rec = IlsRecord.get_record_by_pid(pid, pid_type=pid_type)
     return rec
예제 #7
0
def test_get_record_by_pid_and_pid_type(testdata, pid, pid_type, expected_cls):
    """Test get_record_by_pid with pid_type."""
    record = IlsRecord.get_record_by_pid(pid, pid_type=pid_type)

    assert isinstance(record, expected_cls)
    assert record["pid"] == pid
    assert record._pid_type == pid_type
예제 #8
0
    def _build_child(self, parent_pid, child_pid, relation_type):
        """Return the relation object with metadata of the parent."""
        # this is a child, relations_metadata are stored in the parent
        pid = parent_pid.pid_value
        pid_type = parent_pid.pid_type

        r = self._build_relations_object(pid, pid_type)

        # fetch the parent to retrieve any extra `relations_metadata`
        from invenio_app_ils.records.api import IlsRecord
        parent = IlsRecord.get_record_by_pid(pid, pid_type=pid_type)

        # get `relations_metadata` field data from the parent referring to this
        # record
        metadata = RecordRelationsMetadata.get_metadata_for(
            parent, relation_type, child_pid.pid_value, child_pid.pid_type)
        # `relations_metadata` has pid and pid_type of the child
        # replace it with the parent ones
        if metadata and "pid" in metadata and "pid_type" in metadata:
            metadata["pid"] = pid
            metadata["pid_type"] = pid_type

        # merge with any `relations_metadata`
        r.update(metadata or {})

        # add also the title of the parent
        r["title"] = parent.get("title", "")
        r["relation_type"] = relation_type

        return r
예제 #9
0
def index_related_records(indexed, related):
    """Index related records."""
    referenced = []
    for pid, pid_type in related:
        referenced.append(
            dict(pid_type=pid_type,
                 record=IlsRecord.get_record_by_pid(pid, pid_type=pid_type)))

    indexer = ReferencedRecordsIndexer()
    indexer.index(indexed, referenced)
예제 #10
0
    def test_get_record_by_pid_and_pid_type():
        """Test get_record_by_pid with pid_type."""
        tests = [("docid-1", "docid", Document), ("serid-1", "serid", Series)]

        for pid, pid_type, expected_cls in tests:
            record = IlsRecord.get_record_by_pid(pid, pid_type=pid_type)

            assert isinstance(record, expected_cls)
            assert record["pid"] == pid
            assert record._pid_type == pid_type
예제 #11
0
def index_related_record(pid, rec_type, related_pid, related_pid_type):
    """Index document to re-compute circulation information."""
    related = IlsRecord.get_record_by_pid(related_pid,
                                          pid_type=related_pid_type)
    log_func = partial(_log,
                       origin_rec_type=rec_type,
                       origin_recid=pid,
                       dest_rec_type=related.__class__.__name__)
    log_func(msg=MSG_ORIGIN)
    _index_record_by_pid(related.__class__, related["pid"], log_func)
예제 #12
0
def index_related_records_after_record_changed(pid, pid_type, rec_type):
    """Index related records after a document/series has been indexed."""
    record = IlsRecord.get_record_by_pid(pid, pid_type=pid_type)
    relations = record.relations.get()
    eta = datetime.utcnow() + current_app.config["ILS_INDEXER_TASK_DELAY"]
    for relation_type, related_records in relations.items():
        for obj in related_records:
            index_related_record.apply_async(
                (pid, rec_type, obj["pid"], obj["pid_type"]),
                eta=eta,
            )
예제 #13
0
def get_related_records(document_pid):
    """Get referenced records via relations."""
    referenced = []
    doc_record_cls = current_app_ils.document_record_cls
    record = doc_record_cls.get_record_by_pid(document_pid)
    relations = record.relations
    for relation_type, related_records in relations.items():
        for obj in related_records:
            rec = IlsRecord.get_record_by_pid(obj["pid_value"],
                                              pid_type=obj["pid_type"])
            referenced.append(dict(pid_type=obj["pid_type"], record=rec))
    return referenced
예제 #14
0
def get_related_records(series_pid):
    """Get referenced records via relations."""
    referenced = []
    series_record_cls = current_app_ils.series_record_cls
    record = series_record_cls.get_record_by_pid(series_pid)
    relations = record.relations.get()
    for relation_type, related_records in relations.items():
        for obj in related_records:
            rec = IlsRecord.get_record_by_pid(obj["pid"],
                                              pid_type=obj["pid_type"])
            referenced.append(dict(pid_type=obj["pid_type"], record=rec))
    return referenced
예제 #15
0
    def _build_relation_obj(self, related_pid, relation_type):
        """Return the relation object with metadata."""
        pid_value = related_pid.pid_value
        pid_type = related_pid.pid_type

        r = self.build_relations_object(pid_value, pid_type, relation_type)

        # fetch the sequence to retrieve useful metadata (title, ...)
        from invenio_app_ils.records.api import IlsRecord
        seq_rec = IlsRecord.get_record_by_pid(pid_value, pid_type=pid_type)

        # copy relevant fields from the sequence record into the relation
        relevant_fields = self.get_relevant_fields_from(seq_rec)
        r.update(relevant_fields)
        return r
예제 #16
0
 def _extend_related_records(self, record, size):
     """Extend record's related_record data with more fields."""
     count = {
         relation.name: 0
         for relation in current_app.config["PIDRELATIONS_RELATION_TYPES"]
     }
     related_records = []
     for obj in record["related_records"]:
         count[obj["relation_type"]] += 1
         if count[obj["relation_type"]] > size:
             continue
         related = IlsRecord.get_record_by_pid(obj["pid"],
                                               pid_type=obj["pid_type"])
         obj["title"] = related.get("title", "")
         obj["edition"] = related.get("edition", "")
         obj["language"] = related.get("language", "")
         related_records.append(obj)
     record["related_records"] = related_records
     record["related_records_count"] = count
예제 #17
0
    def _build_relation_obj(self, child, parent_pid, relation_type):
        """Return the relation object with any extra metadata."""
        pid_value = parent_pid.pid_value
        pid_type = parent_pid.pid_type

        r = self.build_relations_object(pid_value, pid_type, relation_type)

        metadata = RelationsExtraMetadata.get_extra_metadata_from(
            child, relation_type, parent_pid.pid_value, parent_pid.pid_type)
        # copy the extra metadata into the relation, if any
        r.update(metadata)

        # fetch the parent to retrieve useful metadata (title, ...)
        from invenio_app_ils.records.api import IlsRecord
        parent = IlsRecord.get_record_by_pid(pid_value, pid_type=pid_type)

        # copy relevant fields from parent into the relation
        relevant_fields = self.get_relevant_fields_from(parent)
        r.update(relevant_fields)
        return r
예제 #18
0
 def post(self, record, **kwargs):
     """Update relations."""
     for obj in request.get_json():
         related = IlsRecord.get_record_by_pid(obj["pid"],
                                               pid_type=obj["pid_type"])
         relation_type = RelatedRecords.get_relation_by_name(
             obj["relation_type"])
         action = obj.get("action", "")
         if action == "add":
             record.related.add(related, relation_type)
         elif action == "remove":
             record.related.remove(related, relation_type)
         else:
             raise RelatedRecordError(("Failed to update related records - "
                                       "invalid action: {}").format(action))
     record.commit()
     db.session.commit()
     size = self.get_size(record)
     self._extend_related_records(record, size)
     return self.make_response(record["pid"], record, 200)
예제 #19
0
    def _build_relation_obj(self, sibling_pid, relation_type):
        """Return the relation object with metadata."""
        pid_value = sibling_pid.pid_value
        pid_type = sibling_pid.pid_type

        r = self.build_relations_object(pid_value, pid_type, relation_type)

        # fetch the sibling to retrieve useful metadata (title, ...) and also
        # any optional extra metadata for this relation
        from invenio_app_ils.records.api import IlsRecord
        sibling = IlsRecord.get_record_by_pid(pid_value, pid_type=pid_type)

        metadata = self._get_extra_metadata(self.record, sibling,
                                            relation_type)
        # copy the extra metadata into the relation, if any
        r.update(metadata)

        # copy relevant fields from sibling into the relation
        relevant_fields = self.get_relevant_fields_from(sibling)
        r.update(relevant_fields)
        return r
예제 #20
0
    def _delete_sibling_relation(self, record, relation_type, payload):
        """Delete a Siblings relation from current record to the given PID.

        Expected payload:

            {
                pid_value: <pid_value>,
                pid_type: <pid_type>,
                relation_type: "<relation name>"
            }
        """
        pid_value, pid_type, _ = self._validate_siblings_creation_payload(
            payload)

        second = IlsRecord.get_record_by_pid(pid_value, pid_type=pid_type)

        rr = RecordRelationsSiblings()
        modified_record, _ = rr.remove(first=record,
                                       second=second,
                                       relation_type=relation_type)
        return modified_record, record, second