示例#1
0
class Marc21Record(Record):
    """Define API for Marc21 create and manipulate."""

    model_cls = RecordMetadata
    versions_model_cls = VersionsState
    parent_record_cls = Marc21Parent

    index = IndexField("marc21records-marc21-marc21-v1.0.0",
                       search_alias="marc21records-marc21")

    parent = ParentField(Marc21Parent,
                         create=True,
                         soft_delete=False,
                         hard_delete=True)

    pid = PIDField(
        key="id",
        provider=MarcRecordProvider,
        context_cls=MarcPIDFieldContext,
        resolver_cls=MarcResolver,
        delete=False,
    )

    files = FilesField(
        store=False,
        file_cls=RecordFile,
        create=False,
        delete=False,
    )

    bucket_id = ModelField(dump=False)

    bucket = ModelField(dump=False)
示例#2
0
class Marc21Draft(Draft):
    """Marc21 draft API."""

    model_cls = DraftMetadata
    versions_model_cls = VersionsState
    parent_record_cls = Marc21Parent

    index = IndexField("marc21records-drafts-marc21-v1.0.0",
                       search_alias="marc21records-marc21")

    parent = ParentField(Marc21Parent,
                         create=True,
                         soft_delete=False,
                         hard_delete=True)

    pid = PIDField(
        key="id",
        provider=MarcDraftProvider,
        context_cls=MarcPIDFieldContext,
        resolver_cls=MarcResolver,
        delete=False,
    )

    files = FilesField(
        store=False,
        file_cls=DraftFile,
        delete=False,
    )

    bucket_id = ModelField(dump=False)

    bucket = ModelField(dump=False)
示例#3
0
class Draft(DraftBase):
    """Example record API."""

    # Configuration
    model_cls = DraftMetadata
    versions_model_cls = ParentState
    parent_record_cls = ParentRecord

    # System fields
    schema = ConstantField(
        '$schema', 'http://localhost/schemas/records/record-v1.0.0.json')

    index = IndexField('draftsresources-drafts-draft-v1.0.0',
                       search_alias='draftsresources-drafts')

    files = FilesField(
        store=False,
        file_cls=FileDraft,
        # Don't delete, we'll manage in the service
        delete=False,
    )

    bucket_id = ModelField(dump=False)

    bucket = ModelField(dump=False)
示例#4
0
class CommonFieldsMixin:
    """Common system fields between records and drafts."""

    versions_model_cls = models.RDMVersionsState
    parent_record_cls = RDMParent

    schema = ConstantField(
       '$schema', 'local://records/record-v2.0.0.json')

    dumper = ElasticsearchDumper(
        extensions=[
            EDTFDumperExt('metadata.publication_date'),
            EDTFListDumperExt("metadata.dates", "date"),
            RelationDumperExt('relations'),
        ]
    )

    relations = RelationsField(
        languages=PIDListRelation(
            'metadata.languages',
            attrs=['id', 'title'],
            pid_field=Vocabulary.pid.with_type_ctx('languages')
        ),
    )

    bucket_id = ModelField(dump=False)

    bucket = ModelField(dump=False)

    access = RecordAccessField()

    is_published = PIDStatusCheckField(status=PIDStatus.REGISTERED, dump=True)

    pids = DictField("pids")
示例#5
0
class BibliographicRecord(Record):
    """Bibliographic Record API."""

    model_cls = models.RecordMetadata

    index = IndexField('rdmrecords-records-record-v1.0.0',
                       search_alias='rdmrecords-records')

    dumper = ElasticsearchDumper(extensions=[
        EDTFDumperExt('metadata.publication_date'),
        RelationDumperExt('relations'),
    ])

    relations = RelationsField(languages=PIDListRelation(
        'metadata.languages', attrs=['metadata'], pid_field=Language.pid), )

    files = FilesField(
        store=False,
        file_cls=RecordFile,
        # Don't create
        create=False,
        # Don't delete, we'll manage in the service
        delete=False,
    )
    bucket_id = ModelField(dump=False)
    bucket = ModelField(dump=False)
示例#6
0
class Marc21Draft(Draft):
    """Marc21 draft API."""

    model_cls = DraftMetadata

    index = IndexField("marc21records-drafts-marc21-v1.0.0",
                       search_alias="marc21records-marc21")

    pid = PIDField(
        key="id",
        provider=MarcDraftProvider,
        context_cls=MarcPIDFieldContext,
        resolver_cls=MarcResolver,
        delete=False,
    )

    conceptpid = PIDField(
        key="conceptid",
        provider=MarcDraftProvider,
        context_cls=MarcPIDFieldContext,
        resolver_cls=MarcResolver,
        delete=False,
    )

    files = FilesField(
        store=False,
        file_cls=DraftFile,
        delete=False,
    )

    bucket_id = ModelField(dump=False)

    bucket = ModelField(dump=False)
