From 809e08d8c245ceeb3b0e6d3a6a81c50f4c9de055 Mon Sep 17 00:00:00 2001 From: Lars Holm Nielsen Date: Thu, 1 Jun 2017 12:51:40 +0200 Subject: [PATCH 1/3] openaire: helper functions * Adds helper functions for determining OpenAIRE type of a record. * Adds function to compute an OpenAIRE identifier as well as portal link. (closes #1105) --- tests/unit/openaire/test_openaire_helpers.py | 99 ++++++++++++++++ zenodo/config.py | 10 +- zenodo/modules/openaire/helpers.py | 112 +++++++++++++++++++ 3 files changed, 216 insertions(+), 5 deletions(-) create mode 100644 tests/unit/openaire/test_openaire_helpers.py create mode 100644 zenodo/modules/openaire/helpers.py diff --git a/tests/unit/openaire/test_openaire_helpers.py b/tests/unit/openaire/test_openaire_helpers.py new file mode 100644 index 000000000..5c30ee502 --- /dev/null +++ b/tests/unit/openaire/test_openaire_helpers.py @@ -0,0 +1,99 @@ +# -*- coding: utf-8 -*- +# +# This file is part of Zenodo. +# Copyright (C) 2017 CERN. +# +# Zenodo is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# +# Zenodo is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Zenodo; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307, USA. +# +# In applying this license, CERN does not +# waive the privileges and immunities granted to it by virtue of its status +# as an Intergovernmental Organization or submit itself to any jurisdiction. + +"""Test for OpenAIRE helpers.""" + +from __future__ import absolute_import, print_function + +from zenodo.modules.openaire.helpers import openaire_id, openaire_link, \ + openaire_type + + +def test_openire_type(app, minimal_record): + """Test OpenAIRE type.""" + r = minimal_record + # Default zenodo type is software which has no OpenAIRE type. + assert openaire_type(r) is None + + # Datasets just map to datasets. + r['resource_type']['type'] = 'dataset' + assert openaire_type(r) == 'dataset' + + # Open publications + r['resource_type']['type'] = 'publication' + assert openaire_type(r) == 'publication' + + # Non-open publications + r['access_right'] = 'embargoed' + assert openaire_type(r) is None + # with grants + r['grants'] = [{'id': 'someid'}] + assert openaire_type(r) == 'publication' + + # in ecfunded community + del r['grants'] + r['communities'] = ['ecfunded'] + assert openaire_type(r) == 'publication' + r['communities'] = ['zenodo'] + assert openaire_type(r) is None + + +def test_openire_id(app, minimal_record): + """Test OpenAIRE ID.""" + r = minimal_record + r['doi'] = u'10.5281/zenodo.123' + r['_oai'] = {'id': u'oai:zenodo.org:123'} + + # Default zenodo type is software which has no OpenAIRE type. + assert openaire_id(r) is None + + # Dataset ID + r['resource_type']['type'] = 'dataset' + assert openaire_id(r) == 'r37b0ad08687::204007f516ddcf0a452c2f22d48695ca' + + # Publication ID + r['resource_type']['type'] = 'publication' + assert openaire_id(r) == 'od______2659::47287d1800c112499a117ca17aa1909d' + + +def test_openire_link(app, minimal_record): + """Test OpenAIRE ID.""" + r = minimal_record + r['doi'] = u'10.5281/zenodo.123' + r['_oai'] = {'id': u'oai:zenodo.org:123'} + + # Default zenodo type is software which has no OpenAIRE type. + assert openaire_link(r) is None + + # Dataset ID + r['resource_type']['type'] = 'dataset' + assert openaire_link(r) == \ + 'https://beta.openaire.eu/search/dataset' \ + '?datasetId=r37b0ad08687::204007f516ddcf0a452c2f22d48695ca' + + # Publication ID + r['resource_type']['type'] = 'publication' + assert openaire_link(r) == \ + 'https://beta.openaire.eu/search/publication' \ + '?articleId=od______2659::47287d1800c112499a117ca17aa1909d' diff --git a/zenodo/config.py b/zenodo/config.py index 13fe259d7..7e5c375af 100644 --- a/zenodo/config.py +++ b/zenodo/config.py @@ -275,20 +275,20 @@ def _(x): OPENAIRE_SCHEMAS_HOST = 'zenodo.org' #: Hostname for OpenAIRE's grant resolver. OPENAIRE_JSONRESOLVER_GRANTS_HOST = 'dx.zenodo.org' -#: OpenAIRE Zenodo IDs +#: OpenAIRE data source IDs for Zenodo. OPENAIRE_ZENODO_IDS = { 'publication': 'opendoar____::2659', 'dataset': 're3data_____::r3d100010468', } -#: OpenAIRE Zenodo namespace prefixes +#: OpenAIRE ID namespace prefixes for Zenodo. OPENAIRE_NAMESPACE_PREFIXES = { 'publication': 'od______2659', 'dataset': 'r37b0ad08687', } #: OpenAIRE API endpoint. -OPENAIRE_API_URL = 'https://beta.services.openaire.eu/is/mvc' -# TODO: Check if we are to use Dev or Beta endpoint... -# OPENAIRE_API_URL = 'http://dev.openaire.research-infrastructures.eu/is/mvc' +OPENAIRE_API_URL = 'http://dev.openaire.research-infrastructures.eu/is/mvc' +#: URL to OpenAIRE portal. +OPENAIRE_PORTAL_URL = 'https://beta.openaire.eu' # OpenDefinition # ============== diff --git a/zenodo/modules/openaire/helpers.py b/zenodo/modules/openaire/helpers.py new file mode 100644 index 000000000..253e9bc24 --- /dev/null +++ b/zenodo/modules/openaire/helpers.py @@ -0,0 +1,112 @@ +# -*- coding: utf-8 -*- +# +# This file is part of Zenodo. +# Copyright (C) 2017 CERN. +# +# Zenodo is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# +# Zenodo is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Zenodo; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307, USA. +# +# In applying this license, CERN does not +# waive the privileges and immunities granted to it by virtue of its status +# as an Intergovernmental Organization or submit itself to any jurisdiction. + +"""OpenAIRE related helpers.""" + +from __future__ import absolute_import, print_function + +import hashlib + +from flask import current_app + + +class _OAType(object): + """OpenAIRE types.""" + + publication = 'publication' + dataset = 'dataset' + + +def is_openaire_publication(record): + """Determine if record is a publication for OpenAIRE.""" + types = ['publication', 'presentation', 'poster'] + if record.get('resource_type', {}).get('type') not in types: + return False + + # Has grants, is part of ecfunded community or is open access. + if record.get('grants') or 'ecfunded' in record.get('communities', []) or \ + 'open' == record.get('access_right'): + return True + return False + + +def is_openaire_dataset(record): + """Determine if record is a dataset for OpenAIRE.""" + if record.get('resource_type', {}).get('type') == 'dataset': + return True + return False + + +def openaire_type(record): + """Get the OpenAIRE type of a record.""" + if is_openaire_publication(record): + return _OAType.publication + elif is_openaire_dataset(record): + return _OAType.dataset + return None + + +def openaire_id(record): + """Compute the OpenAIRE identifier.""" + return _openaire_id(record, openaire_type(record)) + + +def _openaire_id(record, oatype): + """Compute the OpenAIRE identifier.""" + prefix = None + value = None + if oatype == _OAType.publication: + # Hard-coded prefix from OpenAIRE. + prefix = current_app.config['OPENAIRE_ID_PREFIX_PUBLICATION'] + value = record.get('_oai', {}).get('id') + elif oatype == _OAType.dataset: + # Hard-coded prefix from OpenAIRE. + prefix = current_app.config['OPENAIRE_ID_PREFIX_DATASET'] + value = record.get('doi') + + if not value or not prefix: + return None + + m = hashlib.md5() + m.update(value.encode('utf8')) + + return '{}::{}'.format(prefix, m.hexdigest()) + + +def openaire_link(record): + """Compute an OpenAIRE link.""" + oatype = openaire_type(record) + oaid = _openaire_id(record, oatype) + + if oatype == _OAType.publication: + return '{}/search/publication?articleId={}'.format( + current_app.config['OPENAIRE_PORTAL_URL'], + oaid, + ) + elif oatype == _OAType.dataset: + return '{}/search/dataset?datasetId={}'.format( + current_app.config['OPENAIRE_PORTAL_URL'], + oaid, + ) + return None From 31ac6a821c9af0d460b195ec578175ba05d5c695 Mon Sep 17 00:00:00 2001 From: Lars Holm Nielsen Date: Thu, 1 Jun 2017 12:46:57 +0200 Subject: [PATCH 2/3] openaire: openaire link on record detail page * Adds link from record to OpenAIRE version of record. (closes #1115) --- setup.py | 1 + zenodo/modules/openaire/views.py | 61 ++++++++++++++++++ .../zenodo_records/box/publishedin.html | 20 ++++-- .../theme/static/img/openaire-horizontal.png | Bin 0 -> 12549 bytes 4 files changed, 76 insertions(+), 6 deletions(-) create mode 100644 zenodo/modules/openaire/views.py create mode 100644 zenodo/modules/theme/static/img/openaire-horizontal.png diff --git a/setup.py b/setup.py index 46a305835..e42c9c52c 100644 --- a/setup.py +++ b/setup.py @@ -204,6 +204,7 @@ 'zenodo_communities = zenodo.modules.communities.views:blueprint', 'zenodo_deposit = zenodo.modules.deposit.views:blueprint', 'zenodo_frontpage = zenodo.modules.frontpage.views:blueprint', + 'zenodo_openaire = zenodo.modules.openaire.views:blueprint', 'zenodo_redirector = zenodo.modules.redirector.views:blueprint', 'zenodo_search_ui = zenodo.modules.search_ui.views:blueprint', 'zenodo_theme = zenodo.modules.theme.views:blueprint', diff --git a/zenodo/modules/openaire/views.py b/zenodo/modules/openaire/views.py new file mode 100644 index 000000000..e86184c04 --- /dev/null +++ b/zenodo/modules/openaire/views.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# +# This file is part of Zenodo. +# Copyright (C) 2017 CERN. +# +# Zenodo is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# +# Zenodo is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Zenodo; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307, USA. +# +# In applying this license, CERN does not +# waive the privileges and immunities granted to it by virtue of its status +# as an Intergovernmental Organization or submit itself to any jurisdiction. + +"""Blueprint for OpenAIRE.""" + +from __future__ import absolute_import, print_function + +import copy +from operator import itemgetter + +import idutils +import six +from flask import Blueprint, current_app, render_template, request +from flask_principal import ActionNeed + +from .helpers import is_openaire_dataset, is_openaire_publication, \ + openaire_link + +blueprint = Blueprint( + 'zenodo_openaire', + __name__ +) + + +@blueprint.app_template_filter('is_openaire_publication') +def is_publication(record): + """Test if record is an OpenAIRE publication.""" + return is_openaire_publication(record) + + +@blueprint.app_template_filter('is_openaire_dataset') +def is_dataset(record): + """Test if record is an OpenAIRE dataset.""" + return is_openaire_publication(record) + + +@blueprint.app_template_filter('openaire_link') +def link(record): + """Generate an OpenAIRE link.""" + return openaire_link(record) diff --git a/zenodo/modules/records/templates/zenodo_records/box/publishedin.html b/zenodo/modules/records/templates/zenodo_records/box/publishedin.html index b8c9bc01f..f16f92fb3 100644 --- a/zenodo/modules/records/templates/zenodo_records/box/publishedin.html +++ b/zenodo/modules/records/templates/zenodo_records/box/publishedin.html @@ -22,12 +22,20 @@ # as an Intergovernmental Organization or submit itself to any jurisdiction. -#} -{% set published_in = record|zenodo_related_links(all_pending_comms + all_accepted_comms) %} +{%- set published_in = record|zenodo_related_links(all_pending_comms + all_accepted_comms) %} +{%- set is_openaire = record|is_openaire_publication %} -{% if published_in %} +{%- if published_in or is_openaire %} -{% endif %} +{%- endif %} diff --git a/zenodo/modules/theme/static/img/openaire-horizontal.png b/zenodo/modules/theme/static/img/openaire-horizontal.png new file mode 100644 index 0000000000000000000000000000000000000000..797a31bf0c08ba7276e93a6dc92d3acbf34050af GIT binary patch literal 12549 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 literal 0 HcmV?d00001 From bad8667ae2cc93b46dfea877e03299a72151eb3f Mon Sep 17 00:00:00 2001 From: Lars Holm Nielsen Date: Thu, 1 Jun 2017 14:45:35 +0200 Subject: [PATCH 3/3] openaire: use object type model for openaire * Stores the OpenAIRE type and resourceType in the object types JSON. --- .../records/test_schemas_openaire_json.py | 2 +- zenodo/modules/openaire/helpers.py | 40 +++++----- zenodo/modules/openaire/schema.py | 51 +++++++------ zenodo/modules/records/data/objecttypes.json | 76 +++++++++++++++++++ .../records/objecttype-v1.0.0.json | 15 ++++ 5 files changed, 144 insertions(+), 40 deletions(-) diff --git a/tests/unit/records/test_schemas_openaire_json.py b/tests/unit/records/test_schemas_openaire_json.py index f70a472e0..71edc3ca9 100644 --- a/tests/unit/records/test_schemas_openaire_json.py +++ b/tests/unit/records/test_schemas_openaire_json.py @@ -80,7 +80,7 @@ def test_resource_types(app, db, minimal_oai_record, recid_pid): assert obj['originalId'] == 'oai:zenodo.org:123' assert obj['collectedFromId'] == 'opendoar____::2659' assert obj['hostedById'] == 'opendoar____::2659' - assert obj['resourceType'] == '0001' + assert obj['resourceType'] == '0004' assert obj['type'] == 'publication' diff --git a/zenodo/modules/openaire/helpers.py b/zenodo/modules/openaire/helpers.py index 253e9bc24..f9f7373be 100644 --- a/zenodo/modules/openaire/helpers.py +++ b/zenodo/modules/openaire/helpers.py @@ -30,6 +30,8 @@ from flask import current_app +from zenodo.modules.records.models import ObjectType + class _OAType(object): """OpenAIRE types.""" @@ -40,8 +42,9 @@ class _OAType(object): def is_openaire_publication(record): """Determine if record is a publication for OpenAIRE.""" - types = ['publication', 'presentation', 'poster'] - if record.get('resource_type', {}).get('type') not in types: + oatype = ObjectType.get_by_dict(record.get('resource_type')).get( + 'openaire', {}) + if not oatype or oatype['type'] != _OAType.publication: return False # Has grants, is part of ecfunded community or is open access. @@ -53,9 +56,9 @@ def is_openaire_publication(record): def is_openaire_dataset(record): """Determine if record is a dataset for OpenAIRE.""" - if record.get('resource_type', {}).get('type') == 'dataset': - return True - return False + oatype = ObjectType.get_by_dict(record.get('resource_type')).get( + 'openaire', {}) + return oatype and oatype['type'] == _OAType.dataset def openaire_type(record): @@ -74,26 +77,29 @@ def openaire_id(record): def _openaire_id(record, oatype): """Compute the OpenAIRE identifier.""" - prefix = None - value = None - if oatype == _OAType.publication: - # Hard-coded prefix from OpenAIRE. - prefix = current_app.config['OPENAIRE_ID_PREFIX_PUBLICATION'] - value = record.get('_oai', {}).get('id') - elif oatype == _OAType.dataset: - # Hard-coded prefix from OpenAIRE. - prefix = current_app.config['OPENAIRE_ID_PREFIX_DATASET'] - value = record.get('doi') + prefix, identifier = openaire_original_id(record, oatype) - if not value or not prefix: + if not identifier or not prefix: return None m = hashlib.md5() - m.update(value.encode('utf8')) + m.update(identifier.encode('utf8')) return '{}::{}'.format(prefix, m.hexdigest()) +def openaire_original_id(record, oatype): + """Original original identifier.""" + prefix = current_app.config['OPENAIRE_NAMESPACE_PREFIXES'].get(oatype) + + value = None + if oatype == _OAType.publication: + value = record.get('_oai', {}).get('id') + elif oatype == _OAType.dataset: + value = record.get('doi') + + return prefix, value + def openaire_link(record): """Compute an OpenAIRE link.""" oatype = openaire_type(record) diff --git a/zenodo/modules/openaire/schema.py b/zenodo/modules/openaire/schema.py index bf65b7faf..178f9fffd 100644 --- a/zenodo/modules/openaire/schema.py +++ b/zenodo/modules/openaire/schema.py @@ -34,6 +34,8 @@ from zenodo.modules.records.models import ObjectType from zenodo.modules.records.serializers.fields import DateString +from .helpers import openaire_original_id, openaire_type + OpenAIREType = namedtuple('OpenAIREType', ('type', 'resource_type')) @@ -60,42 +62,48 @@ class RecordSchemaOpenAIREJSON(Schema): embargoEndDate = DateString(attribute='metadata.embargo_date') publisher = fields.Method('get_publisher') - collectedFromId = fields.Method('get_openaire_id', required=True) - hostedById = fields.Method('get_openaire_id') + collectedFromId = fields.Method('get_datasource_id', required=True) + hostedById = fields.Method('get_datasource_id') linksToProjects = fields.Method('get_links_to_projects') pids = fields.Method('get_pids') - def _resolve_openaire_type(self, obj): - # TODO: Move to utils.py? - metadata = obj.get('metadata') - obj_type = ObjectType.get_by_dict(metadata.get('resource_type')) - if obj_type['internal_id'] == 'dataset': - return OpenAIREType('dataset', '0021') - else: - return OpenAIREType('publication', '0001') + def _openaire_type(self, obj): + return ObjectType.get_by_dict( + obj.get('metadata', {}).get('resource_type') + ).get('openaire') def get_original_id(self, obj): """Get Original Id.""" - openaire_type = self._resolve_openaire_type(obj) - if openaire_type.type == 'publication': - return obj.get('metadata', {}).get('_oai', {}).get('id') - if openaire_type.type == 'dataset': - return obj.get('metadata', {}).get('doi') + oatype = self._openaire_type(obj) + if oatype: + return openaire_original_id( + obj.get('metadata', {}), + oatype['type'] + )[1] + return missing def get_type(self, obj): """Get record type.""" - return self._resolve_openaire_type(obj).type + oatype = self._openaire_type(obj) + if oatype: + return oatype['type'] + return missing def get_resource_type(self, obj): """Get resource type.""" - return self._resolve_openaire_type(obj).resource_type + oatype = self._openaire_type(obj) + if oatype: + return oatype['resourceType'] + return missing - def get_openaire_id(self, obj): + def get_datasource_id(self, obj): """Get OpenAIRE Zenodo ID.""" - # TODO: Move to utils.py? - openaire_type = self._resolve_openaire_type(obj).type - return current_app.config['OPENAIRE_ZENODO_IDS'].get(openaire_type) + oatype = self._openaire_type(obj) + if oatype: + return current_app.config['OPENAIRE_ZENODO_IDS'].get( + oatype['type']) + return missing # Mapped from: http://api.openaire.eu/vocabularies/dnet:access_modes LICENSE_MAPPING = { @@ -134,7 +142,6 @@ def get_pids(self, obj): def get_url(self, obj): """Get record URL.""" - # TODO: Zenodo or DOI URL? ("zenodo.org/..." or "doi.org/...") return current_app.config['ZENODO_RECORDS_UI_LINKS_FORMAT'].format( recid=obj['metadata']['recid']) diff --git a/zenodo/modules/records/data/objecttypes.json b/zenodo/modules/records/data/objecttypes.json index 851276d80..f79c62bfb 100644 --- a/zenodo/modules/records/data/objecttypes.json +++ b/zenodo/modules/records/data/objecttypes.json @@ -25,6 +25,10 @@ {"$ref": "http://zenodo.org/objecttypes/publication/workingpaper"}, {"$ref": "http://zenodo.org/objecttypes/publication/other"} ], + "openaire": { + "resourceType": "0001", + "type": "publication" + }, "csl": "article" }, { @@ -40,6 +44,10 @@ "datacite": {"general": "Text", "type": "Poster"}, "eurepo": "info:eu-repo/semantics/conferencePoster", "schema.org": "http://schema.org/CreativeWork", + "openaire": { + "resourceType": "0004", + "type": "publication" + }, "csl": "graphic" }, { @@ -55,6 +63,10 @@ "datacite": {"general": "Text", "type": "Presentation"}, "eurepo": "info:eu-repo/semantics/lecture", "schema.org": "http://schema.org/CreativeWork", + "openaire": { + "resourceType": "0010", + "type": "publication" + }, "csl": "speech" }, { @@ -70,6 +82,10 @@ "datacite": {"general": "Dataset"}, "eurepo": "info:eu-repo/semantics/other", "schema.org": "http://schema.org/Dataset", + "openaire": { + "resourceType": "0021", + "type": "dataset" + }, "csl": "dataset" }, { @@ -154,6 +170,10 @@ "datacite": {"general": "Text", "type": "Book"}, "eurepo": "info:eu-repo/semantics/book", "parent": {"$ref": "http://zenodo.org/objecttypes/publication"}, + "openaire": { + "resourceType": "0002", + "type": "publication" + }, "csl": "book" }, { @@ -170,6 +190,10 @@ "datacite": {"general": "Text", "type": "Book section"}, "eurepo": "info:eu-repo/semantics/bookPart", "parent": {"$ref": "http://zenodo.org/objecttypes/publication"}, + "openaire": { + "resourceType": "0013", + "type": "publication" + }, "csl": "chapter" }, { @@ -186,6 +210,10 @@ "datacite": {"general": "Text", "type": "Conference paper"}, "eurepo": "info:eu-repo/semantics/conferencePaper", "parent": {"$ref": "http://zenodo.org/objecttypes/publication"}, + "openaire": { + "resourceType": "0004", + "type": "publication" + }, "csl": "paper-conference" }, { @@ -202,6 +230,10 @@ "datacite": {"general": "Text", "type": "Journal article"}, "eurepo": "info:eu-repo/semantics/article", "parent": {"$ref": "http://zenodo.org/objecttypes/publication"}, + "openaire": { + "resourceType": "0001", + "type": "publication" + }, "csl": "article-journal" }, { @@ -218,6 +250,10 @@ "eurepo": "info:eu-repo/semantics/patent", "schema.org": "http://schema.org/CreativeWork", "parent": {"$ref": "http://zenodo.org/objecttypes/publication"}, + "openaire": { + "resourceType": "0019", + "type": "publication" + }, "csl": "patent" }, { @@ -234,6 +270,10 @@ "datacite": {"general": "Text", "type": "Preprint"}, "eurepo": "info:eu-repo/semantics/preprint", "parent": {"$ref": "http://zenodo.org/objecttypes/publication"}, + "openaire": { + "resourceType": "0016", + "type": "publication" + }, "csl": "article" }, { @@ -250,6 +290,10 @@ "datacite": {"general": "Text", "type": "Report"}, "eurepo": "info:eu-repo/semantics/report", "parent": {"$ref": "http://zenodo.org/objecttypes/publication"}, + "openaire": { + "resourceType": "0017", + "type": "publication" + }, "csl": "article" }, { @@ -266,6 +310,10 @@ "datacite": {"general": "Text", "type": "Software documentation"}, "eurepo": "info:eu-repo/semantics/technicalDocumentation", "parent": {"$ref": "http://zenodo.org/objecttypes/publication"}, + "openaire": { + "resourceType": "0032", + "type": "publication" + }, "csl": "article" }, { @@ -282,6 +330,10 @@ "datacite": {"general": "Text", "type": "Thesis"}, "eurepo": "info:eu-repo/semantics/doctoralThesis", "parent": {"$ref": "http://zenodo.org/objecttypes/publication"}, + "openaire": { + "resourceType": "0007", + "type": "publication" + }, "csl": "thesis" }, { @@ -298,6 +350,10 @@ "datacite": {"general": "Text", "type": "Technical note"}, "eurepo": "info:eu-repo/semantics/technicalDocumentation", "parent": {"$ref": "http://zenodo.org/objecttypes/publication"}, + "openaire": { + "resourceType": "0020", + "type": "publication" + }, "csl": "article" }, { @@ -314,6 +370,10 @@ "datacite": {"general": "Text", "type": "Working paper"}, "eurepo": "info:eu-repo/semantics/workingPaper", "parent": {"$ref": "http://zenodo.org/objecttypes/publication"}, + "openaire": { + "resourceType": "0016", + "type": "publication" + }, "csl": "article" }, { @@ -330,6 +390,10 @@ "datacite": {"general": "Text", "type": "Proposal"}, "eurepo": "info:eu-repo/semantics/researchProposal", "parent": {"$ref": "http://zenodo.org/objecttypes/publication"}, + "openaire": { + "resourceType": "0020", + "type": "publication" + }, "csl": "article" }, { @@ -346,6 +410,10 @@ "datacite": {"general": "Text", "type": "Project deliverable"}, "eurepo": "info:eu-repo/semantics/report", "parent": {"$ref": "http://zenodo.org/objecttypes/publication"}, + "openaire": { + "resourceType": "0017", + "type": "publication" + }, "csl": "report" }, { @@ -362,6 +430,10 @@ "datacite": {"general": "Text", "type": "Project milestone"}, "eurepo": "info:eu-repo/semantics/report", "parent": {"$ref": "http://zenodo.org/objecttypes/publication"}, + "openaire": { + "resourceType": "0017", + "type": "publication" + }, "csl": "report" }, { @@ -378,6 +450,10 @@ "datacite": {"general": "Text", "type": "Other"}, "eurepo": "info:eu-repo/semantics/other", "parent": {"$ref": "http://zenodo.org/objecttypes/publication"}, + "openaire": { + "resourceType": "0020", + "type": "publication" + }, "csl": "article" }, { diff --git a/zenodo/modules/records/jsonschemas/records/objecttype-v1.0.0.json b/zenodo/modules/records/jsonschemas/records/objecttype-v1.0.0.json index 717d266aa..8915e91d7 100644 --- a/zenodo/modules/records/jsonschemas/records/objecttype-v1.0.0.json +++ b/zenodo/modules/records/jsonschemas/records/objecttype-v1.0.0.json @@ -57,6 +57,21 @@ "eurepo": { "type": "string" }, + "openaire": { + "type": "object", + "properties": { + "resourceType": { + "type": "string" + }, + "type": { + "type": "string" + }, + "required": [ + "resourceType", + "type" + ] + } + }, "parent": { "type": "object" },