Exemplo n.º 1
0
class SimpleRecordDeposition(DepositionType):
    """Simple record submission - no support for editing nor REST API."""

    workflow = [
        # Pre-fill draft with values passed in from request
        prefill_draft(draft_id='default'),
        # Render form and wait for user to submit
        render_form(draft_id='default'),
        # Create the submission information package by merging form data
        # from all drafts (in this case only one draft exists).
        prepare_sip(),
        # Process metadata to match your JSONAlchemy record model. This will
        # call process_sip_metadata() on your subclass.
        process_sip_metadata(),
        # Reserve a new record id, so that we can provide proper feedback to
        # user before the record has been uploaded.
        create_recid(),
        # Generate MARC based on metadata dictionary.
        finalize_record_sip(is_dump=False),
        # Hold the deposition for admin approval
        hold_for_approval(),
        # Seal the SIP and write MARCXML file and call bibupload on it
        upload_record_sip(),
    ]

    hold_for_upload = False

    @classmethod
    def render_completed(cls, d):
        """Page to render when deposition was successfully completed."""
        ctx = dict(
            deposition=d,
            deposition_type=(None if d.type.is_default() else
                             d.type.get_identifier()),
            uuid=d.id,
            my_depositions=Deposition.get_depositions(current_user,
                                                      type=d.type),
            sip=d.get_latest_sip(),
            format_record=format_record,
        )

        return render_template('deposit/completed.html', **ctx)

    @classmethod
    def process_sip_metadata(cls, deposition, metadata):
        """Implement this method in your subclass to process"""
        """metadata prior to MARC generation."""
        pass