示例#7
0
class CommonFieldsMixin:
    """Common system fields between records and drafts."""

    versions_model_cls = models.RDMVersionsState
    parent_record_cls = RDMParent

    schema = ConstantField(
       '$schema', 'http://localhost/schemas/records/record-v2.0.0.json')

    dumper = ElasticsearchDumper(
        extensions=[
            EDTFDumperExt('metadata.publication_date'),
            EDTFListDumperExt("metadata.dates", "date"),
            RelationDumperExt('relations'),
        ]
    )

    relations = RelationsField(
        languages=PIDListRelation(
            'metadata.languages',
            attrs=['id', 'title'],
            pid_field=Vocabulary.pid.with_type_ctx('languages')
        ),
    )

    bucket_id = ModelField(dump=False)

    bucket = ModelField(dump=False)

    access = RecordAccessField()

    # We redefine the property as we extend the `PIDStatusCheckField` to dump
    # the property in ES in order to be available for aggregation
    is_published = IsPublishedField(status=PIDStatus.REGISTERED)
class LOMDraft(Draft):
    """For representing entries from the 'lom_drafts_metadata'-SQL-table."""

    model_cls = models.LOMDraftMetadata
    parent_record_cls = LOMParent
    versions_model_cls = models.LOMVersionsState

    pid = PIDField(
        key="id",
        provider=LOMDraftRecordIdProvider,
        resolver_cls=LOMResolver,
        context_cls=LOMPIDFieldContext,
        # flag for deleting pid from database on post-record-deletion,
        # delete pid via LOMRecordService instead
        delete=False,
    )
    files = FilesField(
        file_cls=LOMFileDraft,
        delete=False,
        store=False,
    )
    access = RecordAccessField()
    bucket_id = ModelField(dump=False)
    bucket = ModelField(dump=False)
    index = IndexField("lomrecords-drafts-draft-v1.0.0",
                       search_alias="lomrecords")
    is_published = PIDStatusCheckField(status=PIDStatus.REGISTERED, dump=True)
    resource_type = DictField()
示例#9
0
class Marc21Record(Record):
    """Define API for Marc21 create and manipulate."""

    model_cls = RecordMetadata

    index = IndexField("marc21records-marc21-marc21-v1.0.0",
                       search_alias="marc21records-marc21")

    pid = PIDField(
        key="id",
        provider=MarcRecordProvider,
        delete=False,
        context_cls=MarcPIDFieldContext,
        resolver_cls=MarcResolver,
    )

    conceptpid = PIDField(
        key="conceptid",
        provider=MarcRecordProvider,
        delete=False,
        context_cls=MarcPIDFieldContext,
        resolver_cls=MarcResolver,
    )

    files = FilesField(
        store=False,
        file_cls=RecordFile,
        create=False,
        delete=False,
    )

    bucket_id = ModelField(dump=False)

    bucket = ModelField(dump=False)
示例#10
0
class Vocabulary(RecordBase):
    """Example record API."""

    # Configuration
    model_cls = VocabularyMetadata

    dumper = ElasticsearchDumper(
        extensions=[VocabularyTypeElasticsearchDumperExt()]
    )

    # System fields
    schema = ConstantField(
        "$schema",
        "https://localhost/schemas/vocabularies/vocabulary-v1.0.0.json",
    )

    index = IndexField(
        "vocabularies-vocabulary-v1.0.0", search_alias="vocabularies"
    )

    # TODO: This should be changed to use something else than the recidv2
    pid = PIDField("id", provider=RecordIdProviderV2)

    vocabulary_type_id = ModelField()

    vocabulary_type = VocabularyTypeField(dump=False)
示例#11
0
class Draft(Record):
    """Draft base API for metadata creation and manipulation."""

    # WHY: We want to force the model_cls to be specified by the user
    # No default one is given, only the base.
    model_cls = None

    pid = PIDField('id', provider=RecordIdProviderV2, delete=False)

    conceptpid = PIDField('conceptid',
                          provider=RecordIdProviderV2,
                          delete=False)

    expires_at = ModelField()

    fork_version_id = ModelField()
