Beispiel #1
0
class ThroughAwards(ShareObject):
    funder = ShareForeignKey(AbstractAgentWorkRelation)
    award = ShareForeignKey(Award)

    class Meta(ShareObject.Meta):
        unique_together = ('funder', 'award')
        verbose_name_plural = 'through awards'

    matching_criteria = MatchByManyToOne('funder', 'award')
Beispiel #2
0
class ThroughTags(ShareObject):
    tag = ShareForeignKey(Tag, related_name='work_relations')
    creative_work = ShareForeignKey('AbstractCreativeWork', related_name='tag_relations')

    class Meta:
        unique_together = ('tag', 'creative_work')

    class Disambiguation:
        all = ('tag', 'creative_work')
Beispiel #3
0
class Association(ShareObject):
    entity = ShareForeignKey('Entity')
    creative_work = ShareForeignKey(AbstractCreativeWork)

    class Meta:
        unique_together = ('entity', 'creative_work')

    def __str__(self):
        return str(self.entity)
Beispiel #4
0
class Subject(ShareObject):
    name = models.TextField()
    is_deleted = models.BooleanField(default=False)
    uri = ShareURLField(null=True, blank=True)
    taxonomy = models.ForeignKey(SubjectTaxonomy,
                                 editable=False,
                                 on_delete=models.CASCADE)
    parent = ShareForeignKey('Subject',
                             blank=True,
                             null=True,
                             related_name='children')
    central_synonym = ShareForeignKey('Subject',
                                      blank=True,
                                      null=True,
                                      related_name='custom_synonyms')

    @classmethod
    def normalize(cls, node, graph):
        edge = node.related('central_synonym')
        if edge and edge.related and edge.related.id == node.id:
            graph.remove_edge(edge)

    def save(self, *args, **kwargs):
        if self.id is not None and self.parent is not None:
            new_lineage = self.parent.lineage()
            if self in new_lineage:
                raise CyclicalTaxonomyError(
                    'Making {} a child of {} would cause a cycle!'.format(
                        self, self.parent))
        return super().save(*args, **kwargs)

    def lineage(self):
        query = '''
            WITH RECURSIVE lineage_chain(id, parent, depth, path, cycle) AS (
                    SELECT id, parent_id, 1, ARRAY[id], false FROM {table} WHERE id = %(id)s
                  UNION
                    SELECT {table}.id, {table}.parent_id, lineage_chain.depth + 1, path || {table}.id, {table}.id = ANY(path)
                    FROM lineage_chain JOIN {table} ON lineage_chain.parent = {table}.id
                    WHERE NOT cycle
            )
            SELECT {table}.* FROM {table} INNER JOIN lineage_chain ON {table}.id = lineage_chain.id ORDER BY lineage_chain.depth DESC
        '''.format(table=self._meta.db_table)
        lineage = list(
            self._meta.model.objects.raw(query, params={'id': self.id}))
        if lineage[0].parent is not None:
            raise CyclicalTaxonomyError(
                'Subject taxonomy cycle! {}'.format(lineage))
        return lineage

    def __str__(self):
        return self.name

    class Meta:
        unique_together = (('name', 'taxonomy'), ('uri', 'taxonomy'))

    class Disambiguation:
        all = ('name', 'central_synonym')
Beispiel #5
0
class ThroughTags(ShareObject):
    tag = ShareForeignKey(Tag, related_name='work_relations')
    creative_work = ShareForeignKey('AbstractCreativeWork',
                                    related_name='tag_relations')

    class Meta(ShareObject.Meta):
        unique_together = ('tag', 'creative_work')
        verbose_name_plural = 'through tags'

    matching_criteria = MatchByManyToOne('tag', 'creative_work')
Beispiel #6
0
class ThroughAwards(ShareObject):
    funder = ShareForeignKey(AbstractAgentWorkRelation)
    award = ShareForeignKey(Award)

    class Meta:
        unique_together = ('funder', 'award')
        verbose_name_plural = 'through awards'

    class Disambiguation:
        all = ('funder', 'award')