Exemplo n.º 2
0
class upload(DepositionType):
    """
    Zenodo deposition workflow
    """
    workflow = [
        p.IF_ELSE(
            has_submission,
            # Existing deposition
            [
                # Load initial record
                load_record(
                    draft_id='_edit',
                    post_process=process_draft
                ),
                # Render the form and wait until it is completed
                render_form(draft_id='_edit'),
            ],
            # New deposition
            [
                # Load pre-filled data from cache
                prefill_draft(draft_id='_default'),
                # Render the form and wait until it is completed
                render_form(draft_id='_default'),
                # Test if all files are available for API
                api_validate_files(),
            ]
        ),
        # Create the submission information package by merging data
        # from all drafts - i.e. generate the recjson.
        prepare_sip(),
        p.IF_ELSE(
            has_submission,
            [
                # Process SIP recjson
                process_sip_metadata(process_recjson_edit),
                # Merge SIP metadata into record and generate MARC
                merge_record(
                    draft_id='_edit',
                    post_process_load=process_draft,
                    process_export=process_recjson_edit,
                    merge_func=merge,
                ),
                # Set file restrictions
                process_bibdocfile(process=process_files),
            ],
            [
                # Check for reserved recids.
                reserved_recid(),
                # Reserve a new record id
                create_recid(),
                # Register DOI in internal pid store.
                mint_pid(
                    pid_field='doi',
                    pid_store_type='doi',
                    pid_creator=lambda recjson: create_doi(
                        recid=recjson['recid']
                    )['doi'],
                    existing_pid_checker=check_existing_pid,
                ),
                # Process SIP metadata
                process_sip_metadata(process_recjson_new),
            ]
        ),
        # Generate MARC based on recjson structure
        finalize_record_sip(),
        p.IF_ELSE(
            has_submission,
            [
                # Seal the SIP and write MARCXML file and call bibupload on it
                upload_record_sip(),
                # Schedule background tasks.
                run_tasks(update=True),
            ],
            [
                # Note: after upload_record_sip(), has_submission will return
                # True no matter if it's a new or editing of a deposition.
                upload_record_sip(),
                run_tasks(update=False),
            ]
        ),
    ]
    name = "Upload"
    name_plural = "Uploads"
    editable = True
    stopable = True
    enabled = True
    default = True
    api = True
    draft_definitions = {
        '_default': ZenodoForm,
        '_edit': ZenodoEditForm,
    }

    marshal_metadata_fields = dict(
        access_right=fields.String,
        communities=fields.List(fields.Raw),
        conference_acronym=fields.String,
        conference_dates=fields.String,
        conference_place=fields.String,
        conference_title=fields.String,
        conference_url=fields.String,
        conference_session=fields.String,
        conference_session_part=fields.String,
        creators=fields.Raw(default=[]),
        description=fields.String,
        doi=fields.String(default=''),
        embargo_date=ISODate,
        grants=fields.List(fields.Raw),
        image_type=fields.String(default=''),
        imprint_isbn=fields.String,
        imprint_place=fields.String,
        imprint_publisher=fields.String,
        journal_issue=fields.String,
        journal_pages=fields.String,
        journal_title=fields.String,
        journal_volume=fields.String,
        keywords=fields.Raw(default=[]),
        license=fields.String,
        notes=fields.String(default=''),
        partof_pages=fields.String,
        partof_title=fields.String,
        prereserve_doi=fields.Raw,
        publication_date=ISODate,
        publication_type=fields.String(default=''),
        references=fields.List(fields.String, default=[]),
        related_identifiers=fields.Raw(default=[]),
        thesis_supervisors=fields.Raw(default=[]),
        title=fields.String,
        upload_type=fields.String,
    )

    marshal_metadata_edit_fields = marshal_metadata_fields.copy()
    del marshal_metadata_edit_fields['prereserve_doi']
    #marshal_metadata_edit_fields.update(dict(
    #    recid=fields.Integer,
    #    version_id=UTCISODateTime,
    #))

    marshal_deposition_fields = DepositionType.marshal_deposition_fields.copy()
    del marshal_deposition_fields['drafts']

    marshal_draft_fields = DepositionType.marshal_draft_fields.copy()
    marshal_draft_fields['metadata'] = fields.Nested(
        marshal_metadata_fields, attribute='values'
    )
    del marshal_draft_fields['id']
    del marshal_draft_fields['completed']

    @classmethod
    def default_draft_id(cls, deposition):
        if deposition.has_sip() and '_edit' in deposition.drafts:
            return '_edit'
        return '_default'

    @classmethod
    def marshal_deposition(cls, deposition):
        """
        Generate a JSON representation for REST API of a Deposition
        """
        # Get draft
        if deposition.has_sip() and '_edit' in deposition.drafts:
            draft = deposition.get_draft('_edit')
            metadata_fields = cls.marshal_metadata_edit_fields
        elif deposition.has_sip():
            # FIXME: Not based on latest available data in record.
            sip = deposition.get_latest_sip(sealed=True)
            draft = record_to_draft(
                Record.create(sip.package, master_format='marc'),
                post_process=process_draft
            )
            metadata_fields = cls.marshal_metadata_edit_fields
        else:
            draft = deposition.get_or_create_draft('_default')
            metadata_fields = cls.marshal_metadata_fields

        # Fix known differences in marshalling
        draft.values = filter_empty_elements(draft.values)
        if 'grants' not in draft.values:
            draft.values['grants'] = []

        # Set disabled values to None in output
        for field, flags in draft.flags.items():
            if 'disabled' in flags and field in draft.values:
                del draft.values[field]

        # Marshal deposition
        obj = marshal(deposition, cls.marshal_deposition_fields)
        # Marshal the metadata attribute
        obj['metadata'] = marshal(unicodifier(draft.values), metadata_fields)

        # Add record and DOI information from latest SIP
        for sip in deposition.sips:
            if sip.is_sealed():
                recjson = sip.metadata
                if recjson.get('recid'):
                    obj['record_id'] = fields.Integer().format(
                        recjson.get('recid')
                    )
                    obj['record_url'] = fields.String().format(url_for(
                        'record.metadata',
                        recid=recjson.get('recid'),
                        _external=True
                    ))
                if recjson.get('doi') and \
                   recjson.get('doi').startswith(CFG_DATACITE_DOI_PREFIX+"/"):
                    obj['doi'] = fields.String().format(recjson.get('doi'))
                    obj['doi_url'] = fields.String().format(
                        "http://dx.doi.org/%s" % obj['doi']
                    )
                break

        return obj

    @classmethod
    def marshal_draft(cls, obj):
        """
        Generate a JSON representation for REST API of a DepositionDraft
        """
        return marshal(obj, cls.marshal_draft_fields)

    @classmethod
    def api_action(cls, deposition, action_id):
        if action_id == 'publish':
            return deposition.run_workflow(headless=True)
        elif action_id == 'edit':
            # Trick: Works in combination with load_record task to provide
            # proper response codes to API clients.
            if deposition.state == 'done' or deposition.drafts:
                deposition.reinitialize_workflow()
            return deposition.run_workflow(headless=True)
        elif action_id == 'discard':
            deposition.stop_workflow()
            deposition.save()
            return deposition.marshal(), 201
        raise InvalidApiAction(action_id)

    @classmethod
    def api_metadata_schema(cls, draft_id):
        schema = super(upload, cls).api_metadata_schema(draft_id)
        if schema and draft_id == '_edit':
            if 'recid' in schema['schema']:
                del schema['schema']['recid']
            if 'modification_date' in schema['schema']:
                del schema['schema']['modification_date']
        return schema

    @classmethod
    def render_completed(cls, d):
        """
        Render page when deposition was successfully completed
        """
        ctx = dict(
            deposition=d,
            deposition_type=(
                None if d.type.is_default() else d.type.get_identifier()
            ),
            uuid=d.id,
            my_depositions=Deposition.get_depositions(
                current_user, type=d.type
            ),
            sip=d.get_latest_sip(),
            format_record=format_record,
        )

        return render_template('deposit/completed.html', **ctx)