class Community(Record):
    """Community API."""

    pid = PIDField('id', provider=CommunitiesIdProvider, create=False)
    schema = ConstantField('$schema',
                           'local://communities/communities-v1.0.0.json')

    model_cls = models.CommunityMetadata

    index = IndexField("communities-communities-v1.0.0",
                       search_alias="communities")

    access = CommunityAccessField()

    bucket_id = ModelField(dump=False)
    bucket = ModelField(dump=False)
    files = FilesField(
        store=False,
        file_cls=CommunityFile,
        # Don't delete, we'll manage in the service
        delete=False,
    )
示例#13
0
class Record(RecordBase):
    """Example record API."""

    # Configuration
    model_cls = RecordMetadata

    # Model fields
    expires_at = ModelField()

    # System fields
    schema = ConstantField(
        '$schema', 'http://localhost/schemas/records/record-v1.0.0.json')

    index = IndexField('records-record-v1.0.0', search_alias='records')

    pid = PIDField('id', provider=RecordIdProviderV2)

    conceptpid = PIDField('conceptid', provider=RecordIdProviderV2)

    is_published = PIDStatusCheckField(status=PIDStatus.REGISTERED)
示例#14
0
class CommonFieldsMixin:
    """Common system fields between records and drafts."""

    versions_model_cls = models.RDMVersionsState
    parent_record_cls = RDMParent

    schema = ConstantField(
       '$schema', 'local://records/record-v5.0.0.json')

    dumper = ElasticsearchDumper(
        extensions=[
            EDTFDumperExt('metadata.publication_date'),
            EDTFListDumperExt("metadata.dates", "date"),
            RelationDumperExt('relations'),
        ]
    )

    relations = RelationsField(
        creator_affiliations=PIDNestedListRelation(
            'metadata.creators',
            relation_field='affiliations',
            keys=['name'],
            pid_field=Affiliation.pid,
            cache_key='affiliations',
        ),
        contributor_affiliations=PIDNestedListRelation(
            'metadata.contributors',
            relation_field='affiliations',
            keys=['name'],
            pid_field=Affiliation.pid,
            cache_key='affiliations',
        ),
        languages=PIDListRelation(
            'metadata.languages',
            keys=['title'],
            pid_field=Vocabulary.pid.with_type_ctx('languages'),
            cache_key='languages',
        ),
        resource_type=PIDRelation(
            'metadata.resource_type',
            keys=['title', 'props.type', 'props.subtype'],
            pid_field=Vocabulary.pid.with_type_ctx('resourcetypes'),
            cache_key='resource_type',
            value_check=dict(tags=['depositable']),
        ),
        subjects=PIDListRelation(
            'metadata.subjects',
            keys=['subject', 'scheme'],
            pid_field=Subject.pid,
            cache_key='subjects',
        ),
        licenses=PIDListRelation(
            'metadata.rights',
            keys=['title', 'description',
                  'icon', 'props.url', 'props.scheme'],
            pid_field=Vocabulary.pid.with_type_ctx('licenses'),
            cache_key='licenses',
        ),
        related_identifiers=PIDListRelation(
            'metadata.related_identifiers',
            keys=['title'],
            pid_field=Vocabulary.pid.with_type_ctx('resourcetypes'),
            cache_key='resource_type',
            relation_field='resource_type',
            value_check=dict(tags=['linkable']),
        ),
        title_types=PIDListRelation(
            'metadata.additional_titles',
            keys=['title'],
            pid_field=Vocabulary.pid.with_type_ctx('titletypes'),
            cache_key='title_type',
            relation_field='type',
        ),
        title_languages=PIDListRelation(
            'metadata.additional_titles',
            keys=['title'],
            pid_field=Vocabulary.pid.with_type_ctx('languages'),
            cache_key='languages',
            relation_field='lang',
        ),
        creators_role=PIDListRelation(
            'metadata.creators',
            keys=['title'],
            pid_field=Vocabulary.pid.with_type_ctx('creatorsroles'),
            cache_key='role',
            relation_field='role'
        ),
        contributors_role=PIDListRelation(
            'metadata.contributors',
            keys=['title'],
            pid_field=Vocabulary.pid.with_type_ctx('contributorsroles'),
            cache_key='role',
            relation_field='role'
        ),
        description_type=PIDListRelation(
            'metadata.additional_descriptions',
            keys=['title'],
            pid_field=Vocabulary.pid.with_type_ctx('descriptiontypes'),
            cache_key='description_type',
            relation_field='type',
        ),
        description_languages=PIDListRelation(
            'metadata.additional_descriptions',
            keys=['title'],
            pid_field=Vocabulary.pid.with_type_ctx('languages'),
            cache_key='languages',
            relation_field='lang',
        ),
        date_types=PIDListRelation(
            'metadata.dates',
            keys=['title'],
            pid_field=Vocabulary.pid.with_type_ctx('datetypes'),
            cache_key='date_types',
            relation_field='type',
        ),
        relation_types=PIDListRelation(
            'metadata.related_identifiers',
            keys=['title'],
            pid_field=Vocabulary.pid.with_type_ctx('relationtypes'),
            cache_key='relation_types',
            relation_field='relation_type',
        ),
    )

    bucket_id = ModelField(dump=False)

    bucket = ModelField(dump=False)

    access = RecordAccessField()

    is_published = PIDStatusCheckField(status=PIDStatus.REGISTERED, dump=True)

    pids = DictField("pids")
