Source code for asclepias_broker.metadata.api
# -*- coding: utf-8 -*-
#
# Copyright (C) 2018 CERN.
#
# Asclepias Broker is free software; you can redistribute it and/or modify it
# under the terms of the MIT License; see LICENSE file for more details.
"""Metadata functions."""
from datetime import datetime
from typing import List
from flask import current_app
from invenio_db import db
from ..core.models import Identifier, Relation, Relationship
from ..graph.api import get_group_from_id, get_or_create_groups
from ..graph.models import GroupRelationship, GroupType
from .models import GroupMetadata, GroupRelationshipMetadata
# TODO: When merging/splitting groups there is some merging/duplicating of
# metadata as well
[docs]def update_metadata_from_event(relationship: Relationship, payload: dict):
"""Updates the metadata of the source, target and relationship groups."""
# Get identity groups for source and targer
# TODO: Do something for this case?
if relationship.relation == Relation.IsIdenticalTo:
return
src_group = next((id2g.group for id2g in relationship.source.id2groups
if id2g.group.type == GroupType.Identity), None)
trg_group = next((id2g.group for id2g in relationship.target.id2groups
if id2g.group.type == GroupType.Identity), None)
rel_group = GroupRelationship.query.filter_by(
source=src_group, target=trg_group, relation=relationship.relation,
type=GroupType.Identity).one_or_none()
if src_group:
src_metadata = src_group.data or GroupMetadata(group_id=src_group.id)
src_metadata.update(payload['Source'])
if trg_group:
trg_metadata = trg_group.data or GroupMetadata(group_id=trg_group.id)
trg_metadata.update(payload['Target'])
if rel_group:
rel_metadata = rel_group.data or \
GroupRelationshipMetadata(group_relationship_id=rel_group.id)
rel_metadata.update(
{k: v for k, v in payload.items()
if k in ('LinkPublicationDate', 'LinkProvider')})
[docs]def update_metadata(identifier: str, scheme: str, data: dict,
create_identity_events=True,
create_missing_groups=True,
providers: List[str] = None,
link_publication_date: str = None):
"""."""
from ..events.api import EventAPI
# Check if there are identity links that can be created:
identifiers = data.get('Identifier', [])
if create_identity_events and len(identifiers) > 1:
providers = providers or ['unknown']
providers = [{'Name': provider} for provider in providers]
link_publication_date = link_publication_date or \
datetime.now().isoformat()
identifiers = data.get('Identifier')
event = []
source_identifier = identifiers[0]
for target_identifier in identifiers[1:]:
payload = {
'RelationshipType': {
'Name': 'IsRelatedTo',
'SubTypeSchema': 'DataCite',
'SubType': 'IsIdenticalTo'
},
'Target': {
'Identifier': target_identifier,
'Type': {'Name': 'unknown'}
},
'LinkProvider': providers,
'Source': {
'Identifier': source_identifier,
'Type': {'Name': 'unknown'}
},
'LinkPublicationDate': link_publication_date,
}
event.append(payload)
try:
EventAPI.handle_event(event, no_index=True, eager=True)
except ValueError:
current_app.logger.exception(
'Error while processing identity event')
try:
id_value, scheme = identifiers[0]['ID'], identifiers[0]['IDScheme']
id_group = get_group_from_id(id_value, scheme)
if not id_group and create_missing_groups:
identifier = Identifier(
value=id_value, scheme=scheme).fetch_or_create_id()
db.session.commit()
id_group, _ = get_or_create_groups(identifier)
db.session.commit()
id_group.data.update(data)
db.session.commit()
except Exception:
current_app.logger.exception('Error while updating group metadata')