Beispiel #7
0
class ThroughSubjects(ShareObject):
    subject = ShareForeignKey('Subject', related_name='work_relations')
    creative_work = ShareForeignKey('AbstractCreativeWork',
                                    related_name='subject_relations')
    is_deleted = models.BooleanField(default=False)

    class Meta(ShareObject.Meta):
        unique_together = ('subject', 'creative_work')
        verbose_name_plural = 'through subjects'

    matching_criteria = MatchByManyToOne('subject', 'creative_work')
Beispiel #8
0
class Affiliation(ShareObject):
    # start_date = models.DateField()
    # end_date = models.DateField()
    person = ShareForeignKey(Person)
    entity = ShareForeignKey('Entity')

    class Meta:
        unique_together = ('person', 'entity')

    def __str__(self):
        return '{} ({})'.format(self.person, self.entity)
Beispiel #9
0
class AbstractWorkRelation(ShareObject, metaclass=TypedShareObjectMeta):
    subject = ShareForeignKey('AbstractCreativeWork',
                              related_name='outgoing_creative_work_relations')
    related = ShareForeignKey('AbstractCreativeWork',
                              related_name='incoming_creative_work_relations')

    matching_criteria = MatchByManyToOne('subject',
                                         'related',
                                         constrain_types=True)

    class Meta(ShareObject.Meta):
        db_table = 'share_workrelation'
        unique_together = ('subject', 'related', 'type')
Beispiel #10
0
class Contributor(ShareObject):
    cited_name = models.TextField(blank=True)
    bibliographic = models.BooleanField(default=True)
    order_cited = models.PositiveIntegerField(null=True)

    person = ShareForeignKey(Person)
    creative_work = ShareForeignKey('AbstractCreativeWork')

    def __str__(self):
        return '{} -> {}'.format(self.person, self.creative_work)

    class Meta:
        unique_together = ('person', 'creative_work')
Beispiel #11
0
class AbstractAgentWorkRelation(ShareObject, metaclass=TypedShareObjectMeta):
    creative_work = ShareForeignKey('AbstractCreativeWork', related_name='agent_relations')
    agent = ShareForeignKey('AbstractAgent', related_name='work_relations')

    cited_as = models.TextField(blank=True)

    matching_criteria = [
        MatchByManyToOne('creative_work', 'agent', constrain_types=True),
        MatchAgentWorkRelations(),
    ]

    class Meta(ShareObject.Meta):
        db_table = 'share_agentworkrelation'
        unique_together = ('agent', 'creative_work', 'type')
Beispiel #12
0
class Contributor(ShareObject):
    cited_name = models.TextField(blank=True)
    order_cited = models.PositiveIntegerField(null=True)

    person = ShareForeignKey(Person)
    creative_work = ShareForeignKey('AbstractCreativeWork')

    def __str__(self):
        return '{} -> {}'.format(self.person, self.creative_work)

    class Meta:
        index_together = ((
            'cited_name',
            'order_cited',
        ))
Beispiel #13
0
class AgentIdentifier(ShareObject):
    """Unique identifier (in IRI form) for an agent."""
    uri = ShareURLField(unique=True)
    host = models.TextField(editable=False)
    scheme = models.TextField(editable=False)
    agent = ShareForeignKey('AbstractAgent', related_name='identifiers')

    # objects = FilteredEmailsManager()
    # objects_unfiltered = models.Manager()

    @classmethod
    def normalize(self, node, graph):
        try:
            ret = IRILink().execute(node.attrs['uri'])
        except InvalidIRI as e:
            logger.warning('Discarding invalid identifier %s with error %s',
                           node.attrs['uri'], e)
            graph.remove(node)
            return

        if node.attrs['uri'] != ret['IRI']:
            logger.debug('Normalized %s to %s', node.attrs['uri'], ret['IRI'])

        node.attrs = {
            'uri': ret['IRI'],
            'host': ret['authority'],
            'scheme': ret['scheme'],
        }

    def __repr__(self):
        return '<{}({}, {})>'.format(self.__class__.__name__, self.uri,
                                     self.agent_id)

    class Disambiguation:
        all = ('uri', )