示例#15
0
class Draft(Record):
    """Draft base API for metadata creation and manipulation."""

    #: Class attribute to make it easy to check if record is a draft or not.
    is_draft = True

    #
    # Configuration to be set by a subclass
    #

    #: The record's SQLAlchemy model class. Must be set by the subclass.
    model_cls = None
    #: The parent state's SQLAlchemy model class. Must be set by the subclass.
    versions_model_cls = None
    #: The parent record's API class. Must be set by the subclass.
    parent_record_cls = None

    #
    # System fields
    #

    #: The internal persistent identifier. Records and drafts share UUID.
    pid = PIDField('id', provider=DraftRecordIdProviderV2, delete=False)

    #: The parent record - the draft is responsible for creating the parent.
    parent = ParentField(ParentRecord,
                         create=True,
                         soft_delete=False,
                         hard_delete=True)

    #: Version relationship
    versions = VersionsField(create=True, set_next=True)

    #: The expiry date of the draft.
    expires_at = ModelField()

    #: Revision id of record from which this draft was created.
    fork_version_id = ModelField()

    @classmethod
    def new_version(cls, record):
        """Create a draft for a new version of a record.

        The caller is responsible for:
        1) checking if a draft for a new version already exists
        2) moving the record data into the draft data.
        """
        return cls.create(
            {},
            # We create a new id, because this is for a new version.
            id=uuid.uuid4(),
            # Links the draft with the same parent (i.e. a new version).
            parent=record.parent,
            versions=record.versions,
            # New drafts without a record (i.e. unpublished drafts) must set
            # the fork version id to None.
            fork_version_id=None,
        )

    @classmethod
    def edit(cls, record):
        """Create a draft for editing an existing version of a record."""
        try:
            # We soft-delete a draft once it has been published, in order to
            # keep the version_id counter around for optimistic concurrency
            # control (both for ES indexing and for REST API clients)
            draft = cls.get_record(record.id, with_deleted=True)
            if draft.is_deleted:
                draft.undelete()
                # Below line is needed to dump PID back into the draft.
                draft.pid = record.pid
                # Ensure record is link with the parent
                draft.parent = record.parent
                draft.versions = record.versions
                # Ensure we record the revision id we forked from
                draft.fork_version_id = record.revision_id
                # Note, other values like bucket_id values was kept in the
                # soft-deleted record, so we are not setting them again here.
        except NoResultFound:
            # If a draft was ever force deleted, then we will create the draft.
            # This is a very exceptional case as normally, when we edit a
            # record then the soft-deleted draft exists and we are in above
            # case.
            draft = cls.create(
                {},
                # A draft to edit a record must share the id and uuid.
                id_=record.id,
                pid=record.pid,
                # Link it with the same parent record
                parent=record.parent,
                versions=record.versions,
                # Record which record version we forked from.
                fork_version_id=record.revision_id,
            )
        return draft
class Record(RecordBase):

    files = FilesField(store=True, file_cls=FileRecord)
    bucket_id = ModelField()
    bucket = ModelField(dump=False)
示例#17
0
class RecordWithFiles(Record):
    """Example record with file API."""

    files = FilesField(store=False, file_cls=FileRecord)
    bucket_id = ModelField()
    bucket = ModelField(dump=False)
class Record(BaseMarc21Record):
    """Test record class."""

    files = FilesField(store=True, file_cls=RecordFile)
    bucket_id = ModelField()
    bucket = ModelField(dump=False)
示例#19
0
class Record(RecordBase):
    """Mock record class."""
    model_cls = RecordMetadataWithPID
    pid = ModelPIDField()
    pid_status = ModelField()
示例#20
0
 class Record1(Record, SystemFieldsMixin):
     model_cls = Record1Metadata
     dumper = ElasticsearchDumper()
     # Don't do this at home (two system fields on the same model field):
     expires_at = ModelField()
     expires = ModelField('expires_at', dump=False)