Beispiel #14
0
class AbstractCreativeWork(ShareObject, metaclass=TypedShareObjectMeta):
    title = models.TextField(blank=True)
    description = models.TextField(blank=True)

    contributors = ShareManyToManyField(Person, through='Contributor')

    awards = ShareManyToManyField(Award, through='ThroughAwards')
    venues = ShareManyToManyField(Venue, through='ThroughVenues')

    links = ShareManyToManyField('Link', through='ThroughLinks')

    funders = ShareManyToManyField('Funder', through='Association')
    publishers = ShareManyToManyField('Publisher', through='Association')
    institutions = ShareManyToManyField('Institution', through='Association')
    organizations = ShareManyToManyField('Organization', through='Association')

    subject = ShareForeignKey(Tag,
                              related_name='subjected_%(class)s',
                              null=True)
    # Note: Null allows inserting of None but returns it as an empty string
    tags = ShareManyToManyField(Tag,
                                related_name='tagged_%(class)s',
                                through='ThroughTags')
    date_created = models.DateTimeField(null=True, db_index=True)
    date_published = models.DateTimeField(null=True, db_index=True)
    date_updated = models.DateTimeField(null=True, db_index=True)
    free_to_read_type = ShareURLField(blank=True, db_index=True)
    free_to_read_date = models.DateTimeField(null=True, db_index=True)

    rights = models.TextField(blank=True, null=True, db_index=True)
    language = models.TextField(blank=True, null=True, db_index=True)

    def __str__(self):
        return self.title
Beispiel #15
0
class AbstractAgentRelation(ShareObject, metaclass=TypedShareObjectMeta):
    subject = ShareForeignKey('AbstractAgent', related_name='outgoing_agent_relations')
    related = ShareForeignKey('AbstractAgent', related_name='incoming_agent_relations')

    class Disambiguation:
        all = ('subject', 'related')
        constrain_types = True

    class Meta(ShareObject.Meta):
        db_table = 'share_agentrelation'
        unique_together = ('subject', 'related', 'type')

    @classmethod
    def normalize(self, node, graph):
        if len(node.related()) < 2:
            logger.warning('Removing incomplete or circular relation %s, %s', node, node.related())
            graph.remove(node)
Beispiel #16
0
class ThroughSubjects(ShareObject):
    subject = models.ForeignKey('Subject', related_name='work_relations')
    creative_work = ShareForeignKey('AbstractCreativeWork', related_name='subject_relations')

    class Meta:
        unique_together = ('subject', 'creative_work')

    class Disambiguation:
        all = ('subject', 'creative_work')
Beispiel #17
0
class ThroughContributor(ShareObject):
    subject = ShareForeignKey(AbstractAgentWorkRelation, related_name='+')
    related = ShareForeignKey(AbstractAgentWorkRelation, related_name='+')

    def clean(self):
        if self.subject.creative_work != self.related.creative_work:
            raise ValidationError(_('ThroughContributors must contribute to the same AbstractCreativeWork'))
        if self.subject.agent == self.related.agent:
            raise ValidationError(_('A contributor may not contribute through itself'))

    def save(self, *args, **kwargs):
        self.clean()
        return super().save(*args, **kwargs)

    matching_criteria = MatchByManyToOne('subject', 'related')

    class Meta(ShareObject.Meta):
        unique_together = ('subject', 'related')
Beispiel #18
0
class AbstractAgentWorkRelation(ShareObject, metaclass=TypedShareObjectMeta):
    creative_work = ShareForeignKey('AbstractCreativeWork', related_name='agent_relations')
    agent = ShareForeignKey('AbstractAgent', related_name='work_relations')

    cited_as = models.TextField(blank=True)

    @classmethod
    def normalize(self, node, graph):
        for k, v in tuple(node.attrs.items()):
            if isinstance(v, str):
                node.attrs[k] = strip_whitespace(v)

    class Disambiguation:
        all = ('creative_work',)
        any = ('agent', 'cited_as')  # TODO could be multiple people with the same cited_as on a work... could use order_cited for Creators, but what to do for other contributors?
        constrain_types = True

    class Meta:
        db_table = 'share_agentworkrelation'
        unique_together = ('agent', 'creative_work', 'type')
Beispiel #19
0
class AgentIdentifier(ShareObject):
    """Unique identifier (in IRI form) for an agent."""
    uri = ShareURLField(unique=True)
    host = models.TextField(blank=True)
    scheme = models.TextField(blank=True)
    agent = ShareForeignKey('AbstractAgent', related_name='identifiers')

    # objects = FilteredEmailsManager()
    # objects_unfiltered = models.Manager()

    def __repr__(self):
        return '<{}({}, {})>'.format(self.__class__.__name__, self.uri, self.agent_id)

    matching_criteria = MatchByAttrs('uri')
Beispiel #20
0
class WorkIdentifier(ShareObject):
    """
    Unique identifier (in IRI form) for a creative work.
    """
    uri = ShareURLField(unique=True)
    host = models.TextField(editable=False)
    scheme = models.TextField(
        editable=False,
        help_text=
        _('A prefix to URI indicating how the following data should be interpreted.'
          ))
    creative_work = ShareForeignKey('AbstractCreativeWork',
                                    related_name='identifiers')

    # objects = FilteredEmailsManager()
    # objects_unfiltered = models.Manager()

    @classmethod
    def normalize(self, node, graph):
        try:
            ret = IRILink().execute(node.attrs['uri'])
        except InvalidIRI as e:
            logger.warning('Discarding invalid identifier %s with error %s',
                           node.attrs['uri'], e)
            graph.remove(node)
            return

        if ret['authority'] in {'issn', 'orcid.org'
                                } or ret['scheme'] in {'mailto'}:
            logger.warning(
                'Discarding %s %s as an invalid identifier for works',
                ret['authority'], ret['IRI'])
            graph.remove(node)
            return

        if node.attrs['uri'] != ret['IRI']:
            logger.debug('Normalized %s to %s', node.attrs['uri'], ret['IRI'])

        node.attrs = {
            'uri': ret['IRI'],
            'host': ret['authority'],
            'scheme': ret['scheme'],
        }

    def __repr__(self):
        return '<{}({}, {})>'.format(self.__class__.__name__, self.uri,
                                     self.creative_work_id)

    class Disambiguation:
        all = ('uri', )
Beispiel #21
0
class WorkIdentifier(ShareObject):
    """
    Unique identifier (in IRI form) for a creative work.
    """
    uri = ShareURLField(unique=True)
    host = models.TextField(blank=True)
    scheme = models.TextField(blank=True, help_text=_('A prefix to URI indicating how the following data should be interpreted.'))
    creative_work = ShareForeignKey('AbstractCreativeWork', related_name='identifiers')

    # objects = FilteredEmailsManager()
    # objects_unfiltered = models.Manager()

    def __repr__(self):
        return '<{}({}, {})>'.format(self.__class__.__name__, self.uri, self.creative_work_id)

    matching_criteria = MatchByAttrs('uri')
Beispiel #22
0
class ThroughLinks(ShareObject):
    link = ShareForeignKey(Link)
    creative_work = ShareForeignKey('AbstractCreativeWork')

    class Meta:
        unique_together = ('link', 'creative_work')
Beispiel #23
0
class ThroughIdentifiers(ShareObject):
    person = ShareForeignKey(Person)
    identifier = ShareForeignKey(Identifier)

    class Meta:
        unique_together = ('person', 'identifier')
Beispiel #24
0
class PersonEmail(ShareObject):
    email = ShareForeignKey(Email)
    person = ShareForeignKey(Person)

    class Meta:
        unique_together = ('email', 'person')
Beispiel #25
0
class ThroughAwardEntities(ShareObject):
    award = ShareForeignKey('Award')
    entity = ShareForeignKey('Entity')

    class Meta:
        unique_together = ('award', 'entity')
Beispiel #26
0
class ThroughSubjects(ShareObject):
    subject = models.ForeignKey('Subject')
    creative_work = ShareForeignKey('AbstractCreativeWork')

    class Meta:
        unique_together = ('subject', 'creative_work')
Beispiel #27
0
class ThroughVenues(ShareObject):
    venue = ShareForeignKey(Venue)
    creative_work = ShareForeignKey('AbstractCreativeWork')

    class Meta:
        unique_together = ('venue', 'creative_work')
Beispiel #28
0
class ThroughTags(ShareObject):
    tag = ShareForeignKey(Tag)
    creative_work = ShareForeignKey('AbstractCreativeWork')

    class Meta:
        unique_together = ('tag', 'creative_work')
Beispiel #29
0
class ThroughAwards(ShareObject):
    award = ShareForeignKey(Award)
    creative_work = ShareForeignKey('AbstractCreativeWork')

    class Meta:
        unique_together = ('award', 'creative_work')